61 lines
2.7 KiB
Markdown
61 lines
2.7 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
# Prerequisites (once, on operator machine)
|
|
ansible-galaxy collection install community.general community.docker ansible.posix
|
|
echo "yourpassword" > ~/.vault-password-file && chmod 600 ~/.vault-password-file
|
|
|
|
# First-time server setup (run as root)
|
|
ansible-playbook playbooks/bootstrap.yml -u root
|
|
|
|
# Idempotent deploy (all subsequent runs)
|
|
ansible-playbook playbooks/deploy.yml
|
|
|
|
# Edit secrets
|
|
ansible-vault edit inventory/group_vars/all.vault.yml
|
|
|
|
# Check syntax without connecting
|
|
ansible-playbook playbooks/deploy.yml --syntax-check
|
|
|
|
# Dry run
|
|
ansible-playbook playbooks/deploy.yml --check
|
|
|
|
# Run only specific role
|
|
ansible-playbook playbooks/deploy.yml --tags base
|
|
ansible-playbook playbooks/deploy.yml --tags docker
|
|
ansible-playbook playbooks/deploy.yml --tags services
|
|
```
|
|
|
|
## Architecture
|
|
|
|
**Traffic flow:** Internet → Traefik (ports 80/443, TLS via Let's Encrypt ACME) → services. Ports 80 and 443 are open on the server.
|
|
|
|
**Secrets:** All secrets live in `inventory/group_vars/all.vault.yml` (Ansible Vault, AES-256). The file `all.yml` references them via `"{{ vault_* }}"` aliases. The vault password must exist at `~/.vault-password-file` on the operator machine — this path is in `.gitignore` and never committed.
|
|
|
|
**Roles:**
|
|
- `base` — OS hardening: UFW (allow SSH + 80 + 443), fail2ban, sshd config, deploy user
|
|
- `docker` — Docker CE + Compose plugin via official apt repo
|
|
- `services` — renders Jinja2 templates → `/opt/services/`, then runs `docker compose up`
|
|
|
|
**Templates → server files:**
|
|
- `roles/services/templates/docker-compose.yml.j2` → `/opt/services/docker-compose.yml`
|
|
- `roles/services/templates/env.j2` → `/opt/services/.env` (mode 0600)
|
|
- `roles/services/templates/traefik/traefik.yml.j2` → `/opt/services/traefik/traefik.yml`
|
|
- `acme.json` created at `/opt/services/traefik/acme.json` (mode 0600, mounted into Traefik)
|
|
|
|
**Docker networks:**
|
|
- `backend` (internal) — traefik ↔ user-facing services
|
|
- `forgejo-db` (internal) — forgejo ↔ its postgres
|
|
- `plane-internal` (internal) — all plane components (api, worker, beat, db, redis, minio)
|
|
|
|
**Adding a new service:** add container to `docker-compose.yml.j2` on the `backend` network with `traefik.enable=true` and `traefik.http.routers.X.tls.certresolver=letsencrypt` labels, add its domain variable to `all.yml`.
|
|
|
|
## Deployment
|
|
|
|
DNS: add A-records for each subdomain → server IP (or wildcard `*` → IP).
|
|
|
|
Fill `all.vault.yml` → set `domain_base` in `all.yml` → run bootstrap + deploy. Traefik obtains TLS certificates automatically on first request to each domain.
|