Fix fresh-deploy blockers and clean up architecture

- Seed postfix-accounts.cf before mailserver start to satisfy Dovecot's
  requirement for at least one account on first boot
- Add failed_when: false to mail user/alias list tasks (files don't exist
  on first run)
- Add forgejo_runner_version (was undefined); default to 12
- Create /srv/forgejo/data/gitea/conf before deploying app.ini
- Decouple goaccess sync from restic: new enable_goaccess_sync flag with
  its own goaccess_sync_* variables
- Move Docker installation to bootstrap exclusively; rename docker.yml to
  networks.yml (runs docker_network role only)
- Add radicale_password to vault template and setup.sh
- Fix goaccess sync tasks gated on enable_goaccess_sync
- Add upstream bug comment to authorized_key deprecation warning
- Update CLAUDE.md and README.md throughout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Matthias Johnson 2026-02-28 00:51:16 -07:00
parent 75891c3271
commit b38cd94fc8
23 changed files with 400 additions and 307 deletions

View file

@ -20,12 +20,14 @@
enable_mail: true
enable_forgejo: true
enable_monitoring: true
enable_restic: true
enable_restic: false
enable_fail2ban: true
enable_tuwunel: true
enable_nebula: true
enable_diun: true
enable_goaccess: true
enable_goaccess_sync: false
enable_radicale: true
# ============================================================
# System
@ -34,6 +36,7 @@ domain: $domain
server_name: $server_name
server_ip: $server_ip
admin_user: $admin_user
admin_shell: /bin/zsh
admin_ssh_key: "{{ lookup('file', '$ssh_key_pub') }}"
timezone: UTC
@ -44,6 +47,7 @@ caddy_version: "2"
mailserver_version: "latest"
rainloop_version: "latest"
forgejo_version: "11"
forgejo_runner_version: "12"
prometheus_version: "latest"
alloy_version: "latest"
grafana_version: "latest"
@ -143,6 +147,13 @@ goaccess_sites:
- rspamd.$domain
goaccess_user: admin
# Sync reports to a remote host via rsync over SSH (enable_goaccess_sync: true to activate)
# goaccess_sync_host: "uXXXXXX.your-storagebox.de"
# goaccess_sync_user: uXXXXXX
# goaccess_sync_ssh_port: 23
# goaccess_sync_ssh_key: "/root/.ssh/goaccess_sync"
# goaccess_sync_remote_path: "analytics"
# ============================================================
# Diun (Docker Image Update Notifier)
# ============================================================

View file

@ -7,7 +7,10 @@
#
# 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.
# Then add them to vault.yml under dkim_keys:
# dkim_keys:
# $domain: "v=DKIM1; k=rsa; p=..."
# The mail._domainkey record will be created automatically on next dns.yml run.
# ============================================================
dns_zones:
@ -17,15 +20,17 @@ dns_zones:
- name: "@"
type: A
records:
- value: $server_ip
- value: "{{ server_ip }}"
- name: "@"
type: MX
when: "{{ enable_mail | default(false) }}"
records:
- value: "10 {{ mail_hostname }}."
- name: "@"
type: TXT
when: "{{ enable_mail | default(false) }}"
records:
- value: "{{ 'v=spf1 mx -all' | hetzner.hcloud.txt_record }}"
@ -33,96 +38,66 @@ dns_zones:
- name: $server_name
type: A
records:
- value: $server_ip
- value: "{{ server_ip }}"
- name: www
type: A
records:
- value: $server_ip
- value: "{{ server_ip }}"
# Mail subdomain A record (for the mail hostname itself)
# Mail subdomain A record
- name: "{{ mail_hostname.split('.')[0] }}"
type: A
when: "{{ enable_mail | default(false) }}"
records:
- value: $server_ip
- value: "{{ server_ip }}"
# Service CNAMEs
- name: webmail
type: CNAME
when: "{{ enable_mail | default(false) }}"
records:
- value: $server_name.$domain.
- name: code
type: CNAME
when: "{{ enable_forgejo | default(false) }}"
records:
- value: $server_name.$domain.
- name: watch
type: CNAME
when: "{{ enable_monitoring | default(false) }}"
records:
- value: $server_name.$domain.
- name: rspamd
type: CNAME
when: "{{ enable_mail | default(false) }}"
records:
- value: $server_name.$domain.
- name: stats
type: CNAME
when: "{{ enable_goaccess | default(false) }}"
records:
- value: $server_name.$domain.
- name: chat
type: CNAME
when: "{{ enable_tuwunel | default(false) }}"
records:
- value: $server_name.$domain.
- name: cal
type: CNAME
when: "{{ enable_radicale | default(false) }}"
records:
- value: $server_name.$domain.
# DMARC
- name: _dmarc
type: TXT
when: "{{ enable_mail | default(false) }}"
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 }}"

View file

@ -6,6 +6,10 @@
# Edit with: ansible-vault edit $LINDERHOF_DIR/group_vars/all/vault.yml
# ============================================================
# system
root_password: "$root_password"
admin_password: "$admin_password"
# hetzner
hcloud_token: "$hcloud_token"
@ -33,6 +37,10 @@ grafana_admin_password: "$grafana_admin_password"
# token generated with: openssl rand -base64 32
tuwunel_registration_token: "$tuwunel_registration_token"
# radicale
# password generated with: openssl rand -base64 32
radicale_password: "$radicale_password"
# goaccess
# password generated with: openssl rand -base64 32
goaccess_password: "$goaccess_password"
@ -47,9 +55,8 @@ 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:
# DKIM public keys — add 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: ""
# dkim_keys:
# $domain: "v=DKIM1; k=rsa; p=..."