diff --git a/README.md b/README.md index 64bcbb1..a16c261 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,42 @@ Forgejo is configured via `roles/forgejo` using the Forgejo admin CLI with `--pr Note: Forgejo pages that ask for an "OpenID URI" are legacy OpenID 2.0 and are not used for OIDC. +## Email (Postfix + Postmark) + +Transactional email is delivered via Postfix relay to Postmark: + +- **Sender**: `notifications@jfraeys.com` +- **Relay**: `smtp.postmarkapp.com:2525` +- **Auth**: Server token authentication + +Services using email: +- Authelia (password resets) +- Alertmanager (monitoring alerts) +- Forgejo (CI/CD notifications) + +### DNS Records for Email + +Terraform manages these Cloudflare records: + +| Record | Type | Purpose | +|--------|------|---------| +| `YYYYMMDDDDpm._domainkey` | TXT | DKIM signature | +| `pm-bounces` | CNAME | Return-path for bounces | +| `_dmarc` | TXT | DMARC policy | + +Postmark validates these during account setup. + +### Vault Variables + +Add to `secrets/vault.yml`: + +```yaml +POSTFIX_RELAYHOST_USERNAME: "your-postmark-server-token" +POSTFIX_RELAYHOST_PASSWORD: "your-postmark-server-token" +AUTHELIA_SMTP_SENDER: "notifications@jfraeys.com" +AUTHELIA_SMTP_IDENTIFIER: "jfraeys.com" +``` + ## Secrets (Ansible Vault) Secrets are stored in `secrets/vault.yml` (encrypted). @@ -162,6 +198,17 @@ A Forgejo runner is deployed on the `web` host (`roles/forgejo_runner`). - Uses a single `self-hosted` label by default. - The role auto re-registers the runner if labels change. +### AI Scrapers Blocklist + +Forgejo includes a weekly cron job (`roles/forgejo/update-ai-scrapers.sh`) that updates `robots.txt` to block AI scrapers (GPTBot, ClaudeBot, etc.). + +### OIDC Configuration + +Forgejo is configured with: +- Group claim mapping from Authelia (`groups`) +- Admin group: `admins` +- Auto-discovery from `https://auth.jfraeys.com/.well-known/openid-configuration` + To force re-register (e.g. after deleting the runner in Forgejo UI): ```bash @@ -229,17 +276,21 @@ ansible-playbook playbooks/web.yml --ask-vault-pass - Loki is exposed on `services:3100` but allowlisted in UFW to `web` only. - Watchtower is enabled with label-based updates. - Airflow/Spark are intentionally optional and can be enabled later via `deploy_airflow` / `deploy_spark`. +- **Traefik**: Uses file provider as fallback due to Docker API version mismatch (client 1.24 vs server 1.44). Services have static router definitions in `/opt/traefik/dynamic/base.yml`. +- **Postfix**: Relays through Postmark port 2525 (avoids ISP blocking on 587). ## Role layout Services host (`services`): -- `roles/traefik` +- `roles/traefik` (with file provider fallback for Docker API compatibility) +- `roles/postfix` (Postmark SMTP relay for transactional email) - `roles/exporters` (node-exporter + cAdvisor) - `roles/prometheus` - `roles/loki` - `roles/grafana` - `roles/forgejo` +- `roles/alertmanager` (uses localhost:25 Postfix relay) - `roles/watchtower` Web host (`web`):