Aller au contenu

Contributing to the Documentation

Architecture

Mnemosyne assembles documentation from all three repos into a single MkDocs Material site.

┌────────────────────────┐    ┌──────────────────────────┐
│  aletheia/repo/docs/   │    │                          │
│  aletheia/repo/        │───▶│                          │
│     guidelines/        │    │   build.sh (assembler)   │
├────────────────────────┤    │                          │
│  helios/repo/docs/     │───▶│   + extract_infra.py     │
│  helios/repo/content/  │    │     (config → snippets)  │
├────────────────────────┤    │                          │
│  aether/repo/docs/     │───▶│   + mkdocs build         │
│  aether/repo/*.md      │    │                          │
└────────────────────────┘    └────────────┬─────────────┘
                              /opt/docker/mnemosyne/site/
                              → https://docs.groupe-suffren.com
  • Config source (tracked in git): aether/repo/mnemosyne/
  • Runtime output (not tracked): /opt/docker/mnemosyne/
  • Served by nginx at docs.groupe-suffren.com

Build and Preview

cd /opt/docker/aether/repo

make docs-build      # assemble + build static site
make docs-serve      # assemble + dev server on http://localhost:8888 (live reload)
make docs-deploy     # build + deploy nginx config for the site
make docs-check      # validate alert→runbook coverage

make docs-serve is the fastest inner loop — edit a markdown file, save, reload the browser.

Where to Put a New Page

Topic Source location Appears in nav under
Developer / infra ops aether/repo/docs/maintenance/ Developer Guide → Maintenance
Monitoring aether/repo/docs/monitoring/ Developer Guide → Aether → Monitoring
Aether dev conventions aether/repo/docs/development/ (add to mkdocs.yml nav)
Aletheia dev / guidelines aletheia/repo/docs/ or aletheia/repo/guidelines/ Developer Guide → Aletheia
Helios dev / content helios/repo/docs/ or helios/repo/content/ Developer Guide → Helios
French user guide aletheia/repo/docs/guide-utilisateur/ Guide Utilisateur
French admin guide aletheia/repo/docs/guide-admin/ Guide Administrateur

After adding a markdown file, also add it to the nav: block in aether/repo/mnemosyne/mkdocs.yml so it shows up in the navigation.

Convention: Code Comments Hold the "Why"

The authoritative source for why a config value exists is a comment in the config file, not the documentation. This keeps rationale co-located with the setting it explains.

Good:

# 1-hour ban is long enough to deter bots but short enough that a
# self-ban doesn't require on-call intervention (just wait it out).
bantime  = 1h

Bad (rationale only in docs):

bantime  = 1h

When editing a config file, enrich the comments if you change a value or notice missing rationale. Future readers — including Claude — use those comments to judge whether a change is safe.

Convention: Docs Include, Don't Duplicate

Factual data (container names, versions, memory limits, ports, retention values, alert names, thresholds) must never be hardcoded in docs. Use auto-generated snippets instead.

Good:

## Monitoring Stack

<!-- Auto-generated from monitoring/docker-compose.yml -->
<!-- Auto-generated by extract_infra.py — do not edit -->


| Container | Image | Memory Limit |
|---|---|---|
| `monitoring_prometheus` | `prom/prometheus:v3.10.0` | 1024m |
| `monitoring_alertmanager` | `prom/alertmanager:v0.28.1` | 128m |
| `monitoring_grafana` | `grafana/grafana:12.4` | 384m |
| `monitoring_node_exporter` | `prom/node-exporter:v1.10.2` | 64m |
| `monitoring_cadvisor` | `gcr.io/cadvisor/cadvisor:v0.55.1` | 256m |
| `monitoring_postgres_exporter` | `prometheuscommunity/postgres-exporter:v0.19.1` | 48m |
| `monitoring_redis_exporter` | `oliver006/redis_exporter:v1.82.0` | 48m |
| `monitoring_blackbox_exporter` | `prom/blackbox-exporter:v0.26.0` | 64m |
| `monitoring_loki` | `grafana/loki:3.6` | 384m |
| `monitoring_alloy` | `grafana/alloy:v1.14.1` | 384m |
| `monitoring_nginx_exporter` | `nginx/nginx-prometheus-exporter:1.4` | 32m |
| `monitoring_celery_exporter` | `danihodovic/celery-exporter:0.10.10` | 128m |

Bad:

## Monitoring Stack

| Container | Image | Memory |
|---|---|---|
| prometheus | prom/prometheus:v3.10.0 | 384m |
...

The first pattern auto-updates when configs change. The second drifts silently.

Available snippets

Generated into _generated/ on every make docs-build. Include with --8<-- "_generated/<name>.md".

Snippet Source
monitoring-stack.md monitoring/docker-compose.yml
shared-services.md shared/docker-compose.yml
alert-catalog.md monitoring/prometheus/alerts/*.rules.yml
backup-scope.md backups/scripts/backup.sh
makefile-targets.md Makefile help text
retention-periods.md multiple (docker-compose, loki, backup)
monitored-domains.md monitoring/prometheus/prometheus.yml
ssh-config.md security/sshd-00-hardening.conf
fail2ban-jails.md security/fail2ban-aletheia.conf
kernel-hardening.md security/sysctl-hardening.conf
firewall-rules.md security/iptables-setup-docker.sh

Adding a new extractor

If you need a snippet for data that's not yet covered:

  1. Add a function to mnemosyne/scripts/extract_infra.py following the existing pattern
  2. Register it in the EXTRACTORS dict at the bottom of the file
  3. Run python3 mnemosyne/scripts/extract_infra.py <repo> /tmp/check to verify output
  4. Include the new snippet in the relevant doc via --8<--

Convention: Alert Rules Need Runbooks

Every alert defined in monitoring/prometheus/alerts/*.rules.yml must have a matching entry in docs/monitoring/runbooks.md. The make docs-check target validates this, and the pre-commit hook runs it automatically when alert rule files are staged.

When adding a new alert rule:

  1. Define the rule in the appropriate *.rules.yml file
  2. Add a runbook section to docs/monitoring/runbooks.md — at minimum, what the alert means and the first thing to check
  3. Commit together. If you forget step 2, the pre-commit hook will warn.

Convention: Alert Rules Reference Real Metrics

make docs-check also diffs every metric name an alert expr: references against the metric names live Prometheus actually has (/api/v1/label/__name__/values). This catches the class make test-alerts structurally cannot: a rule built on a metric nothing emits — a wrong exporter name, or a metric that needs a feature flag no one turned on — passes every promtool test (the test author invents the series from the same wrong assumption) while being dead in production. Three rules have been found dead exactly this way.

The check (mnemosyne/scripts/check_metric_existence.py) needs a running monitoring_prometheus, so it runs for real on the host / in the pre-commit path and skips loudly — never silent-passes — when Prometheus is unreachable (a laptop, offline CI). A metric that is legitimately absent in the steady state (only appears after an event or feature flag) goes in the script's ALLOWLIST with a reason; treat that as a tracked deferral to remove once the metric exists, not a resolution.

Markdown Conventions

  • Heading hierarchy: top-level # matches the page title once. Use ## for sections.
  • Admonitions: use !!! warning, !!! danger, !!! note, !!! tip, !!! info. Reserve danger for data-loss or security risks.
  • Code blocks: always specify the language (```bash, ```yaml, ```markdown) for syntax highlighting.
  • Commands: show the full command with the directory context if it matters. Prefer cd /opt/docker/aether/repo && make foo over make foo.
  • File paths: use backticks for inline paths (`docs/maintenance/backups.md`).
  • Links: use relative markdown links within the same section ([backups](backups.md)); absolute paths only for external references.

Testing Locally

Always preview changes before committing:

make docs-serve
# visit http://localhost:8888, navigate to your page
# edit, save, reload

The dev server re-assembles on every file change, so edits show up immediately.

Build Warnings

make docs-build emits warnings for broken links, missing nav entries, and bad references. Some are pre-existing (cross-repo archive links) but don't add new ones. Fix new warnings before committing.

make docs-build 2>&1 | grep -E "WARNING.*<your-file>"

Enforcement Summary

Rule Enforced by
Every alert has a runbook make docs-check + pre-commit hook
Every alert references a metric that exists make docs-check metric-existence check (needs live Prometheus)
Factual data comes from configs, not hardcoded Code review + docs_check.sh drift detection
Config rationale lives in comments Code review
New page appears in nav make docs-build warnings
Links resolve make docs-build warnings