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/AGENTS.md b/AGENTS.md index 2daefc8..200f476 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -49,6 +49,12 @@ Do not run: - `terraform apply` - `terraform destroy` +If `terraform init` fails because access to `registry.terraform.io` is forbidden, do not summarize the error vaguely. Report the exact stderr. Continue with: +- `terraform fmt -check -recursive` +- static review of changed `.tf` files + +Only run `terraform validate` when provider installation is available locally or registry access succeeds. + ## Ansible rules Allowed: 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/infrastructure/terraform/docker/authelia.tf b/infrastructure/terraform/docker/authelia.tf index 76cadc9..9e1bb5d 100644 --- a/infrastructure/terraform/docker/authelia.tf +++ b/infrastructure/terraform/docker/authelia.tf @@ -4,11 +4,11 @@ resource "docker_container" "authelia" { restart = local.docker_containers["authelia"].restart_policy - labels = local.docker_containers["authelia"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/crowdsec.tf b/infrastructure/terraform/docker/crowdsec.tf index 450ffe9..2dae90d 100644 --- a/infrastructure/terraform/docker/crowdsec.tf +++ b/infrastructure/terraform/docker/crowdsec.tf @@ -4,11 +4,11 @@ resource "docker_container" "crowdsec" { restart = local.docker_containers["crowdsec"].restart_policy - labels = local.docker_containers["crowdsec"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/docker-socket-proxy.tf b/infrastructure/terraform/docker/docker-socket-proxy.tf index cfd43d7..8d67095 100644 --- a/infrastructure/terraform/docker/docker-socket-proxy.tf +++ b/infrastructure/terraform/docker/docker-socket-proxy.tf @@ -4,11 +4,11 @@ resource "docker_container" "docker_socket_proxy" { restart = local.docker_containers["docker-socket-proxy"].restart_policy - labels = local.docker_containers["docker-socket-proxy"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/docker-update-exporter.tf b/infrastructure/terraform/docker/docker-update-exporter.tf index 6dae8e9..130ff1e 100644 --- a/infrastructure/terraform/docker/docker-update-exporter.tf +++ b/infrastructure/terraform/docker/docker-update-exporter.tf @@ -4,11 +4,11 @@ resource "docker_container" "docker_update_exporter" { restart = local.docker_containers["docker-update-exporter"].restart_policy - labels = local.docker_containers["docker-update-exporter"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/error-pages.tf b/infrastructure/terraform/docker/error-pages.tf index b18c69b..318c868 100644 --- a/infrastructure/terraform/docker/error-pages.tf +++ b/infrastructure/terraform/docker/error-pages.tf @@ -4,11 +4,11 @@ resource "docker_container" "error_pages" { restart = local.docker_containers["error-pages"].restart_policy - labels = local.docker_containers["error-pages"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/gitea.tf b/infrastructure/terraform/docker/gitea.tf index 2cc7ebf..459788f 100644 --- a/infrastructure/terraform/docker/gitea.tf +++ b/infrastructure/terraform/docker/gitea.tf @@ -4,11 +4,11 @@ resource "docker_container" "gitea" { restart = local.docker_containers["gitea"].restart_policy - labels = local.docker_containers["gitea"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/gotify.tf b/infrastructure/terraform/docker/gotify.tf index a32a13f..e0a5885 100644 --- a/infrastructure/terraform/docker/gotify.tf +++ b/infrastructure/terraform/docker/gotify.tf @@ -4,11 +4,11 @@ resource "docker_container" "gotify" { restart = local.docker_containers["gotify"].restart_policy - labels = local.docker_containers["gotify"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/grafana.tf b/infrastructure/terraform/docker/grafana.tf index 44b8407..d64fc3c 100644 --- a/infrastructure/terraform/docker/grafana.tf +++ b/infrastructure/terraform/docker/grafana.tf @@ -4,11 +4,11 @@ resource "docker_container" "grafana" { restart = local.docker_containers["grafana"].restart_policy - labels = local.docker_containers["grafana"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/gramps-redis.tf b/infrastructure/terraform/docker/gramps-redis.tf index 345818e..93df3b3 100644 --- a/infrastructure/terraform/docker/gramps-redis.tf +++ b/infrastructure/terraform/docker/gramps-redis.tf @@ -4,11 +4,11 @@ resource "docker_container" "gramps_redis" { restart = local.docker_containers["gramps-redis"].restart_policy - labels = local.docker_containers["gramps-redis"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/gramps-web-celery.tf b/infrastructure/terraform/docker/gramps-web-celery.tf index dc8bdf4..d259f9c 100644 --- a/infrastructure/terraform/docker/gramps-web-celery.tf +++ b/infrastructure/terraform/docker/gramps-web-celery.tf @@ -4,11 +4,11 @@ resource "docker_container" "gramps_web_celery" { restart = local.docker_containers["gramps-web-celery"].restart_policy - labels = local.docker_containers["gramps-web-celery"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/gramps-web.tf b/infrastructure/terraform/docker/gramps-web.tf index 6f89819..0b90a90 100644 --- a/infrastructure/terraform/docker/gramps-web.tf +++ b/infrastructure/terraform/docker/gramps-web.tf @@ -4,11 +4,11 @@ resource "docker_container" "gramps_web" { restart = local.docker_containers["gramps-web"].restart_policy - labels = local.docker_containers["gramps-web"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/influxdb.tf b/infrastructure/terraform/docker/influxdb.tf index 27bb71f..cefbb62 100644 --- a/infrastructure/terraform/docker/influxdb.tf +++ b/infrastructure/terraform/docker/influxdb.tf @@ -4,11 +4,11 @@ resource "docker_container" "influxdb" { restart = local.docker_containers["influxdb"].restart_policy - labels = local.docker_containers["influxdb"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/monitor-kuma.tf b/infrastructure/terraform/docker/monitor-kuma.tf index e0c07a2..dbca121 100644 --- a/infrastructure/terraform/docker/monitor-kuma.tf +++ b/infrastructure/terraform/docker/monitor-kuma.tf @@ -4,11 +4,11 @@ resource "docker_container" "monitor_kuma" { restart = local.docker_containers["monitor-kuma"].restart_policy - labels = local.docker_containers["monitor-kuma"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/mtls-bridge.tf b/infrastructure/terraform/docker/mtls-bridge.tf index 34cb535..1af1644 100644 --- a/infrastructure/terraform/docker/mtls-bridge.tf +++ b/infrastructure/terraform/docker/mtls-bridge.tf @@ -4,11 +4,11 @@ resource "docker_container" "mtls_bridge" { restart = local.docker_containers["mtls-bridge"].restart_policy - labels = local.docker_containers["mtls-bridge"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/nextcloud-db.tf b/infrastructure/terraform/docker/nextcloud-db.tf index 83e0e04..b3d910d 100644 --- a/infrastructure/terraform/docker/nextcloud-db.tf +++ b/infrastructure/terraform/docker/nextcloud-db.tf @@ -4,11 +4,11 @@ resource "docker_container" "nextcloud_db" { restart = local.docker_containers["nextcloud-db"].restart_policy - labels = local.docker_containers["nextcloud-db"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/nextcloud-redis.tf b/infrastructure/terraform/docker/nextcloud-redis.tf index 1ccce18..832e04a 100644 --- a/infrastructure/terraform/docker/nextcloud-redis.tf +++ b/infrastructure/terraform/docker/nextcloud-redis.tf @@ -4,11 +4,11 @@ resource "docker_container" "nextcloud_redis" { restart = local.docker_containers["nextcloud-redis"].restart_policy - labels = local.docker_containers["nextcloud-redis"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/nextcloud-webapp.tf b/infrastructure/terraform/docker/nextcloud-webapp.tf index 0d9d8e9..632dcca 100644 --- a/infrastructure/terraform/docker/nextcloud-webapp.tf +++ b/infrastructure/terraform/docker/nextcloud-webapp.tf @@ -4,11 +4,11 @@ resource "docker_container" "nextcloud_webapp" { restart = local.docker_containers["nextcloud-webapp"].restart_policy - labels = local.docker_containers["nextcloud-webapp"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/node-exporter.tf b/infrastructure/terraform/docker/node-exporter.tf index f0b2a07..a0d7035 100644 --- a/infrastructure/terraform/docker/node-exporter.tf +++ b/infrastructure/terraform/docker/node-exporter.tf @@ -4,11 +4,11 @@ resource "docker_container" "node_exporter" { restart = local.docker_containers["node-exporter"].restart_policy - labels = local.docker_containers["node-exporter"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/node-red.tf b/infrastructure/terraform/docker/node-red.tf index c78746a..2256b1b 100644 --- a/infrastructure/terraform/docker/node-red.tf +++ b/infrastructure/terraform/docker/node-red.tf @@ -4,11 +4,11 @@ resource "docker_container" "node_red" { restart = local.docker_containers["node-red"].restart_policy - labels = local.docker_containers["node-red"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/passbolt-db.tf b/infrastructure/terraform/docker/passbolt-db.tf index 9e4cc60..9e2af1e 100644 --- a/infrastructure/terraform/docker/passbolt-db.tf +++ b/infrastructure/terraform/docker/passbolt-db.tf @@ -4,11 +4,11 @@ resource "docker_container" "passbolt_db" { restart = local.docker_containers["passbolt-db"].restart_policy - labels = local.docker_containers["passbolt-db"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/passbolt-webapp.tf b/infrastructure/terraform/docker/passbolt-webapp.tf index 6c31238..8429c2b 100644 --- a/infrastructure/terraform/docker/passbolt-webapp.tf +++ b/infrastructure/terraform/docker/passbolt-webapp.tf @@ -4,11 +4,11 @@ resource "docker_container" "passbolt_webapp" { restart = local.docker_containers["passbolt-webapp"].restart_policy - labels = local.docker_containers["passbolt-webapp"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/pihole-exporter.tf b/infrastructure/terraform/docker/pihole-exporter.tf index 3730b90..16d2d10 100644 --- a/infrastructure/terraform/docker/pihole-exporter.tf +++ b/infrastructure/terraform/docker/pihole-exporter.tf @@ -4,11 +4,11 @@ resource "docker_container" "pihole_exporter" { restart = local.docker_containers["pihole-exporter"].restart_policy - labels = local.docker_containers["pihole-exporter"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/portainer.tf b/infrastructure/terraform/docker/portainer.tf index 09f758d..5f62e2a 100644 --- a/infrastructure/terraform/docker/portainer.tf +++ b/infrastructure/terraform/docker/portainer.tf @@ -4,11 +4,11 @@ resource "docker_container" "portainer" { restart = local.docker_containers["portainer"].restart_policy - labels = local.docker_containers["portainer"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/prometheus.tf b/infrastructure/terraform/docker/prometheus.tf index 15cde8e..44594c5 100644 --- a/infrastructure/terraform/docker/prometheus.tf +++ b/infrastructure/terraform/docker/prometheus.tf @@ -4,11 +4,11 @@ resource "docker_container" "prometheus" { restart = local.docker_containers["prometheus"].restart_policy - labels = local.docker_containers["prometheus"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/searxng-webapp.tf b/infrastructure/terraform/docker/searxng-webapp.tf index b011414..15b54a0 100644 --- a/infrastructure/terraform/docker/searxng-webapp.tf +++ b/infrastructure/terraform/docker/searxng-webapp.tf @@ -4,11 +4,11 @@ resource "docker_container" "searxng-webapp" { restart = local.docker_containers["searxng-webapp"].restart_policy - labels = local.docker_containers["searxng-webapp"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/telegraf.tf b/infrastructure/terraform/docker/telegraf.tf index 2826cc3..9bf166c 100644 --- a/infrastructure/terraform/docker/telegraf.tf +++ b/infrastructure/terraform/docker/telegraf.tf @@ -4,11 +4,11 @@ resource "docker_container" "telegraf" { restart = local.docker_containers["telegraf"].restart_policy - labels = local.docker_containers["telegraf"].useful_labels lifecycle { ignore_changes = [ env, + labels, ] } } diff --git a/infrastructure/terraform/docker/traefik.tf b/infrastructure/terraform/docker/traefik.tf index 3d20c86..7ce0158 100644 --- a/infrastructure/terraform/docker/traefik.tf +++ b/infrastructure/terraform/docker/traefik.tf @@ -4,7 +4,6 @@ resource "docker_container" "traefik" { restart = local.docker_containers["traefik"].restart_policy - labels = local.docker_containers["traefik"].useful_labels network_mode = "core_traefik" ports { @@ -64,6 +63,7 @@ resource "docker_container" "traefik" { lifecycle { ignore_changes = [ env, + labels, ] } } 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" + ] +}