# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview **Sovereign** is an Ansible project that deploys a complete self-hosted infrastructure stack for small businesses using Docker and Docker Compose on a single Linux host. ## Architecture ### Services | Role | Tool | Subdomain | |------|------|-----------| | common | Traefik (reverse proxy + TLS) | `traefik.` | | graylog | Graylog + OpenSearch + MongoDB | `logs.` | | authentik | Authentik (identity provider) | `auth.` | | minio | MinIO (object storage) | `s3.`, `minio.` | | nextcloud | Nextcloud + MariaDB + Redis | `cloud.` | | stalwart | Stalwart Mail (SMTP/IMAP) | `mail.` | | roundcube | Roundcube (webmail) | `webmail.` | | matrix | Synapse + Element | `matrix.`, `chat.` | | jitsi | Jitsi Meet | `meet.` | | headscale | Headscale (WireGuard mesh VPN) | `headscale.` | | wazuh | Wazuh Manager + Indexer + Dashboard | `wazuh.` | | vaultwarden | Vaultwarden + PostgreSQL | `vault.` | | forgejo | Forgejo + PostgreSQL | `git.` | | uptimekuma | Uptime Kuma (uptime monitoring) | `status.` | | automatisch | Automatisch (workflow automation) | `automate.` | | twenty | Twenty CRM + PostgreSQL + Redis | `crm.` | ### Design Principles - **Single authentication**: All services authenticate via Authentik OIDC/OAuth2 - **Single config per deployment**: All variables live in `inventories/production/group_vars/all.yml` - **Centralized logging**: Every container ships logs via GELF UDP to Graylog (`graylog_host:12201`) - **Networking**: All services share an external Docker network named `sovereign` for Traefik routing; each service has its own `internal` network for db/cache isolation - **Deployment order**: `site.yml` deploys Graylog first (logging), then Authentik (auth), then all other services ### Tenant Configuration All deployment variables are in one place: `inventories/production/group_vars/all.yml`. For a new tenant/deployment, copy this file and update `base_domain`, passwords, and secrets. All service subdomains derive from `base_domain`. ## Project Structure ``` sovereign/ ├── ansible.cfg ├── requirements.yml # Ansible Galaxy collections ├── inventories/ │ └── production/ │ ├── hosts.yml │ └── group_vars/ │ └── all.yml # ← single tenant config file ├── playbooks/ │ └── site.yml └── roles/ └── / ├── defaults/main.yml ├── handlers/main.yml ├── tasks/main.yml └── templates/ ├── docker-compose.yml.j2 └── ... # service-specific configs ``` Each role deploys its Docker Compose stack to `/opt/sovereign//` on the target host. ## Common Commands ```bash # Install required Ansible collections ansible-galaxy collection install -r requirements.yml # Run a full deployment ansible-playbook playbooks/site.yml # Deploy a single service ansible-playbook playbooks/site.yml --tags authentik # Dry run ansible-playbook playbooks/site.yml --check --diff # Syntax check ansible-playbook playbooks/site.yml --syntax-check # Lint ansible-lint ``` ### Environment variables for inventory ```bash export SOVEREIGN_HOST=your-server-ip export SOVEREIGN_USER=ubuntu export SOVEREIGN_SSH_KEY=~/.ssh/id_rsa ``` ## Initial Setup Notes Before first deployment, update `inventories/production/group_vars/all.yml`: 1. Set `base_domain` 2. Replace all `changeme_*` passwords and secrets with secure values 3. Generate `graylog_root_password_sha2`: `echo -n yourpassword | sha256sum` 4. Create Authentik OIDC applications for each service that uses SSO (MinIO, Headscale, Vaultwarden, Forgejo) and fill in the `changeme_*_oidc_secret` placeholders in the respective compose templates 5. Wazuh requires TLS certificates — see Wazuh Docker documentation for generating certs before first run