diff --git a/.gitignore b/.gitignore index 2cb6149..bc71de5 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ monitoring/influxdb/* !monitoring/influxdb/docker-compose.yml secrets/* !secrets/.env.secrets.example +!secrets/inventory.json !.env.example core/traefik/certs/* !core/traefik/certs/.gitkeep diff --git a/README.md b/README.md index a47a406..f930f03 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ If you only read one section, read **[Source-of-truth boundaries](docs/source-of - Docker environment composition and `services-up.sh`: [docs/docker-environment.md](docs/docker-environment.md) - Terraform workflows (brownfield import/reconciliation): [docs/terraform-workflows.md](docs/terraform-workflows.md) - Infrastructure inventory intent and outputs: [docs/infrastructure-inventory.md](docs/infrastructure-inventory.md) -- Deployment prerequisites and secrets setup: [DEPLOYMENT.md](DEPLOYMENT.md) -- Secrets inventory: [SECURITY_SECRETS_INVENTORY.md](SECURITY_SECRETS_INVENTORY.md) +- Deployment prerequisites and secrets setup: [docs/deployment-prerequisites.md](docs/deployment-prerequisites.md) +- Secrets inventory: [docs/security-secrets.md](docs/security-secrets.md) Terraform subtrees: diff --git a/SECURITY_SECRETS_INVENTORY.md b/SECURITY_SECRETS_INVENTORY.md deleted file mode 100644 index 7a7e4a0..0000000 --- a/SECURITY_SECRETS_INVENTORY.md +++ /dev/null @@ -1,55 +0,0 @@ -# Security Secrets Inventory - -This inventory tracks values expected in local secret material and where they are consumed. - -## Scope and authority - -- Canonical example template: `secrets/.env.secrets.example` -- Runtime-loaded secret env file: `secrets/stack-secrets.env` (local, non-committed) -- Docker secret files: `secrets/*.txt` (local, non-committed) - -For setup steps, see [DEPLOYMENT.md](DEPLOYMENT.md). - -## Secrets expected in `secrets/.env.secrets.example` - -| Variable | Used by | Purpose / Notes | -|---|---|---| -| `NEXTCLOUD_DB_USER` | `apps/nextcloud/docker-compose.yml` | Nextcloud database username (non-secret identifier but environment-specific). | -| `NEXTCLOUD_ADMIN_USER` | `apps/nextcloud/docker-compose.yml` | Initial Nextcloud admin username. | -| `NEXTCLOUD_SMTP_FROM_ADDRESS` | `apps/nextcloud/docker-compose.yml` | SMTP sender local-part for outbound mail configuration. | -| `NEXTCLOUD_SMTP_DOMAIN` | `apps/nextcloud/docker-compose.yml` | SMTP sender domain for outbound mail configuration. | -| `NEXTCLOUD_SMTP_NAME` | `apps/nextcloud/docker-compose.yml` | Derived from address + domain in the example file. | -| `PASSBOLT_DB_NAME` | `apps/passbolt/docker-compose.yml` | Passbolt database name. | -| `PASSBOLT_DB_USER` | `apps/passbolt/docker-compose.yml` | Passbolt database username. | -| `PASSBOLT_GPG_SERVER_KEY_FINGERPRINT` | `apps/passbolt/docker-compose.yml` | Passbolt server GPG key fingerprint. | -| `GRAMPSWEB_SECRET_KEY` | `apps/gramps/docker-compose.yml` | Secret key used by Gramps Web for session/security signing. | -| `GRAMPSWEB_EMAIL_HOST_USER` | `apps/gramps/docker-compose.yml` | SMTP username for Gramps outbound email. | -| `GRAMPSWEB_EMAIL_HOST_PASSWORD` | `apps/gramps/docker-compose.yml` | SMTP password for Gramps outbound email. | -| `GOTIFY_DEFAULTUSER_NAME` | `monitoring/gotify/docker-compose.yml` | Gotify default username. | -| `GOTIFY_DEFAULTUSER_PASS` | `monitoring/gotify/docker-compose.yml` | Gotify default user password. | -| `INFLUXDB_INIT_USERNAME` | `monitoring/prometheus/docker-compose.yml` | InfluxDB initial username. | -| `PIHOLE_PASSWORD` | `monitoring/prometheus/docker-compose.yml` | Exporter auth / Pi-hole integration password. | - -## Secrets managed outside `.env.secrets.example` - -The following sensitive values are intentionally provided via Docker secret files (`*_FILE`) or other mounted secret files instead of the shared `.env` template: - -- Database/root passwords for Nextcloud, Passbolt, and supporting services. -- Redis runtime password loaded from a Docker secret. -- `DOCKER_INFLUXDB_INIT_PASSWORD` loaded from Docker secret in monitoring. -- Uptime Kuma basic-auth password loaded via `password_file` in Prometheus config. -- Core stack secret values injected via env substitution (for example Authelia and CrowdSec values). - -## Commit safety rules - -Never commit: - -- `secrets/stack-secrets.env` -- `secrets/*.txt` real secret files -- real Terraform `.tfvars` containing credentials -- Terraform state files with sensitive runtime metadata - -## Related docs - -- [DEPLOYMENT.md](DEPLOYMENT.md) -- [docs/source-of-truth.md](docs/source-of-truth.md) diff --git a/DEPLOYMENT.md b/docs/deployment-prerequisites.md similarity index 87% rename from DEPLOYMENT.md rename to docs/deployment-prerequisites.md index ce642cb..cc4c114 100644 --- a/DEPLOYMENT.md +++ b/docs/deployment-prerequisites.md @@ -44,6 +44,6 @@ If migrating from older states where secrets were committed, rotate upstream val ## Related docs -- [SECURITY_SECRETS_INVENTORY.md](SECURITY_SECRETS_INVENTORY.md) -- [docs/docker-environment.md](docs/docker-environment.md) -- [docs/source-of-truth.md](docs/source-of-truth.md) +- [`./security-secrets.md`](./security-secrets.md) +- [`./docker-environment.md`](./docker-environment.md) +- [`./source-of-truth.md`](./source-of-truth.md) diff --git a/docs/docker-environment.md b/docs/docker-environment.md index cb7aafb..d0f4c63 100644 --- a/docs/docker-environment.md +++ b/docs/docker-environment.md @@ -46,7 +46,7 @@ Use this when focused on one service family. ### Deployment prerequisites -Before runtime operations, follow [DEPLOYMENT.md](../DEPLOYMENT.md) to create required local secret files. +Before runtime operations, follow [deployment-prerequisites.md](deployment-prerequisites.md) to create required local secret files. ## What not to do diff --git a/docs/repo-structure.md b/docs/repo-structure.md index cc7cccd..b186800 100644 --- a/docs/repo-structure.md +++ b/docs/repo-structure.md @@ -17,8 +17,8 @@ This page explains where to find authoritative files quickly. - `services-up.sh` — runtime composition entrypoint for multi-compose environment. - `default-network.yml` — shared docker network definitions used across compose files. - `default-environment.env` — non-secret default env values for compose rendering. -- `DEPLOYMENT.md` — prerequisite setup before runtime operations. -- `SECURITY_SECRETS_INVENTORY.md` — tracked secret-variable inventory and usage map. +- `docs/deployment-prerequisites.md` — prerequisite setup before runtime operations. +- `docs/security-secrets.md` — secrets documentation and inventory model. ## Terraform layout diff --git a/docs/security-secrets.md b/docs/security-secrets.md new file mode 100644 index 0000000..a318e20 --- /dev/null +++ b/docs/security-secrets.md @@ -0,0 +1,52 @@ +# Security Secrets + +## Overview + +This page explains how secret material is organized in this repository and where to find both human-readable and machine-readable references. + +For machine-readable inventory metadata, use [`../secrets/inventory.json`](../secrets/inventory.json). + +## Scope and authority + +- Canonical example template: [`../secrets/.env.secrets.example`](../secrets/.env.secrets.example) +- Runtime-loaded secret env file (local, non-committed): `../secrets/stack-secrets.env` +- Docker secret files (local, non-committed): `../secrets/*.txt` + +Treat the example template as the canonical shape for expected environment variables. + +## Secret material types + +1. **Template variables in `.env.secrets.example`** + - Document expected variable names and usage expectations. +2. **Local runtime env file (`stack-secrets.env`)** + - Holds local runtime secret values loaded during compose rendering. +3. **Local Docker secret files (`*.txt`)** + - Hold password/token material consumed via `*_FILE` style configuration. +4. **Externally managed secret inputs** + - Some values are managed outside shared templates and provided through file mounts or environment substitution. + +## Machine-readable inventory + +- Primary automation source: [`../secrets/inventory.json`](../secrets/inventory.json) +- Human guidance source: this page + +Automation should parse `secrets/inventory.json` directly rather than scraping Markdown tables. + +## Setup and deployment prerequisites + +Before running compose operations, follow [`./deployment-prerequisites.md`](./deployment-prerequisites.md). + +## Commit safety rules + +Never commit: + +- `secrets/stack-secrets.env` +- real `secrets/*.txt` secret files +- real Terraform `.tfvars` files containing credentials +- Terraform state files with sensitive runtime metadata + +## Related docs + +- [`./deployment-prerequisites.md`](./deployment-prerequisites.md) +- [`./docker-environment.md`](./docker-environment.md) +- [`./source-of-truth.md`](./source-of-truth.md) diff --git a/docs/source-of-truth.md b/docs/source-of-truth.md index 5e39f1a..57ab7e5 100644 --- a/docs/source-of-truth.md +++ b/docs/source-of-truth.md @@ -9,7 +9,7 @@ This repository has multiple layers. Knowing the authority for each layer preven | Application/runtime container composition | `services-up.sh` + Compose files under `core/`, `apps/`, `monitoring/` | What runs in the Docker environment and how services are wired. | | Docker shared baseline inputs | `default-network.yml`, `default-environment.env`, `secrets/stack-secrets.env` | Shared network/env material applied during compose rendering. | | Infrastructure inventory and reconciliation | Terraform under `infrastructure/terraform/` | Codified inventory of existing infrastructure and relationships, especially Proxmox VMs and selected Docker mirrors. | -| Secret policy and inventory | `SECURITY_SECRETS_INVENTORY.md` + local secret files in `secrets/` | What secrets exist and where they are expected. | +| Secret policy and inventory | `docs/security-secrets.md` + `secrets/inventory.json` + local secret files in `secrets/` | What secrets exist, where they are expected, and what automation should parse. | ## Practical meaning diff --git a/secrets/inventory.json b/secrets/inventory.json new file mode 100644 index 0000000..305163b --- /dev/null +++ b/secrets/inventory.json @@ -0,0 +1,152 @@ +{ + "scope_and_authority": { + "canonical_example_template": "secrets/.env.secrets.example", + "runtime_loaded_secret_env_file": "secrets/stack-secrets.env", + "docker_secret_files_pattern": "secrets/*.txt" + }, + "env_template_variables": [ + { + "variable": "NEXTCLOUD_DB_USER", + "used_by": "apps/nextcloud/docker-compose.yml", + "purpose": "Nextcloud database username (non-secret identifier but environment-specific)." + }, + { + "variable": "NEXTCLOUD_ADMIN_USER", + "used_by": "apps/nextcloud/docker-compose.yml", + "purpose": "Initial Nextcloud admin username." + }, + { + "variable": "NEXTCLOUD_SMTP_FROM_ADDRESS", + "used_by": "apps/nextcloud/docker-compose.yml", + "purpose": "SMTP sender local-part for outbound mail configuration." + }, + { + "variable": "NEXTCLOUD_SMTP_DOMAIN", + "used_by": "apps/nextcloud/docker-compose.yml", + "purpose": "SMTP sender domain for outbound mail configuration." + }, + { + "variable": "NEXTCLOUD_SMTP_NAME", + "used_by": "apps/nextcloud/docker-compose.yml", + "purpose": "SMTP display/sender name derived from address + domain in the example file." + }, + { + "variable": "PASSBOLT_DB_NAME", + "used_by": "apps/passbolt/docker-compose.yml", + "purpose": "Passbolt database name." + }, + { + "variable": "PASSBOLT_DB_USER", + "used_by": "apps/passbolt/docker-compose.yml", + "purpose": "Passbolt database username." + }, + { + "variable": "PASSBOLT_GPG_SERVER_KEY_FINGERPRINT", + "used_by": "apps/passbolt/docker-compose.yml", + "purpose": "Passbolt server GPG key fingerprint." + }, + { + "variable": "GRAMPSWEB_SECRET_KEY", + "used_by": "apps/gramps/docker-compose.yml", + "purpose": "Secret key used by Gramps Web for session/security signing." + }, + { + "variable": "GRAMPSWEB_EMAIL_HOST_USER", + "used_by": "apps/gramps/docker-compose.yml", + "purpose": "SMTP username for Gramps outbound email." + }, + { + "variable": "GRAMPSWEB_EMAIL_HOST_PASSWORD", + "used_by": "apps/gramps/docker-compose.yml", + "purpose": "SMTP password for Gramps outbound email." + }, + { + "variable": "GOTIFY_DEFAULTUSER_NAME", + "used_by": "monitoring/gotify/docker-compose.yml", + "purpose": "Gotify default username." + }, + { + "variable": "GOTIFY_DEFAULTUSER_PASS", + "used_by": "monitoring/gotify/docker-compose.yml", + "purpose": "Gotify default user password." + }, + { + "variable": "INFLUXDB_INIT_USERNAME", + "used_by": "monitoring/prometheus/docker-compose.yml", + "purpose": "InfluxDB initial username." + }, + { + "variable": "PIHOLE_PASSWORD", + "used_by": "monitoring/prometheus/docker-compose.yml", + "purpose": "Exporter auth / Pi-hole integration password." + } + ], + "file_based_secrets": [ + { + "path": "secrets/nextcloud_db_root_password.txt", + "purpose": "Nextcloud MariaDB root password file.", + "managed_by": "local_file", + "committed": false + }, + { + "path": "secrets/nextcloud_db_password.txt", + "purpose": "Nextcloud MariaDB application user password file.", + "managed_by": "local_file", + "committed": false + }, + { + "path": "secrets/nextcloud_admin_password.txt", + "purpose": "Initial Nextcloud admin password file.", + "managed_by": "local_file", + "committed": false + }, + { + "path": "secrets/nextcloud_smtp_password.txt", + "purpose": "Nextcloud SMTP account password file.", + "managed_by": "local_file", + "committed": false + }, + { + "path": "secrets/nextcloud_redis_password.txt", + "purpose": "Nextcloud Redis runtime password file.", + "managed_by": "local_file", + "committed": false + }, + { + "path": "secrets/passbolt_db_password.txt", + "purpose": "Passbolt database user password file.", + "managed_by": "local_file", + "committed": false + }, + { + "path": "secrets/influxdb_init_password.txt", + "purpose": "InfluxDB initialization password file.", + "managed_by": "local_file", + "committed": false + }, + { + "path": "secrets/prometheus_kuma_basic_auth_password.txt", + "purpose": "Uptime Kuma Prometheus scrape basic-auth password file.", + "managed_by": "local_file", + "committed": false + } + ], + "externally_managed_secrets": [ + "Database/root passwords for Nextcloud, Passbolt, and supporting services are provided via Docker secret files.", + "Redis runtime password is loaded from a Docker secret file.", + "DOCKER_INFLUXDB_INIT_PASSWORD is loaded from a Docker secret in monitoring.", + "Uptime Kuma basic-auth password is loaded via password_file in Prometheus configuration.", + "Core stack secret values (for example Authelia and CrowdSec values) are injected via environment substitution." + ], + "commit_safety_rules": [ + "Never commit secrets/stack-secrets.env.", + "Never commit real secrets/*.txt files.", + "Never commit real Terraform .tfvars containing credentials.", + "Never commit Terraform state files with sensitive runtime metadata." + ], + "related_docs": [ + "docs/security-secrets.md", + "docs/deployment-prerequisites.md", + "docs/source-of-truth.md" + ] +}