docs(readme): add Postmark email integration and update service docs

- Add Email section with Postfix/Postmark configuration
- Document DNS records (DKIM, return-path, DMARC) for email
- Update Forgejo section with AI scrapers blocklist and OIDC details
- Update Role layout to include Postfix and Traefik file provider notes
- Add Notes about Traefik Docker API workaround and Postfix port 2525
This commit is contained in:
Jeremie Fraeys 2026-03-06 10:36:22 -05:00
parent 9668b6f84e
commit bb12e5396c
No known key found for this signature in database

View file

@ -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`):