initial commit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
75891c3271
129 changed files with 8046 additions and 0 deletions
164
inventory/group_vars/all/config.yml.setup
Normal file
164
inventory/group_vars/all/config.yml.setup
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
---
|
||||
# ============================================================
|
||||
# Linderhof Configuration
|
||||
# ============================================================
|
||||
# Generated by setup.sh — edit freely to match your needs.
|
||||
# Secrets are stored separately in vault.yml.
|
||||
# Tunable defaults live in each role's defaults/main.yml.
|
||||
#
|
||||
# To override any variable for this stack without editing this file,
|
||||
# create $LINDERHOF_DIR/group_vars/all/overrides.yml, e.g.:
|
||||
# mail_hostname: mail2.$domain
|
||||
# caddy_sites:
|
||||
# - $domain
|
||||
# - example2.com
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# Services — set to false to disable
|
||||
# ============================================================
|
||||
enable_mail: true
|
||||
enable_forgejo: true
|
||||
enable_monitoring: true
|
||||
enable_restic: true
|
||||
enable_fail2ban: true
|
||||
enable_tuwunel: true
|
||||
enable_nebula: true
|
||||
enable_diun: true
|
||||
enable_goaccess: true
|
||||
|
||||
# ============================================================
|
||||
# System
|
||||
# ============================================================
|
||||
domain: $domain
|
||||
server_name: $server_name
|
||||
server_ip: $server_ip
|
||||
admin_user: $admin_user
|
||||
admin_ssh_key: "{{ lookup('file', '$ssh_key_pub') }}"
|
||||
timezone: UTC
|
||||
|
||||
# ============================================================
|
||||
# Image versions (update when Diun notifies of new releases)
|
||||
# ============================================================
|
||||
caddy_version: "2"
|
||||
mailserver_version: "latest"
|
||||
rainloop_version: "latest"
|
||||
forgejo_version: "11"
|
||||
prometheus_version: "latest"
|
||||
alloy_version: "latest"
|
||||
grafana_version: "latest"
|
||||
loki_version: "latest"
|
||||
diun_version: "latest"
|
||||
tuwunel_version: "latest"
|
||||
radicale_version: "latest"
|
||||
nebula_version: "1.9.5"
|
||||
|
||||
# ============================================================
|
||||
# Caddy (web server / reverse proxy)
|
||||
# ============================================================
|
||||
# Static sites served as file servers — each gets /srv/caddy/sites/<domain>/
|
||||
# Override in overrides.yml to add more domains.
|
||||
caddy_sites:
|
||||
- $domain
|
||||
|
||||
# Service subdomains — override individually in overrides.yml
|
||||
webmail_domain: webmail.$domain
|
||||
rspamd_domain: rspamd.$domain
|
||||
grafana_domain: watch.$domain
|
||||
goaccess_domain: stats.$domain
|
||||
radicale_domain: cal.$domain
|
||||
|
||||
# Service ports — defined here so caddy can reference them when run standalone
|
||||
rainloop_port: 8888
|
||||
rspamd_port: 11334
|
||||
forgejo_port: 3000
|
||||
grafana_port: 3000
|
||||
tuwunel_port: 6167
|
||||
radicale_port: 5232
|
||||
caddy_metrics_port: 9000
|
||||
|
||||
# ============================================================
|
||||
# Mail (docker-mailserver + rainloop)
|
||||
# ============================================================
|
||||
# Override mail_hostname in overrides.yml if migrating (e.g. mail2.$domain)
|
||||
mail_hostname: mail.$domain
|
||||
|
||||
mail_domains:
|
||||
- $domain
|
||||
# Add more domains this mail server should handle:
|
||||
# mail_domains:
|
||||
# - $domain
|
||||
# - example2.com
|
||||
|
||||
mail_users:
|
||||
- address: $admin_user@$domain
|
||||
password: "{{ mail_passwords['$admin_user@$domain'] }}"
|
||||
- address: git@$domain
|
||||
password: "{{ mail_passwords['git@$domain'] }}"
|
||||
- address: notifications@$domain
|
||||
password: "{{ mail_passwords['notifications@$domain'] }}"
|
||||
|
||||
mail_aliases:
|
||||
- from: root@$domain
|
||||
to: $admin_user@$domain
|
||||
- from: dmarc@$domain
|
||||
to: $admin_user@$domain
|
||||
- from: postmaster@$domain
|
||||
to: $admin_user@$domain
|
||||
- from: hostmaster@$domain
|
||||
to: $admin_user@$domain
|
||||
- from: webmaster@$domain
|
||||
to: $admin_user@$domain
|
||||
- from: abuse@$domain
|
||||
to: $admin_user@$domain
|
||||
|
||||
# ============================================================
|
||||
# Forgejo (git hosting)
|
||||
# ============================================================
|
||||
forgejo_domain: code.$domain
|
||||
|
||||
# ============================================================
|
||||
# Monitoring
|
||||
# ============================================================
|
||||
grafana_root_url: "https://{{ grafana_domain }}"
|
||||
|
||||
# ============================================================
|
||||
# Restic (encrypted backups)
|
||||
# ============================================================
|
||||
restic_backend_type: "sftp"
|
||||
# restic_host: "uXXXXXX.your-storagebox.de"
|
||||
# restic_user: uXXXXXX
|
||||
# restic_ssh_port: 23
|
||||
# restic_remote_path: "backups/$server_name"
|
||||
# restic_ssh_key: "/root/.ssh/island_restic_backup"
|
||||
|
||||
# ============================================================
|
||||
# GoAccess (web analytics)
|
||||
# ============================================================
|
||||
goaccess_sites:
|
||||
- $domain
|
||||
- code.$domain
|
||||
- watch.$domain
|
||||
- webmail.$domain
|
||||
- rspamd.$domain
|
||||
goaccess_user: admin
|
||||
|
||||
# ============================================================
|
||||
# Diun (Docker Image Update Notifier)
|
||||
# ============================================================
|
||||
diun_notify_email: true
|
||||
diun_email_user: notifications@$domain
|
||||
## diun_email_password: defined in vault.yml
|
||||
diun_email_to: $admin_user@$domain
|
||||
|
||||
# ============================================================
|
||||
# Tuwunel (Matrix homeserver)
|
||||
# ============================================================
|
||||
tuwunel_server_name: $domain
|
||||
tuwunel_domain: chat.$domain
|
||||
|
||||
# ============================================================
|
||||
# Nebula (overlay network)
|
||||
# ============================================================
|
||||
nebula_subnet: "192.168.100.0/24"
|
||||
nebula_lighthouse_ip: "192.168.100.1"
|
||||
128
inventory/group_vars/all/dns.yml.setup
Normal file
128
inventory/group_vars/all/dns.yml.setup
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
---
|
||||
# ============================================================
|
||||
# Linderhof DNS Zones
|
||||
# ============================================================
|
||||
# Generated by setup.sh — edit to match your DNS needs.
|
||||
# This file is loaded automatically by Ansible as part of group_vars.
|
||||
#
|
||||
# After first mail deployment, retrieve DKIM keys with:
|
||||
# docker exec mailserver cat /tmp/docker-mailserver/rspamd/dkim/$domain/mail.pub
|
||||
# Add them to vault.yml and uncomment the mail._domainkey records below.
|
||||
# ============================================================
|
||||
|
||||
dns_zones:
|
||||
- zone: $domain
|
||||
records:
|
||||
# Root domain
|
||||
- name: "@"
|
||||
type: A
|
||||
records:
|
||||
- value: $server_ip
|
||||
|
||||
- name: "@"
|
||||
type: MX
|
||||
records:
|
||||
- value: "10 {{ mail_hostname }}."
|
||||
|
||||
- name: "@"
|
||||
type: TXT
|
||||
records:
|
||||
- value: "{{ 'v=spf1 mx -all' | hetzner.hcloud.txt_record }}"
|
||||
|
||||
# Server A record
|
||||
- name: $server_name
|
||||
type: A
|
||||
records:
|
||||
- value: $server_ip
|
||||
|
||||
- name: www
|
||||
type: A
|
||||
records:
|
||||
- value: $server_ip
|
||||
|
||||
# Mail subdomain A record (for the mail hostname itself)
|
||||
- name: "{{ mail_hostname.split('.')[0] }}"
|
||||
type: A
|
||||
records:
|
||||
- value: $server_ip
|
||||
|
||||
# Service CNAMEs
|
||||
- name: webmail
|
||||
type: CNAME
|
||||
records:
|
||||
- value: $server_name.$domain.
|
||||
|
||||
- name: code
|
||||
type: CNAME
|
||||
records:
|
||||
- value: $server_name.$domain.
|
||||
|
||||
- name: watch
|
||||
type: CNAME
|
||||
records:
|
||||
- value: $server_name.$domain.
|
||||
|
||||
- name: rspamd
|
||||
type: CNAME
|
||||
records:
|
||||
- value: $server_name.$domain.
|
||||
|
||||
- name: stats
|
||||
type: CNAME
|
||||
records:
|
||||
- value: $server_name.$domain.
|
||||
|
||||
- name: chat
|
||||
type: CNAME
|
||||
records:
|
||||
- value: $server_name.$domain.
|
||||
|
||||
- name: cal
|
||||
type: CNAME
|
||||
records:
|
||||
- value: $server_name.$domain.
|
||||
|
||||
# DMARC
|
||||
- name: _dmarc
|
||||
type: TXT
|
||||
records:
|
||||
- value: "{{ 'v=DMARC1; p=none; rua=mailto:dmarc@$domain' | hetzner.hcloud.txt_record }}"
|
||||
|
||||
# DKIM — uncomment after first mail deployment and add key to vault.yml
|
||||
# - name: mail._domainkey
|
||||
# type: TXT
|
||||
# records:
|
||||
# - value: "{{ dkim_keys['$domain'] | hetzner.hcloud.txt_record }}"
|
||||
|
||||
# Extra domains (additional mail-hosted domains) — add as needed:
|
||||
# - zone: example2.com
|
||||
# records:
|
||||
# - name: "@"
|
||||
# type: A
|
||||
# records:
|
||||
# - value: $server_ip
|
||||
#
|
||||
# - name: "@"
|
||||
# type: MX
|
||||
# records:
|
||||
# - value: "10 {{ mail_hostname }}."
|
||||
#
|
||||
# - name: "@"
|
||||
# type: TXT
|
||||
# records:
|
||||
# - value: "{{ 'v=spf1 mx -all' | hetzner.hcloud.txt_record }}"
|
||||
#
|
||||
# - name: www
|
||||
# type: CNAME
|
||||
# records:
|
||||
# - value: example2.com.
|
||||
#
|
||||
# - name: _dmarc
|
||||
# type: TXT
|
||||
# records:
|
||||
# - value: "{{ 'v=DMARC1; p=none; rua=mailto:dmarc@example2.com' | hetzner.hcloud.txt_record }}"
|
||||
#
|
||||
# # - name: mail._domainkey
|
||||
# # type: TXT
|
||||
# # records:
|
||||
# # - value: "{{ dkim_keys['example2.com'] | hetzner.hcloud.txt_record }}"
|
||||
55
inventory/group_vars/all/vault.yml.setup
Normal file
55
inventory/group_vars/all/vault.yml.setup
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
# ============================================================
|
||||
# Linderhof Secrets
|
||||
# ============================================================
|
||||
# Generated by setup.sh
|
||||
# Edit with: ansible-vault edit $LINDERHOF_DIR/group_vars/all/vault.yml
|
||||
# ============================================================
|
||||
|
||||
# hetzner
|
||||
hcloud_token: "$hcloud_token"
|
||||
|
||||
# mail
|
||||
# passwords generated with: openssl rand -base64 32
|
||||
mail_passwords:
|
||||
$admin_user@$domain: "$admin_mail_password"
|
||||
git@$domain: "$git_mail_password"
|
||||
notifications@$domain: "$notifications_mail_password"
|
||||
rspamd_web_password: "$rspamd_web_password"
|
||||
rainloop_admin_password: "$rainloop_admin_password"
|
||||
|
||||
# forgejo
|
||||
# keys generated with: openssl rand -hex 32
|
||||
forgejo_secret_key: "$forgejo_secret_key"
|
||||
forgejo_internal_token: "$forgejo_internal_token"
|
||||
forgejo_jwt_secret: "$forgejo_jwt_secret"
|
||||
forgejo_smtp_password: "$notifications_mail_password"
|
||||
|
||||
# monitoring
|
||||
# password generated with: openssl rand -base64 32
|
||||
grafana_admin_password: "$grafana_admin_password"
|
||||
|
||||
# tuwunel
|
||||
# token generated with: openssl rand -base64 32
|
||||
tuwunel_registration_token: "$tuwunel_registration_token"
|
||||
|
||||
# goaccess
|
||||
# password generated with: openssl rand -base64 32
|
||||
goaccess_password: "$goaccess_password"
|
||||
|
||||
# diun (uses the notifications mail account)
|
||||
diun_email_password: "$notifications_mail_password"
|
||||
|
||||
# restic
|
||||
# password generated with: openssl rand -base64 32
|
||||
restic_password: "$restic_password"
|
||||
|
||||
# fail2ban (optional — IPs/CIDRs to whitelist)
|
||||
# fail2ban_ignoreip: "your-home-ip/32"
|
||||
|
||||
# DKIM public keys — one entry per domain
|
||||
# Retrieve after first mail deployment:
|
||||
# docker exec mailserver cat /tmp/docker-mailserver/rspamd/dkim/$domain/mail.pub
|
||||
# Format: "v=DKIM1; k=rsa; p=<base64 public key>"
|
||||
dkim_keys:
|
||||
$domain: ""
|
||||
21
inventory/hosts.yml.example
Normal file
21
inventory/hosts.yml.example
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
# ============================================================
|
||||
# Linderhof Inventory
|
||||
# ============================================================
|
||||
# Copy this file to hosts.yml (gitignored) and fill in your values.
|
||||
# For single-host deployments, just update the connection info.
|
||||
# All configuration is in group_vars/all/config.yml
|
||||
#
|
||||
# For multi-host, add hosts and override variables per-host:
|
||||
# hostname:
|
||||
# ansible_host: 1.2.3.4
|
||||
# mail_hostname: mail.example.com # override
|
||||
# ============================================================
|
||||
|
||||
all:
|
||||
hosts:
|
||||
my-server:
|
||||
ansible_host: 1.2.3.4
|
||||
ansible_user: deploy
|
||||
ansible_become: true
|
||||
ansible_become_method: sudo
|
||||
Loading…
Add table
Add a link
Reference in a new issue