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

@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Overview
Island is an Ansible-based self-hosting infrastructure stack that deploys email, web server, git hosting, Matrix homeserver, monitoring, and backup services using Docker Compose on Ubuntu servers.
Linderhof is an Ansible-based self-hosting infrastructure stack that deploys email, web server, git hosting, Matrix homeserver, monitoring, and backup services using Docker Compose on Ubuntu servers.
## Common Commands
@ -37,23 +37,31 @@ Note: Inventory and vault password are set via `ANSIBLE_INVENTORY` and `ANSIBLE_
**Deployment Pattern:** Each service is deployed to `/srv/<service>/` on the target host with a `compose.yml` and environment files.
**Standalone Playbooks** (not in `site.yml`):
- `provision.yml` - Provision a cloud VM (Hetzner). Usage: `ansible-playbook playbooks/provision.yml`
- `provision.yml` - Provision a cloud VM (Hetzner)
- `dns.yml` - Manage DNS zones/records via Hetzner DNS API
- `bootstrap.yml` - First-time server setup (run once as root before site.yml)
**Full deployment order** (fresh server):
1. `provision.yml` - create server, auto-writes IP to hosts.yml and config.yml
2. `dns.yml` - create DNS records
3. `bootstrap.yml` - users, SSH hardening, packages, Docker (connects as root)
4. `site.yml` - deploy all services
**Playbook Execution Order** (via `site.yml`):
1. bootstrap.yml - SSH, sudo, users, base packages (manual only)
2. docker.yml - Docker engine installation
3. docker_network.yml - Pre-create all Docker networks (must run before any service)
4. nebula.yml - Overlay network (Nebula)
5. caddy.yml - Web server / reverse proxy
6. mail.yml - Email (docker-mailserver + rainloop)
7. forgejo.yml - Git server
8. tuwunel.yml - Matrix homeserver (Tuwunel)
9. monitoring.yml - Prometheus, Grafana, Loki, Alloy
10. goaccess.yml - Web analytics
11. diun.yml - Docker image update notifications
12. restic.yml - Encrypted backups
13. fail2ban.yml - Intrusion prevention
1. networks.yml - Pre-create all Docker networks (must run before any service)
2. nebula.yml - Overlay network (Nebula)
3. caddy.yml - Web server / reverse proxy
4. mail.yml - Email (docker-mailserver + rainloop)
5. forgejo.yml - Git server
6. tuwunel.yml - Matrix homeserver (Tuwunel)
7. radicale.yml - CalDAV/CardDAV
8. monitoring.yml - Prometheus, Grafana, Loki, Alloy
9. goaccess.yml - Web analytics
10. diun.yml - Docker image update notifications
11. restic.yml - Encrypted backups
12. fail2ban.yml - Intrusion prevention
**Mail TLS:** on first deployment, the mail role stops Caddy, runs certbot standalone to acquire a Let's Encrypt cert for `mail_hostname`, then restarts Caddy. subsequent runs skip this (cert already exists). Caddy owns port 80 so standalone is the only viable approach without a DNS challenge plugin.
**Role Structure:** Each role in `roles/` contains:
- `tasks/main.yml` - Core provisioning tasks
@ -90,6 +98,9 @@ caddy_sites:
- `enable_forgejo`
- `enable_tuwunel`
- `enable_monitoring`
- `enable_goaccess`
- `enable_goaccess_sync`
- `enable_radicale`
- `enable_restic`
- `enable_fail2ban`
- `enable_nebula`