diff --git a/.github/workflows/generate-docs.yml b/.github/workflows/generate-docs.yml
index 6efa5db..d63f726 100644
--- a/.github/workflows/generate-docs.yml
+++ b/.github/workflows/generate-docs.yml
@@ -7,12 +7,14 @@ on:
- "docs/generated/**"
- "docs/diagrams/**"
- "docs/public/**"
+ - "site/**"
pull_request:
branches: [main]
paths-ignore:
- "docs/generated/**"
- "docs/diagrams/**"
- "docs/public/**"
+ - "site/**"
workflow_dispatch:
inputs:
commit_generated_docs:
@@ -30,6 +32,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
- name: Install tooling
run: |
sudo apt-get update
@@ -55,7 +59,9 @@ jobs:
docs/diagrams
docs/public
- name: Commit generated docs
- if: github.event_name == 'workflow_dispatch' && inputs.commit_generated_docs == 'true'
+ if: >
+ github.event_name == 'push' ||
+ (github.event_name == 'workflow_dispatch' && inputs.commit_generated_docs == 'true')
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "docs: regenerate environment documentation"
diff --git a/docs/automation.md b/docs/automation.md
new file mode 100644
index 0000000..a7275dd
--- /dev/null
+++ b/docs/automation.md
@@ -0,0 +1,14 @@
+# Automation
+
+This section describes automation systems associated with this environment.
+
+Current state:
+
+- CI documentation generation in GitHub Actions.
+- Static parsing and rendering from repository configuration.
+- No live service interaction during documentation generation.
+
+Future content can document:
+
+- Docker update automation.
+- Node-RED automation flows and operational patterns.
diff --git a/docs/diagrams/docker-compose.dot b/docs/diagrams/docker-compose.dot
new file mode 100644
index 0000000..4eff403
--- /dev/null
+++ b/docs/diagrams/docker-compose.dot
@@ -0,0 +1,4 @@
+digraph Compose {
+ rankdir=LR;
+ node [fontname=Helvetica];
+}
diff --git a/docs/diagrams/docker-compose.svg b/docs/diagrams/docker-compose.svg
new file mode 100644
index 0000000..cd8a7c6
--- /dev/null
+++ b/docs/diagrams/docker-compose.svg
@@ -0,0 +1 @@
+
diff --git a/docs/docker.md b/docs/docker.md
new file mode 100644
index 0000000..5f545ea
--- /dev/null
+++ b/docs/docker.md
@@ -0,0 +1,13 @@
+# Docker Environment
+
+This environment is orchestrated from central Docker Compose definitions committed in this repository.
+
+Compose source files are rendered into a resolved configuration during docs generation, then summarized into generated markdown and diagrams.
+
+Generated outputs:
+
+- [Compose Inventory](generated/compose-inventory.md)
+- [Resolved Compose Config](generated/docker-compose.resolved.yml)
+- [Docker Compose Diagram](diagrams/docker-compose.svg)
+
+Generated documentation is produced by CI from repository files only. Documentation generation does not start containers.
diff --git a/docs/generated/compose-files.txt b/docs/generated/compose-files.txt
new file mode 100644
index 0000000..b602f4c
--- /dev/null
+++ b/docs/generated/compose-files.txt
@@ -0,0 +1,24 @@
+default-network.yml
+apps/gitea/docker-compose.yml
+apps/gramps/docker-compose.yml
+apps/nextcloud/docker-compose.yml
+apps/passbolt/docker-compose.yml
+apps/searxng/docker-compose.yml
+core/authelia/docker-compose.yml
+core/crowdsec/docker-compose.yml
+core/error-pages/docker-compose.yml
+core/test/docker-compose.yml
+core/traefik/docker-compose.yml
+monitoring/docker-exporter/docker-compose.yml
+monitoring/docker-socket-proxy/docker-compose.yml
+monitoring/gotify/docker-compose.yml
+monitoring/grafana/docker-compose.yml
+monitoring/influxdb/docker-compose.yml
+monitoring/mtls-bridge/docker-compose.yml
+monitoring/node-exporter/docker-compose.yml
+monitoring/node-red/docker-compose.yml
+monitoring/pihole-exporter/docker-compose.yml
+monitoring/portainer/docker-compose.yml
+monitoring/prometheus/docker-compose.yml
+monitoring/telegraf/docker-compose.yml
+monitoring/uptime-kuma/docker-compose.yml
diff --git a/docs/generated/compose-inventory.md b/docs/generated/compose-inventory.md
new file mode 100644
index 0000000..c079bfa
--- /dev/null
+++ b/docs/generated/compose-inventory.md
@@ -0,0 +1,26 @@
+# Docker Compose Inventory
+
+Source fingerprint: `d6aa78e3317a`
+
+## Summary
+
+| Item | Count |
+|---|---:|
+| Services | 0 |
+| Networks | 0 |
+| Volumes | 0 |
+
+## Services
+
+| Service | Container | Image | Build | Profiles | Networks | Ports | Restart |
+|---|---|---|---|---|---|---|---|
+
+## Networks
+
+| Network | Driver | External |
+|---|---|---|
+
+## Volumes
+
+| Volume | External |
+|---|---|
diff --git a/docs/generated/docker-compose.resolved.yml b/docs/generated/docker-compose.resolved.yml
new file mode 100644
index 0000000..2a4d71d
--- /dev/null
+++ b/docs/generated/docker-compose.resolved.yml
@@ -0,0 +1,2 @@
+name: core
+services: {}
diff --git a/docs/generated/index.md b/docs/generated/index.md
new file mode 100644
index 0000000..4ebaf24
--- /dev/null
+++ b/docs/generated/index.md
@@ -0,0 +1,12 @@
+# Generated Documentation
+
+This directory contains documentation generated automatically from repository configuration.
+
+## Files
+
+- [Compose file list](compose-files.txt)
+- [Resolved Docker Compose config](docker-compose.resolved.yml)
+- [Compose inventory](compose-inventory.md)
+- [Traefik routes](traefik-routes.md)
+- [Prometheus rules](prometheus-rules.md)
+- [Docker Compose diagram](../diagrams/docker-compose.svg)
diff --git a/docs/generated/prometheus-rules.md b/docs/generated/prometheus-rules.md
new file mode 100644
index 0000000..3566e5c
--- /dev/null
+++ b/docs/generated/prometheus-rules.md
@@ -0,0 +1,7 @@
+# Prometheus Rules
+
+| File | Group | Alert | Expr | For | Labels | Annotations |
+|---|---|---|---|---|---|---|
+| monitoring/prometheus/rules/alerts.yml | system | HostHighCPU | 100 * (1 - avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[2m]))) > 90 | 2m | {'severity': 'warning'} | {'summary': 'High CPU usage on host'} |
+| monitoring/prometheus/rules/alerts.yml | system | ContainerRestarting | increase(container_restart_count[10m]) > 3 | 1m | {'severity': 'warning'} | {'summary': 'Container restarting frequently'} |
+| monitoring/prometheus/rules/alerts.yml | system | AlwaysFiring | vector(1) | 10s | {'severity': 'critical'} | {'summary': 'This alert should always fire'} |
diff --git a/docs/generated/traefik-routes.md b/docs/generated/traefik-routes.md
new file mode 100644
index 0000000..f7e82b1
--- /dev/null
+++ b/docs/generated/traefik-routes.md
@@ -0,0 +1,3 @@
+# Traefik Routes
+
+No Traefik routes were detected.
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..b38b1ca
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,30 @@
+# Infrastructure Documentation
+
+This documentation describes the Docker-based infrastructure, reverse proxy configuration, monitoring stack, automation services, and generated inventory for this environment.
+
+Some sections are manually written. Other sections are generated automatically by GitHub Actions from the repository configuration.
+
+## Sections
+
+- [Docker Environment](docker.md)
+- [Networking and Reverse Proxy](networking.md)
+- [Monitoring and Alerting](monitoring.md)
+- [Automation](automation.md)
+- [Operations](operations.md)
+- [Public Showcase](showcase.md)
+
+## Generated Documentation
+
+- [Compose Inventory](generated/compose-inventory.md)
+- [Traefik Routes](generated/traefik-routes.md)
+- [Prometheus Rules](generated/prometheus-rules.md)
+- [Resolved Compose Config](generated/docker-compose.resolved.yml)
+- [Docker Compose Diagram](diagrams/docker-compose.svg)
+
+## Public-safe Output
+
+Sanitized documentation intended for public sharing is generated under:
+
+```text
+docs/public/
+```
diff --git a/docs/monitoring.md b/docs/monitoring.md
new file mode 100644
index 0000000..a42a723
--- /dev/null
+++ b/docs/monitoring.md
@@ -0,0 +1,11 @@
+# Monitoring and Alerting
+
+Monitoring documentation is generated from static rule files committed in this repository.
+
+- Prometheus rule files are parsed statically.
+- Live Prometheus APIs are not queried.
+- Future improvements can include Grafana dashboard and alert contact-point summaries.
+
+Generated asset:
+
+- [Prometheus Rules](generated/prometheus-rules.md)
diff --git a/docs/networking.md b/docs/networking.md
new file mode 100644
index 0000000..dbe8f34
--- /dev/null
+++ b/docs/networking.md
@@ -0,0 +1,12 @@
+# Networking and Reverse Proxy
+
+Networking and reverse-proxy documentation is generated from Docker Compose metadata.
+
+- Traefik labels are parsed statically from Compose definitions.
+- Service-to-network relationships are represented in generated diagrams.
+- Sensitive internal values are redacted in public-facing output.
+
+Related generated assets:
+
+- [Traefik Routes](generated/traefik-routes.md)
+- [Docker Compose Diagram](diagrams/docker-compose.svg)
diff --git a/docs/operations.md b/docs/operations.md
new file mode 100644
index 0000000..6e088ec
--- /dev/null
+++ b/docs/operations.md
@@ -0,0 +1,30 @@
+# Operations
+
+## Local docs generation
+
+```bash
+chmod +x scripts/docs/*.sh
+scripts/docs/generate-all.sh
+```
+
+## Inspect generated changes
+
+```bash
+git status -- docs/generated docs/diagrams docs/public
+```
+
+## GitHub Actions artifacts
+
+Use the **Generate documentation** workflow run and download the `generated-documentation` artifact from the run summary.
+
+## Commit behavior
+
+- Pull requests generate docs and upload artifacts only.
+- Pushes to `main` generate docs, upload artifacts, and commit generated docs when changes exist.
+- Manual workflow runs can commit generated docs when enabled through workflow input.
+
+## Troubleshooting
+
+- Confirm required tooling (`python3`, `jq`, `graphviz`, `docker compose`) is available.
+- Re-run generation after documentation script changes.
+- Review `docs/public` output for redaction coverage before sharing.
diff --git a/docs/public/compose-inventory.md b/docs/public/compose-inventory.md
new file mode 100644
index 0000000..c079bfa
--- /dev/null
+++ b/docs/public/compose-inventory.md
@@ -0,0 +1,26 @@
+# Docker Compose Inventory
+
+Source fingerprint: `d6aa78e3317a`
+
+## Summary
+
+| Item | Count |
+|---|---:|
+| Services | 0 |
+| Networks | 0 |
+| Volumes | 0 |
+
+## Services
+
+| Service | Container | Image | Build | Profiles | Networks | Ports | Restart |
+|---|---|---|---|---|---|---|---|
+
+## Networks
+
+| Network | Driver | External |
+|---|---|---|
+
+## Volumes
+
+| Volume | External |
+|---|---|
diff --git a/docs/public/docker-compose.svg b/docs/public/docker-compose.svg
new file mode 100644
index 0000000..cd8a7c6
--- /dev/null
+++ b/docs/public/docker-compose.svg
@@ -0,0 +1 @@
+
diff --git a/docs/public/index.md b/docs/public/index.md
new file mode 100644
index 0000000..f600c19
--- /dev/null
+++ b/docs/public/index.md
@@ -0,0 +1,12 @@
+# Public Infrastructure Summary
+
+This folder contains sanitized documentation generated from the infrastructure repository.
+
+Sensitive values such as internal domain names, private IP addresses, tokens, passwords, and secrets are redacted.
+
+## Documents
+
+- [Compose Inventory](compose-inventory.md)
+- [Traefik Routes](traefik-routes.md)
+- [Prometheus Rules](prometheus-rules.md)
+- [Docker Compose Diagram](docker-compose.svg)
diff --git a/docs/public/prometheus-rules.md b/docs/public/prometheus-rules.md
new file mode 100644
index 0000000..3566e5c
--- /dev/null
+++ b/docs/public/prometheus-rules.md
@@ -0,0 +1,7 @@
+# Prometheus Rules
+
+| File | Group | Alert | Expr | For | Labels | Annotations |
+|---|---|---|---|---|---|---|
+| monitoring/prometheus/rules/alerts.yml | system | HostHighCPU | 100 * (1 - avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[2m]))) > 90 | 2m | {'severity': 'warning'} | {'summary': 'High CPU usage on host'} |
+| monitoring/prometheus/rules/alerts.yml | system | ContainerRestarting | increase(container_restart_count[10m]) > 3 | 1m | {'severity': 'warning'} | {'summary': 'Container restarting frequently'} |
+| monitoring/prometheus/rules/alerts.yml | system | AlwaysFiring | vector(1) | 10s | {'severity': 'critical'} | {'summary': 'This alert should always fire'} |
diff --git a/docs/public/traefik-routes.md b/docs/public/traefik-routes.md
new file mode 100644
index 0000000..f7e82b1
--- /dev/null
+++ b/docs/public/traefik-routes.md
@@ -0,0 +1,3 @@
+# Traefik Routes
+
+No Traefik routes were detected.
diff --git a/docs/showcase.md b/docs/showcase.md
new file mode 100644
index 0000000..8650b40
--- /dev/null
+++ b/docs/showcase.md
@@ -0,0 +1,14 @@
+# Public Showcase
+
+This environment showcases practical infrastructure operations with a documentation-first approach.
+
+Highlights:
+
+- Container orchestration with Docker Compose.
+- Reverse proxy routing and TLS-focused service exposure patterns.
+- Monitoring and alerting configuration via version-controlled rules.
+- Documentation automation through CI.
+- Generated architecture diagrams to aid operational understanding.
+- Sanitized public documentation for safe sharing.
+
+This page intentionally avoids private hostnames, internal-only URLs, credentials, and secret values.
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 0000000..0a9985e
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,20 @@
+site_name: Infrastructure Documentation
+site_description: Generated and maintained infrastructure documentation
+repo_url: https://github.com/beatz174-bit/docker
+docs_dir: docs
+
+nav:
+ - Home: index.md
+ - Docker Environment: docker.md
+ - Networking: networking.md
+ - Monitoring: monitoring.md
+ - Automation: automation.md
+ - Operations: operations.md
+ - Public Showcase: showcase.md
+ - Generated:
+ - Compose Inventory: generated/compose-inventory.md
+ - Traefik Routes: generated/traefik-routes.md
+ - Prometheus Rules: generated/prometheus-rules.md
+
+theme:
+ name: mkdocs
diff --git a/scripts/docs/generate-all.sh b/scripts/docs/generate-all.sh
index ada707a..7690e59 100755
--- a/scripts/docs/generate-all.sh
+++ b/scripts/docs/generate-all.sh
@@ -7,5 +7,6 @@ scripts/docs/render-compose-config.sh
python3 scripts/docs/generate-compose-inventory.py docs/generated/docker-compose.resolved.yml docs/generated/compose-inventory.md
python3 scripts/docs/generate-traefik-routes.py docs/generated/docker-compose.resolved.yml docs/generated/traefik-routes.md
python3 scripts/docs/generate-prometheus-rules.py docs/generated/prometheus-rules.md
+python3 scripts/docs/generate-docs-index.py docs/generated/index.md
python3 scripts/docs/generate-diagrams.py docs/generated/docker-compose.resolved.yml docs/diagrams/docker-compose.dot docs/diagrams/docker-compose.svg
python3 scripts/docs/sanitize-public-docs.py docs/generated docs/diagrams docs/public
diff --git a/scripts/docs/generate-compose-inventory.py b/scripts/docs/generate-compose-inventory.py
index e705372..00e46d9 100644
--- a/scripts/docs/generate-compose-inventory.py
+++ b/scripts/docs/generate-compose-inventory.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
+import hashlib
import sys, yaml
-from datetime import datetime, timezone
def md(v): return str(v).replace('|','\\|') if v is not None else ''
@@ -9,7 +9,9 @@ with open(inp) as f: c=yaml.safe_load(f) or {}
svcs=c.get('services',{}) or {}
nets=c.get('networks',{}) or {}
vols=c.get('volumes',{}) or {}
-lines=["# Docker Compose Inventory","",f"Generated: {datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')}","","## Summary","","| Item | Count |","|---|---:|",f"| Services | {len(svcs)} |",f"| Networks | {len(nets)} |",f"| Volumes | {len(vols)} |","","## Services","","| Service | Container | Image | Build | Profiles | Networks | Ports | Restart |","|---|---|---|---|---|---|---|---|"]
+raw=open(inp,'rb').read()
+fingerprint=hashlib.sha256(raw).hexdigest()[:12]
+lines=["# Docker Compose Inventory","",f"Source fingerprint: `{fingerprint}`","","## Summary","","| Item | Count |","|---|---:|",f"| Services | {len(svcs)} |",f"| Networks | {len(nets)} |",f"| Volumes | {len(vols)} |","","## Services","","| Service | Container | Image | Build | Profiles | Networks | Ports | Restart |","|---|---|---|---|---|---|---|---|"]
for n,s in sorted(svcs.items()):
build=s.get('build','')
if isinstance(build,dict): build=build.get('context','')
diff --git a/scripts/docs/generate-docs-index.py b/scripts/docs/generate-docs-index.py
new file mode 100644
index 0000000..5f4fd60
--- /dev/null
+++ b/scripts/docs/generate-docs-index.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python3
+from pathlib import Path
+import sys
+
+out = Path(sys.argv[1])
+out.parent.mkdir(parents=True, exist_ok=True)
+out.write_text(
+ """# Generated Documentation
+
+This directory contains documentation generated automatically from repository configuration.
+
+## Files
+
+- [Compose file list](compose-files.txt)
+- [Resolved Docker Compose config](docker-compose.resolved.yml)
+- [Compose inventory](compose-inventory.md)
+- [Traefik routes](traefik-routes.md)
+- [Prometheus rules](prometheus-rules.md)
+- [Docker Compose diagram](../diagrams/docker-compose.svg)
+"""
+)
diff --git a/scripts/docs/sanitize-public-docs.py b/scripts/docs/sanitize-public-docs.py
index c75342a..78012cb 100644
--- a/scripts/docs/sanitize-public-docs.py
+++ b/scripts/docs/sanitize-public-docs.py
@@ -1,18 +1,46 @@
#!/usr/bin/env python3
-import sys,re,shutil
+import re
+import sys
from pathlib import Path
-srcg,srcd,out=sys.argv[1],sys.argv[2],sys.argv[3]
-outp=Path(out)
-outp.mkdir(parents=True,exist_ok=True)
-for src in [Path(srcg),Path(srcd)]:
- for f in src.rglob('*'):
- if not f.is_file(): continue
- rel=f.relative_to(src)
- dest=outp/src.name/rel
- dest.parent.mkdir(parents=True,exist_ok=True)
- txt=f.read_text(errors='ignore')
- txt=re.sub(r'\b[a-zA-Z0-9.-]+\.lan\.ddnsgeek\.com\b','',txt)
- txt=re.sub(r'\b(?:10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3})\b','',txt)
- txt=re.sub(r'(?i)\b(password|token|api_key|secret)\s*[:=]\s*[^\s\n]+',r'\1=',txt)
- txt=re.sub(r'(?m)^([A-Z0-9_]*(?:PASSWORD|TOKEN|API_KEY|SECRET)[A-Z0-9_]*)\s*[:=]\s*.*$',r'\1=',txt)
- dest.write_text(txt)
+
+src_generated = Path(sys.argv[1])
+src_diagrams = Path(sys.argv[2])
+out_dir = Path(sys.argv[3])
+out_dir.mkdir(parents=True, exist_ok=True)
+
+
+def sanitize_text(content: str) -> str:
+ content = re.sub(r'\b[a-zA-Z0-9.-]+\.lan\.ddnsgeek\.com\b', '', content)
+ content = re.sub(
+ r'\b(?:10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3})\b',
+ '',
+ content,
+ )
+ content = re.sub(r'(?i)\b(password|token|api[_-]?key|secret)\s*[:=]\s*[^\s\n]+', r'\1=', content)
+ content = re.sub(r'(?m)^([A-Z0-9_]*(?:PASSWORD|TOKEN|API_KEY|SECRET)[A-Z0-9_]*)\s*[:=]\s*.*$', r'\1=', content)
+ return content
+
+for name in ['compose-inventory.md', 'traefik-routes.md', 'prometheus-rules.md']:
+ src = src_generated / name
+ if src.exists():
+ (out_dir / name).write_text(sanitize_text(src.read_text(errors='ignore')))
+
+svg_src = src_diagrams / 'docker-compose.svg'
+if svg_src.exists():
+ (out_dir / 'docker-compose.svg').write_text(sanitize_text(svg_src.read_text(errors='ignore')))
+
+(out_dir / 'index.md').write_text(
+ """# Public Infrastructure Summary
+
+This folder contains sanitized documentation generated from the infrastructure repository.
+
+Sensitive values such as internal domain names, private IP addresses, tokens, passwords, and secrets are redacted.
+
+## Documents
+
+- [Compose Inventory](compose-inventory.md)
+- [Traefik Routes](traefik-routes.md)
+- [Prometheus Rules](prometheus-rules.md)
+- [Docker Compose Diagram](docker-compose.svg)
+"""
+)