Compare commits
202 Commits
4d681021e1
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| c89b8129ec | |||
| c98b2d8232 | |||
| 3a9b3786c5 | |||
| 1131eceb94 | |||
| 586be50567 | |||
| d0e08b8fc1 | |||
| 487117b31a | |||
| 82fa90d843 | |||
| ef1e7432ee | |||
| 427ea20e43 | |||
| 3298219ccf | |||
| b30c7f3a8a | |||
| 374511c123 | |||
| 313f7f1c21 | |||
| 6aa78525c2 | |||
| 5e0de23ff7 | |||
| 3c655dabcf | |||
| 60e59f95a8 | |||
| cdf37fb2c9 | |||
| f56b734cb4 | |||
| 10c4373c0e | |||
| 2619d86dc1 | |||
| 1b679a4f09 | |||
| 02033cd3f9 | |||
| d932bc57d0 | |||
| c4cfa8081f | |||
| 90c9094a6f | |||
| 36c5f2b1e3 | |||
| 7bc2729ef6 | |||
| 9d79f828e4 | |||
| 22b3659cdf | |||
| 4440fddb2b | |||
| d74000fbd0 | |||
| 9efdb5c781 | |||
| e7fd52616d | |||
| b7b4b4d36d | |||
| 40f5a3ce0d | |||
| 8e43118661 | |||
| 0e76f3cef1 | |||
| 8d18ab7059 | |||
| 6a959d85c3 | |||
| 79c583eca3 | |||
| 7fcafed3f9 | |||
| 0b67830d7f | |||
| d878a0f9b8 | |||
| 9c38910a67 | |||
| 4a38a9421d | |||
| 5d32693925 | |||
| 696cecfecb | |||
| c0360a14b9 | |||
| 5589594d2c | |||
| 0bd41b2fb1 | |||
| 5f10d0366e | |||
| 9f98101c5d | |||
| 0c20676590 | |||
| 59e2c2b9a3 | |||
| 61d49e85a3 | |||
| 8f84ed6d83 | |||
| 24cbb02bff | |||
| 685a472572 | |||
| 9de1bee542 | |||
| 306e2c14db | |||
| 63b47b59b5 | |||
| 52bd2d9fa2 | |||
| 034ad17cf9 | |||
| ef2846562b | |||
| 52e2102f93 | |||
| a9b21912db | |||
| c9e4aeb8d6 | |||
| 96a44d5da6 | |||
| 0d936677e5 | |||
| 5c38b92bc8 | |||
| fc5c882193 | |||
| a4501d4034 | |||
| c0958d8f02 | |||
| 2a97864a06 | |||
| bd23339edd | |||
| f8091a5c76 | |||
| 6a2639f931 | |||
| fae5e119d1 | |||
| 872038d0c9 | |||
| 7a6db9fcfd | |||
| d6a8979d55 | |||
| a9a8a708d3 | |||
| 749c0d500d | |||
| 8f112af65b | |||
| 580e9b9aed | |||
| c77db36865 | |||
| e11dc22999 | |||
| 862ddd42f8 | |||
| d0e7e52150 | |||
| f0aa9941d8 | |||
| 6789451bd6 | |||
| b8d9e62954 | |||
| 9f36dabcdc | |||
| 3c78e9c140 | |||
| 40a976f712 | |||
| 451be4ab0d | |||
| b848d6b807 | |||
| 4695839df4 | |||
| cb92ebc70e | |||
| 5c3bc0317c | |||
| c7dd9f2229 | |||
| 7258d150ad | |||
| 020d6ecb79 | |||
| b3cc235164 | |||
| b422a55c02 | |||
| b6d2e4ee62 | |||
| 438cf57127 | |||
| 6ada434618 | |||
| 2a6c905eb8 | |||
| 9ad21c5846 | |||
| 2bab864d5e | |||
| ebae1ed990 | |||
| 5e49b6774b | |||
| 228413d780 | |||
| 7279ade925 | |||
| a826c85e08 | |||
| 1918b83061 | |||
| fa54b956a7 | |||
| d69c74e537 | |||
| 0654d9673f | |||
| ff0c413d06 | |||
| f69028963b | |||
| 624d7be17c | |||
| b17adee7cc | |||
| 27c5c3f631 | |||
| 361d2dc87b | |||
| 2499924afc | |||
| b2ff514a71 | |||
| b5cfdde00f | |||
| d99e2767b5 | |||
| 7f8e920fa1 | |||
| c10b834be0 | |||
| f08a567933 | |||
| 85d7859b14 | |||
| d06c53ef0b | |||
| 85cf56fcaf | |||
| a576dfdaa0 | |||
| cf516ab1f4 | |||
| e7feec9146 | |||
| 49caca5700 | |||
| 97f0bac724 | |||
| f8370b6a99 | |||
| d27a994fe6 | |||
| 937c6164d8 | |||
| 4eed2fd710 | |||
| ba41ce7eb0 | |||
| 26b7b461a3 | |||
| 72cda2dc92 | |||
| 2b83cd5599 | |||
| c0ed8cfc5f | |||
| 7646f8187b | |||
| 8d462a83c7 | |||
| 29856c4d1c | |||
| ce626ee0c8 | |||
| 18104468aa | |||
| f136f49e51 | |||
| ee609201b3 | |||
| 25f91e301c | |||
| cbdf9c9562 | |||
| de82d295fb | |||
| 8224009aa6 | |||
| d98f74a9d0 | |||
| 3d49ebdeee | |||
| a515e3e25b | |||
| 0a3cfa4631 | |||
| 15b349604c | |||
| 4a0ab9d184 | |||
| 155373a171 | |||
| a29fcc85d0 | |||
| b6ff09513f | |||
| a0b9dd980b | |||
| 649965e97a | |||
| db57390bf9 | |||
| 4e61ac701f | |||
| cd47fe324e | |||
| d6baa39bf4 | |||
| 6f47e654a8 | |||
| 24047b0eaa | |||
| 0ddbb7d7ad | |||
| 43f25321d7 | |||
| 9678c6a8f1 | |||
| c1401e3e08 | |||
| 5c600d0af0 | |||
| e3d463d511 | |||
| ff2d323309 | |||
| 47a5908430 | |||
| 8448f2bb94 | |||
| cfbefed2e3 | |||
| 3b3f06a727 | |||
| 8c82830af8 | |||
| 9ebb3c6c93 | |||
| 86fba4f43f | |||
| d6325494c7 | |||
| 2021ef37ae | |||
| aae70d93b4 | |||
| 7bc4d6699d | |||
| e4dd0394fe | |||
| 1a65661474 | |||
| 01279edc5b | |||
| 4d713b02f3 |
@@ -0,0 +1,71 @@
|
||||
name: Generate Docs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 */6 * * *"
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKER_HOST: tcp://docker-socket-proxy:2375
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install docker CLI
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y docker.io docker-compose
|
||||
|
||||
- name: Generate docs
|
||||
run: |
|
||||
scripts/docs/generate-all.sh
|
||||
|
||||
- name: Validate generated docs
|
||||
run: |
|
||||
set -e
|
||||
|
||||
test -s docs/generated/docker-compose.resolved.yml
|
||||
test -s docs/generated/host-topology.md
|
||||
test -s docs/public/physical-topology.svg
|
||||
test -s docs/public/docker-traefik-dynu.svg
|
||||
|
||||
! grep -R "Host inventory JSON not found" docs/public docs/diagrams
|
||||
! grep -R "Generate terraform inventory" docs/public docs/diagrams
|
||||
|
||||
# Ensure no obvious secrets leaked
|
||||
! grep -R -E -i "password|token|api[_-]?key|secret" docs/public \
|
||||
|| (echo "Secret-like string detected"; exit 1)
|
||||
|
||||
- name: Commit changes
|
||||
run: |
|
||||
git config user.name "docs-bot"
|
||||
git config user.email "docs-bot@local"
|
||||
|
||||
git add docs/generated docs/diagrams docs/public data/terraform/proxmox-inventory.json || true
|
||||
|
||||
if git diff --cached --quiet; then
|
||||
echo "No changes to commit"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git commit -m "docs: regenerate documentation artifacts"
|
||||
|
||||
- name: Push to Gitea
|
||||
run: |
|
||||
git push origin HEAD:main
|
||||
|
||||
- name: Push to GitHub mirror
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_PUSH_TOKEN }}
|
||||
GITHUB_MIRROR_REPO: ${{ vars.GITHUB_MIRROR_REPO }}
|
||||
run: |
|
||||
test -n "$GITHUB_TOKEN"
|
||||
test -n "$GITHUB_MIRROR_REPO"
|
||||
git remote add github "https://$GITHUB_TOKEN@github.com/$GITHUB_MIRROR_REPO.git" || true
|
||||
git push github HEAD:main
|
||||
@@ -0,0 +1,24 @@
|
||||
name: Validate Docs (Gitea)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- "docs/**"
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Validate docs
|
||||
run: |
|
||||
set -e
|
||||
|
||||
test -d docs/public
|
||||
test -s docs/public/physical-topology.svg
|
||||
|
||||
! grep -R "Host inventory JSON not found" docs/public
|
||||
! grep -R "Generate terraform inventory" docs/public
|
||||
@@ -0,0 +1,35 @@
|
||||
name: Validate committed public docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
validate-public-docs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Ensure committed docs/public exists
|
||||
run: |
|
||||
test -d docs/public
|
||||
test -n "$(find docs/public -mindepth 1 -print -quit)"
|
||||
- name: Install MkDocs
|
||||
run: |
|
||||
python3 -m pip install --user mkdocs
|
||||
- name: Validate docs content
|
||||
run: |
|
||||
set -e
|
||||
test -s docs/public/physical-topology.svg
|
||||
test -s docs/public/docker-traefik-dynu.svg
|
||||
! grep -R "Host inventory JSON not found" docs/public
|
||||
! grep -R "Generate terraform inventory" docs/public
|
||||
! rg -n -i "password|token|api[_-]?key|secret" docs/public
|
||||
- name: Build MkDocs site
|
||||
run: |
|
||||
python3 -m mkdocs build -f mkdocs-public.yml --strict
|
||||
@@ -0,0 +1,84 @@
|
||||
name: Publish documentation site
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: github-pages
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Ensure committed docs/public exists
|
||||
run: |
|
||||
test -d docs/public
|
||||
test -n "$(find docs/public -mindepth 1 -print -quit)"
|
||||
|
||||
- name: Install Graphviz
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y graphviz
|
||||
dot -V
|
||||
|
||||
- name: Validate sanitized diagram artifacts
|
||||
run: |
|
||||
test -f docs/public/physical-topology.svg
|
||||
test -f docs/public/docker-traefik-dynu.svg
|
||||
! rg -n "Graphviz dot not found" docs/public/*.svg
|
||||
! rg -n "lan\.ddnsgeek\.com" docs/public/*.svg docs/public/*.md
|
||||
! rg -n -i "password|token|api_key|secret" docs/public/*.svg
|
||||
|
||||
- name: Install MkDocs
|
||||
run: |
|
||||
python3 -m pip install --user mkdocs
|
||||
|
||||
- name: Build public MkDocs site
|
||||
run: |
|
||||
python3 -m mkdocs build -f mkdocs-public.yml --strict
|
||||
|
||||
- name: Verify published content excludes internal/generated docs
|
||||
run: |
|
||||
test -d site-public
|
||||
test ! -e site-public/generated
|
||||
test ! -e site-public/docker
|
||||
|
||||
- name: Verify expected 404-only paths are not generated
|
||||
run: |
|
||||
test ! -e site-public/generated/compose-inventory/index.html
|
||||
test ! -e site-public/generated/prometheus-rules/index.html
|
||||
test ! -e site-public/docker/index.html
|
||||
|
||||
- name: Configure GitHub Pages
|
||||
uses: actions/configure-pages@v5
|
||||
|
||||
- name: Upload GitHub Pages artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: site-public
|
||||
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
+27
@@ -4,6 +4,7 @@
|
||||
#!**/Dockerfile
|
||||
#!docker-compose.yml
|
||||
**/data/
|
||||
apps/gitea/runner-data/
|
||||
**/db/
|
||||
**/database/
|
||||
apps/nextcloud/config/
|
||||
@@ -21,6 +22,32 @@ apps/searxng/*
|
||||
venv/
|
||||
core/authelia/users_database.yml
|
||||
monitoring/influxdb/*
|
||||
!monitoring/influxdb/docker-compose.yml
|
||||
secrets/*
|
||||
!secrets/.env.secrets.example
|
||||
!secrets/inventory.json
|
||||
!.env.example
|
||||
core/traefik/certs/*
|
||||
!core/traefik/certs/.gitkeep
|
||||
site/
|
||||
|
||||
# Docs generation artifacts intentionally tracked
|
||||
!data/terraform/proxmox-inventory.json
|
||||
!infrastructure/terraform/dynu/generated/
|
||||
!infrastructure/terraform/dynu/generated/dynu_dns_records_inventory.json
|
||||
!docs/generated/
|
||||
!docs/generated/docker-compose.resolved.yml
|
||||
!docs/generated/host-topology.md
|
||||
!docs/diagrams/
|
||||
!docs/diagrams/*.svg
|
||||
!docs/public/
|
||||
!docs/public/*.md
|
||||
!docs/public/*.svg
|
||||
|
||||
# Terraform local/state artifacts
|
||||
**/.terraform/
|
||||
**/.terraform.lock.hcl
|
||||
*.tfstate
|
||||
*.tfstate.*
|
||||
*.tfvars
|
||||
*.tfvars.json
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# Codex instructions for this repository
|
||||
|
||||
This repository contains:
|
||||
- Docker Compose infrastructure
|
||||
- Terraform configuration
|
||||
- Ansible configuration
|
||||
|
||||
## General rules
|
||||
|
||||
Prefer validation and linting over execution.
|
||||
Do not make assumptions about runtime access.
|
||||
Do not run destructive commands.
|
||||
Do not install repo changes unless explicitly requested.
|
||||
|
||||
## Docker / Compose rules
|
||||
|
||||
This environment does not have Docker daemon access.
|
||||
Do not use commands that require `/var/run/docker.sock`.
|
||||
|
||||
Allowed:
|
||||
- `docker compose config`
|
||||
- `docker compose -f <file> config`
|
||||
- `./services-up.sh --profile all config`
|
||||
|
||||
Not allowed:
|
||||
- `docker compose up`
|
||||
- `docker compose down`
|
||||
- `docker compose run`
|
||||
- `docker compose exec`
|
||||
- `docker build`
|
||||
- `docker pull`
|
||||
|
||||
When validating Docker changes:
|
||||
1. Prefer `./services-up.sh --profile all config` if available.
|
||||
2. If that does not fit the task, use `docker compose -f ... config`.
|
||||
3. Only create temporary placeholder env files if validation requires them.
|
||||
4. Do not commit placeholder env files unless explicitly requested.
|
||||
|
||||
## Terraform rules
|
||||
|
||||
Allowed:
|
||||
- `terraform fmt -check -recursive`
|
||||
- `terraform init -backend=false -input=false`
|
||||
- `terraform validate`
|
||||
- `tflint`
|
||||
|
||||
Do not apply infrastructure changes unless explicitly requested.
|
||||
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:
|
||||
- `ansible-lint`
|
||||
- `ansible-playbook --syntax-check <playbook>`
|
||||
|
||||
Do not run playbooks against real hosts unless explicitly requested.
|
||||
|
||||
## Shell / YAML rules
|
||||
|
||||
Allowed:
|
||||
- `shellcheck`
|
||||
- `yamllint`
|
||||
- `yq`
|
||||
- `jq`
|
||||
|
||||
## Expected workflow
|
||||
|
||||
When making changes:
|
||||
1. Edit the smallest necessary set of files.
|
||||
2. Run the safest available validation commands.
|
||||
3. Report validation results clearly.
|
||||
4. If validation is blocked by missing secrets, env files, or remote/provider access, say so explicitly instead of guessing.
|
||||
@@ -1,49 +0,0 @@
|
||||
# Deployment prerequisites (required)
|
||||
|
||||
Before running `docker compose up`, you **must** provision runtime secrets.
|
||||
|
||||
## 1) Create non-committed secret files
|
||||
|
||||
```bash
|
||||
cp secrets/.env.secrets.example secrets/stack-secrets.env
|
||||
chmod 600 secrets/stack-secrets.env
|
||||
```
|
||||
|
||||
Create these Docker secret files (all ignored by git):
|
||||
|
||||
- `secrets/nextcloud_db_root_password.txt`
|
||||
- `secrets/nextcloud_db_password.txt`
|
||||
- `secrets/nextcloud_admin_password.txt`
|
||||
- `secrets/nextcloud_smtp_password.txt`
|
||||
- `secrets/nextcloud_redis_password.txt`
|
||||
- `secrets/passbolt_db_password.txt`
|
||||
- `secrets/gramps_db_password.txt`
|
||||
- `secrets/influxdb_init_password.txt`
|
||||
- `secrets/prometheus_kuma_basic_auth_password.txt`
|
||||
|
||||
Recommended permissions:
|
||||
|
||||
```bash
|
||||
chmod 600 secrets/*.txt
|
||||
```
|
||||
|
||||
## 2) Rotate previously committed credentials
|
||||
|
||||
These values were previously hardcoded and must be rotated in upstream systems immediately:
|
||||
|
||||
- Database credentials (Nextcloud, Passbolt, Gramps, InfluxDB).
|
||||
- Nextcloud SMTP app password.
|
||||
- Authelia reset JWT secret, session secret, storage encryption key.
|
||||
- Traefik CrowdSec LAPI key.
|
||||
- Gotify admin password.
|
||||
- Prometheus Uptime Kuma basic-auth password.
|
||||
|
||||
## 3) Start stack
|
||||
|
||||
After secrets are provisioned:
|
||||
|
||||
```bash
|
||||
docker compose -f core/docker-compose.yml up -d
|
||||
docker compose -f monitoring/prometheus/docker-compose.yml up -d
|
||||
docker compose -f apps/nextcloud/docker-compose.yml up -d
|
||||
```
|
||||
@@ -0,0 +1,188 @@
|
||||
# Homelab Docker + Terraform Inventory Repository
|
||||
|
||||
This repository is both:
|
||||
|
||||
1. **operational** (Docker Compose application/runtime definition), and
|
||||
2. **documentary/inventory-oriented** (Terraform capture of Proxmox VMs, host metadata, and selected Docker objects).
|
||||
|
||||
If you only read one section, read **[Source-of-truth boundaries](docs/source-of-truth.md)** first.
|
||||
|
||||
---
|
||||
|
||||
## Quick navigation
|
||||
|
||||
- Architecture overview: [docs/architecture.md](docs/architecture.md)
|
||||
- Repository layout: [docs/repo-structure.md](docs/repo-structure.md)
|
||||
- Source-of-truth boundaries and guardrails: [docs/source-of-truth.md](docs/source-of-truth.md)
|
||||
- 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)
|
||||
- Dynu DNS read-only inventory workflow: [docs/dynu-dns-inventory.md](docs/dynu-dns-inventory.md)
|
||||
- Generated host topology doc: [docs/generated/host-topology.md](docs/generated/host-topology.md)
|
||||
- Ansible bootstrap workflows: [docs/ansible-workflows.md](docs/ansible-workflows.md)
|
||||
- Deployment prerequisites and secrets setup: [docs/deployment-prerequisites.md](docs/deployment-prerequisites.md)
|
||||
- Secrets inventory: [docs/security-secrets.md](docs/security-secrets.md)
|
||||
|
||||
Codex helper scripts:
|
||||
|
||||
- Initial Codex environment/bootstrap setup: [scripts/codex-setup.sh](scripts/codex-setup.sh)
|
||||
- Codex environment maintenance/refresh: [scripts/codex-maintenance.sh](scripts/codex-maintenance.sh)
|
||||
|
||||
Infrastructure subtrees:
|
||||
|
||||
- Ansible foundation docs: [infrastructure/ansible/README.md](infrastructure/ansible/README.md)
|
||||
- Terraform root docs: [infrastructure/terraform/README.md](infrastructure/terraform/README.md)
|
||||
- Terraform Docker mirror: [infrastructure/terraform/docker/README.md](infrastructure/terraform/docker/README.md)
|
||||
- Terraform Proxmox inventory: [infrastructure/terraform/proxmox/README.md](infrastructure/terraform/proxmox/README.md)
|
||||
|
||||
---
|
||||
|
||||
## Operating model
|
||||
|
||||
### Docker Compose (runtime authority)
|
||||
|
||||
- Compose files under `core/`, `apps/`, and `monitoring/` describe runtime services.
|
||||
- `services-up.sh` composes the environment by discovering compose files and applying common env/network inputs.
|
||||
- For service runtime behavior, start from Compose files and `services-up.sh` (not Terraform).
|
||||
|
||||
|
||||
### Ansible (bootstrap foundation)
|
||||
|
||||
- Ansible under `infrastructure/ansible/` is a phase-1 foundation for inventory/configuration scaffolding.
|
||||
- It supports safe validation (inventory parsing and playbook syntax checks) while hosts/devices are onboarded gradually.
|
||||
- It does not replace Compose runtime authority or Terraform reconciliation authority at this stage.
|
||||
|
||||
### Terraform (inventory and reconciliation authority)
|
||||
|
||||
- Terraform under `infrastructure/terraform/` is used to codify and reconcile existing infrastructure.
|
||||
- Current repo usage emphasizes **brownfield import-first workflows** and safe reconciliation.
|
||||
- Terraform captures:
|
||||
- Proxmox VM configuration for existing VMs.
|
||||
- Physical host metadata in locals/outputs.
|
||||
- Documentation-oriented Docker container mirroring (limited, selective).
|
||||
|
||||
Terraform here is **not** a replacement for Docker Compose deployment.
|
||||
|
||||
---
|
||||
|
||||
## Guardrails
|
||||
|
||||
- Do not run destructive Terraform commands casually.
|
||||
- Do not treat generated Terraform config as final without manual review.
|
||||
- Do not commit real secrets, credentials, or local state.
|
||||
- Keep one-resource-per-file patterns where already established in Terraform subdirectories.
|
||||
- Prefer shaping outputs for documentation/tooling consumption over dumping raw provider objects.
|
||||
|
||||
See [docs/source-of-truth.md](docs/source-of-truth.md) and [docs/terraform-workflows.md](docs/terraform-workflows.md) for concrete do/don't guidance.
|
||||
|
||||
---
|
||||
|
||||
## High-level architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Internet((Internet Clients)) -->|HTTPS 443 / HTTP 80| Traefik[Traefik Ingress\nACME TLS + Security Middlewares]
|
||||
|
||||
subgraph DockerHost[Primary Docker Host]
|
||||
Traefik
|
||||
Authelia[Authelia SSO / ForwardAuth]
|
||||
CrowdSec[CrowdSec + Traefik Bouncer]
|
||||
ErrPages[Error Pages Fallback]
|
||||
|
||||
subgraph Apps[Business / User Applications]
|
||||
Nextcloud[Nextcloud]
|
||||
Passbolt[Passbolt]
|
||||
Gitea[Gitea]
|
||||
FamilyTree[Gramps Web]
|
||||
Searxng[SearXNG]
|
||||
end
|
||||
|
||||
subgraph Ops[Operations & Monitoring]
|
||||
Grafana[Grafana]
|
||||
Prometheus[Prometheus]
|
||||
InfluxDB[InfluxDB]
|
||||
NodeRED[Node-RED]
|
||||
Portainer[Portainer]
|
||||
UptimeKuma[Uptime Kuma]
|
||||
Gotify[Gotify Notifications]
|
||||
end
|
||||
end
|
||||
|
||||
Traefik --> Apps
|
||||
Traefik --> Ops
|
||||
Traefik -->|ForwardAuth for selected routes| Authelia
|
||||
Traefik -->|Threat decisions| CrowdSec
|
||||
Traefik -->|4xx/5xx fallback| ErrPages
|
||||
|
||||
Prometheus --> Grafana
|
||||
Prometheus --> Gotify
|
||||
```
|
||||
|
||||
For request-flow and network detail, see [docs/architecture.md](docs/architecture.md).
|
||||
|
||||
## Public docs publication workflow
|
||||
|
||||
Public docs are generated on the Docker host and committed to this repository. GitHub Actions only publishes committed content from `docs/public`.
|
||||
|
||||
1. Generate public docs locally from the repository root:
|
||||
|
||||
```bash
|
||||
./scripts/generate-public-docs.sh
|
||||
```
|
||||
|
||||
2. Inspect the generated changes:
|
||||
|
||||
```bash
|
||||
git diff -- docs/public docs/generated docs/diagrams
|
||||
```
|
||||
|
||||
3. Commit the generated public docs (and any supporting generated files you intend to version):
|
||||
|
||||
```bash
|
||||
git add docs/public docs/generated docs/diagrams
|
||||
git commit -m "docs: regenerate public docs"
|
||||
```
|
||||
|
||||
4. Push your branch:
|
||||
|
||||
```bash
|
||||
git push
|
||||
```
|
||||
|
||||
Only files under `docs/public` are published by GitHub Pages. Internal/generated documentation is not published unless it is deliberately copied/sanitized into `docs/public`.
|
||||
|
||||
### Regenerating architecture docs (Prometheus + Dynu DNS)
|
||||
|
||||
```bash
|
||||
# Refresh Dynu live inventory and generated resources/import helpers
|
||||
cd infrastructure/terraform/dynu
|
||||
terraform apply -refresh-only
|
||||
python3 scripts/generate-brownfield-records.py --overwrite
|
||||
|
||||
# Regenerate architecture docs from Prometheus + Dynu inventory
|
||||
cd ../../..
|
||||
python3 scripts/render_prometheus_docs.py \
|
||||
--inventory-file docs/runtime/prometheus-inventory.json \
|
||||
--dynu-dns-inventory-file infrastructure/terraform/dynu/generated/dynu_dns_records_inventory.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Codex setup and maintenance scripts
|
||||
|
||||
The repository includes helper scripts for Codex sessions that need local tooling and safe placeholder secret material for validation-only workflows:
|
||||
|
||||
- `scripts/codex-setup.sh`
|
||||
- Installs baseline CLI dependencies (shell/yaml/terraform/ansible tooling).
|
||||
- Prepares `secrets/stack-secrets.env` from templates and creates dummy file-based secret placeholders based on `secrets/inventory.json`.
|
||||
- Installs/refreshed baseline Ansible collections when `infrastructure/ansible/collections/requirements.yml` is present.
|
||||
- Runs safe Ansible bootstrap checks (version, inventory parse, playbook syntax check) without live connectivity operations.
|
||||
- Prints installed tool versions for quick verification.
|
||||
|
||||
- `scripts/codex-maintenance.sh`
|
||||
- Refreshes Python-based linting/automation tooling.
|
||||
- Reconciles placeholder secret files against current `secrets/inventory.json` (creates missing, removes stale).
|
||||
- Rebuilds `secrets/stack-secrets.env` with dummy values for compose-config validation.
|
||||
- Refreshes Ansible collections and repeats safe inventory/syntax validation checks.
|
||||
|
||||
Both scripts are intended for local validation environments and should not be treated as production provisioning automation.
|
||||
@@ -1,31 +0,0 @@
|
||||
# Credential Inventory (apps/, core/, monitoring/)
|
||||
|
||||
## apps/
|
||||
- `apps/nextcloud/docker-compose.yml`
|
||||
- `MYSQL_PASSWORD` (nextcloud-webapp) -> `MYSQL_PASSWORD_FILE` + Docker secret.
|
||||
- `SMTP_PASSWORD` -> `SMTP_PASSWORD_FILE` + Docker secret.
|
||||
- `REDIS_HOST_PASSWORD` -> `REDIS_HOST_PASSWORD_FILE` + Docker secret.
|
||||
- `MYSQL_ROOT_PASSWORD`, `MYSQL_PASSWORD`, `NEXTCLOUD_ADMIN_PASSWORD` (nextcloud-db) -> `_FILE` variants + Docker secrets.
|
||||
- Redis `--requirepass` inline value -> read from Docker secret at runtime.
|
||||
- `apps/passbolt/docker-compose.yml`
|
||||
- `MYSQL_PASSWORD`, `DATASOURCES_DEFAULT_PASSWORD` -> `_FILE` variants + Docker secret.
|
||||
- `apps/gramps/docker-compose.yml`
|
||||
- `POSTGRES_PASSWORD` -> `POSTGRES_PASSWORD_FILE` + Docker secret.
|
||||
- `DB_URI` password + `INITIAL_ADMIN_PASSWORD` -> env references from non-committed secrets env file.
|
||||
|
||||
## core/
|
||||
- `core/authelia/configuration.yml`
|
||||
- `identity_validation.reset_password.jwt_secret` -> `${AUTHELIA_JWT_SECRET}`.
|
||||
- `session.secret` -> `${AUTHELIA_SESSION_SECRET}`.
|
||||
- `storage.encryption_key` -> `${AUTHELIA_STORAGE_ENCRYPTION_KEY}`.
|
||||
- `core/traefik/dynamic.yml`
|
||||
- `crowdsecLapiKey` -> `${CROWDSEC_LAPI_KEY}`.
|
||||
|
||||
## monitoring/
|
||||
- `monitoring/gotify/docker-compose.yml`
|
||||
- `GOTIFY_DEFAULTUSER_PASS` -> `${GOTIFY_DEFAULTUSER_PASS}` from non-committed secrets env file.
|
||||
- `monitoring/prometheus/docker-compose.yml`
|
||||
- `DOCKER_INFLUXDB_INIT_PASSWORD` -> `DOCKER_INFLUXDB_INIT_PASSWORD_FILE` + Docker secret.
|
||||
- `PIHOLE_PASSWORD` -> `${PIHOLE_PASSWORD}` from non-committed secrets env file.
|
||||
- `monitoring/prometheus/prometheus.yml`
|
||||
- Uptime Kuma basic_auth `password` -> `password_file` mounted from non-committed secret file.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Gitea
|
||||
|
||||
## Gitea Actions
|
||||
|
||||
Gitea Actions is enabled by setting:
|
||||
|
||||
- `GITEA__actions__ENABLED=true`
|
||||
|
||||
## Runner service
|
||||
|
||||
The repository includes a dedicated Gitea Actions runner service named:
|
||||
|
||||
- `gitea-runner`
|
||||
|
||||
The runner uses Docker through the existing Docker socket proxy:
|
||||
|
||||
- `DOCKER_HOST=tcp://docker-socket-proxy:2375`
|
||||
|
||||
The runner intentionally **does not** mount:
|
||||
|
||||
- `/var/run/docker.sock`
|
||||
|
||||
## Registration token
|
||||
|
||||
Generate a runner registration token from the Gitea UI:
|
||||
|
||||
- Site Administration → Actions → Runners
|
||||
- or Repo → Settings → Actions → Runners
|
||||
|
||||
Put the token in your env/secrets file:
|
||||
|
||||
- `GITEA_RUNNER_REGISTRATION_TOKEN=...`
|
||||
|
||||
## Start the runner
|
||||
|
||||
- `./services-up.sh --profile gitea up -d gitea-runner`
|
||||
- or `./services-up.sh --profile all up -d gitea-runner`
|
||||
|
||||
## Logs
|
||||
|
||||
- `docker logs -f gitea-runner`
|
||||
|
||||
## Labels
|
||||
|
||||
Common workflow label:
|
||||
|
||||
- `runs-on: ubuntu-latest`
|
||||
|
||||
This should match the configured labels, for example:
|
||||
|
||||
- `GITEA_RUNNER_LABELS=ubuntu-latest:docker://node:20-bookworm,...`
|
||||
|
||||
## Security note
|
||||
|
||||
The runner can control Docker through `docker-socket-proxy`. This is safer than mounting the raw Docker socket directly, but workflows still have meaningful control over Docker. Only trusted repositories/users should be allowed to run workflows on this runner.
|
||||
@@ -9,6 +9,7 @@ services:
|
||||
- USER_GID=${GITEA_USER_GID}
|
||||
- GITEA__database__DB_TYPE=${GITEA_DB_TYPE}
|
||||
- GITEA__server__ROOT_URL=${GITEA_ROOT_URL}
|
||||
- GITEA__actions__ENABLED=true
|
||||
volumes:
|
||||
- ${PROJECT_ROOT}/apps/gitea/data:/data
|
||||
networks:
|
||||
@@ -31,6 +32,25 @@ services:
|
||||
retries: 6
|
||||
start_period: 120s
|
||||
|
||||
gitea-runner:
|
||||
profiles: ["apps","all","gitea","ci"]
|
||||
container_name: gitea-runner
|
||||
image: gitea/act_runner:latest
|
||||
restart: always
|
||||
depends_on:
|
||||
- gitea
|
||||
- docker-socket-proxy
|
||||
environment:
|
||||
- GITEA_INSTANCE_URL=${GITEA_ROOT_URL}
|
||||
- GITEA_RUNNER_REGISTRATION_TOKEN=${GITEA_RUNNER_REGISTRATION_TOKEN}
|
||||
- GITEA_RUNNER_NAME=${GITEA_RUNNER_NAME}
|
||||
- GITEA_RUNNER_LABELS=${GITEA_RUNNER_LABELS}
|
||||
- DOCKER_HOST=${DOCKER_SOCKET_PROXY_HOST}
|
||||
volumes:
|
||||
- ${PROJECT_ROOT}/apps/gitea/runner-data:/data
|
||||
networks:
|
||||
- traefik
|
||||
|
||||
#volumes:
|
||||
# gitea_data:
|
||||
|
||||
|
||||
@@ -1,50 +1,39 @@
|
||||
services:
|
||||
gramps-db:
|
||||
profiles: ["apps","all","gramps"]
|
||||
image: postgres:13
|
||||
container_name: gramps-db
|
||||
restart: always
|
||||
env_file:
|
||||
- ${SECRETS_ENV_FILE}
|
||||
environment:
|
||||
POSTGRES_USER: ${GRAMPS_DB_USER}
|
||||
POSTGRES_PASSWORD_FILE: /run/secrets/gramps_db_password
|
||||
POSTGRES_DB: ${GRAMPS_DB_NAME}
|
||||
secrets:
|
||||
- gramps_db_password
|
||||
volumes:
|
||||
- ${PROJECT_ROOT}/apps/gramps/db:/var/lib/postgresql
|
||||
networks:
|
||||
- gramps
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -h gramps-db -p 5432 -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 12
|
||||
start_period: 30s
|
||||
|
||||
grampsweb:
|
||||
profiles: ["apps","all","gramps"]
|
||||
image: ghcr.io/gramps-project/grampsweb:latest
|
||||
container_name: gramps-web
|
||||
depends_on:
|
||||
- gramps-db
|
||||
- gramps-redis
|
||||
- grampsweb_celery
|
||||
restart: always
|
||||
env_file:
|
||||
- ${SECRETS_ENV_FILE}
|
||||
# env_file:
|
||||
# - ${SECRETS_ENV_FILE}
|
||||
environment:
|
||||
DB_URI: ${GRAMPS_DB_URI}
|
||||
GRAMPSWEB_LOGLEVEL: ${GRAMPSWEB_LOGLEVEL}
|
||||
# default admin user created on first run:
|
||||
INITIAL_ADMIN: ${GRAMPS_INITIAL_ADMIN}
|
||||
INITIAL_ADMIN_PASSWORD: ${GRAMPS_INITIAL_ADMIN_PASSWORD}
|
||||
# optional: storage paths inside container
|
||||
GRAMPSWEB_MEDIAPATH: ${GRAMPSWEB_MEDIAPATH}
|
||||
GRAMPSWEB_TREE: "${GRAMPSWEB_TREE}"
|
||||
TZ: ${TZ}
|
||||
GRAMPSWEB_TREE: ${GRAMPSWEB_TREE}
|
||||
GRAMPSWEB_BASE_URL: ${GRAMPSWEB_BASE_URL}
|
||||
GRAMPSWEB_SECRET_KEY: ${GRAMPSWEB_SECRET_KEY}
|
||||
GRAMPSWEB_REGISTRATION_DISABLED: ${GRAMPSWEB_REGISTRATION_DISABLED}
|
||||
GRAMPSWEB_EMAIL_HOST: ${GRAMPSWEB_EMAIL_HOST}
|
||||
GRAMPSWEB_EMAIL_PORT: ${GRAMPSWEB_EMAIL_PORT}
|
||||
GRAMPSWEB_EMAIL_HOST_USER: ${GRAMPSWEB_EMAIL_HOST_USER}
|
||||
GRAMPSWEB_EMAIL_HOST_PASSWORD: ${GRAMPSWEB_EMAIL_HOST_PASSWORD}
|
||||
GRAMPSWEB_EMAIL_USE_SSL: ${GRAMPSWEB_EMAIL_USE_SSL}
|
||||
GRAMPSWEB_EMAIL_USE_STARTTLS: ${GRAMPSWEB_EMAIL_USE_STARTTLS}
|
||||
GRAMPSWEB_DEFAULT_FROM_EMAIL: ${GRAMPSWEB_DEFAULT_FROM_EMAIL}
|
||||
GRAMPSWEB_CELERY_CONFIG__broker_url: redis://gramps-redis:6379/0
|
||||
GRAMPSWEB_CELERY_CONFIG__result_backend: redis://gramps-redis:6379/0
|
||||
GRAMPSWEB_RATELIMIT_STORAGE_URI: redis://gramps-redis:6379/1
|
||||
volumes:
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/users:/app/users
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/media:/app/media
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/index:/app/indexdir
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/thumbnail_cache:/app/thumbnail_cache
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/cache:/app/cache
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/secret:/app/secret
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/db:/root/.gramps/grampsdb
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/media:/app/media
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/tmp:/tmp
|
||||
labels:
|
||||
- "traefik.http.routers.gramps.rule=Host(`familytree.lan.ddnsgeek.com`)"
|
||||
- "traefik.enable=true"
|
||||
@@ -65,9 +54,67 @@ services:
|
||||
retries: 6
|
||||
start_period: 60s
|
||||
|
||||
grampsweb_celery:
|
||||
profiles: ["apps","all","gramps"]
|
||||
image: ghcr.io/gramps-project/grampsweb:latest
|
||||
container_name: gramps-web-celery
|
||||
command: celery -A gramps_webapi.celery worker --loglevel=INFO --concurrency=2
|
||||
depends_on:
|
||||
- gramps-redis
|
||||
restart: always
|
||||
# env_file:
|
||||
# - ${SECRETS_ENV_FILE}
|
||||
environment:
|
||||
TZ: ${TZ}
|
||||
GRAMPSWEB_TREE: ${GRAMPSWEB_TREE}
|
||||
GRAMPSWEB_BASE_URL: ${GRAMPSWEB_BASE_URL}
|
||||
GRAMPSWEB_SECRET_KEY: ${GRAMPSWEB_SECRET_KEY}
|
||||
GRAMPSWEB_REGISTRATION_DISABLED: ${GRAMPSWEB_REGISTRATION_DISABLED}
|
||||
GRAMPSWEB_EMAIL_HOST: ${GRAMPSWEB_EMAIL_HOST}
|
||||
GRAMPSWEB_EMAIL_PORT: ${GRAMPSWEB_EMAIL_PORT}
|
||||
GRAMPSWEB_EMAIL_HOST_USER: ${GRAMPSWEB_EMAIL_HOST_USER}
|
||||
GRAMPSWEB_EMAIL_HOST_PASSWORD: ${GRAMPSWEB_EMAIL_HOST_PASSWORD}
|
||||
GRAMPSWEB_EMAIL_USE_SSL: ${GRAMPSWEB_EMAIL_USE_SSL}
|
||||
GRAMPSWEB_EMAIL_USE_STARTTLS: ${GRAMPSWEB_EMAIL_USE_STARTTLS}
|
||||
GRAMPSWEB_DEFAULT_FROM_EMAIL: ${GRAMPSWEB_DEFAULT_FROM_EMAIL}
|
||||
GRAMPSWEB_CELERY_CONFIG__broker_url: redis://gramps-redis:6379/0
|
||||
GRAMPSWEB_CELERY_CONFIG__result_backend: redis://gramps-redis:6379/0
|
||||
GRAMPSWEB_RATELIMIT_STORAGE_URI: redis://gramps-redis:6379/1
|
||||
volumes:
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/users:/app/users
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/index:/app/indexdir
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/thumbnail_cache:/app/thumbnail_cache
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/cache:/app/cache
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/secret:/app/secret
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/db:/root/.gramps/grampsdb
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/media:/app/media
|
||||
- ${PROJECT_ROOT}/apps/gramps/data/tmp:/tmp
|
||||
networks:
|
||||
- gramps
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- pgrep -f "celery.*gramps_webapi.celery.*worker" >/dev/null
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 6
|
||||
start_period: 60s
|
||||
|
||||
gramps-redis:
|
||||
profiles: ["apps","all","gramps"]
|
||||
image: valkey/valkey:8-alpine
|
||||
container_name: gramps-redis
|
||||
restart: always
|
||||
networks:
|
||||
- gramps
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- valkey-cli -h 127.0.0.1 -p 6379 ping | grep -q PONG
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 6
|
||||
start_period: 10s
|
||||
|
||||
networks:
|
||||
gramps:
|
||||
|
||||
secrets:
|
||||
gramps_db_password:
|
||||
file: ${PROJECT_ROOT}/secrets/gramps_db_password.txt
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
services:
|
||||
authelia:
|
||||
profiles: ["core","all","authelia", "traefik"]
|
||||
image: authelia/authelia
|
||||
restart: always
|
||||
build:
|
||||
context: ${PROJECT_ROOT}/core/authelia
|
||||
# env_file:
|
||||
# - ${PROJECT_ROOT}/secrets/stack-secrets.env
|
||||
# environment:
|
||||
# - AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET:${AUTHELIA_JWT_SECRET}
|
||||
# - AUTHELIA_SESSION_SECRET:${AUTHELIA_SESSION_SECRET}
|
||||
# - AUTHELIA_STORAGE_ENCRYPTION_KEY:${AUTHELIA_STORAGE_ENCRYPTION_KEY}
|
||||
volumes:
|
||||
- ${PROJECT_ROOT}/core/authelia:/config
|
||||
networks:
|
||||
# - reverse_proxy
|
||||
- traefik
|
||||
container_name: authelia
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.authelia.rule=Host(`auth.lan.ddnsgeek.com`)
|
||||
- traefik.http.routers.authelia.entrypoints=websecure
|
||||
- traefik.http.routers.authelia.tls=true
|
||||
- traefik.http.routers.authelia.tls.certresolver=myresolver
|
||||
- io.portainer.accesscontrol.public
|
||||
- traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://auth.lan.ddnsgeek.com/
|
||||
- traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true
|
||||
- traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User,Remote-Groups
|
||||
- traefik.http.middlewares.authelia.forwardauth.maxResponseBodySize=2097152
|
||||
@@ -0,0 +1,23 @@
|
||||
services:
|
||||
crowdsec:
|
||||
profiles: ["core","all","crowdsec", "traefik"]
|
||||
# image: crowdsecurity/crowdsec:latest
|
||||
build: ${PROJECT_ROOT}/core/crowdsec
|
||||
container_name: crowdsec
|
||||
restart: always
|
||||
environment:
|
||||
- COLLECTIONS=crowdsecurity/traefik
|
||||
# - CROWDSEC_LAPI_KEY=${CROWDSEC_LAPI_KEY}
|
||||
volumes:
|
||||
- ${PROJECT_ROOT}/core/crowdsec/logs:/logs:ro
|
||||
- ${PROJECT_ROOT}/core/crowdsec/data:/var/lib/crowdsec/data
|
||||
- ${PROJECT_ROOT}/core/crowdsec/config:/etc/crowdsec
|
||||
networks:
|
||||
# - reverse_proxy
|
||||
- traefik
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "cscli metrics || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 15s
|
||||
@@ -1,132 +0,0 @@
|
||||
services:
|
||||
traefik:
|
||||
profiles: ["core","all","traefik"]
|
||||
image: traefik:3
|
||||
container_name: traefik
|
||||
restart: always
|
||||
read_only: true
|
||||
hostname: traefik.lan.ddnsgeek.com
|
||||
depends_on:
|
||||
- docker-socket-proxy
|
||||
- error-pages
|
||||
- authelia
|
||||
- crowdsec
|
||||
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
|
||||
build:
|
||||
context: ${PROJECT_ROOT}/core
|
||||
# env_file:
|
||||
# - ${PROJECT_ROOT}/secrets/stack-secrets.env
|
||||
|
||||
volumes:
|
||||
- ${PROJECT_ROOT}/core/traefik/data/letsencrypt:/letsencrypt
|
||||
- ${PROJECT_ROOT}/core/traefik/data/logs:/logs
|
||||
- ${PROJECT_ROOT}/core/traefik/dynamic.yml:/etc/traefik/dynamic.yml:ro
|
||||
- ${PROJECT_ROOT}/core/traefik/traefik.yml:/etc/traefik/traefik.yml:ro
|
||||
- ${PROJECT_ROOT}/core/traefik/data/plugins:/plugins-storage
|
||||
|
||||
healthcheck:
|
||||
test: traefik healthcheck --ping
|
||||
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.traefik.rule=Host(`traefik.lan.ddnsgeek.com`)"
|
||||
- "traefik.http.routers.traefik.service=api@internal"
|
||||
- "traefik.http.routers.traefik.entrypoints=websecure"
|
||||
- "traefik.http.routers.traefik.tls.certresolver=myresolver"
|
||||
- "traefik.http.routers.traefik.middlewares=authelia"
|
||||
- "io.portainer.accesscontrol.public"
|
||||
- "traefik.docker.network=core_traefik"
|
||||
- "traefik.http.routers.traefik.observability.tracing=true"
|
||||
|
||||
networks:
|
||||
# - reverse_proxy
|
||||
# - prometheus_edge
|
||||
- traefik
|
||||
crowdsec:
|
||||
# image: crowdsecurity/crowdsec:latest
|
||||
profiles: ["core","all","traefik"]
|
||||
build: ${PROJECT_ROOT}/core/crowdsec
|
||||
container_name: crowdsec
|
||||
restart: always
|
||||
environment:
|
||||
- COLLECTIONS=crowdsecurity/traefik
|
||||
# - CROWDSEC_LAPI_KEY=${CROWDSEC_LAPI_KEY}
|
||||
volumes:
|
||||
- ${PROJECT_ROOT}/core/crowdsec/logs:/logs:ro
|
||||
- ${PROJECT_ROOT}/core/crowdsec/data:/var/lib/crowdsec/data
|
||||
- ${PROJECT_ROOT}/core/crowdsec/config:/etc/crowdsec
|
||||
networks:
|
||||
# - reverse_proxy
|
||||
- traefik
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "cscli metrics || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 15s
|
||||
|
||||
error-pages:
|
||||
profiles: ["core","all","traefik"]
|
||||
image: tarampampam/error-pages:3
|
||||
restart: always
|
||||
container_name: error-pages
|
||||
read_only: true
|
||||
environment:
|
||||
TEMPLATE_NAME: ${ERROR_PAGES_TEMPLATE_NAME}
|
||||
networks:
|
||||
# - reverse_proxy
|
||||
- traefik
|
||||
hostname: error-pages
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# use as "fallback" for any NON-registered services (with priority below normal)
|
||||
- "traefik.http.routers.error-pages-router.rule=HostRegexp(`{host:.+}`)"
|
||||
# should say that all of your services work on https
|
||||
- "traefik.http.routers.error-pages-router.entrypoints=web"
|
||||
- "traefik.http.routers.error-pages-router.middlewares=error-pages-middleware"
|
||||
# "errors" middleware settings
|
||||
- "traefik.http.middlewares.error-pages-middleware.errors.status=400-599"
|
||||
- "traefik.http.middlewares.error-pages-middleware.errors.service=error-pages-service"
|
||||
- "traefik.http.middlewares.error-pages-middleware.errors.query=/{status}.html"
|
||||
# define service properties
|
||||
- "traefik.http.services.error-pages-service.loadbalancer.server.port=8080"
|
||||
- "io.portainer.accesscontrol.public"
|
||||
|
||||
authelia:
|
||||
profiles: ["core","all","traefik"]
|
||||
image: authelia/authelia
|
||||
restart: always
|
||||
build:
|
||||
context: ${PROJECT_ROOT}/core/authelia
|
||||
# env_file:
|
||||
# - ${PROJECT_ROOT}/secrets/stack-secrets.env
|
||||
# environment:
|
||||
# - AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET:${AUTHELIA_JWT_SECRET}
|
||||
# - AUTHELIA_SESSION_SECRET:${AUTHELIA_SESSION_SECRET}
|
||||
# - AUTHELIA_STORAGE_ENCRYPTION_KEY:${AUTHELIA_STORAGE_ENCRYPTION_KEY}
|
||||
volumes:
|
||||
- ${PROJECT_ROOT}/core/authelia:/config
|
||||
networks:
|
||||
# - reverse_proxy
|
||||
- traefik
|
||||
container_name: authelia
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.authelia.rule=Host(`auth.lan.ddnsgeek.com`)
|
||||
- traefik.http.routers.authelia.entrypoints=websecure
|
||||
- traefik.http.routers.authelia.tls=true
|
||||
- traefik.http.routers.authelia.tls.certresolver=myresolver
|
||||
- io.portainer.accesscontrol.public
|
||||
- traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://auth.lan.ddnsgeek.com/
|
||||
- traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true
|
||||
- traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User,Remote-Groups
|
||||
- traefik.http.middlewares.authelia.forwardauth.maxResponseBodySize=2097152
|
||||
#networks:
|
||||
# reverse_proxy:
|
||||
# driver: bridge
|
||||
# prometheus_edge:
|
||||
# external: true
|
||||
@@ -0,0 +1,27 @@
|
||||
services:
|
||||
error-pages:
|
||||
profiles: ["core","all","error-pages", "traefik"]
|
||||
image: tarampampam/error-pages:3
|
||||
restart: always
|
||||
container_name: error-pages
|
||||
read_only: true
|
||||
environment:
|
||||
TEMPLATE_NAME: ${ERROR_PAGES_TEMPLATE_NAME}
|
||||
networks:
|
||||
# - reverse_proxy
|
||||
- traefik
|
||||
hostname: error-pages
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# use as "fallback" for any NON-registered services (with priority below normal)
|
||||
- "traefik.http.routers.error-pages-router.rule=HostRegexp(`{host:.+}`)"
|
||||
# should say that all of your services work on https
|
||||
- "traefik.http.routers.error-pages-router.entrypoints=web"
|
||||
- "traefik.http.routers.error-pages-router.middlewares=error-pages-middleware"
|
||||
# "errors" middleware settings
|
||||
- "traefik.http.middlewares.error-pages-middleware.errors.status=400-599"
|
||||
- "traefik.http.middlewares.error-pages-middleware.errors.service=error-pages-service"
|
||||
- "traefik.http.middlewares.error-pages-middleware.errors.query=/{status}.html"
|
||||
# define service properties
|
||||
- "traefik.http.services.error-pages-service.loadbalancer.server.port=8080"
|
||||
- "io.portainer.accesscontrol.public"
|
||||
@@ -17,8 +17,8 @@ services:
|
||||
container_name: docker-update-exporter-test
|
||||
stdin_open: true
|
||||
tty: true
|
||||
depends_on:
|
||||
- docker-socket-proxy
|
||||
# depends_on:
|
||||
# - docker-socket-proxy
|
||||
environment:
|
||||
DOCKER_HOST: tcp://docker-socket-proxy:2375
|
||||
volumes:
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Private-admin mTLS for Traefik
|
||||
|
||||
`private-admin` routers are configured to require client certificates via the Traefik TLS option `mtls-private-admin@file`.
|
||||
|
||||
## Certificate paths
|
||||
|
||||
- Trusted client CA bundle expected by Traefik:
|
||||
- `core/traefik/certs/ca/clients-ca.crt`
|
||||
- CA private key (keep secret, never commit):
|
||||
- `core/traefik/certs/ca/clients-ca.key`
|
||||
- Issued client certs:
|
||||
- `core/traefik/certs/clients/<client-name>/`
|
||||
|
||||
## Bootstrap
|
||||
|
||||
From repository root:
|
||||
|
||||
```bash
|
||||
./core/traefik/scripts/init-mtls-ca.sh
|
||||
./core/traefik/scripts/issue-mtls-client-cert.sh admin-laptop
|
||||
```
|
||||
|
||||
The second command exports a PKCS#12 bundle (`.p12`) for browser import and also leaves PEM `.crt`/`.key` artifacts for CLI usage.
|
||||
|
||||
## Revocation workflow
|
||||
|
||||
Because Traefik is configured with `clientAuth.caFiles`, revoked cert serials are not enforced by default.
|
||||
|
||||
- Use `./core/traefik/scripts/revoke-mtls-client-cert.sh <client-name>` to quarantine a client cert bundle.
|
||||
- For strict revocation, rotate the CA (`init-mtls-ca.sh` after removing old CA) and re-issue all trusted client certs.
|
||||
|
||||
## Deploy
|
||||
|
||||
After CA/certs are in place, restart Traefik to ensure updated files are loaded:
|
||||
|
||||
```bash
|
||||
docker compose -f core/traefik/docker-compose.yml up -d traefik
|
||||
```
|
||||
@@ -0,0 +1,50 @@
|
||||
services:
|
||||
traefik:
|
||||
profiles: ["core","all","traefik"]
|
||||
image: traefik:3
|
||||
container_name: traefik
|
||||
restart: always
|
||||
read_only: true
|
||||
hostname: traefik.lan.ddnsgeek.com
|
||||
depends_on:
|
||||
- docker-socket-proxy
|
||||
- error-pages
|
||||
- authelia
|
||||
- crowdsec
|
||||
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
|
||||
build:
|
||||
context: ${PROJECT_ROOT}/core
|
||||
# env_file:
|
||||
# - ${PROJECT_ROOT}/secrets/stack-secrets.env
|
||||
|
||||
volumes:
|
||||
- ${PROJECT_ROOT}/core/traefik/data/letsencrypt:/letsencrypt
|
||||
- ${PROJECT_ROOT}/core/traefik/data/logs:/logs
|
||||
- ${PROJECT_ROOT}/core/traefik/certs:/etc/traefik/certs:ro
|
||||
- ${PROJECT_ROOT}/core/traefik/dynamic.yml:/etc/traefik/dynamic.yml:ro
|
||||
- ${PROJECT_ROOT}/core/traefik/traefik.yml:/etc/traefik/traefik.yml:ro
|
||||
- ${PROJECT_ROOT}/core/traefik/data/plugins:/plugins-storage
|
||||
|
||||
healthcheck:
|
||||
test: traefik healthcheck --ping
|
||||
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.traefik.rule=Host(`traefik.lan.ddnsgeek.com`)"
|
||||
- "traefik.http.routers.traefik.service=api@internal"
|
||||
- "traefik.http.routers.traefik.entrypoints=websecure"
|
||||
- "traefik.http.routers.traefik.tls.certresolver=myresolver"
|
||||
- "traefik.http.routers.traefik.tls.options=mtls-private-admin@file"
|
||||
- "traefik.http.routers.traefik.middlewares=authelia"
|
||||
- "io.portainer.accesscontrol.public"
|
||||
- "traefik.docker.network=core_traefik"
|
||||
- "traefik.http.routers.traefik.observability.tracing=true"
|
||||
|
||||
networks:
|
||||
# - reverse_proxy
|
||||
# - prometheus_edge
|
||||
- traefik
|
||||
@@ -31,3 +31,13 @@ http:
|
||||
- crowdsec@file
|
||||
# - tracing-middleware@file
|
||||
- error-pages-middleware@docker
|
||||
|
||||
tls:
|
||||
options:
|
||||
mtls-private-admin:
|
||||
minVersion: VersionTLS12
|
||||
sniStrict: true
|
||||
clientAuth:
|
||||
caFiles:
|
||||
- /etc/traefik/certs/ca/clients-ca.crt
|
||||
clientAuthType: RequireAndVerifyClientCert
|
||||
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TRAEFIK_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
CA_DIR="${TRAEFIK_ROOT}/certs/ca"
|
||||
|
||||
CA_KEY="${CA_DIR}/clients-ca.key"
|
||||
CA_CERT="${CA_DIR}/clients-ca.crt"
|
||||
CA_SERIAL="${CA_DIR}/clients-ca.srl"
|
||||
|
||||
DAYS="${DAYS:-3650}"
|
||||
SUBJECT="${SUBJECT:-/CN=Traefik Private Admin Client CA/O=Homelab}"
|
||||
|
||||
mkdir -p "${CA_DIR}"
|
||||
chmod 700 "${CA_DIR}"
|
||||
|
||||
if [[ -f "${CA_KEY}" || -f "${CA_CERT}" ]]; then
|
||||
echo "Refusing to overwrite existing CA material in ${CA_DIR}."
|
||||
echo "Delete existing files first if you intentionally want to rotate the CA."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
openssl genrsa -out "${CA_KEY}" 4096
|
||||
chmod 600 "${CA_KEY}"
|
||||
|
||||
openssl req -x509 -new -nodes \
|
||||
-key "${CA_KEY}" \
|
||||
-sha256 \
|
||||
-days "${DAYS}" \
|
||||
-subj "${SUBJECT}" \
|
||||
-out "${CA_CERT}"
|
||||
chmod 644 "${CA_CERT}"
|
||||
|
||||
rm -f "${CA_SERIAL}"
|
||||
|
||||
echo "Created mTLS client CA: ${CA_CERT}"
|
||||
echo "Use issue-mtls-client-cert.sh to issue client certificates signed by this CA."
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Usage: $0 <client-name> [days]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CLIENT_NAME="$1"
|
||||
DAYS="${2:-825}"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TRAEFIK_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
CA_DIR="${TRAEFIK_ROOT}/certs/ca"
|
||||
CLIENT_DIR="${TRAEFIK_ROOT}/certs/clients/${CLIENT_NAME}"
|
||||
|
||||
CA_KEY="${CA_DIR}/clients-ca.key"
|
||||
CA_CERT="${CA_DIR}/clients-ca.crt"
|
||||
CA_SERIAL="${CA_DIR}/clients-ca.srl"
|
||||
|
||||
CLIENT_KEY="${CLIENT_DIR}/${CLIENT_NAME}.key"
|
||||
CLIENT_CSR="${CLIENT_DIR}/${CLIENT_NAME}.csr"
|
||||
CLIENT_CERT="${CLIENT_DIR}/${CLIENT_NAME}.crt"
|
||||
CLIENT_P12="${CLIENT_DIR}/${CLIENT_NAME}.p12"
|
||||
OPENSSL_EXT="${CLIENT_DIR}/client.ext"
|
||||
|
||||
if [[ ! -f "${CA_KEY}" || ! -f "${CA_CERT}" ]]; then
|
||||
echo "Missing CA material. Run init-mtls-ca.sh first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -d "${CLIENT_DIR}" ]]; then
|
||||
echo "Client directory already exists (${CLIENT_DIR}); refusing to overwrite."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "${CLIENT_DIR}"
|
||||
chmod 700 "${CLIENT_DIR}"
|
||||
|
||||
cat > "${OPENSSL_EXT}" <<EXT
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage = digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = clientAuth
|
||||
subjectAltName = DNS:${CLIENT_NAME}
|
||||
EXT
|
||||
|
||||
openssl genrsa -out "${CLIENT_KEY}" 2048
|
||||
chmod 600 "${CLIENT_KEY}"
|
||||
|
||||
openssl req -new -key "${CLIENT_KEY}" -subj "/CN=${CLIENT_NAME}" -out "${CLIENT_CSR}"
|
||||
|
||||
openssl x509 -req \
|
||||
-in "${CLIENT_CSR}" \
|
||||
-CA "${CA_CERT}" \
|
||||
-CAkey "${CA_KEY}" \
|
||||
-CAcreateserial \
|
||||
-out "${CLIENT_CERT}" \
|
||||
-days "${DAYS}" \
|
||||
-sha256 \
|
||||
-extfile "${OPENSSL_EXT}"
|
||||
chmod 644 "${CLIENT_CERT}"
|
||||
|
||||
openssl pkcs12 -export \
|
||||
-inkey "${CLIENT_KEY}" \
|
||||
-in "${CLIENT_CERT}" \
|
||||
-certfile "${CA_CERT}" \
|
||||
-name "${CLIENT_NAME}" \
|
||||
-out "${CLIENT_P12}"
|
||||
chmod 600 "${CLIENT_P12}"
|
||||
|
||||
rm -f "${CLIENT_CSR}" "${OPENSSL_EXT}"
|
||||
|
||||
echo "Issued client certificate for ${CLIENT_NAME}."
|
||||
echo "CRT: ${CLIENT_CERT}"
|
||||
echo "KEY: ${CLIENT_KEY}"
|
||||
echo "P12: ${CLIENT_P12}"
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Usage: $0 <client-name>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CLIENT_NAME="$1"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TRAEFIK_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
CLIENT_DIR="${TRAEFIK_ROOT}/certs/clients/${CLIENT_NAME}"
|
||||
REVOKED_DIR="${TRAEFIK_ROOT}/certs/revoked"
|
||||
|
||||
if [[ ! -d "${CLIENT_DIR}" ]]; then
|
||||
echo "No certificate directory found for client '${CLIENT_NAME}'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "${REVOKED_DIR}"
|
||||
|
||||
STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
|
||||
mv "${CLIENT_DIR}" "${REVOKED_DIR}/${CLIENT_NAME}-${STAMP}"
|
||||
|
||||
echo "Moved client certificate material to ${REVOKED_DIR}/${CLIENT_NAME}-${STAMP}."
|
||||
echo "Note: Traefik clientAuth with a CA file does not enforce revocation lists by default."
|
||||
echo "For immediate hard revocation, rotate the client CA and re-issue trusted client certificates."
|
||||
@@ -24,7 +24,16 @@ entryPoints:
|
||||
web:
|
||||
address: ":80"
|
||||
forwardedHeaders:
|
||||
insecure: true
|
||||
# Trust forwarding headers only from upstream proxies/LBs under our control.
|
||||
# Network assumptions for this stack:
|
||||
# - 127.0.0.1/32: local host-side reverse-proxy hops
|
||||
# - 192.168.2.0/24: LAN edge proxies
|
||||
# - 172.21.0.0/16: pinned Docker subnet for the traefik bridge network
|
||||
insecure: false
|
||||
trustedIPs:
|
||||
- "127.0.0.1/32"
|
||||
- "192.168.2.0/24"
|
||||
- "172.21.0.0/16"
|
||||
http:
|
||||
redirections:
|
||||
entryPoint:
|
||||
@@ -34,7 +43,11 @@ entryPoints:
|
||||
websecure:
|
||||
address: ":443"
|
||||
forwardedHeaders:
|
||||
insecure: true
|
||||
insecure: false
|
||||
trustedIPs:
|
||||
- "127.0.0.1/32"
|
||||
- "192.168.2.0/24"
|
||||
- "172.21.0.0/16"
|
||||
http:
|
||||
middlewares:
|
||||
- default-chain@file
|
||||
|
||||
+23
-3
@@ -13,6 +13,11 @@ GITEA_USER_UID=1000
|
||||
GITEA_USER_GID=1000
|
||||
GITEA_DB_TYPE=sqlite3
|
||||
GITEA_ROOT_URL=https://gitea.lan.ddnsgeek.com/
|
||||
# Generate a token in Gitea: Site Administration → Actions → Runners
|
||||
# or Repo → Settings → Actions → Runners
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN=vYDNxzMvayREkXoaAR3x3UREkxQB2PU4eORzmkZ9
|
||||
GITEA_RUNNER_NAME=docker-runner-01
|
||||
GITEA_RUNNER_LABELS=ubuntu-latest:docker://node:20-bookworm,ubuntu-22.04:docker://node:20-bookworm,linux:docker://node:20-bookworm,docker:docker://docker:cli
|
||||
|
||||
# Grafana
|
||||
GRAFANA_ROOT_URL=https://grafana.lan.ddnsgeek.com/
|
||||
@@ -39,9 +44,14 @@ PASSBOLT_APP_FULL_BASE_URL=https://passbolt.lan.ddnsgeek.com
|
||||
PASSBOLT_DATASOURCES_DEFAULT_HOST=passbolt-db
|
||||
|
||||
# Gramps
|
||||
GRAMPSWEB_LOGLEVEL=INFO
|
||||
GRAMPSWEB_MEDIAPATH=/app/media
|
||||
GRAMPSWEB_TREE=main
|
||||
GRAMPSWEB_BASE_URL=https://familytree.lan.ddnsgeek.com
|
||||
GRAMPSWEB_REGISTRATION_DISABLED=true
|
||||
GRAMPSWEB_EMAIL_HOST=smtp.gmail.com
|
||||
GRAMPSWEB_EMAIL_PORT=587
|
||||
GRAMPSWEB_EMAIL_USE_SSL=false
|
||||
GRAMPSWEB_EMAIL_USE_STARTTLS=true
|
||||
GRAMPSWEB_DEFAULT_FROM_EMAIL=beatz174@gmail.com
|
||||
|
||||
# Prometheus stack
|
||||
INFLUXDB_INIT_MODE=setup
|
||||
@@ -61,4 +71,14 @@ PORTAINER_GODEBUG=netdns=cgo
|
||||
|
||||
# Node-red
|
||||
DOCKER_SOCKET_PROXY_HOST=tcp://docker-socket-proxy:2375
|
||||
DOCKER_SOCKET_PROXY_LOG_LEVEL=debug
|
||||
DOCKER_SOCKET_PROXY_LOG_LEVEL=info
|
||||
NODE_COMPOSE_ROOT=/compose
|
||||
|
||||
# mTLS bridge
|
||||
MTLS_BRIDGE_LOG_LEVEL=DEBUG
|
||||
MTLS_BRIDGE_TIMEOUT=5
|
||||
MTLS_BRIDGE_CLIENT_KEY=/certs/clients/office-pc/office-pc.key
|
||||
MTLS_BRIDGE_CLIENT_CERT=/certs/clients/office-pc/office-pc.crt
|
||||
MTLS_BRIDGE_TARGET_URL=http://node-red:1880
|
||||
MTLS_BRIDGE_ALLOWED_PATHS_FILE=
|
||||
MTLS_BRIDGE_CORS_ALLOW_ORIGIN=https://grafana.lan.ddnsgeek.com
|
||||
|
||||
+3
-1
@@ -1,5 +1,7 @@
|
||||
networks:
|
||||
traefik:
|
||||
driver: bridge
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.21.0.0/16
|
||||
monitor:
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# Generated Documentation
|
||||
|
||||
## Local generation
|
||||
|
||||
Install prerequisites:
|
||||
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y graphviz
|
||||
```
|
||||
|
||||
Then generate and validate public docs:
|
||||
|
||||
```bash
|
||||
chmod +x scripts/docs/*.sh
|
||||
scripts/docs/generate-all.sh
|
||||
python3 -m mkdocs build -f mkdocs-public.yml --strict
|
||||
```
|
||||
|
||||
NixOS-friendly alternative:
|
||||
|
||||
```bash
|
||||
nix shell nixpkgs#graphviz nixpkgs#python3 nixpkgs#python3Packages.pyyaml
|
||||
```
|
||||
|
||||
This pipeline only runs `docker compose config` and static parsing. It does **not** start containers.
|
||||
|
||||
## CI behaviour
|
||||
|
||||
GitHub Actions workflow `.github/workflows/generate-docs.yml` validates committed public docs and diagrams and runs a strict public MkDocs build.
|
||||
|
||||
## Outputs
|
||||
|
||||
- `docs/generated`: resolved compose config and markdown inventories
|
||||
- `docs/diagrams`: generated DOT and SVG diagrams
|
||||
- `docs/public`: sanitized copy for public sharing
|
||||
|
||||
## Publication safety
|
||||
|
||||
- `docs/public` is intended for public sharing after sanitization.
|
||||
- `docs/generated` and `docs/diagrams` may include internal details and should be treated as internal by default.
|
||||
@@ -0,0 +1,72 @@
|
||||
# Ansible Workflows (Bootstrap / Phase 1)
|
||||
|
||||
Ansible is being introduced as a minimal, maintainable foundation for host/device inventory and future configuration workflows.
|
||||
|
||||
## Why introduce Ansible now
|
||||
|
||||
- The repository already has strong runtime and infrastructure boundaries (Compose + Terraform).
|
||||
- A small Ansible baseline allows gradual host onboarding without forcing immediate large-scale automation.
|
||||
- It enables safe validation workflows (`inventory --list`, playbook syntax checks) before real execution.
|
||||
|
||||
## What Ansible is for in this repository (right now)
|
||||
|
||||
- YAML inventory structure for hosts/devices to be onboarded over time.
|
||||
- Group and host variable scaffolding for future incremental adoption.
|
||||
- Validation-oriented starter playbook and local tooling checks.
|
||||
|
||||
## What Ansible is not for yet
|
||||
|
||||
- Replacing Docker Compose runtime authority.
|
||||
- Replacing Terraform inventory/reconciliation authority.
|
||||
- Becoming the current source of truth for NixOS host management.
|
||||
- Becoming the current source of truth for all network automation.
|
||||
|
||||
## Directory layout
|
||||
|
||||
- `infrastructure/ansible/ansible.cfg`
|
||||
- `infrastructure/ansible/inventory/hosts.yml`
|
||||
- `infrastructure/ansible/inventory/group_vars/`
|
||||
- `infrastructure/ansible/inventory/host_vars/`
|
||||
- `infrastructure/ansible/playbooks/ping.yml`
|
||||
- `infrastructure/ansible/collections/requirements.yml`
|
||||
|
||||
## Add a host (gradual onboarding)
|
||||
|
||||
1. Open `infrastructure/ansible/inventory/hosts.yml`.
|
||||
2. Add the host under an appropriate group (`linux`, `network`, `virtualization`, or `nixos`).
|
||||
3. Add non-sensitive defaults under group vars only when shared across hosts.
|
||||
4. Add host-specific values in `inventory/host_vars/<hostname>.yml`.
|
||||
5. Keep secrets out of committed files.
|
||||
|
||||
Example pattern:
|
||||
|
||||
```yaml
|
||||
linux:
|
||||
hosts:
|
||||
my-host:
|
||||
ansible_host: my-host.local
|
||||
```
|
||||
|
||||
## Validation commands
|
||||
|
||||
Run from repository root:
|
||||
|
||||
```bash
|
||||
ansible --version
|
||||
ansible-lint --version
|
||||
ansible-inventory -i infrastructure/ansible/inventory/hosts.yml --list
|
||||
ansible-playbook -i infrastructure/ansible/inventory/hosts.yml infrastructure/ansible/playbooks/ping.yml --syntax-check
|
||||
```
|
||||
|
||||
Install/update baseline collections:
|
||||
|
||||
```bash
|
||||
ansible-galaxy collection install -r infrastructure/ansible/collections/requirements.yml -p infrastructure/ansible/collections
|
||||
```
|
||||
|
||||
## Guardrails for future expansion
|
||||
|
||||
- Keep changes incremental (one host/group/playbook change at a time).
|
||||
- Prefer simple playbooks before introducing roles.
|
||||
- Add network-platform/NixOS-specific logic only when those boundaries are explicitly adopted.
|
||||
- Keep documentation aligned with source-of-truth boundaries when Ansible authority evolves.
|
||||
@@ -0,0 +1,95 @@
|
||||
# Architecture Summary
|
||||
|
||||
## Overview
|
||||
|
||||
This stack uses **Traefik v3** as internet-facing ingress for application and operations UIs. Service routing is label-driven from Docker Compose files, with shared Docker networks (`traefik`, `monitor`) connecting reverse-proxied and telemetry services.
|
||||
|
||||
TLS is terminated at Traefik (ACME HTTP challenge), with hardening via middleware chains, Authelia forward-auth for selected routes, CrowdSec integration, and mTLS options for private-admin paths.
|
||||
|
||||
## Network / Request Flow
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
C[Internet Client] -->|80/443| T[Traefik Ingress]
|
||||
T -->|HTTP->HTTPS redirect| T
|
||||
T -->|ACME HTTP challenge| LE[Let's Encrypt ACME]
|
||||
|
||||
subgraph TraefikNet[Docker network: traefik]
|
||||
A[Authelia]
|
||||
CS[CrowdSec LAPI]
|
||||
EP[Error Pages]
|
||||
|
||||
NC[Nextcloud]
|
||||
PB[Passbolt]
|
||||
GT[Gitea]
|
||||
GW[Gramps Web]
|
||||
SX[SearXNG]
|
||||
|
||||
GF[Grafana]
|
||||
PR[Prometheus]
|
||||
NR[Node-RED]
|
||||
PT[Portainer]
|
||||
UK[Uptime Kuma]
|
||||
IF[InfluxDB]
|
||||
GO[Gotify]
|
||||
end
|
||||
|
||||
T -->|forwardAuth for selected services| A
|
||||
T -->|plugin decisions| CS
|
||||
T -->|4xx/5xx middleware| EP
|
||||
|
||||
T --> NC
|
||||
T --> PB
|
||||
T --> GT
|
||||
T --> GW
|
||||
T --> SX
|
||||
|
||||
T --> GF
|
||||
T --> PR
|
||||
T --> NR
|
||||
T --> PT
|
||||
T --> UK
|
||||
T --> IF
|
||||
T --> GO
|
||||
|
||||
subgraph MonitorNet[Docker network: monitor]
|
||||
NE[Node Exporter]
|
||||
TE[Telegraf]
|
||||
DE[Docker Update Exporter]
|
||||
PE[Pi-hole Exporter]
|
||||
DSP[Docker Socket Proxy]
|
||||
end
|
||||
|
||||
PR --> NE
|
||||
PR --> TE
|
||||
PR --> DE
|
||||
PR --> PE
|
||||
PR --> UK
|
||||
PR -->|remote scrape| RH[Remote Hosts]
|
||||
TE --> DSP
|
||||
NR --> DSP
|
||||
PT --> DSP
|
||||
T --> DSP
|
||||
```
|
||||
|
||||
## Key components
|
||||
|
||||
- **Ingress/security plane:** Traefik, Authelia, CrowdSec, Error Pages.
|
||||
- **User-facing apps:** Nextcloud, Passbolt, Gitea, Gramps Web, SearXNG.
|
||||
- **Monitoring/ops:** Prometheus, Grafana, InfluxDB, Node-RED, Uptime Kuma, Portainer, Gotify.
|
||||
- **Support plane:** Docker Socket Proxy for controlled Docker API access.
|
||||
|
||||
## Relationship to Terraform inventory
|
||||
|
||||
Terraform in `infrastructure/terraform/` captures infrastructure inventory and reconciliation state for Proxmox VMs, physical host metadata, and selected Docker mirrors.
|
||||
|
||||
Use architecture docs together with:
|
||||
|
||||
- [docs/source-of-truth.md](source-of-truth.md)
|
||||
- [docs/terraform-workflows.md](terraform-workflows.md)
|
||||
- [docs/infrastructure-inventory.md](infrastructure-inventory.md)
|
||||
- [docs/generated/host-topology.md](generated/host-topology.md)
|
||||
|
||||
## Notes on runtime vs declared state
|
||||
|
||||
Runtime scrape targets and health signals are useful observed-state inputs, but they do not replace declared config authority from Compose/Terraform sources.
|
||||
@@ -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.
|
||||
@@ -0,0 +1,49 @@
|
||||
# Deployment Prerequisites
|
||||
|
||||
Before running compose operations, provision local secret material.
|
||||
|
||||
## 1) Create non-committed secret env file
|
||||
|
||||
```bash
|
||||
cp secrets/.env.secrets.example secrets/stack-secrets.env
|
||||
chmod 600 secrets/stack-secrets.env
|
||||
```
|
||||
|
||||
## 2) Create required Docker secret files
|
||||
|
||||
All files below are expected locally and are gitignored:
|
||||
|
||||
- `secrets/nextcloud_db_root_password.txt`
|
||||
- `secrets/nextcloud_db_password.txt`
|
||||
- `secrets/nextcloud_admin_password.txt`
|
||||
- `secrets/nextcloud_smtp_password.txt`
|
||||
- `secrets/nextcloud_redis_password.txt`
|
||||
- `secrets/passbolt_db_password.txt`
|
||||
- `secrets/influxdb_init_password.txt`
|
||||
- `secrets/prometheus_kuma_basic_auth_password.txt`
|
||||
|
||||
Recommended permissions:
|
||||
|
||||
```bash
|
||||
chmod 600 secrets/*.txt
|
||||
```
|
||||
|
||||
## 3) Validate composed configuration
|
||||
|
||||
Use the repository composition entrypoint:
|
||||
|
||||
```bash
|
||||
./services-up.sh --profile all config
|
||||
```
|
||||
|
||||
This confirms compose rendering with shared env/network inputs before any runtime operation.
|
||||
|
||||
## 4) Rotate previously committed credentials
|
||||
|
||||
If migrating from older states where secrets were committed, rotate upstream values immediately (DB credentials, app passwords, auth keys, and API tokens).
|
||||
|
||||
## Related docs
|
||||
|
||||
- [`./security-secrets.md`](./security-secrets.md)
|
||||
- [`./docker-environment.md`](./docker-environment.md)
|
||||
- [`./source-of-truth.md`](./source-of-truth.md)
|
||||
@@ -0,0 +1,75 @@
|
||||
digraph Compose {
|
||||
rankdir=LR;
|
||||
node [fontname="Helvetica"];
|
||||
"svc:authelia" [label="authelia", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:crowdsec" [label="crowdsec", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:docker-socket-proxy" [label="docker-socket-proxy", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:docker-update-exporter" [label="docker-update-exporter", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:error-pages" [label="error-pages", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:gitea" [label="gitea", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:gitea-runner" [label="gitea-runner", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:gotify" [label="gotify", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:grafana" [label="grafana", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:gramps-redis" [label="gramps-redis", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:grampsweb" [label="grampsweb", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:grampsweb_celery" [label="grampsweb_celery", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:influxdb" [label="influxdb", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:monitor-kuma" [label="monitor-kuma", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:mtls-bridge" [label="mtls-bridge", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:nextcloud-db" [label="nextcloud-db", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:nextcloud-redis" [label="nextcloud-redis", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:nextcloud-webapp" [label="nextcloud-webapp", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:node-exporter" [label="node-exporter", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:node-red" [label="node-red", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:passbolt-db" [label="passbolt-db", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:passbolt-webapp" [label="passbolt-webapp", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:pihole-exporter" [label="pihole-exporter", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:portainer" [label="portainer", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:prometheus" [label="prometheus", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:searxng-webapp" [label="searxng-webapp", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:telegraf" [label="telegraf", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"svc:traefik" [label="traefik", shape=box, style=filled, fillcolor="#dfefff"];
|
||||
"net:gramps" [label="gramps", shape=ellipse, style=filled, fillcolor="#f4f4f4"];
|
||||
"net:monitor" [label="monitor", shape=ellipse, style=filled, fillcolor="#f4f4f4"];
|
||||
"net:nextcloud" [label="nextcloud", shape=ellipse, style=filled, fillcolor="#f4f4f4"];
|
||||
"net:passbolt" [label="passbolt", shape=ellipse, style=filled, fillcolor="#f4f4f4"];
|
||||
"net:traefik" [label="traefik", shape=ellipse, style=filled, fillcolor="#f4f4f4"];
|
||||
"svc:authelia" -> "net:traefik";
|
||||
"svc:crowdsec" -> "net:traefik";
|
||||
"svc:docker-socket-proxy" -> "net:monitor";
|
||||
"svc:docker-socket-proxy" -> "net:traefik";
|
||||
"svc:docker-update-exporter" -> "net:monitor";
|
||||
"svc:error-pages" -> "net:traefik";
|
||||
"svc:gitea" -> "net:traefik";
|
||||
"svc:gitea-runner" -> "net:traefik";
|
||||
"svc:gotify" -> "net:traefik";
|
||||
"svc:grafana" -> "net:monitor";
|
||||
"svc:grafana" -> "net:traefik";
|
||||
"svc:gramps-redis" -> "net:gramps";
|
||||
"svc:grampsweb" -> "net:gramps";
|
||||
"svc:grampsweb" -> "net:traefik";
|
||||
"svc:grampsweb_celery" -> "net:gramps";
|
||||
"svc:influxdb" -> "net:monitor";
|
||||
"svc:influxdb" -> "net:traefik";
|
||||
"svc:monitor-kuma" -> "net:monitor";
|
||||
"svc:monitor-kuma" -> "net:traefik";
|
||||
"svc:mtls-bridge" -> "net:monitor";
|
||||
"svc:mtls-bridge" -> "net:traefik";
|
||||
"svc:nextcloud-db" -> "net:nextcloud";
|
||||
"svc:nextcloud-redis" -> "net:nextcloud";
|
||||
"svc:nextcloud-webapp" -> "net:nextcloud";
|
||||
"svc:nextcloud-webapp" -> "net:traefik";
|
||||
"svc:node-exporter" -> "net:monitor";
|
||||
"svc:node-red" -> "net:monitor";
|
||||
"svc:node-red" -> "net:traefik";
|
||||
"svc:passbolt-db" -> "net:passbolt";
|
||||
"svc:passbolt-webapp" -> "net:passbolt";
|
||||
"svc:passbolt-webapp" -> "net:traefik";
|
||||
"svc:pihole-exporter" -> "net:monitor";
|
||||
"svc:portainer" -> "net:traefik";
|
||||
"svc:prometheus" -> "net:monitor";
|
||||
"svc:prometheus" -> "net:traefik";
|
||||
"svc:searxng-webapp" -> "net:traefik";
|
||||
"svc:telegraf" -> "net:monitor";
|
||||
"svc:traefik" -> "net:traefik";
|
||||
}
|
||||
@@ -0,0 +1,439 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.43.0 (0)
|
||||
-->
|
||||
<!-- Title: Compose Pages: 1 -->
|
||||
<svg width="334pt" height="1502pt"
|
||||
viewBox="0.00 0.00 334.49 1502.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1498)">
|
||||
<title>Compose</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-1498 330.49,-1498 330.49,4 -4,4"/>
|
||||
<!-- svc:authelia -->
|
||||
<g id="node1" class="node">
|
||||
<title>svc:authelia</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="126,-738 54,-738 54,-702 126,-702 126,-738"/>
|
||||
<text text-anchor="middle" x="90" y="-716.3" font-family="Helvetica,sans-Serif" font-size="14.00">authelia</text>
|
||||
</g>
|
||||
<!-- net:traefik -->
|
||||
<g id="node33" class="node">
|
||||
<title>net:traefik</title>
|
||||
<ellipse fill="#f4f4f4" stroke="black" cx="271.25" cy="-774" rx="40.09" ry="18"/>
|
||||
<text text-anchor="middle" x="271.25" y="-770.3" font-family="Helvetica,sans-Serif" font-size="14.00">traefik</text>
|
||||
</g>
|
||||
<!-- svc:authelia->net:traefik -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>svc:authelia->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M126.41,-730.67C155.5,-739.43 196.8,-751.87 227.69,-761.18"/>
|
||||
<polygon fill="black" stroke="black" points="226.74,-764.55 237.32,-764.08 228.76,-757.85 226.74,-764.55"/>
|
||||
</g>
|
||||
<!-- svc:crowdsec -->
|
||||
<g id="node2" class="node">
|
||||
<title>svc:crowdsec</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="130.5,-684 49.5,-684 49.5,-648 130.5,-648 130.5,-684"/>
|
||||
<text text-anchor="middle" x="90" y="-662.3" font-family="Helvetica,sans-Serif" font-size="14.00">crowdsec</text>
|
||||
</g>
|
||||
<!-- svc:crowdsec->net:traefik -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>svc:crowdsec->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M130.61,-674.06C146.59,-678.3 164.81,-684.44 180,-693 206.25,-707.78 231.35,-731.35 248.38,-749.26"/>
|
||||
<polygon fill="black" stroke="black" points="246.24,-752.1 255.62,-757.03 251.37,-747.33 246.24,-752.1"/>
|
||||
</g>
|
||||
<!-- svc:docker-socket-proxy -->
|
||||
<g id="node3" class="node">
|
||||
<title>svc:docker-socket-proxy</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="167.5,-954 12.5,-954 12.5,-918 167.5,-918 167.5,-954"/>
|
||||
<text text-anchor="middle" x="90" y="-932.3" font-family="Helvetica,sans-Serif" font-size="14.00">docker-socket-proxy</text>
|
||||
</g>
|
||||
<!-- net:monitor -->
|
||||
<g id="node30" class="node">
|
||||
<title>net:monitor</title>
|
||||
<ellipse fill="#f4f4f4" stroke="black" cx="271.25" cy="-1206" rx="46.29" ry="18"/>
|
||||
<text text-anchor="middle" x="271.25" y="-1202.3" font-family="Helvetica,sans-Serif" font-size="14.00">monitor</text>
|
||||
</g>
|
||||
<!-- svc:docker-socket-proxy->net:monitor -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>svc:docker-socket-proxy->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M167.53,-953.71C172.02,-956.38 176.24,-959.46 180,-963 242.3,-1021.6 261.83,-1127.12 267.77,-1177.6"/>
|
||||
<polygon fill="black" stroke="black" points="264.31,-1178.21 268.86,-1187.78 271.27,-1177.46 264.31,-1178.21"/>
|
||||
</g>
|
||||
<!-- svc:docker-socket-proxy->net:traefik -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>svc:docker-socket-proxy->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M165.31,-917.9C170.5,-915.32 175.46,-912.37 180,-909 218.01,-880.82 244.97,-831.56 259.03,-800.98"/>
|
||||
<polygon fill="black" stroke="black" points="262.27,-802.31 263.14,-791.76 255.87,-799.46 262.27,-802.31"/>
|
||||
</g>
|
||||
<!-- svc:docker-update-exporter -->
|
||||
<g id="node4" class="node">
|
||||
<title>svc:docker-update-exporter</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="180,-1494 0,-1494 0,-1458 180,-1458 180,-1494"/>
|
||||
<text text-anchor="middle" x="90" y="-1472.3" font-family="Helvetica,sans-Serif" font-size="14.00">docker-update-exporter</text>
|
||||
</g>
|
||||
<!-- svc:docker-update-exporter->net:monitor -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>svc:docker-update-exporter->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M168.37,-1457.79C172.55,-1455.23 176.47,-1452.32 180,-1449 242.3,-1390.4 261.83,-1284.88 267.77,-1234.4"/>
|
||||
<polygon fill="black" stroke="black" points="271.27,-1234.54 268.86,-1224.22 264.31,-1233.79 271.27,-1234.54"/>
|
||||
</g>
|
||||
<!-- svc:error-pages -->
|
||||
<g id="node5" class="node">
|
||||
<title>svc:error-pages</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="137.5,-630 42.5,-630 42.5,-594 137.5,-594 137.5,-630"/>
|
||||
<text text-anchor="middle" x="90" y="-608.3" font-family="Helvetica,sans-Serif" font-size="14.00">error-pages</text>
|
||||
</g>
|
||||
<!-- svc:error-pages->net:traefik -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>svc:error-pages->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M137.71,-619.76C152.25,-623.79 167.68,-629.86 180,-639 218.01,-667.18 244.97,-716.44 259.03,-747.02"/>
|
||||
<polygon fill="black" stroke="black" points="255.87,-748.54 263.14,-756.24 262.27,-745.69 255.87,-748.54"/>
|
||||
</g>
|
||||
<!-- svc:gitea -->
|
||||
<g id="node6" class="node">
|
||||
<title>svc:gitea</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="117,-576 63,-576 63,-540 117,-540 117,-576"/>
|
||||
<text text-anchor="middle" x="90" y="-554.3" font-family="Helvetica,sans-Serif" font-size="14.00">gitea</text>
|
||||
</g>
|
||||
<!-- svc:gitea->net:traefik -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>svc:gitea->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M117.07,-560.28C136.41,-563.2 162.37,-569.85 180,-585 229.98,-627.95 254.42,-704.8 264.44,-746.04"/>
|
||||
<polygon fill="black" stroke="black" points="261.07,-747 266.73,-755.95 267.88,-745.42 261.07,-747"/>
|
||||
</g>
|
||||
<!-- svc:gitea-runner -->
|
||||
<g id="node7" class="node">
|
||||
<title>svc:gitea-runner</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="142,-522 38,-522 38,-486 142,-486 142,-522"/>
|
||||
<text text-anchor="middle" x="90" y="-500.3" font-family="Helvetica,sans-Serif" font-size="14.00">gitea-runner</text>
|
||||
</g>
|
||||
<!-- svc:gitea-runner->net:traefik -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>svc:gitea-runner->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M142.31,-511.04C155.9,-515.03 169.65,-521.26 180,-531 242.3,-589.6 261.83,-695.12 267.77,-745.6"/>
|
||||
<polygon fill="black" stroke="black" points="264.31,-746.21 268.86,-755.78 271.27,-745.46 264.31,-746.21"/>
|
||||
</g>
|
||||
<!-- svc:gotify -->
|
||||
<g id="node8" class="node">
|
||||
<title>svc:gotify</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="118,-468 62,-468 62,-432 118,-432 118,-468"/>
|
||||
<text text-anchor="middle" x="90" y="-446.3" font-family="Helvetica,sans-Serif" font-size="14.00">gotify</text>
|
||||
</g>
|
||||
<!-- svc:gotify->net:traefik -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>svc:gotify->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M118.17,-451.6C137.81,-454.16 163.67,-460.68 180,-477 254.99,-551.96 268.02,-687.13 270.03,-745.69"/>
|
||||
<polygon fill="black" stroke="black" points="266.53,-745.79 270.29,-755.69 273.53,-745.61 266.53,-745.79"/>
|
||||
</g>
|
||||
<!-- svc:grafana -->
|
||||
<g id="node9" class="node">
|
||||
<title>svc:grafana</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="125.5,-1278 54.5,-1278 54.5,-1242 125.5,-1242 125.5,-1278"/>
|
||||
<text text-anchor="middle" x="90" y="-1256.3" font-family="Helvetica,sans-Serif" font-size="14.00">grafana</text>
|
||||
</g>
|
||||
<!-- svc:grafana->net:monitor -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>svc:grafana->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M125.56,-1249.59C153.74,-1241.1 193.78,-1229.04 224.6,-1219.75"/>
|
||||
<polygon fill="black" stroke="black" points="225.69,-1223.08 234.26,-1216.84 223.67,-1216.38 225.69,-1223.08"/>
|
||||
</g>
|
||||
<!-- svc:grafana->net:traefik -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>svc:grafana->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M125.54,-1257.93C144.23,-1254.97 166.25,-1248.21 180,-1233 238.17,-1168.67 262.1,-892.17 268.43,-802.32"/>
|
||||
<polygon fill="black" stroke="black" points="271.93,-802.3 269.13,-792.08 264.95,-801.82 271.93,-802.3"/>
|
||||
</g>
|
||||
<!-- svc:gramps-redis -->
|
||||
<g id="node10" class="node">
|
||||
<title>svc:gramps-redis</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="144.5,-360 35.5,-360 35.5,-324 144.5,-324 144.5,-360"/>
|
||||
<text text-anchor="middle" x="90" y="-338.3" font-family="Helvetica,sans-Serif" font-size="14.00">gramps-redis</text>
|
||||
</g>
|
||||
<!-- net:gramps -->
|
||||
<g id="node29" class="node">
|
||||
<title>net:gramps</title>
|
||||
<ellipse fill="#f4f4f4" stroke="black" cx="271.25" cy="-342" rx="45.49" ry="18"/>
|
||||
<text text-anchor="middle" x="271.25" y="-338.3" font-family="Helvetica,sans-Serif" font-size="14.00">gramps</text>
|
||||
</g>
|
||||
<!-- svc:gramps-redis->net:gramps -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>svc:gramps-redis->net:gramps</title>
|
||||
<path fill="none" stroke="black" d="M144.78,-342C167.14,-342 193.05,-342 215.51,-342"/>
|
||||
<polygon fill="black" stroke="black" points="215.56,-345.5 225.56,-342 215.56,-338.5 215.56,-345.5"/>
|
||||
</g>
|
||||
<!-- svc:grampsweb -->
|
||||
<g id="node11" class="node">
|
||||
<title>svc:grampsweb</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="139,-414 41,-414 41,-378 139,-378 139,-414"/>
|
||||
<text text-anchor="middle" x="90" y="-392.3" font-family="Helvetica,sans-Serif" font-size="14.00">grampsweb</text>
|
||||
</g>
|
||||
<!-- svc:grampsweb->net:gramps -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>svc:grampsweb->net:gramps</title>
|
||||
<path fill="none" stroke="black" d="M139.03,-381.53C165.7,-373.5 198.68,-363.56 224.9,-355.66"/>
|
||||
<polygon fill="black" stroke="black" points="226.03,-358.98 234.59,-352.74 224.01,-352.27 226.03,-358.98"/>
|
||||
</g>
|
||||
<!-- svc:grampsweb->net:traefik -->
|
||||
<g id="edge14" class="edge">
|
||||
<title>svc:grampsweb->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M139.27,-401.34C154.08,-405.21 169.28,-411.81 180,-423 225.12,-470.09 256.34,-671.08 266.59,-745.84"/>
|
||||
<polygon fill="black" stroke="black" points="263.14,-746.48 267.95,-755.92 270.08,-745.55 263.14,-746.48"/>
|
||||
</g>
|
||||
<!-- svc:grampsweb_celery -->
|
||||
<g id="node12" class="node">
|
||||
<title>svc:grampsweb_celery</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="163.5,-306 16.5,-306 16.5,-270 163.5,-270 163.5,-306"/>
|
||||
<text text-anchor="middle" x="90" y="-284.3" font-family="Helvetica,sans-Serif" font-size="14.00">grampsweb_celery</text>
|
||||
</g>
|
||||
<!-- svc:grampsweb_celery->net:gramps -->
|
||||
<g id="edge15" class="edge">
|
||||
<title>svc:grampsweb_celery->net:gramps</title>
|
||||
<path fill="none" stroke="black" d="M151.18,-306.13C175.28,-313.39 202.57,-321.61 224.94,-328.35"/>
|
||||
<polygon fill="black" stroke="black" points="223.94,-331.71 234.52,-331.24 225.96,-325 223.94,-331.71"/>
|
||||
</g>
|
||||
<!-- svc:influxdb -->
|
||||
<g id="node13" class="node">
|
||||
<title>svc:influxdb</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="127,-1224 53,-1224 53,-1188 127,-1188 127,-1224"/>
|
||||
<text text-anchor="middle" x="90" y="-1202.3" font-family="Helvetica,sans-Serif" font-size="14.00">influxdb</text>
|
||||
</g>
|
||||
<!-- svc:influxdb->net:monitor -->
|
||||
<g id="edge16" class="edge">
|
||||
<title>svc:influxdb->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M127.27,-1206C152.33,-1206 186.13,-1206 214.57,-1206"/>
|
||||
<polygon fill="black" stroke="black" points="214.79,-1209.5 224.79,-1206 214.79,-1202.5 214.79,-1209.5"/>
|
||||
</g>
|
||||
<!-- svc:influxdb->net:traefik -->
|
||||
<g id="edge17" class="edge">
|
||||
<title>svc:influxdb->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M127.17,-1203.5C145.42,-1200.36 166.5,-1193.56 180,-1179 231.57,-1123.4 259.36,-885.3 267.6,-802.51"/>
|
||||
<polygon fill="black" stroke="black" points="271.1,-802.62 268.59,-792.33 264.14,-801.94 271.1,-802.62"/>
|
||||
</g>
|
||||
<!-- svc:monitor-kuma -->
|
||||
<g id="node14" class="node">
|
||||
<title>svc:monitor-kuma</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="146.5,-1170 33.5,-1170 33.5,-1134 146.5,-1134 146.5,-1170"/>
|
||||
<text text-anchor="middle" x="90" y="-1148.3" font-family="Helvetica,sans-Serif" font-size="14.00">monitor-kuma</text>
|
||||
</g>
|
||||
<!-- svc:monitor-kuma->net:monitor -->
|
||||
<g id="edge18" class="edge">
|
||||
<title>svc:monitor-kuma->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M146.73,-1168.79C171.73,-1176.32 200.85,-1185.1 224.54,-1192.23"/>
|
||||
<polygon fill="black" stroke="black" points="223.75,-1195.65 234.33,-1195.18 225.77,-1188.94 223.75,-1195.65"/>
|
||||
</g>
|
||||
<!-- svc:monitor-kuma->net:traefik -->
|
||||
<g id="edge19" class="edge">
|
||||
<title>svc:monitor-kuma->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M146.69,-1144.49C159.02,-1140.46 171.06,-1134.33 180,-1125 225.12,-1077.91 256.34,-876.92 266.59,-802.16"/>
|
||||
<polygon fill="black" stroke="black" points="270.08,-802.45 267.95,-792.08 263.14,-801.52 270.08,-802.45"/>
|
||||
</g>
|
||||
<!-- svc:mtls-bridge -->
|
||||
<g id="node15" class="node">
|
||||
<title>svc:mtls-bridge</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="138.5,-1116 41.5,-1116 41.5,-1080 138.5,-1080 138.5,-1116"/>
|
||||
<text text-anchor="middle" x="90" y="-1094.3" font-family="Helvetica,sans-Serif" font-size="14.00">mtls-bridge</text>
|
||||
</g>
|
||||
<!-- svc:mtls-bridge->net:monitor -->
|
||||
<g id="edge20" class="edge">
|
||||
<title>svc:mtls-bridge->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M138.76,-1108.34C152.58,-1112.41 167.34,-1117.87 180,-1125 206.25,-1139.78 231.35,-1163.35 248.38,-1181.26"/>
|
||||
<polygon fill="black" stroke="black" points="246.24,-1184.1 255.62,-1189.03 251.37,-1179.33 246.24,-1184.1"/>
|
||||
</g>
|
||||
<!-- svc:mtls-bridge->net:traefik -->
|
||||
<g id="edge21" class="edge">
|
||||
<title>svc:mtls-bridge->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M138.53,-1092.51C153.46,-1088.63 168.92,-1082.07 180,-1071 254.99,-996.04 268.02,-860.87 270.03,-802.31"/>
|
||||
<polygon fill="black" stroke="black" points="273.53,-802.39 270.29,-792.31 266.53,-802.21 273.53,-802.39"/>
|
||||
</g>
|
||||
<!-- svc:nextcloud-db -->
|
||||
<g id="node16" class="node">
|
||||
<title>svc:nextcloud-db</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="144,-90 36,-90 36,-54 144,-54 144,-90"/>
|
||||
<text text-anchor="middle" x="90" y="-68.3" font-family="Helvetica,sans-Serif" font-size="14.00">nextcloud-db</text>
|
||||
</g>
|
||||
<!-- net:nextcloud -->
|
||||
<g id="node31" class="node">
|
||||
<title>net:nextcloud</title>
|
||||
<ellipse fill="#f4f4f4" stroke="black" cx="271.25" cy="-180" rx="55.49" ry="18"/>
|
||||
<text text-anchor="middle" x="271.25" y="-176.3" font-family="Helvetica,sans-Serif" font-size="14.00">nextcloud</text>
|
||||
</g>
|
||||
<!-- svc:nextcloud-db->net:nextcloud -->
|
||||
<g id="edge22" class="edge">
|
||||
<title>svc:nextcloud-db->net:nextcloud</title>
|
||||
<path fill="none" stroke="black" d="M144.33,-84.04C156.48,-87.9 169.03,-92.82 180,-99 206.09,-113.7 231.04,-137.06 248.07,-154.93"/>
|
||||
<polygon fill="black" stroke="black" points="245.93,-157.77 255.31,-162.7 251.06,-153 245.93,-157.77"/>
|
||||
</g>
|
||||
<!-- svc:nextcloud-redis -->
|
||||
<g id="node17" class="node">
|
||||
<title>svc:nextcloud-redis</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="152,-198 28,-198 28,-162 152,-162 152,-198"/>
|
||||
<text text-anchor="middle" x="90" y="-176.3" font-family="Helvetica,sans-Serif" font-size="14.00">nextcloud-redis</text>
|
||||
</g>
|
||||
<!-- svc:nextcloud-redis->net:nextcloud -->
|
||||
<g id="edge23" class="edge">
|
||||
<title>svc:nextcloud-redis->net:nextcloud</title>
|
||||
<path fill="none" stroke="black" d="M152.18,-180C169.48,-180 188.35,-180 205.83,-180"/>
|
||||
<polygon fill="black" stroke="black" points="205.94,-183.5 215.94,-180 205.94,-176.5 205.94,-183.5"/>
|
||||
</g>
|
||||
<!-- svc:nextcloud-webapp -->
|
||||
<g id="node18" class="node">
|
||||
<title>svc:nextcloud-webapp</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="162.5,-252 17.5,-252 17.5,-216 162.5,-216 162.5,-252"/>
|
||||
<text text-anchor="middle" x="90" y="-230.3" font-family="Helvetica,sans-Serif" font-size="14.00">nextcloud-webapp</text>
|
||||
</g>
|
||||
<!-- svc:nextcloud-webapp->net:nextcloud -->
|
||||
<g id="edge24" class="edge">
|
||||
<title>svc:nextcloud-webapp->net:nextcloud</title>
|
||||
<path fill="none" stroke="black" d="M151.18,-215.87C173.57,-209.12 198.72,-201.55 220.11,-195.1"/>
|
||||
<polygon fill="black" stroke="black" points="221.4,-198.37 229.97,-192.13 219.38,-191.67 221.4,-198.37"/>
|
||||
</g>
|
||||
<!-- svc:nextcloud-webapp->net:traefik -->
|
||||
<g id="edge25" class="edge">
|
||||
<title>svc:nextcloud-webapp->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M162.89,-247.71C169.31,-251.2 175.18,-255.56 180,-261 212.66,-297.85 255.07,-643.36 267,-745.62"/>
|
||||
<polygon fill="black" stroke="black" points="263.55,-746.27 268.18,-755.8 270.51,-745.47 263.55,-746.27"/>
|
||||
</g>
|
||||
<!-- svc:node-exporter -->
|
||||
<g id="node19" class="node">
|
||||
<title>svc:node-exporter</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="148,-1440 32,-1440 32,-1404 148,-1404 148,-1440"/>
|
||||
<text text-anchor="middle" x="90" y="-1418.3" font-family="Helvetica,sans-Serif" font-size="14.00">node-exporter</text>
|
||||
</g>
|
||||
<!-- svc:node-exporter->net:monitor -->
|
||||
<g id="edge26" class="edge">
|
||||
<title>svc:node-exporter->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M148.25,-1412.27C159.68,-1408.33 170.94,-1402.79 180,-1395 229.98,-1352.05 254.42,-1275.2 264.44,-1233.96"/>
|
||||
<polygon fill="black" stroke="black" points="267.88,-1234.58 266.73,-1224.05 261.07,-1233 267.88,-1234.58"/>
|
||||
</g>
|
||||
<!-- svc:node-red -->
|
||||
<g id="node20" class="node">
|
||||
<title>svc:node-red</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="129.5,-1062 50.5,-1062 50.5,-1026 129.5,-1026 129.5,-1062"/>
|
||||
<text text-anchor="middle" x="90" y="-1040.3" font-family="Helvetica,sans-Serif" font-size="14.00">node-red</text>
|
||||
</g>
|
||||
<!-- svc:node-red->net:monitor -->
|
||||
<g id="edge27" class="edge">
|
||||
<title>svc:node-red->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M129.57,-1049.69C146.29,-1053.6 165.34,-1060.13 180,-1071 218.01,-1099.18 244.97,-1148.44 259.03,-1179.02"/>
|
||||
<polygon fill="black" stroke="black" points="255.87,-1180.54 263.14,-1188.24 262.27,-1177.69 255.87,-1180.54"/>
|
||||
</g>
|
||||
<!-- svc:node-red->net:traefik -->
|
||||
<g id="edge28" class="edge">
|
||||
<title>svc:node-red->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M129.95,-1040.03C147.14,-1036.46 166.48,-1029.72 180,-1017 242.3,-958.4 261.83,-852.88 267.77,-802.4"/>
|
||||
<polygon fill="black" stroke="black" points="271.27,-802.54 268.86,-792.22 264.31,-801.79 271.27,-802.54"/>
|
||||
</g>
|
||||
<!-- svc:passbolt-db -->
|
||||
<g id="node21" class="node">
|
||||
<title>svc:passbolt-db</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="139,-36 41,-36 41,0 139,0 139,-36"/>
|
||||
<text text-anchor="middle" x="90" y="-14.3" font-family="Helvetica,sans-Serif" font-size="14.00">passbolt-db</text>
|
||||
</g>
|
||||
<!-- net:passbolt -->
|
||||
<g id="node32" class="node">
|
||||
<title>net:passbolt</title>
|
||||
<ellipse fill="#f4f4f4" stroke="black" cx="271.25" cy="-72" rx="48.99" ry="18"/>
|
||||
<text text-anchor="middle" x="271.25" y="-68.3" font-family="Helvetica,sans-Serif" font-size="14.00">passbolt</text>
|
||||
</g>
|
||||
<!-- svc:passbolt-db->net:passbolt -->
|
||||
<g id="edge29" class="edge">
|
||||
<title>svc:passbolt-db->net:passbolt</title>
|
||||
<path fill="none" stroke="black" d="M139.03,-32.47C165.15,-40.34 197.32,-50.03 223.27,-57.85"/>
|
||||
<polygon fill="black" stroke="black" points="222.3,-61.21 232.88,-60.74 224.32,-54.51 222.3,-61.21"/>
|
||||
</g>
|
||||
<!-- svc:passbolt-webapp -->
|
||||
<g id="node22" class="node">
|
||||
<title>svc:passbolt-webapp</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="157.5,-144 22.5,-144 22.5,-108 157.5,-108 157.5,-144"/>
|
||||
<text text-anchor="middle" x="90" y="-122.3" font-family="Helvetica,sans-Serif" font-size="14.00">passbolt-webapp</text>
|
||||
</g>
|
||||
<!-- svc:passbolt-webapp->net:passbolt -->
|
||||
<g id="edge30" class="edge">
|
||||
<title>svc:passbolt-webapp->net:passbolt</title>
|
||||
<path fill="none" stroke="black" d="M151.18,-107.87C174.64,-100.8 201.13,-92.82 223.16,-86.19"/>
|
||||
<polygon fill="black" stroke="black" points="224.37,-89.48 232.94,-83.24 222.35,-82.77 224.37,-89.48"/>
|
||||
</g>
|
||||
<!-- svc:passbolt-webapp->net:traefik -->
|
||||
<g id="edge31" class="edge">
|
||||
<title>svc:passbolt-webapp->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M157.85,-136.93C166.26,-140.81 174,-146.02 180,-153 189.88,-164.49 250.79,-625.33 266.53,-745.56"/>
|
||||
<polygon fill="black" stroke="black" points="263.1,-746.33 267.87,-755.8 270.04,-745.43 263.1,-746.33"/>
|
||||
</g>
|
||||
<!-- svc:pihole-exporter -->
|
||||
<g id="node23" class="node">
|
||||
<title>svc:pihole-exporter</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="151.5,-1386 28.5,-1386 28.5,-1350 151.5,-1350 151.5,-1386"/>
|
||||
<text text-anchor="middle" x="90" y="-1364.3" font-family="Helvetica,sans-Serif" font-size="14.00">pihole-exporter</text>
|
||||
</g>
|
||||
<!-- svc:pihole-exporter->net:monitor -->
|
||||
<g id="edge32" class="edge">
|
||||
<title>svc:pihole-exporter->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M151.62,-1355.78C161.68,-1352.07 171.57,-1347.25 180,-1341 218.01,-1312.82 244.97,-1263.56 259.03,-1232.98"/>
|
||||
<polygon fill="black" stroke="black" points="262.27,-1234.31 263.14,-1223.76 255.87,-1231.46 262.27,-1234.31"/>
|
||||
</g>
|
||||
<!-- svc:portainer -->
|
||||
<g id="node24" class="node">
|
||||
<title>svc:portainer</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="130,-900 50,-900 50,-864 130,-864 130,-900"/>
|
||||
<text text-anchor="middle" x="90" y="-878.3" font-family="Helvetica,sans-Serif" font-size="14.00">portainer</text>
|
||||
</g>
|
||||
<!-- svc:portainer->net:traefik -->
|
||||
<g id="edge33" class="edge">
|
||||
<title>svc:portainer->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M130.17,-874.06C146.25,-869.82 164.67,-863.64 180,-855 206.25,-840.22 231.35,-816.65 248.38,-798.74"/>
|
||||
<polygon fill="black" stroke="black" points="251.37,-800.67 255.62,-790.97 246.24,-795.9 251.37,-800.67"/>
|
||||
</g>
|
||||
<!-- svc:prometheus -->
|
||||
<g id="node25" class="node">
|
||||
<title>svc:prometheus</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="140,-1008 40,-1008 40,-972 140,-972 140,-1008"/>
|
||||
<text text-anchor="middle" x="90" y="-986.3" font-family="Helvetica,sans-Serif" font-size="14.00">prometheus</text>
|
||||
</g>
|
||||
<!-- svc:prometheus->net:monitor -->
|
||||
<g id="edge34" class="edge">
|
||||
<title>svc:prometheus->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M140.37,-997.26C154.39,-1001.24 168.86,-1007.42 180,-1017 229.98,-1059.95 254.42,-1136.8 264.44,-1178.04"/>
|
||||
<polygon fill="black" stroke="black" points="261.07,-1179 266.73,-1187.95 267.88,-1177.42 261.07,-1179"/>
|
||||
</g>
|
||||
<!-- svc:prometheus->net:traefik -->
|
||||
<g id="edge35" class="edge">
|
||||
<title>svc:prometheus->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M140.37,-982.74C154.39,-978.76 168.86,-972.58 180,-963 229.98,-920.05 254.42,-843.2 264.44,-801.96"/>
|
||||
<polygon fill="black" stroke="black" points="267.88,-802.58 266.73,-792.05 261.07,-801 267.88,-802.58"/>
|
||||
</g>
|
||||
<!-- svc:searxng-webapp -->
|
||||
<g id="node26" class="node">
|
||||
<title>svc:searxng-webapp</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="156,-846 24,-846 24,-810 156,-810 156,-846"/>
|
||||
<text text-anchor="middle" x="90" y="-824.3" font-family="Helvetica,sans-Serif" font-size="14.00">searxng-webapp</text>
|
||||
</g>
|
||||
<!-- svc:searxng-webapp->net:traefik -->
|
||||
<g id="edge36" class="edge">
|
||||
<title>svc:searxng-webapp->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M151.18,-809.87C176.26,-802.32 204.79,-793.72 227.63,-786.84"/>
|
||||
<polygon fill="black" stroke="black" points="228.81,-790.14 237.37,-783.9 226.79,-783.44 228.81,-790.14"/>
|
||||
</g>
|
||||
<!-- svc:telegraf -->
|
||||
<g id="node27" class="node">
|
||||
<title>svc:telegraf</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="125.5,-1332 54.5,-1332 54.5,-1296 125.5,-1296 125.5,-1332"/>
|
||||
<text text-anchor="middle" x="90" y="-1310.3" font-family="Helvetica,sans-Serif" font-size="14.00">telegraf</text>
|
||||
</g>
|
||||
<!-- svc:telegraf->net:monitor -->
|
||||
<g id="edge37" class="edge">
|
||||
<title>svc:telegraf->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M125.8,-1307.18C142.85,-1302.93 163.26,-1296.43 180,-1287 206.25,-1272.22 231.35,-1248.65 248.38,-1230.74"/>
|
||||
<polygon fill="black" stroke="black" points="251.37,-1232.67 255.62,-1222.97 246.24,-1227.9 251.37,-1232.67"/>
|
||||
</g>
|
||||
<!-- svc:traefik -->
|
||||
<g id="node28" class="node">
|
||||
<title>svc:traefik</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="121,-792 59,-792 59,-756 121,-756 121,-792"/>
|
||||
<text text-anchor="middle" x="90" y="-770.3" font-family="Helvetica,sans-Serif" font-size="14.00">traefik</text>
|
||||
</g>
|
||||
<!-- svc:traefik->net:traefik -->
|
||||
<g id="edge38" class="edge">
|
||||
<title>svc:traefik->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M121,-774C148.16,-774 188.69,-774 220.66,-774"/>
|
||||
<polygon fill="black" stroke="black" points="220.71,-777.5 230.71,-774 220.71,-770.5 220.71,-777.5"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 24 KiB |
@@ -0,0 +1,118 @@
|
||||
digraph DockerTraefikDynu {
|
||||
graph [rankdir=LR, compound=true, splines=polyline, nodesep=0.9, ranksep=1.6, fontname="Helvetica", concentrate=true, newrank=true];
|
||||
node [fontname="Helvetica", fontsize=11, style="rounded,filled"];
|
||||
edge [fontname="Helvetica", fontsize=9, color="#334155"];
|
||||
"dynu" [label="Dynu / Public DNS", shape=box, fillcolor="#fde68a"];
|
||||
"svc:traefik" [label="Traefik", shape=box, fillcolor="#bfdbfe"];
|
||||
"dynu" -> "svc:traefik" [penwidth=1.6];
|
||||
"svc:authelia" [label="authelia
|
||||
[TLS]", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:authelia" [penwidth=1.4];
|
||||
"dns:auth.<domain>" [label="auth.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:auth.<domain>" -> "dynu";
|
||||
"svc:gitea" [label="gitea
|
||||
:3000
|
||||
[TLS]", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:gitea" [penwidth=1.4];
|
||||
"dns:gitea.<domain>" [label="gitea.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:gitea.<domain>" -> "dynu";
|
||||
"svc:gotify" [label="gotify
|
||||
:80", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:gotify" [penwidth=1.4];
|
||||
"dns:gotify.<domain>" [label="gotify.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:gotify.<domain>" -> "dynu";
|
||||
"svc:grafana" [label="grafana
|
||||
:3000", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:grafana" [penwidth=1.4];
|
||||
"dns:grafana.<domain>" [label="grafana.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:grafana.<domain>" -> "dynu";
|
||||
"svc:grampsweb" [label="grampsweb", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:grampsweb" [penwidth=1.4];
|
||||
"dns:familytree.<domain>" [label="familytree.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:familytree.<domain>" -> "dynu";
|
||||
"svc:influxdb" [label="influxdb
|
||||
:8086
|
||||
[authelia]", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:influxdb" [penwidth=1.4];
|
||||
"dns:influxdb.<domain>" [label="influxdb.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:influxdb.<domain>" -> "dynu";
|
||||
"svc:monitor-kuma" [label="monitor-kuma
|
||||
[TLS]", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:monitor-kuma" [penwidth=1.4];
|
||||
"dns:monitor-kuma.<domain>" [label="monitor-kuma.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:monitor-kuma.<domain>" -> "dynu";
|
||||
"svc:mtls-bridge" [label="mtls-bridge
|
||||
:8080
|
||||
[mTLS]", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:mtls-bridge" [penwidth=1.4];
|
||||
"dns:mtls-bridge.<domain>" [label="mtls-bridge.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:mtls-bridge.<domain>" -> "dynu";
|
||||
"svc:nextcloud-webapp" [label="nextcloud-webapp", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:nextcloud-webapp" [penwidth=1.4];
|
||||
"dns:nextcloud.<domain>" [label="nextcloud.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:nextcloud.<domain>" -> "dynu";
|
||||
"svc:node-red" [label="node-red
|
||||
:1880
|
||||
[authelia]", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:node-red" [penwidth=1.4];
|
||||
"dns:node-red.<domain>" [label="node-red.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:node-red.<domain>" -> "dynu";
|
||||
"svc:passbolt-webapp" [label="passbolt-webapp", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:passbolt-webapp" [penwidth=1.4];
|
||||
"dns:passbolt.<domain>" [label="passbolt.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:passbolt.<domain>" -> "dynu";
|
||||
"svc:portainer" [label="portainer
|
||||
:9000
|
||||
[TLS]", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:portainer" [penwidth=1.4];
|
||||
"dns:portainer.<domain>" [label="portainer.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:portainer.<domain>" -> "dynu";
|
||||
"svc:prometheus" [label="prometheus
|
||||
:9090
|
||||
[authelia]", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:prometheus" [penwidth=1.4];
|
||||
"dns:prometheus.<domain>" [label="prometheus.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:prometheus.<domain>" -> "dynu";
|
||||
"svc:searxng-webapp" [label="searxng-webapp", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:searxng-webapp" [penwidth=1.4];
|
||||
"dns:searxng.<domain>" [label="searxng.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:searxng.<domain>" -> "dynu";
|
||||
"svc:traefik" [label="traefik
|
||||
[authelia]", shape=box, fillcolor="#dcfce7"];
|
||||
"svc:traefik" -> "svc:traefik" [penwidth=1.4];
|
||||
"dns:traefik.<domain>" [label="traefik.<domain>", shape=note, fillcolor="#fef3c7"];
|
||||
"dns:traefik.<domain>" -> "dynu";
|
||||
{ rank=same; "dns:auth.<domain>"; "dns:familytree.<domain>"; "dns:gitea.<domain>"; "dns:gotify.<domain>"; "dns:grafana.<domain>"; "dns:influxdb.<domain>"; "dns:monitor-kuma.<domain>"; "dns:mtls-bridge.<domain>"; "dns:nextcloud.<domain>"; "dns:node-red.<domain>"; "dns:passbolt.<domain>"; "dns:portainer.<domain>"; "dns:prometheus.<domain>"; "dns:searxng.<domain>"; "dns:traefik.<domain>"; }
|
||||
subgraph "cluster_networks" {
|
||||
label="Docker backend networks"; style="rounded,dashed"; color="#d1d5db";
|
||||
"net:gramps" [label="gramps", shape=ellipse, fillcolor="#f8fafc"];
|
||||
"net:monitor" [label="monitor", shape=ellipse, fillcolor="#f8fafc"];
|
||||
"net:nextcloud" [label="nextcloud", shape=ellipse, fillcolor="#f8fafc"];
|
||||
"net:passbolt" [label="passbolt", shape=ellipse, fillcolor="#f8fafc"];
|
||||
"net:traefik" [label="traefik", shape=ellipse, fillcolor="#f8fafc"];
|
||||
}
|
||||
"svc:authelia" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:gitea" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:gotify" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:grafana" -> "net:monitor" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:grafana" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:grampsweb" -> "net:gramps" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:grampsweb" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:influxdb" -> "net:monitor" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:influxdb" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:monitor-kuma" -> "net:monitor" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:monitor-kuma" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:mtls-bridge" -> "net:monitor" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:mtls-bridge" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:nextcloud-webapp" -> "net:nextcloud" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:nextcloud-webapp" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:node-red" -> "net:monitor" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:node-red" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:passbolt-webapp" -> "net:passbolt" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:passbolt-webapp" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:portainer" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:prometheus" -> "net:monitor" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:prometheus" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:searxng-webapp" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
"svc:traefik" -> "net:traefik" [style=dashed, color="#94a3b8", arrowsize=0.7];
|
||||
}
|
||||
@@ -0,0 +1,611 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.43.0 (0)
|
||||
-->
|
||||
<!-- Title: DockerTraefikDynu Pages: 1 -->
|
||||
<svg width="1113pt" height="1536pt"
|
||||
viewBox="0.00 0.00 1113.39 1536.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1532)">
|
||||
<title>DockerTraefikDynu</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-1532 1109.39,-1532 1109.39,4 -4,4"/>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_networks</title>
|
||||
<path fill="none" stroke="#d1d5db" stroke-dasharray="5,2" d="M922,-650C922,-650 1093.39,-650 1093.39,-650 1099.39,-650 1105.39,-656 1105.39,-662 1105.39,-662 1105.39,-1117 1105.39,-1117 1105.39,-1123 1099.39,-1129 1093.39,-1129 1093.39,-1129 922,-1129 922,-1129 916,-1129 910,-1123 910,-1117 910,-1117 910,-662 910,-662 910,-656 916,-650 922,-650"/>
|
||||
<text text-anchor="middle" x="1007.69" y="-1113.8" font-family="Helvetica,sans-Serif" font-size="14.00">Docker backend networks</text>
|
||||
</g>
|
||||
<!-- dynu -->
|
||||
<g id="node1" class="node">
|
||||
<title>dynu</title>
|
||||
<path fill="#fde68a" stroke="black" d="M374,-789C374,-789 282,-789 282,-789 276,-789 270,-783 270,-777 270,-777 270,-765 270,-765 270,-759 276,-753 282,-753 282,-753 374,-753 374,-753 380,-753 386,-759 386,-765 386,-765 386,-777 386,-777 386,-783 380,-789 374,-789"/>
|
||||
<text text-anchor="middle" x="328" y="-768.2" font-family="Helvetica,sans-Serif" font-size="11.00">Dynu / Public DNS</text>
|
||||
</g>
|
||||
<!-- svc:traefik -->
|
||||
<g id="node2" class="node">
|
||||
<title>svc:traefik</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M559,-789C559,-789 513,-789 513,-789 507,-789 501,-783 501,-777 501,-777 501,-765 501,-765 501,-759 507,-753 513,-753 513,-753 559,-753 559,-753 565,-753 571,-759 571,-765 571,-765 571,-777 571,-777 571,-783 565,-789 559,-789"/>
|
||||
<text text-anchor="middle" x="536" y="-774.2" font-family="Helvetica,sans-Serif" font-size="11.00">traefik</text>
|
||||
<text text-anchor="middle" x="536" y="-762.2" font-family="Helvetica,sans-Serif" font-size="11.00">[authelia]</text>
|
||||
</g>
|
||||
<!-- dynu->svc:traefik -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>dynu->svc:traefik</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.6" d="M386.11,-771C419.13,-771 460.06,-771 490.64,-771"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.6" points="491,-774.5 501,-771 491,-767.5 491,-774.5"/>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:traefik -->
|
||||
<g id="edge30" class="edge">
|
||||
<title>svc:traefik->svc:traefik</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M511.86,-789.35C485.91,-817.82 493.95,-854 536,-854 574.1,-854 584.29,-824.29 566.55,-797.52"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="569.07,-795.06 560.14,-789.35 563.55,-799.38 569.07,-795.06"/>
|
||||
</g>
|
||||
<!-- svc:authelia -->
|
||||
<g id="node3" class="node">
|
||||
<title>svc:authelia</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M763,-789C763,-789 726,-789 726,-789 720,-789 714,-783 714,-777 714,-777 714,-765 714,-765 714,-759 720,-753 726,-753 726,-753 763,-753 763,-753 769,-753 775,-759 775,-765 775,-765 775,-777 775,-777 775,-783 769,-789 763,-789"/>
|
||||
<text text-anchor="middle" x="744.5" y="-774.2" font-family="Helvetica,sans-Serif" font-size="11.00">authelia</text>
|
||||
<text text-anchor="middle" x="744.5" y="-762.2" font-family="Helvetica,sans-Serif" font-size="11.00">[TLS]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:authelia -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>svc:traefik->svc:authelia</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M571.1,-771C607.43,-771 664.91,-771 703.39,-771"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="703.71,-774.5 713.71,-771 703.71,-767.5 703.71,-774.5"/>
|
||||
</g>
|
||||
<!-- svc:gitea -->
|
||||
<g id="node5" class="node">
|
||||
<title>svc:gitea</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M759.5,-688C759.5,-688 729.5,-688 729.5,-688 723.5,-688 717.5,-682 717.5,-676 717.5,-676 717.5,-656 717.5,-656 717.5,-650 723.5,-644 729.5,-644 729.5,-644 759.5,-644 759.5,-644 765.5,-644 771.5,-650 771.5,-656 771.5,-656 771.5,-676 771.5,-676 771.5,-682 765.5,-688 759.5,-688"/>
|
||||
<text text-anchor="middle" x="744.5" y="-675.2" font-family="Helvetica,sans-Serif" font-size="11.00">gitea</text>
|
||||
<text text-anchor="middle" x="744.5" y="-663.2" font-family="Helvetica,sans-Serif" font-size="11.00">:3000</text>
|
||||
<text text-anchor="middle" x="744.5" y="-651.2" font-family="Helvetica,sans-Serif" font-size="11.00">[TLS]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:gitea -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>svc:traefik->svc:gitea</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M571.1,-753.66C608.91,-734.44 669.61,-703.57 707.98,-684.06"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="709.89,-687.01 717.22,-679.36 706.72,-680.77 709.89,-687.01"/>
|
||||
</g>
|
||||
<!-- svc:gotify -->
|
||||
<g id="node7" class="node">
|
||||
<title>svc:gotify</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M759.5,-579C759.5,-579 729.5,-579 729.5,-579 723.5,-579 717.5,-573 717.5,-567 717.5,-567 717.5,-555 717.5,-555 717.5,-549 723.5,-543 729.5,-543 729.5,-543 759.5,-543 759.5,-543 765.5,-543 771.5,-549 771.5,-555 771.5,-555 771.5,-567 771.5,-567 771.5,-573 765.5,-579 759.5,-579"/>
|
||||
<text text-anchor="middle" x="744.5" y="-564.2" font-family="Helvetica,sans-Serif" font-size="11.00">gotify</text>
|
||||
<text text-anchor="middle" x="744.5" y="-552.2" font-family="Helvetica,sans-Serif" font-size="11.00">:80</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:gotify -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>svc:traefik->svc:gotify</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M553.8,-752.96C592.77,-711.11 686,-611 686,-611 686,-611 700.43,-598.45 714.83,-585.93"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="717.49,-588.25 722.74,-579.05 712.9,-582.97 717.49,-588.25"/>
|
||||
</g>
|
||||
<!-- svc:grafana -->
|
||||
<g id="node9" class="node">
|
||||
<title>svc:grafana</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M762,-999C762,-999 727,-999 727,-999 721,-999 715,-993 715,-987 715,-987 715,-975 715,-975 715,-969 721,-963 727,-963 727,-963 762,-963 762,-963 768,-963 774,-969 774,-975 774,-975 774,-987 774,-987 774,-993 768,-999 762,-999"/>
|
||||
<text text-anchor="middle" x="744.5" y="-984.2" font-family="Helvetica,sans-Serif" font-size="11.00">grafana</text>
|
||||
<text text-anchor="middle" x="744.5" y="-972.2" font-family="Helvetica,sans-Serif" font-size="11.00">:3000</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:grafana -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>svc:traefik->svc:grafana</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M553.8,-789.04C592.77,-830.89 686,-931 686,-931 686,-931 700.43,-943.55 714.83,-956.07"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="712.9,-959.03 722.74,-962.95 717.49,-953.75 712.9,-959.03"/>
|
||||
</g>
|
||||
<!-- svc:grampsweb -->
|
||||
<g id="node11" class="node">
|
||||
<title>svc:grampsweb</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M772.5,-1528C772.5,-1528 716.5,-1528 716.5,-1528 710.5,-1528 704.5,-1522 704.5,-1516 704.5,-1516 704.5,-1504 704.5,-1504 704.5,-1498 710.5,-1492 716.5,-1492 716.5,-1492 772.5,-1492 772.5,-1492 778.5,-1492 784.5,-1498 784.5,-1504 784.5,-1504 784.5,-1516 784.5,-1516 784.5,-1522 778.5,-1528 772.5,-1528"/>
|
||||
<text text-anchor="middle" x="744.5" y="-1507.2" font-family="Helvetica,sans-Serif" font-size="11.00">grampsweb</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:grampsweb -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>svc:traefik->svc:grampsweb</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M540.91,-789.07C564.42,-897.78 686,-1460 686,-1460 686,-1460 700.43,-1472.55 714.83,-1485.07"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="712.9,-1488.03 722.74,-1491.95 717.49,-1482.75 712.9,-1488.03"/>
|
||||
</g>
|
||||
<!-- svc:influxdb -->
|
||||
<g id="node13" class="node">
|
||||
<title>svc:influxdb</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M767.5,-898C767.5,-898 721.5,-898 721.5,-898 715.5,-898 709.5,-892 709.5,-886 709.5,-886 709.5,-866 709.5,-866 709.5,-860 715.5,-854 721.5,-854 721.5,-854 767.5,-854 767.5,-854 773.5,-854 779.5,-860 779.5,-866 779.5,-866 779.5,-886 779.5,-886 779.5,-892 773.5,-898 767.5,-898"/>
|
||||
<text text-anchor="middle" x="744.5" y="-885.2" font-family="Helvetica,sans-Serif" font-size="11.00">influxdb</text>
|
||||
<text text-anchor="middle" x="744.5" y="-873.2" font-family="Helvetica,sans-Serif" font-size="11.00">:8086</text>
|
||||
<text text-anchor="middle" x="744.5" y="-861.2" font-family="Helvetica,sans-Serif" font-size="11.00">[authelia]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:influxdb -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>svc:traefik->svc:influxdb</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M571.1,-788.34C606.37,-806.27 661.57,-834.34 699.97,-853.87"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="698.85,-857.22 709.35,-858.64 702.02,-850.98 698.85,-857.22"/>
|
||||
</g>
|
||||
<!-- svc:monitor-kuma -->
|
||||
<g id="node15" class="node">
|
||||
<title>svc:monitor-kuma</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M778.5,-1427C778.5,-1427 710.5,-1427 710.5,-1427 704.5,-1427 698.5,-1421 698.5,-1415 698.5,-1415 698.5,-1403 698.5,-1403 698.5,-1397 704.5,-1391 710.5,-1391 710.5,-1391 778.5,-1391 778.5,-1391 784.5,-1391 790.5,-1397 790.5,-1403 790.5,-1403 790.5,-1415 790.5,-1415 790.5,-1421 784.5,-1427 778.5,-1427"/>
|
||||
<text text-anchor="middle" x="744.5" y="-1412.2" font-family="Helvetica,sans-Serif" font-size="11.00">monitor-kuma</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1400.2" font-family="Helvetica,sans-Serif" font-size="11.00">[TLS]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:monitor-kuma -->
|
||||
<g id="edge14" class="edge">
|
||||
<title>svc:traefik->svc:monitor-kuma</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M541.62,-789.24C566.77,-888.49 686,-1359 686,-1359 686,-1359 700.43,-1371.55 714.83,-1384.07"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="712.9,-1387.03 722.74,-1390.95 717.49,-1381.75 712.9,-1387.03"/>
|
||||
</g>
|
||||
<!-- svc:mtls-bridge -->
|
||||
<g id="node17" class="node">
|
||||
<title>svc:mtls-bridge</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M772,-1326C772,-1326 717,-1326 717,-1326 711,-1326 705,-1320 705,-1314 705,-1314 705,-1294 705,-1294 705,-1288 711,-1282 717,-1282 717,-1282 772,-1282 772,-1282 778,-1282 784,-1288 784,-1294 784,-1294 784,-1314 784,-1314 784,-1320 778,-1326 772,-1326"/>
|
||||
<text text-anchor="middle" x="744.5" y="-1313.2" font-family="Helvetica,sans-Serif" font-size="11.00">mtls-bridge</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1301.2" font-family="Helvetica,sans-Serif" font-size="11.00">:8080</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1289.2" font-family="Helvetica,sans-Serif" font-size="11.00">[mTLS]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:mtls-bridge -->
|
||||
<g id="edge16" class="edge">
|
||||
<title>svc:traefik->svc:mtls-bridge</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M542.66,-789.19C569.88,-876.69 686,-1250 686,-1250 686,-1250 698.77,-1262 712.28,-1274.68"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="710.1,-1277.43 719.78,-1281.72 714.89,-1272.33 710.1,-1277.43"/>
|
||||
</g>
|
||||
<!-- svc:nextcloud-webapp -->
|
||||
<g id="node19" class="node">
|
||||
<title>svc:nextcloud-webapp</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M791,-137C791,-137 698,-137 698,-137 692,-137 686,-131 686,-125 686,-125 686,-113 686,-113 686,-107 692,-101 698,-101 698,-101 791,-101 791,-101 797,-101 803,-107 803,-113 803,-113 803,-125 803,-125 803,-131 797,-137 791,-137"/>
|
||||
<text text-anchor="middle" x="744.5" y="-116.2" font-family="Helvetica,sans-Serif" font-size="11.00">nextcloud-webapp</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:nextcloud-webapp -->
|
||||
<g id="edge18" class="edge">
|
||||
<title>svc:traefik->svc:nextcloud-webapp</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M541.62,-752.85C566.77,-654.11 686,-186 686,-186 686,-186 704.96,-163.91 721.1,-145.1"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="723.93,-147.18 727.79,-137.31 718.62,-142.62 723.93,-147.18"/>
|
||||
</g>
|
||||
<!-- svc:node-red -->
|
||||
<g id="node21" class="node">
|
||||
<title>svc:node-red</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M767.5,-1217C767.5,-1217 721.5,-1217 721.5,-1217 715.5,-1217 709.5,-1211 709.5,-1205 709.5,-1205 709.5,-1185 709.5,-1185 709.5,-1179 715.5,-1173 721.5,-1173 721.5,-1173 767.5,-1173 767.5,-1173 773.5,-1173 779.5,-1179 779.5,-1185 779.5,-1185 779.5,-1205 779.5,-1205 779.5,-1211 773.5,-1217 767.5,-1217"/>
|
||||
<text text-anchor="middle" x="744.5" y="-1204.2" font-family="Helvetica,sans-Serif" font-size="11.00">node-red</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1192.2" font-family="Helvetica,sans-Serif" font-size="11.00">:1880</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1180.2" font-family="Helvetica,sans-Serif" font-size="11.00">[authelia]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:node-red -->
|
||||
<g id="edge20" class="edge">
|
||||
<title>svc:traefik->svc:node-red</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M544.29,-789.1C574.2,-863.38 686,-1141 686,-1141 686,-1141 698.77,-1153 712.28,-1165.68"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="710.1,-1168.43 719.78,-1172.72 714.89,-1163.33 710.1,-1168.43"/>
|
||||
</g>
|
||||
<!-- svc:passbolt-webapp -->
|
||||
<g id="node23" class="node">
|
||||
<title>svc:passbolt-webapp</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M787.5,-36C787.5,-36 701.5,-36 701.5,-36 695.5,-36 689.5,-30 689.5,-24 689.5,-24 689.5,-12 689.5,-12 689.5,-6 695.5,0 701.5,0 701.5,0 787.5,0 787.5,0 793.5,0 799.5,-6 799.5,-12 799.5,-12 799.5,-24 799.5,-24 799.5,-30 793.5,-36 787.5,-36"/>
|
||||
<text text-anchor="middle" x="744.5" y="-15.2" font-family="Helvetica,sans-Serif" font-size="11.00">passbolt-webapp</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:passbolt-webapp -->
|
||||
<g id="edge22" class="edge">
|
||||
<title>svc:traefik->svc:passbolt-webapp</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M540.83,-752.92C564.15,-642.88 686,-68 686,-68 686,-68 700.43,-55.45 714.83,-42.93"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="717.49,-45.25 722.74,-36.05 712.9,-39.97 717.49,-45.25"/>
|
||||
</g>
|
||||
<!-- svc:portainer -->
|
||||
<g id="node25" class="node">
|
||||
<title>svc:portainer</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M766,-478C766,-478 723,-478 723,-478 717,-478 711,-472 711,-466 711,-466 711,-446 711,-446 711,-440 717,-434 723,-434 723,-434 766,-434 766,-434 772,-434 778,-440 778,-446 778,-446 778,-466 778,-466 778,-472 772,-478 766,-478"/>
|
||||
<text text-anchor="middle" x="744.5" y="-465.2" font-family="Helvetica,sans-Serif" font-size="11.00">portainer</text>
|
||||
<text text-anchor="middle" x="744.5" y="-453.2" font-family="Helvetica,sans-Serif" font-size="11.00">:9000</text>
|
||||
<text text-anchor="middle" x="744.5" y="-441.2" font-family="Helvetica,sans-Serif" font-size="11.00">[TLS]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:portainer -->
|
||||
<g id="edge24" class="edge">
|
||||
<title>svc:traefik->svc:portainer</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M547.48,-752.65C581.39,-693.24 686,-510 686,-510 686,-510 698.77,-498 712.28,-485.32"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="714.89,-487.67 719.78,-478.28 710.1,-482.57 714.89,-487.67"/>
|
||||
</g>
|
||||
<!-- svc:prometheus -->
|
||||
<g id="node27" class="node">
|
||||
<title>svc:prometheus</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M774,-1108C774,-1108 715,-1108 715,-1108 709,-1108 703,-1102 703,-1096 703,-1096 703,-1076 703,-1076 703,-1070 709,-1064 715,-1064 715,-1064 774,-1064 774,-1064 780,-1064 786,-1070 786,-1076 786,-1076 786,-1096 786,-1096 786,-1102 780,-1108 774,-1108"/>
|
||||
<text text-anchor="middle" x="744.5" y="-1095.2" font-family="Helvetica,sans-Serif" font-size="11.00">prometheus</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1083.2" font-family="Helvetica,sans-Serif" font-size="11.00">:9090</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1071.2" font-family="Helvetica,sans-Serif" font-size="11.00">[authelia]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:prometheus -->
|
||||
<g id="edge26" class="edge">
|
||||
<title>svc:traefik->svc:prometheus</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M547.48,-789.35C581.39,-848.76 686,-1032 686,-1032 686,-1032 698.77,-1044 712.28,-1056.68"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="710.1,-1059.43 719.78,-1063.72 714.89,-1054.33 710.1,-1059.43"/>
|
||||
</g>
|
||||
<!-- svc:searxng-webapp -->
|
||||
<g id="node29" class="node">
|
||||
<title>svc:searxng-webapp</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M786,-369C786,-369 703,-369 703,-369 697,-369 691,-363 691,-357 691,-357 691,-345 691,-345 691,-339 697,-333 703,-333 703,-333 786,-333 786,-333 792,-333 798,-339 798,-345 798,-345 798,-357 798,-357 798,-363 792,-369 786,-369"/>
|
||||
<text text-anchor="middle" x="744.5" y="-348.2" font-family="Helvetica,sans-Serif" font-size="11.00">searxng-webapp</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:searxng-webapp -->
|
||||
<g id="edge28" class="edge">
|
||||
<title>svc:traefik->svc:searxng-webapp</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M544.29,-752.9C574.2,-678.62 686,-401 686,-401 686,-401 700.43,-388.45 714.83,-375.93"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="717.49,-378.25 722.74,-369.05 712.9,-372.97 717.49,-378.25"/>
|
||||
</g>
|
||||
<!-- net:traefik -->
|
||||
<g id="node36" class="node">
|
||||
<title>net:traefik</title>
|
||||
<ellipse fill="#f8fafc" stroke="black" cx="1007.69" cy="-878" rx="31.04" ry="18"/>
|
||||
<text text-anchor="middle" x="1007.69" y="-875.2" font-family="Helvetica,sans-Serif" font-size="11.00">traefik</text>
|
||||
</g>
|
||||
<!-- svc:traefik->net:traefik -->
|
||||
<g id="edge55" class="edge">
|
||||
<title>svc:traefik->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M542.75,-752.82C570.13,-666.27 686,-300 686,-300 686,-300 803,-300 803,-300 803,-300 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- svc:authelia->net:traefik -->
|
||||
<g id="edge32" class="edge">
|
||||
<title>svc:authelia->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M775.21,-783.17C824.86,-803.51 924.25,-844.23 975.12,-865.06"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="974.26,-867.36 981.67,-867.75 976.12,-862.83 974.26,-867.36"/>
|
||||
</g>
|
||||
<!-- dns:auth.<domain> -->
|
||||
<g id="node4" class="node">
|
||||
<title>dns:auth.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="123.5,-1496 25.5,-1496 25.5,-1460 129.5,-1460 129.5,-1490 123.5,-1496"/>
|
||||
<polyline fill="none" stroke="black" points="123.5,-1496 123.5,-1490 "/>
|
||||
<polyline fill="none" stroke="black" points="129.5,-1490 123.5,-1490 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-1475.2" font-family="Helvetica,sans-Serif" font-size="11.00">auth.<domain></text>
|
||||
</g>
|
||||
<!-- dns:auth.<domain>->dynu -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>dns:auth.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-1459.95C128.03,-1445.63 155,-1428 155,-1428 155,-1428 286.65,-925.11 319.6,-799.28"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="323.07,-799.82 322.22,-789.26 316.3,-798.05 323.07,-799.82"/>
|
||||
</g>
|
||||
<!-- svc:gitea->net:traefik -->
|
||||
<g id="edge33" class="edge">
|
||||
<title>svc:gitea->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M768.56,-688.05C784.55,-703.36 803,-721 803,-721 803,-721 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- dns:gitea.<domain> -->
|
||||
<g id="node6" class="node">
|
||||
<title>dns:gitea.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="125,-1395 24,-1395 24,-1359 131,-1359 131,-1389 125,-1395"/>
|
||||
<polyline fill="none" stroke="black" points="125,-1395 125,-1389 "/>
|
||||
<polyline fill="none" stroke="black" points="131,-1389 125,-1389 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-1374.2" font-family="Helvetica,sans-Serif" font-size="11.00">gitea.<domain></text>
|
||||
</g>
|
||||
<!-- dns:gitea.<domain>->dynu -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>dns:gitea.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-1358.95C128.03,-1344.63 155,-1327 155,-1327 155,-1327 283.58,-911.36 318.4,-798.82"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="321.76,-799.77 321.38,-789.18 315.08,-797.7 321.76,-799.77"/>
|
||||
</g>
|
||||
<!-- svc:gotify->net:traefik -->
|
||||
<g id="edge34" class="edge">
|
||||
<title>svc:gotify->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-579.05C782.73,-593.37 803,-611 803,-611 803,-611 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- dns:gotify.<domain> -->
|
||||
<g id="node8" class="node">
|
||||
<title>dns:gotify.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="126,-1294 23,-1294 23,-1258 132,-1258 132,-1288 126,-1294"/>
|
||||
<polyline fill="none" stroke="black" points="126,-1294 126,-1288 "/>
|
||||
<polyline fill="none" stroke="black" points="132,-1288 126,-1288 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-1273.2" font-family="Helvetica,sans-Serif" font-size="11.00">gotify.<domain></text>
|
||||
</g>
|
||||
<!-- dns:gotify.<domain>->dynu -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>dns:gotify.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-1257.95C128.03,-1243.63 155,-1226 155,-1226 155,-1226 279.21,-897.41 316.53,-798.71"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="319.89,-799.71 320.15,-789.12 313.34,-797.23 319.89,-799.71"/>
|
||||
</g>
|
||||
<!-- net:monitor -->
|
||||
<g id="node33" class="node">
|
||||
<title>net:monitor</title>
|
||||
<ellipse fill="#f8fafc" stroke="black" cx="1007.69" cy="-979" rx="35.46" ry="18"/>
|
||||
<text text-anchor="middle" x="1007.69" y="-976.2" font-family="Helvetica,sans-Serif" font-size="11.00">monitor</text>
|
||||
</g>
|
||||
<!-- svc:grafana->net:monitor -->
|
||||
<g id="edge35" class="edge">
|
||||
<title>svc:grafana->net:monitor</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M774.2,-980.78C820.4,-980.43 911.47,-979.73 964.89,-979.32"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="965.19,-981.77 972.17,-979.26 965.15,-976.87 965.19,-981.77"/>
|
||||
</g>
|
||||
<!-- svc:grafana->net:traefik -->
|
||||
<g id="edge36" class="edge">
|
||||
<title>svc:grafana->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M774.2,-969.68C823.41,-950.28 923.53,-910.8 974.83,-890.57"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="975.82,-892.81 981.44,-887.96 974.03,-888.25 975.82,-892.81"/>
|
||||
</g>
|
||||
<!-- dns:grafana.<domain> -->
|
||||
<g id="node10" class="node">
|
||||
<title>dns:grafana.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="132,-1193 17,-1193 17,-1157 138,-1157 138,-1187 132,-1193"/>
|
||||
<polyline fill="none" stroke="black" points="132,-1193 132,-1187 "/>
|
||||
<polyline fill="none" stroke="black" points="138,-1187 132,-1187 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-1172.2" font-family="Helvetica,sans-Serif" font-size="11.00">grafana.<domain></text>
|
||||
</g>
|
||||
<!-- dns:grafana.<domain>->dynu -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>dns:grafana.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-1156.95C128.03,-1142.63 155,-1125 155,-1125 155,-1125 273.61,-880.89 313.84,-798.09"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="317.01,-799.57 318.23,-789.04 310.72,-796.51 317.01,-799.57"/>
|
||||
</g>
|
||||
<!-- net:gramps -->
|
||||
<g id="node32" class="node">
|
||||
<title>net:gramps</title>
|
||||
<ellipse fill="#f8fafc" stroke="black" cx="1007.69" cy="-1080" rx="34.76" ry="18"/>
|
||||
<text text-anchor="middle" x="1007.69" y="-1077.2" font-family="Helvetica,sans-Serif" font-size="11.00">gramps</text>
|
||||
</g>
|
||||
<!-- svc:grampsweb->net:gramps -->
|
||||
<g id="edge37" class="edge">
|
||||
<title>svc:grampsweb->net:gramps</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-1491.95C782.73,-1477.63 803,-1460 803,-1460 803,-1460 949.23,-1187.21 993.89,-1103.88"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="996.27,-1104.64 997.41,-1097.32 991.95,-1102.33 996.27,-1104.64"/>
|
||||
</g>
|
||||
<!-- svc:grampsweb->net:traefik -->
|
||||
<g id="edge38" class="edge">
|
||||
<title>svc:grampsweb->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-1491.95C782.73,-1477.63 803,-1460 803,-1460 803,-1460 910,-929 910,-929 910,-929 949.05,-908.4 977.52,-893.39"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="978.73,-895.52 983.78,-890.09 976.45,-891.18 978.73,-895.52"/>
|
||||
</g>
|
||||
<!-- dns:familytree.<domain> -->
|
||||
<g id="node12" class="node">
|
||||
<title>dns:familytree.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="139,-1092 10,-1092 10,-1056 145,-1056 145,-1086 139,-1092"/>
|
||||
<polyline fill="none" stroke="black" points="139,-1092 139,-1086 "/>
|
||||
<polyline fill="none" stroke="black" points="145,-1086 139,-1086 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-1071.2" font-family="Helvetica,sans-Serif" font-size="11.00">familytree.<domain></text>
|
||||
</g>
|
||||
<!-- dns:familytree.<domain>->dynu -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>dns:familytree.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-1055.95C128.03,-1041.63 155,-1024 155,-1024 155,-1024 264.64,-862.73 308.84,-797.71"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="311.9,-799.43 314.63,-789.2 306.11,-795.5 311.9,-799.43"/>
|
||||
</g>
|
||||
<!-- svc:influxdb->net:monitor -->
|
||||
<g id="edge39" class="edge">
|
||||
<title>svc:influxdb->net:monitor</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M779.65,-889.47C829.7,-909.2 922.46,-945.78 972.53,-965.53"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="971.89,-967.91 979.3,-968.2 973.69,-963.35 971.89,-967.91"/>
|
||||
</g>
|
||||
<!-- svc:influxdb->net:traefik -->
|
||||
<g id="edge40" class="edge">
|
||||
<title>svc:influxdb->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M779.65,-876.26C828.54,-876.64 918.2,-877.32 968.99,-877.71"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="969.17,-880.16 976.19,-877.77 969.21,-875.26 969.17,-880.16"/>
|
||||
</g>
|
||||
<!-- dns:influxdb.<domain> -->
|
||||
<g id="node14" class="node">
|
||||
<title>dns:influxdb.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="132.5,-991 16.5,-991 16.5,-955 138.5,-955 138.5,-985 132.5,-991"/>
|
||||
<polyline fill="none" stroke="black" points="132.5,-991 132.5,-985 "/>
|
||||
<polyline fill="none" stroke="black" points="138.5,-985 132.5,-985 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-970.2" font-family="Helvetica,sans-Serif" font-size="11.00">influxdb.<domain></text>
|
||||
</g>
|
||||
<!-- dns:influxdb.<domain>->dynu -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>dns:influxdb.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-954.95C128.03,-940.63 155,-923 155,-923 155,-923 250.14,-838.92 298.91,-795.83"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="301.42,-798.28 306.59,-789.03 296.78,-793.03 301.42,-798.28"/>
|
||||
</g>
|
||||
<!-- svc:monitor-kuma->net:monitor -->
|
||||
<g id="edge41" class="edge">
|
||||
<title>svc:monitor-kuma->net:monitor</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-1390.95C782.73,-1376.63 803,-1359 803,-1359 803,-1359 910,-1030 910,-1030 910,-1030 947.73,-1010.1 976.05,-995.16"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="977.25,-997.3 982.29,-991.87 974.96,-992.97 977.25,-997.3"/>
|
||||
</g>
|
||||
<!-- svc:monitor-kuma->net:traefik -->
|
||||
<g id="edge42" class="edge">
|
||||
<title>svc:monitor-kuma->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-1390.95C782.73,-1376.63 803,-1359 803,-1359 803,-1359 910,-929 910,-929 910,-929 949.05,-908.4 977.52,-893.39"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="978.73,-895.52 983.78,-890.09 976.45,-891.18 978.73,-895.52"/>
|
||||
</g>
|
||||
<!-- dns:monitor-kuma.<domain> -->
|
||||
<g id="node16" class="node">
|
||||
<title>dns:monitor-kuma.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="149,-890 0,-890 0,-854 155,-854 155,-884 149,-890"/>
|
||||
<polyline fill="none" stroke="black" points="149,-890 149,-884 "/>
|
||||
<polyline fill="none" stroke="black" points="155,-884 149,-884 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-869.2" font-family="Helvetica,sans-Serif" font-size="11.00">monitor-kuma.<domain></text>
|
||||
</g>
|
||||
<!-- dns:monitor-kuma.<domain>->dynu -->
|
||||
<g id="edge15" class="edge">
|
||||
<title>dns:monitor-kuma.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M122.93,-853.94C165.02,-836.83 228.32,-811.11 273.25,-792.85"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="274.59,-796.08 282.54,-789.07 271.96,-789.59 274.59,-796.08"/>
|
||||
</g>
|
||||
<!-- svc:mtls-bridge->net:monitor -->
|
||||
<g id="edge43" class="edge">
|
||||
<title>svc:mtls-bridge->net:monitor</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M769.22,-1281.72C785.06,-1266.85 803,-1250 803,-1250 803,-1250 910,-1030 910,-1030 910,-1030 947.73,-1010.1 976.05,-995.16"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="977.25,-997.3 982.29,-991.87 974.96,-992.97 977.25,-997.3"/>
|
||||
</g>
|
||||
<!-- svc:mtls-bridge->net:traefik -->
|
||||
<g id="edge44" class="edge">
|
||||
<title>svc:mtls-bridge->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M769.22,-1281.72C785.06,-1266.85 803,-1250 803,-1250 803,-1250 910,-929 910,-929 910,-929 949.05,-908.4 977.52,-893.39"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="978.73,-895.52 983.78,-890.09 976.45,-891.18 978.73,-895.52"/>
|
||||
</g>
|
||||
<!-- dns:mtls-bridge.<domain> -->
|
||||
<g id="node18" class="node">
|
||||
<title>dns:mtls-bridge.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="142,-789 7,-789 7,-753 148,-753 148,-783 142,-789"/>
|
||||
<polyline fill="none" stroke="black" points="142,-789 142,-783 "/>
|
||||
<polyline fill="none" stroke="black" points="148,-783 142,-783 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-768.2" font-family="Helvetica,sans-Serif" font-size="11.00">mtls-bridge.<domain></text>
|
||||
</g>
|
||||
<!-- dns:mtls-bridge.<domain>->dynu -->
|
||||
<g id="edge17" class="edge">
|
||||
<title>dns:mtls-bridge.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M148.05,-771C182.94,-771 225.03,-771 259.61,-771"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="259.62,-774.5 269.62,-771 259.62,-767.5 259.62,-774.5"/>
|
||||
</g>
|
||||
<!-- net:nextcloud -->
|
||||
<g id="node34" class="node">
|
||||
<title>net:nextcloud</title>
|
||||
<ellipse fill="#f8fafc" stroke="black" cx="1007.69" cy="-777" rx="42.89" ry="18"/>
|
||||
<text text-anchor="middle" x="1007.69" y="-774.2" font-family="Helvetica,sans-Serif" font-size="11.00">nextcloud</text>
|
||||
</g>
|
||||
<!-- svc:nextcloud-webapp->net:nextcloud -->
|
||||
<g id="edge45" class="edge">
|
||||
<title>svc:nextcloud-webapp->net:nextcloud</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M761.21,-137.31C778.24,-157.15 803,-186 803,-186 803,-186 910,-727 910,-727 910,-727 945.48,-745.35 973.46,-759.81"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="972.67,-762.17 980.02,-763.2 974.92,-757.81 972.67,-762.17"/>
|
||||
</g>
|
||||
<!-- svc:nextcloud-webapp->net:traefik -->
|
||||
<g id="edge46" class="edge">
|
||||
<title>svc:nextcloud-webapp->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M761.21,-137.31C778.24,-157.15 803,-186 803,-186 803,-186 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- dns:nextcloud.<domain> -->
|
||||
<g id="node20" class="node">
|
||||
<title>dns:nextcloud.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="138,-688 11,-688 11,-652 144,-652 144,-682 138,-688"/>
|
||||
<polyline fill="none" stroke="black" points="138,-688 138,-682 "/>
|
||||
<polyline fill="none" stroke="black" points="144,-682 138,-682 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-667.2" font-family="Helvetica,sans-Serif" font-size="11.00">nextcloud.<domain></text>
|
||||
</g>
|
||||
<!-- dns:nextcloud.<domain>->dynu -->
|
||||
<g id="edge19" class="edge">
|
||||
<title>dns:nextcloud.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M122.93,-688.06C165.02,-705.17 228.32,-730.89 273.25,-749.15"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="271.96,-752.41 282.54,-752.93 274.59,-745.92 271.96,-752.41"/>
|
||||
</g>
|
||||
<!-- svc:node-red->net:monitor -->
|
||||
<g id="edge47" class="edge">
|
||||
<title>svc:node-red->net:monitor</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M769.22,-1172.72C785.06,-1157.85 803,-1141 803,-1141 803,-1141 910,-1030 910,-1030 910,-1030 947.73,-1010.1 976.05,-995.16"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="977.25,-997.3 982.29,-991.87 974.96,-992.97 977.25,-997.3"/>
|
||||
</g>
|
||||
<!-- svc:node-red->net:traefik -->
|
||||
<g id="edge48" class="edge">
|
||||
<title>svc:node-red->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M769.22,-1172.72C785.06,-1157.85 803,-1141 803,-1141 803,-1141 910,-929 910,-929 910,-929 949.05,-908.4 977.52,-893.39"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="978.73,-895.52 983.78,-890.09 976.45,-891.18 978.73,-895.52"/>
|
||||
</g>
|
||||
<!-- dns:node-red.<domain> -->
|
||||
<g id="node22" class="node">
|
||||
<title>dns:node-red.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="135.5,-587 13.5,-587 13.5,-551 141.5,-551 141.5,-581 135.5,-587"/>
|
||||
<polyline fill="none" stroke="black" points="135.5,-587 135.5,-581 "/>
|
||||
<polyline fill="none" stroke="black" points="141.5,-581 135.5,-581 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-566.2" font-family="Helvetica,sans-Serif" font-size="11.00">node-red.<domain></text>
|
||||
</g>
|
||||
<!-- dns:node-red.<domain>->dynu -->
|
||||
<g id="edge21" class="edge">
|
||||
<title>dns:node-red.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-587.05C128.03,-601.37 155,-619 155,-619 155,-619 250.14,-703.08 298.91,-746.17"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="296.78,-748.97 306.59,-752.97 301.42,-743.72 296.78,-748.97"/>
|
||||
</g>
|
||||
<!-- net:passbolt -->
|
||||
<g id="node35" class="node">
|
||||
<title>net:passbolt</title>
|
||||
<ellipse fill="#f8fafc" stroke="black" cx="1007.69" cy="-676" rx="37.77" ry="18"/>
|
||||
<text text-anchor="middle" x="1007.69" y="-673.2" font-family="Helvetica,sans-Serif" font-size="11.00">passbolt</text>
|
||||
</g>
|
||||
<!-- svc:passbolt-webapp->net:passbolt -->
|
||||
<g id="edge49" class="edge">
|
||||
<title>svc:passbolt-webapp->net:passbolt</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-36.05C782.73,-50.37 803,-68 803,-68 803,-68 960.4,-537.83 998.48,-651.47"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="996.16,-652.27 1000.71,-658.13 1000.81,-650.72 996.16,-652.27"/>
|
||||
</g>
|
||||
<!-- svc:passbolt-webapp->net:traefik -->
|
||||
<g id="edge50" class="edge">
|
||||
<title>svc:passbolt-webapp->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-36.05C782.73,-50.37 803,-68 803,-68 803,-68 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- dns:passbolt.<domain> -->
|
||||
<g id="node24" class="node">
|
||||
<title>dns:passbolt.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="134,-486 15,-486 15,-450 140,-450 140,-480 134,-486"/>
|
||||
<polyline fill="none" stroke="black" points="134,-486 134,-480 "/>
|
||||
<polyline fill="none" stroke="black" points="140,-480 134,-480 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-465.2" font-family="Helvetica,sans-Serif" font-size="11.00">passbolt.<domain></text>
|
||||
</g>
|
||||
<!-- dns:passbolt.<domain>->dynu -->
|
||||
<g id="edge23" class="edge">
|
||||
<title>dns:passbolt.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-486.05C128.03,-500.37 155,-518 155,-518 155,-518 264.64,-679.27 308.84,-744.29"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="306.11,-746.5 314.63,-752.8 311.9,-742.57 306.11,-746.5"/>
|
||||
</g>
|
||||
<!-- svc:portainer->net:traefik -->
|
||||
<g id="edge51" class="edge">
|
||||
<title>svc:portainer->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M769.22,-478.28C785.06,-493.15 803,-510 803,-510 803,-510 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- dns:portainer.<domain> -->
|
||||
<g id="node26" class="node">
|
||||
<title>dns:portainer.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="135.5,-385 13.5,-385 13.5,-349 141.5,-349 141.5,-379 135.5,-385"/>
|
||||
<polyline fill="none" stroke="black" points="135.5,-385 135.5,-379 "/>
|
||||
<polyline fill="none" stroke="black" points="141.5,-379 135.5,-379 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-364.2" font-family="Helvetica,sans-Serif" font-size="11.00">portainer.<domain></text>
|
||||
</g>
|
||||
<!-- dns:portainer.<domain>->dynu -->
|
||||
<g id="edge25" class="edge">
|
||||
<title>dns:portainer.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-385.05C128.03,-399.37 155,-417 155,-417 155,-417 273.61,-661.11 313.84,-743.91"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="310.72,-745.49 318.23,-752.96 317.01,-742.43 310.72,-745.49"/>
|
||||
</g>
|
||||
<!-- svc:prometheus->net:monitor -->
|
||||
<g id="edge52" class="edge">
|
||||
<title>svc:prometheus->net:monitor</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M786.03,-1069.4C837.48,-1048.32 925.31,-1012.34 973.18,-992.73"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="974.11,-995 979.66,-990.07 972.26,-990.46 974.11,-995"/>
|
||||
</g>
|
||||
<!-- svc:prometheus->net:traefik -->
|
||||
<g id="edge53" class="edge">
|
||||
<title>svc:prometheus->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M769.22,-1063.72C785.06,-1048.85 803,-1032 803,-1032 803,-1032 910,-929 910,-929 910,-929 949.05,-908.4 977.52,-893.39"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="978.73,-895.52 983.78,-890.09 976.45,-891.18 978.73,-895.52"/>
|
||||
</g>
|
||||
<!-- dns:prometheus.<domain> -->
|
||||
<g id="node28" class="node">
|
||||
<title>dns:prometheus.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="144,-284 5,-284 5,-248 150,-248 150,-278 144,-284"/>
|
||||
<polyline fill="none" stroke="black" points="144,-284 144,-278 "/>
|
||||
<polyline fill="none" stroke="black" points="150,-278 144,-278 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-263.2" font-family="Helvetica,sans-Serif" font-size="11.00">prometheus.<domain></text>
|
||||
</g>
|
||||
<!-- dns:prometheus.<domain>->dynu -->
|
||||
<g id="edge27" class="edge">
|
||||
<title>dns:prometheus.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-284.05C128.03,-298.37 155,-316 155,-316 155,-316 279.21,-644.59 316.53,-743.29"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="313.34,-744.77 320.15,-752.88 319.89,-742.29 313.34,-744.77"/>
|
||||
</g>
|
||||
<!-- svc:searxng-webapp->net:traefik -->
|
||||
<g id="edge54" class="edge">
|
||||
<title>svc:searxng-webapp->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-369.05C782.73,-383.37 803,-401 803,-401 803,-401 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- dns:searxng.<domain> -->
|
||||
<g id="node30" class="node">
|
||||
<title>dns:searxng.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="133,-183 16,-183 16,-147 139,-147 139,-177 133,-183"/>
|
||||
<polyline fill="none" stroke="black" points="133,-183 133,-177 "/>
|
||||
<polyline fill="none" stroke="black" points="139,-177 133,-177 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-162.2" font-family="Helvetica,sans-Serif" font-size="11.00">searxng.<domain></text>
|
||||
</g>
|
||||
<!-- dns:searxng.<domain>->dynu -->
|
||||
<g id="edge29" class="edge">
|
||||
<title>dns:searxng.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-183.05C128.03,-197.37 155,-215 155,-215 155,-215 283.58,-630.64 318.4,-743.18"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="315.08,-744.3 321.38,-752.82 321.76,-742.23 315.08,-744.3"/>
|
||||
</g>
|
||||
<!-- dns:traefik.<domain> -->
|
||||
<g id="node31" class="node">
|
||||
<title>dns:traefik.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="128.5,-82 20.5,-82 20.5,-46 134.5,-46 134.5,-76 128.5,-82"/>
|
||||
<polyline fill="none" stroke="black" points="128.5,-82 128.5,-76 "/>
|
||||
<polyline fill="none" stroke="black" points="134.5,-76 128.5,-76 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-61.2" font-family="Helvetica,sans-Serif" font-size="11.00">traefik.<domain></text>
|
||||
</g>
|
||||
<!-- dns:traefik.<domain>->dynu -->
|
||||
<g id="edge31" class="edge">
|
||||
<title>dns:traefik.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-82.05C128.03,-96.37 155,-114 155,-114 155,-114 286.65,-616.89 319.6,-742.72"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="316.3,-743.95 322.22,-752.74 323.07,-742.18 316.3,-743.95"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 41 KiB |
@@ -0,0 +1,4 @@
|
||||
digraph PhysicalTopology {
|
||||
graph [rankdir=LR, fontname="Helvetica", nodesep=1.0, ranksep=1.5];
|
||||
"placeholder:inventory" [shape=note, style="filled", fillcolor="#fef3c7", label="Host inventory JSON not found.\nGenerate terraform inventory and rerun scripts/docs/generate-all.sh\n(--host-inventory <path>)."];
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.43.0 (0)
|
||||
-->
|
||||
<!-- Title: PhysicalTopology Pages: 1 -->
|
||||
<svg width="514pt" height="61pt"
|
||||
viewBox="0.00 0.00 514.00 61.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 57)">
|
||||
<title>PhysicalTopology</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-57 510,-57 510,4 -4,4"/>
|
||||
<!-- placeholder:inventory -->
|
||||
<g id="node1" class="node">
|
||||
<title>placeholder:inventory</title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="500,-53 0,-53 0,0 506,0 506,-47 500,-53"/>
|
||||
<polyline fill="none" stroke="black" points="500,-53 500,-47 "/>
|
||||
<polyline fill="none" stroke="black" points="506,-47 500,-47 "/>
|
||||
<text text-anchor="middle" x="253" y="-37.8" font-family="Times,serif" font-size="14.00">Host inventory JSON not found.</text>
|
||||
<text text-anchor="middle" x="253" y="-22.8" font-family="Times,serif" font-size="14.00">Generate terraform inventory and rerun scripts/docs/generate-all.sh</text>
|
||||
<text text-anchor="middle" x="253" y="-7.8" font-family="Times,serif" font-size="14.00">(--host-inventory <path>).</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,61 @@
|
||||
# Docker Environment Composition
|
||||
|
||||
This repo uses multi-file Docker Compose with a wrapper script as the composition entrypoint.
|
||||
|
||||
## Composition source of truth
|
||||
|
||||
`services-up.sh` is the composition authority for this repository.
|
||||
|
||||
It:
|
||||
|
||||
1. discovers compose files under `apps/`, `monitoring/`, and `core/`,
|
||||
2. prepends shared baseline files,
|
||||
3. applies `default-environment.env` and `secrets/stack-secrets.env`,
|
||||
4. invokes `docker compose` with a stable project name.
|
||||
|
||||
Because of this, when validating or understanding runtime composition, prefer running:
|
||||
|
||||
```bash
|
||||
./services-up.sh --profile all config
|
||||
```
|
||||
|
||||
## Inputs used by `services-up.sh`
|
||||
|
||||
- `default-network.yml`
|
||||
- discovered `docker-compose.yml` / `docker-compose.yaml` files under `core/`, `apps/`, `monitoring/`
|
||||
- `default-environment.env`
|
||||
- `secrets/stack-secrets.env` (local, not committed)
|
||||
|
||||
## Typical workflows
|
||||
|
||||
### Validate final composed model
|
||||
|
||||
```bash
|
||||
./services-up.sh --profile all config
|
||||
```
|
||||
|
||||
Use this to review merged services, networks, volumes, profiles, and environment substitution.
|
||||
|
||||
### Validate one compose file directly
|
||||
|
||||
```bash
|
||||
docker compose -f apps/nextcloud/docker-compose.yml config
|
||||
```
|
||||
|
||||
Use this when focused on one service family.
|
||||
|
||||
### Deployment prerequisites
|
||||
|
||||
Before runtime operations, follow [deployment-prerequisites.md](deployment-prerequisites.md) to create required local secret files.
|
||||
|
||||
## What not to do
|
||||
|
||||
- Do not treat archived compose files in `archive/` as active runtime definitions.
|
||||
- Do not hardcode secrets in committed compose files.
|
||||
- Do not bypass `services-up.sh` when trying to understand full active composition.
|
||||
|
||||
## Related docs
|
||||
|
||||
- [docs/source-of-truth.md](source-of-truth.md)
|
||||
- [docs/repo-structure.md](repo-structure.md)
|
||||
- [docs/architecture.md](architecture.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.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Documentation Strategy
|
||||
|
||||
This repository's documentation should help both humans and Codex agents make safe, accurate changes.
|
||||
|
||||
## Principles
|
||||
|
||||
1. **Authority first**: identify authoritative files clearly (Compose + `services-up.sh` for runtime; Terraform for structured inventory/reconciliation).
|
||||
2. **Task-oriented docs**: include practical workflow steps, not only conceptual text.
|
||||
3. **No speculation**: document implemented behavior, not aspirational designs without code evidence.
|
||||
4. **Cross-linking**: root README and topic docs should point to each other for discoverability.
|
||||
5. **Safety clarity**: explicitly note what should not be committed or applied casually.
|
||||
|
||||
## Documentation quality checklist
|
||||
|
||||
Before merging doc changes, check:
|
||||
|
||||
- Is this statement verifiable from current repo files?
|
||||
- Does this conflict with existing docs?
|
||||
- Does this clarify source-of-truth boundaries?
|
||||
- Does this improve a real workflow for contributors/Codex?
|
||||
- Are sensitive details excluded?
|
||||
|
||||
## Recommended update cadence
|
||||
|
||||
Update docs when any of these change:
|
||||
|
||||
- `services-up.sh` composition behavior,
|
||||
- major Compose directory or profile structure,
|
||||
- Terraform workflow conventions,
|
||||
- inventory output shapes,
|
||||
- secret handling conventions.
|
||||
|
||||
## Audience-specific outcomes
|
||||
|
||||
- Humans should quickly understand how to operate the repo safely.
|
||||
- Future Codex runs should quickly identify authoritative files, guardrails, and reconciliation workflows.
|
||||
@@ -0,0 +1,139 @@
|
||||
# Dynu DNS Read-Only Inventory
|
||||
|
||||
This repository includes a **read-only** Dynu DNS inventory workflow for `lan.ddnsgeek.com`.
|
||||
|
||||
> This integration is intentionally read-only. No Dynu mutations are permitted in this repo at this stage.
|
||||
|
||||
## Scope
|
||||
|
||||
- Fetch live DNS/domain data from Dynu using **GET requests only**.
|
||||
- Correlate Dynu hostnames with Traefik `Host(...)` rules found in compose files.
|
||||
- Generate local inventory artifacts for documentation.
|
||||
|
||||
## Safety Guard Rails
|
||||
|
||||
- Scripts fail unless `DYNU_READ_ONLY=true`.
|
||||
- No Dynu write methods (`POST`, `PUT`, `PATCH`, `DELETE`) are implemented.
|
||||
- No Terraform Dynu provider/resources/modules are introduced.
|
||||
- No Ansible Dynu mutation tasks are introduced.
|
||||
- API secrets are read from environment variables and are never logged.
|
||||
|
||||
## Correlation logic
|
||||
|
||||
`scripts/dynu/correlate_dynu_with_traefik.py` uses compose files as the source of truth and parses them as YAML.
|
||||
|
||||
It supports both common label formats:
|
||||
|
||||
- list style:
|
||||
|
||||
```yaml
|
||||
labels:
|
||||
- "traefik.http.routers.app.rule=Host(`app.lan.ddnsgeek.com`)"
|
||||
```
|
||||
|
||||
- map style:
|
||||
|
||||
```yaml
|
||||
labels:
|
||||
traefik.http.routers.app.rule: "Host(`app.lan.ddnsgeek.com`)"
|
||||
```
|
||||
|
||||
The parser extracts hostnames from router rules such as:
|
||||
|
||||
- `Host(`a`)`
|
||||
- `Host("a")`
|
||||
- `Host('a')`
|
||||
- multi-host rules (comma-delimited)
|
||||
- combined expressions such as `Host(...) && PathPrefix(...)`
|
||||
|
||||
## Route metadata in inventory
|
||||
|
||||
Each discovered hostname mapping includes:
|
||||
|
||||
- fqdn
|
||||
- compose service name
|
||||
- compose file path
|
||||
- stack area (`apps`, `monitoring`, `core`)
|
||||
- router label key(s)
|
||||
- raw router rule
|
||||
- `uses_tls`
|
||||
- `tls_options`
|
||||
- `middlewares`
|
||||
- `uses_mtls`
|
||||
- `uses_authelia`
|
||||
|
||||
mTLS is metadata only and **never blocks mapping**.
|
||||
|
||||
## Validation model
|
||||
|
||||
The generated JSON/Markdown include a top-level `validation` section with:
|
||||
|
||||
- `allowed_unmapped_hostnames`
|
||||
- `unexpected_unmapped_hostnames`
|
||||
- `duplicate_hostnames`
|
||||
- `ambiguous_hostnames`
|
||||
- `validation_ok`
|
||||
|
||||
Current policy:
|
||||
|
||||
- `edge.lan.ddnsgeek.com` is the only allowed unmapped DNS hostname.
|
||||
- every other `*.lan.ddnsgeek.com` DNS hostname should map to a compose/Traefik-discovered service.
|
||||
|
||||
Optional strict mode:
|
||||
|
||||
- Set `DYNU_ENFORCE_VALIDATION=true` to make the correlate script exit non-zero when unexpected unmapped hostnames exist.
|
||||
|
||||
## Required Environment Variables
|
||||
|
||||
- `DYNU_API_KEY` (required for fetch)
|
||||
- `DYNU_BASE_URL` (optional, defaults to `https://api.dynu.com`)
|
||||
- `DYNU_READ_ONLY` (**must** be `true`)
|
||||
|
||||
Recommended local secrets file (not committed): `secrets/dynu.env`
|
||||
|
||||
```bash
|
||||
DYNU_API_KEY=replace-with-real-api-key
|
||||
DYNU_READ_ONLY=true
|
||||
DYNU_BASE_URL=https://api.dynu.com
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- Keep values unquoted unless required by your shell.
|
||||
- `scripts/dynu/build_dns_inventory.sh` will auto-load `secrets/dynu.env` when present.
|
||||
|
||||
## Commands
|
||||
|
||||
Run directly:
|
||||
|
||||
```bash
|
||||
DYNU_READ_ONLY=true DYNU_API_KEY=... python3 scripts/dynu/fetch_dynu_dns.py
|
||||
DYNU_READ_ONLY=true python3 scripts/dynu/correlate_dynu_with_traefik.py
|
||||
```
|
||||
|
||||
Or run the wrapper:
|
||||
|
||||
```bash
|
||||
scripts/dynu/build_dns_inventory.sh
|
||||
```
|
||||
|
||||
## Artifacts
|
||||
|
||||
- `data/dns/dynu_live.json` (generated, untracked by default due to repo `data/` ignore)
|
||||
- `data/dns/dynu_traefik_inventory.json` (generated, untracked by default)
|
||||
- `docs/generated/dns-inventory.md` (generated documentation artifact)
|
||||
|
||||
Because `data/` is gitignored in this repository, JSON outputs are intentionally local-only unless ignore behavior changes in the future.
|
||||
|
||||
## Ansible Wrapper (Read-Only)
|
||||
|
||||
A syntax-safe wrapper playbook is provided at:
|
||||
|
||||
- `infrastructure/ansible/playbooks/dns-inventory.yml`
|
||||
|
||||
It only executes the local read-only scripts and does not call write-capable Dynu APIs.
|
||||
|
||||
## Not Managed Yet
|
||||
|
||||
Dynu DNS records are **not** managed by Terraform or Ansible in this repository at this stage.
|
||||
No configuration in this repository sends Dynu mutation requests.
|
||||
@@ -0,0 +1,26 @@
|
||||
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
|
||||
apps/shift-recorder/docker-compose.yml
|
||||
apps/stockfill/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
|
||||
@@ -0,0 +1,61 @@
|
||||
# Docker Compose Inventory
|
||||
|
||||
Source fingerprint: `0fad36c3fed6`
|
||||
|
||||
## Summary
|
||||
|
||||
| Item | Count |
|
||||
|---|---:|
|
||||
| Services | 30 |
|
||||
| Networks | 5 |
|
||||
| Volumes | 0 |
|
||||
|
||||
## Services
|
||||
|
||||
| Service | Container | Image | Build | Profiles | Networks | Ports | Restart |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| authelia | authelia | authelia/authelia | /home/nixos/docker/core/authelia | core, all, authelia, traefik | traefik | | always |
|
||||
| crowdsec | crowdsec | | /home/nixos/docker/core/crowdsec | core, all, crowdsec, traefik | traefik | | always |
|
||||
| docker-socket-proxy | docker-socket-proxy | tecnativa/docker-socket-proxy:latest | | monitoring, all, docker-socket-proxy, core, traefik, prometheus | monitor, traefik | | unless-stopped |
|
||||
| docker-update-exporter | docker-update-exporter | | /home/nixos/docker/monitoring/docker-exporter | monitoring, all, docker-exporter, prometheus | monitor | | unless-stopped |
|
||||
| error-pages | error-pages | tarampampam/error-pages:3 | | core, all, error-pages, traefik | traefik | | always |
|
||||
| gitea | gitea | gitea/gitea:latest | | apps, all, gitea | traefik | | always |
|
||||
| gitea-runner | gitea-runner | gitea/act_runner:latest | | apps, all, gitea, ci | traefik | | always |
|
||||
| gotify | gotify | gotify/server:latest | | monitoring, all, gotify | traefik | | always |
|
||||
| grafana | grafana | grafana/grafana:latest | | monitoring, all, grafana | monitor, traefik | | unless-stopped |
|
||||
| gramps-redis | gramps-redis | valkey/valkey:8-alpine | | apps, all, gramps | gramps | | always |
|
||||
| grampsweb | gramps-web | ghcr.io/gramps-project/grampsweb:latest | | apps, all, gramps | gramps, traefik | | always |
|
||||
| grampsweb_celery | gramps-web-celery | ghcr.io/gramps-project/grampsweb:latest | | apps, all, gramps | gramps | | always |
|
||||
| influxdb | influxdb | influxdb:2.7 | | monitoring, all, influxdb, prometheus | monitor, traefik | | unless-stopped |
|
||||
| monitor-kuma | monitor-kuma | louislam/uptime-kuma:2.1.1 | | monitoring, all, uptime-kuma | monitor, traefik | | always |
|
||||
| mtls-bridge | mtls-bridge | | /home/nixos/docker/monitoring/mtls-bridge | monitoring, all, mtls-bridge | monitor, traefik | | unless-stopped |
|
||||
| nextcloud-db | nextcloud-db | mariadb:11.4 | | apps, all, nextcloud | nextcloud | | always |
|
||||
| nextcloud-redis | nextcloud-redis | redis | | apps, all, nextcloud | nextcloud | | always |
|
||||
| nextcloud-webapp | nextcloud-webapp | | /home/nixos/docker/apps/nextcloud | apps, all, nextcloud | nextcloud, traefik | | always |
|
||||
| node-exporter | node-exporter | prom/node-exporter:latest | | monitoring, all, node-exporter, prometheus | monitor | | unless-stopped |
|
||||
| node-red | node-red | | /home/nixos/docker/monitoring/node-red | monitoring, all, node-red | monitor, traefik | | unless-stopped |
|
||||
| passbolt-db | passbolt-db | mariadb:12 | | apps, all, passbolt | passbolt | | always |
|
||||
| passbolt-webapp | passbolt-webapp | passbolt/passbolt:latest-ce | | apps, all, passbolt | passbolt, traefik | | always |
|
||||
| pihole-exporter | pihole-exporter | ekofr/pihole-exporter:latest | | monitoring, all, pihole-exporter, prometheus | monitor | {'mode': 'ingress', 'target': 9617, 'published': '9617', 'protocol': 'tcp'} | unless-stopped |
|
||||
| portainer | portainer | portainer/portainer-ce:latest | | monitoring, all, portainer | traefik | | unless-stopped |
|
||||
| prometheus | prometheus | prom/prometheus:latest | | monitoring, all, prometheus | monitor, traefik | | unless-stopped |
|
||||
| searxng-webapp | searxng-webapp | searxng/searxng | | apps, all, searxng | traefik | | always |
|
||||
| shift-recorder-web | shift-recorder | | /home/nixos/docker/apps/shift-recorder | apps, all, shift-recorder | traefik | | unless-stopped |
|
||||
| stockfill | stockfill | | /home/nixos/docker/apps/stockfill | apps, all, stockfill | traefik | | unless-stopped |
|
||||
| telegraf | telegraf | telegraf:latest | | monitoring, all, telegraf, prometheus | monitor | | unless-stopped |
|
||||
| traefik | traefik | traefik:3 | /home/nixos/docker/core | core, all, traefik | traefik | {'mode': 'ingress', 'target': 80, 'published': '80', 'protocol': 'tcp'}, {'mode': 'ingress', 'target': 443, 'published': '443', 'protocol': 'tcp'} | always |
|
||||
|
||||
## Networks
|
||||
|
||||
| Network | Driver | External |
|
||||
|---|---|---|
|
||||
| gramps | | False |
|
||||
| monitor | | False |
|
||||
| nextcloud | | False |
|
||||
| passbolt | | False |
|
||||
| traefik | bridge | False |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Volume | External |
|
||||
|---|---|
|
||||
@@ -0,0 +1,65 @@
|
||||
# DNS Inventory (Dynu + Traefik)
|
||||
|
||||
> This integration is intentionally read-only. No Dynu mutations are permitted in this repo at this stage.
|
||||
|
||||
- Base domain: `lan.ddnsgeek.com`
|
||||
- Dynu fetched at: `2026-04-21T04:18:38+00:00`
|
||||
- Inventory generated at: `2026-04-21T04:18:39+00:00`
|
||||
|
||||
## Summary
|
||||
|
||||
- Traefik hostnames discovered: **17**
|
||||
- Dynu hostnames discovered: **20**
|
||||
- Mapped hostnames: **17**
|
||||
- DNS-only hostnames: **3**
|
||||
- Traefik-only hostnames: **0**
|
||||
- Ambiguous hostnames: **0**
|
||||
|
||||
## Validation
|
||||
|
||||
- Validation ok: **false**
|
||||
- Allowed unmapped hostnames: `edge.lan.ddnsgeek.com`
|
||||
- Unexpected unmapped hostnames: **1**
|
||||
- Duplicate hostnames: **1**
|
||||
- Ambiguous hostnames: **0**
|
||||
|
||||
### Allowed unmapped hostnames
|
||||
|
||||
- `edge.lan.ddnsgeek.com`
|
||||
|
||||
### Unexpected unmapped hostnames
|
||||
|
||||
- `kuma.lan.ddnsgeek.com`
|
||||
|
||||
### Duplicate hostnames
|
||||
|
||||
- `mtls-bridge.lan.ddnsgeek.com`
|
||||
|
||||
### Ambiguous hostnames
|
||||
|
||||
_None._
|
||||
|
||||
## Correlation
|
||||
|
||||
| Hostname | Status | Reasons | Service(s) | Route metadata | DNS records |
|
||||
|---|---|---|---|---|---|
|
||||
| `auth.lan.ddnsgeek.com` | `mapped` | `mapped` | core/authelia | authelia [tls=true, mtls=false, authelia=false, tls_options=-, middlewares=-] | A: |
|
||||
| `edge.lan.ddnsgeek.com` | `allowed_unmapped` | `allowed_unmapped, dns_only` | - | - | A: |
|
||||
| `familytree.lan.ddnsgeek.com` | `mapped` | `mapped` | apps/grampsweb | gramps [tls=true, mtls=false, authelia=false, tls_options=-, middlewares=-] | A: |
|
||||
| `gitea.lan.ddnsgeek.com` | `mapped` | `mapped` | apps/gitea | gitea [tls=true, mtls=false, authelia=false, tls_options=-, middlewares=-] | A: |
|
||||
| `gotify.lan.ddnsgeek.com` | `mapped` | `mapped` | monitoring/gotify | gotify [tls=true, mtls=true, authelia=false, tls_options=mtls-private-admin@file, middlewares=-] | A: |
|
||||
| `grafana.lan.ddnsgeek.com` | `mapped` | `mapped` | monitoring/grafana | grafana [tls=true, mtls=true, authelia=false, tls_options=mtls-private-admin@file, middlewares=-] | A: |
|
||||
| `influxdb.lan.ddnsgeek.com` | `mapped` | `mapped` | monitoring/influxdb | influxdb [tls=true, mtls=true, authelia=true, tls_options=mtls-private-admin@file, middlewares=authelia] | A: |
|
||||
| `kuma.lan.ddnsgeek.com` | `unexpected_unmapped` | `unexpected_unmapped, dns_only` | - | - | A:120.155.63.223 |
|
||||
| `lan.ddnsgeek.com` | `dns_only` | `dns_only` | - | - | SOA: |
|
||||
| `monitor-kuma.lan.ddnsgeek.com` | `mapped` | `mapped` | monitoring/monitor-kuma | monitor [tls=true, mtls=true, authelia=false, tls_options=mtls-private-admin@file, middlewares=-] | A: |
|
||||
| `mtls-bridge.lan.ddnsgeek.com` | `mapped` | `mapped` | monitoring/mtls-bridge | mtls-bridge [tls=true, mtls=true, authelia=false, tls_options=-, middlewares=mtls-bridge-auth,mtls-bridge-cors]<br>mtls-bridge-preflight [tls=true, mtls=true, authelia=false, tls_options=-, middlewares=mtls-bridge-cors] | A: |
|
||||
| `nextcloud.lan.ddnsgeek.com` | `mapped` | `mapped` | apps/nextcloud-webapp | nextcloud [tls=true, mtls=false, authelia=false, tls_options=-, middlewares=nextcloud-dav,nextcloud-webfinger] | A: |
|
||||
| `node-red.lan.ddnsgeek.com` | `mapped` | `mapped` | monitoring/node-red | node-red [tls=true, mtls=true, authelia=true, tls_options=mtls-private-admin@file, middlewares=authelia] | A: |
|
||||
| `passbolt.lan.ddnsgeek.com` | `mapped` | `mapped` | apps/passbolt-webapp | passbolt [tls=true, mtls=false, authelia=false, tls_options=-, middlewares=-] | A: |
|
||||
| `portainer.lan.ddnsgeek.com` | `mapped` | `mapped` | monitoring/portainer | portainer [tls=true, mtls=true, authelia=false, tls_options=mtls-private-admin@file, middlewares=-] | A: |
|
||||
| `prometheus.lan.ddnsgeek.com` | `mapped` | `mapped` | monitoring/prometheus | prometheus [tls=true, mtls=true, authelia=true, tls_options=mtls-private-admin@file, middlewares=authelia] | A: |
|
||||
| `searxng.lan.ddnsgeek.com` | `mapped` | `mapped` | apps/searxng-webapp | searxng [tls=true, mtls=false, authelia=false, tls_options=-, middlewares=-] | A: |
|
||||
| `shifts.lan.ddnsgeek.com` | `mapped` | `mapped` | apps/shift-recorder-web | shifts [tls=true, mtls=false, authelia=false, tls_options=-, middlewares=-] | A: |
|
||||
| `stockfill.lan.ddnsgeek.com` | `mapped` | `mapped` | apps/stockfill | stockfill [tls=true, mtls=false, authelia=false, tls_options=-, middlewares=-] | A: |
|
||||
| `traefik.lan.ddnsgeek.com` | `mapped` | `mapped` | core/traefik | traefik [tls=true, mtls=true, authelia=true, tls_options=mtls-private-admin@file, middlewares=authelia] | A: |
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
||||
# Host Topology
|
||||
|
||||
> Generated by `scripts/docs/generate_host_topology.py` on 2026-05-12T18:32:09+00:00.
|
||||
|
||||
## Topology Diagram
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
phys_pve["pve\nphysical"]
|
||||
phys_raspberrypi["raspberrypi\nphysical"]
|
||||
virt_docker["docker\nvirtual"]
|
||||
phys_pve --> virt_docker
|
||||
virt_nix_cache["nix-cache\nvirtual"]
|
||||
phys_pve --> virt_nix_cache
|
||||
virt_pbs["pbs\nvirtual"]
|
||||
phys_pve --> virt_pbs
|
||||
virt_pihole["pihole\nvirtual"]
|
||||
phys_pve --> virt_pihole
|
||||
virt_server_nixos["server-nixos\nvirtual"]
|
||||
phys_pve --> virt_server_nixos
|
||||
```
|
||||
|
||||
## Physical Hosts
|
||||
|
||||
| Name | Type | Role | Management | OS | Hypervisor | Location | Notes |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| pve | physical | proxmox | pve.sweet.home | debian | proxmox | home | Primary Proxmox VE host |
|
||||
| raspberrypi | physical | edge | raspberrypi.tail13f623.ts.net | debian | | riverglades | Raspberry Pi host |
|
||||
|
||||
## Virtual Hosts
|
||||
|
||||
| Name | Type | Role | Parent/Node | Management | OS | Notes |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| docker | virtual | docker-host | pve | | linux | Primary Docker VM |
|
||||
| nix-cache | virtual | cache | pve | | linux | Nix binary cache VM |
|
||||
| pbs | virtual | backup | pve | | linux | Proxmox Backup Server VM |
|
||||
| pihole | virtual | dns | pve | | linux | DNS filtering VM |
|
||||
| server-nixos | virtual | nixos-server | pve | | nixos | General-purpose NixOS VM |
|
||||
@@ -0,0 +1,11 @@
|
||||
# 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)
|
||||
- [Docker Compose diagram](../diagrams/docker-compose.svg)
|
||||
@@ -0,0 +1,23 @@
|
||||
# Traefik Routes
|
||||
|
||||
| Service | Router | Rule | Entrypoints | TLS | Middlewares | Target Port |
|
||||
|---|---|---|---|---|---|---|
|
||||
| authelia | authelia | Host(`auth.lan.ddnsgeek.com`) | websecure | true | | |
|
||||
| error-pages | error-pages-router | HostRegexp(`{host:.+}`) | web | | error-pages-middleware | |
|
||||
| gitea | gitea | Host(`gitea.lan.ddnsgeek.com`) | websecure | true | | 3000 |
|
||||
| gotify | gotify | Host(`gotify.lan.ddnsgeek.com`) | websecure | | | 80 |
|
||||
| grafana | grafana | Host(`grafana.lan.ddnsgeek.com`) | websecure | | | 3000 |
|
||||
| grampsweb | gramps | Host(`familytree.lan.ddnsgeek.com`) | websecure | | | 5000 |
|
||||
| influxdb | influxdb | Host(`influxdb.lan.ddnsgeek.com`) | websecure | | authelia | 8086 |
|
||||
| monitor-kuma | monitor | Host(`monitor-kuma.lan.ddnsgeek.com`) | websecure | true | | 3001 |
|
||||
| mtls-bridge | mtls-bridge | Host(`mtls-bridge.lan.ddnsgeek.com`) | websecure | | mtls-bridge-auth,mtls-bridge-cors | 8080 |
|
||||
| mtls-bridge | mtls-bridge-preflight | Host(`mtls-bridge.lan.ddnsgeek.com`) && Method(`OPTIONS`) | websecure | | mtls-bridge-cors | |
|
||||
| nextcloud-webapp | nextcloud | Host(`nextcloud.lan.ddnsgeek.com`) | websecure | | nextcloud-dav, nextcloud-webfinger | |
|
||||
| node-red | node-red | Host(`node-red.lan.ddnsgeek.com`) | websecure | | authelia | 1880 |
|
||||
| passbolt-webapp | passbolt | Host(`passbolt.lan.ddnsgeek.com`) | websecure | | | |
|
||||
| portainer | portainer | Host(`portainer.lan.ddnsgeek.com`) | websecure | true | | 9000 |
|
||||
| prometheus | prometheus | Host(`prometheus.lan.ddnsgeek.com`) | websecure | | authelia | 9090 |
|
||||
| searxng-webapp | searxng | Host(`searxng.lan.ddnsgeek.com`) | websecure | | | 8080 |
|
||||
| shift-recorder-web | shifts | Host(`shifts.lan.ddnsgeek.com`) | websecure | true | | 80 |
|
||||
| stockfill | stockfill | Host(`stockfill.lan.ddnsgeek.com`) | websecure | true | | 80 |
|
||||
| traefik | traefik | Host(`traefik.lan.ddnsgeek.com`) | websecure | | authelia | |
|
||||
@@ -0,0 +1,29 @@
|
||||
# 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)
|
||||
- [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/
|
||||
```
|
||||
@@ -0,0 +1,76 @@
|
||||
# Infrastructure Inventory Model
|
||||
|
||||
This repository treats infrastructure inventory as first-class documentation.
|
||||
|
||||
## Intent
|
||||
|
||||
The goal is not only deployment configuration, but also a maintainable map of:
|
||||
|
||||
- what hosts/VMs exist,
|
||||
- how they are identified,
|
||||
- what selected runtime objects are mirrored into Terraform,
|
||||
- what outputs can be consumed by docs and future tooling.
|
||||
|
||||
## Current inventory sources
|
||||
|
||||
### 1) Terraform Proxmox layer
|
||||
|
||||
`infrastructure/terraform/proxmox/` contains imported/reconciled VM resources and local metadata for physical hosts.
|
||||
|
||||
This is currently the most structured host/VM inventory in the repo.
|
||||
|
||||
### 2) Terraform Docker layer
|
||||
|
||||
`infrastructure/terraform/docker/` contains selective Docker container resources used as documentation-oriented mirrors.
|
||||
|
||||
These resources should match existing running containers, not redefine runtime composition strategy.
|
||||
|
||||
|
||||
### 3) Ansible bootstrap layer
|
||||
|
||||
`infrastructure/ansible/` provides an emerging inventory/configuration scaffold for hosts and devices.
|
||||
|
||||
Current scope is intentionally limited to structure, variables scaffolding, and safe validation workflows.
|
||||
|
||||
### 4) Compose runtime definitions
|
||||
|
||||
Compose files define intended service runtime composition, networking, labels, and integration.
|
||||
|
||||
### 5) Architecture docs
|
||||
|
||||
`docs/architecture.md` provides a human-readable topology view based on repository configuration and observed runtime signals.
|
||||
|
||||
### 6) Dynu DNS read-only inventory
|
||||
|
||||
`scripts/dynu/` and `docs/dynu-dns-inventory.md` provide a strictly read-only DNS inventory workflow:
|
||||
|
||||
- fetch Dynu DNS data with GET-only API usage,
|
||||
- correlate Dynu hostnames with Traefik `Host(...)` labels in Compose sources,
|
||||
- generate local JSON and markdown artifacts for documentation pipelines.
|
||||
|
||||
Dynu write operations are intentionally blocked in this repository stage.
|
||||
|
||||
### 7) Terraform Dynu DNS layer
|
||||
|
||||
`infrastructure/terraform/dynu/` is the brownfield Terraform DNS mirror/reconciliation root for Dynu domain/record inventory outputs.
|
||||
|
||||
At this stage it is primarily documentation-oriented catalog output, ready for one-object-at-a-time imports.
|
||||
|
||||
## Output shaping expectations
|
||||
|
||||
When adding Terraform outputs for documentation/tooling:
|
||||
|
||||
- prefer concise inventory maps/lists,
|
||||
- include stable identifiers and roles,
|
||||
- avoid raw giant provider objects where possible,
|
||||
- include descriptions so future consumers understand intent.
|
||||
|
||||
## Limitations today
|
||||
|
||||
- Generated host topology document: `docs/generated/host-topology.md` (via `scripts/docs/build_host_topology.sh`).
|
||||
- No full generated inventory document pipeline is present yet.
|
||||
- Some Terraform files still include generated boilerplate comments requiring ongoing cleanup.
|
||||
- Ansible is currently a bootstrap inventory/configuration layer and is not authoritative for full operations yet.
|
||||
- NixOS operational management is not yet implemented as an Ansible authority in this repo.
|
||||
|
||||
These limitations are expected for the current adoption stage.
|
||||
@@ -0,0 +1,10 @@
|
||||
# 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:
|
||||
|
||||
@@ -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)
|
||||
@@ -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.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Docker Compose Inventory
|
||||
|
||||
Source fingerprint: `232be78ef441`
|
||||
|
||||
## Summary
|
||||
|
||||
| Item | Count |
|
||||
|---|---:|
|
||||
| Services | 28 |
|
||||
| Networks | 5 |
|
||||
| Volumes | 0 |
|
||||
|
||||
## Services
|
||||
|
||||
| Service | Container | Image | Build | Profiles | Networks | Ports | Restart |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| authelia | authelia | authelia/authelia | /home/nixos/docker/core/authelia | core, all, authelia, traefik | traefik | | always |
|
||||
| crowdsec | crowdsec | | /home/nixos/docker/core/crowdsec | core, all, crowdsec, traefik | traefik | | always |
|
||||
| docker-socket-proxy | docker-socket-proxy | tecnativa/docker-socket-proxy:latest | | monitoring, all, docker-socket-proxy, core, traefik, prometheus | monitor, traefik | | unless-stopped |
|
||||
| docker-update-exporter | docker-update-exporter | | /home/nixos/docker/monitoring/docker-exporter | monitoring, all, docker-exporter, prometheus | monitor | | unless-stopped |
|
||||
| error-pages | error-pages | tarampampam/error-pages:3 | | core, all, error-pages, traefik | traefik | | always |
|
||||
| gitea | gitea | gitea/gitea:latest | | apps, all, gitea | traefik | | always |
|
||||
| gitea-runner | gitea-runner | gitea/act_runner:latest | | apps, all, gitea, ci | traefik | | always |
|
||||
| gotify | gotify | gotify/server:latest | | monitoring, all, gotify | traefik | | always |
|
||||
| grafana | grafana | grafana/grafana:latest | | monitoring, all, grafana | monitor, traefik | | unless-stopped |
|
||||
| gramps-redis | gramps-redis | valkey/valkey:8-alpine | | apps, all, gramps | gramps | | always |
|
||||
| grampsweb | gramps-web | ghcr.io/gramps-project/grampsweb:latest | | apps, all, gramps | gramps, traefik | | always |
|
||||
| grampsweb_celery | gramps-web-celery | ghcr.io/gramps-project/grampsweb:latest | | apps, all, gramps | gramps | | always |
|
||||
| influxdb | influxdb | influxdb:2.7 | | monitoring, all, influxdb, prometheus | monitor, traefik | | unless-stopped |
|
||||
| monitor-kuma | monitor-kuma | louislam/uptime-kuma:2.1.1 | | monitoring, all, uptime-kuma | monitor, traefik | | always |
|
||||
| mtls-bridge | mtls-bridge | | /home/nixos/docker/monitoring/mtls-bridge | monitoring, all, mtls-bridge | monitor, traefik | | unless-stopped |
|
||||
| nextcloud-db | nextcloud-db | mariadb:11.4 | | apps, all, nextcloud | nextcloud | | always |
|
||||
| nextcloud-redis | nextcloud-redis | redis | | apps, all, nextcloud | nextcloud | | always |
|
||||
| nextcloud-webapp | nextcloud-webapp | | /home/nixos/docker/apps/nextcloud | apps, all, nextcloud | nextcloud, traefik | | always |
|
||||
| node-exporter | node-exporter | prom/node-exporter:latest | | monitoring, all, node-exporter, prometheus | monitor | | unless-stopped |
|
||||
| node-red | node-red | | /home/nixos/docker/monitoring/node-red | monitoring, all, node-red | monitor, traefik | | unless-stopped |
|
||||
| passbolt-db | passbolt-db | mariadb:12 | | apps, all, passbolt | passbolt | | always |
|
||||
| passbolt-webapp | passbolt-webapp | passbolt/passbolt:latest-ce | | apps, all, passbolt | passbolt, traefik | | always |
|
||||
| pihole-exporter | pihole-exporter | ekofr/pihole-exporter:latest | | monitoring, all, pihole-exporter, prometheus | monitor | {'mode': 'ingress', 'target': 9617, 'published': '9617', 'protocol': 'tcp'} | unless-stopped |
|
||||
| portainer | portainer | portainer/portainer-ce:latest | | monitoring, all, portainer | traefik | | unless-stopped |
|
||||
| prometheus | prometheus | prom/prometheus:latest | | monitoring, all, prometheus | monitor, traefik | | unless-stopped |
|
||||
| searxng-webapp | searxng-webapp | searxng/searxng | | apps, all, searxng | traefik | | always |
|
||||
| telegraf | telegraf | telegraf:latest | | monitoring, all, telegraf, prometheus | monitor | | unless-stopped |
|
||||
| traefik | traefik | traefik:3 | /home/nixos/docker/core | core, all, traefik | traefik | {'mode': 'ingress', 'target': 80, 'published': '80', 'protocol': 'tcp'}, {'mode': 'ingress', 'target': 443, 'published': '443', 'protocol': 'tcp'} | always |
|
||||
|
||||
## Networks
|
||||
|
||||
| Network | Driver | External |
|
||||
|---|---|---|
|
||||
| gramps | | False |
|
||||
| monitor | | False |
|
||||
| nextcloud | | False |
|
||||
| passbolt | | False |
|
||||
| traefik | bridge | False |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Volume | External |
|
||||
|---|---|
|
||||
@@ -0,0 +1,19 @@
|
||||
# Infrastructure diagrams
|
||||
|
||||
## Physical / virtual topology
|
||||
|
||||
This view groups containers by inferred host and service role (edge/proxy/auth, monitoring, automation, apps, and supporting storage/services).
|
||||
|
||||
<div class="diagram-wrap">
|
||||
<img src="physical-topology.svg" alt="Physical topology">
|
||||
</div>
|
||||
|
||||
## Docker, Traefik and Dynu routing
|
||||
|
||||
This view shows sanitised public DNS names flowing to Traefik, then to exposed Docker services, with backend Docker network membership shown as secondary context.
|
||||
|
||||
_Diagrams are generated from Compose data and Traefik labels._
|
||||
|
||||
<div class="diagram-wrap">
|
||||
<img src="docker-traefik-dynu.svg" alt="Docker Traefik Dynu">
|
||||
</div>
|
||||
@@ -0,0 +1,439 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.43.0 (0)
|
||||
-->
|
||||
<!-- Title: Compose Pages: 1 -->
|
||||
<svg width="334pt" height="1502pt"
|
||||
viewBox="0.00 0.00 334.49 1502.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1498)">
|
||||
<title>Compose</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-1498 330.49,-1498 330.49,4 -4,4"/>
|
||||
<!-- svc:authelia -->
|
||||
<g id="node1" class="node">
|
||||
<title>svc:authelia</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="126,-738 54,-738 54,-702 126,-702 126,-738"/>
|
||||
<text text-anchor="middle" x="90" y="-716.3" font-family="Helvetica,sans-Serif" font-size="14.00">authelia</text>
|
||||
</g>
|
||||
<!-- net:traefik -->
|
||||
<g id="node33" class="node">
|
||||
<title>net:traefik</title>
|
||||
<ellipse fill="#f4f4f4" stroke="black" cx="271.25" cy="-774" rx="40.09" ry="18"/>
|
||||
<text text-anchor="middle" x="271.25" y="-770.3" font-family="Helvetica,sans-Serif" font-size="14.00">traefik</text>
|
||||
</g>
|
||||
<!-- svc:authelia->net:traefik -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>svc:authelia->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M126.41,-730.67C155.5,-739.43 196.8,-751.87 227.69,-761.18"/>
|
||||
<polygon fill="black" stroke="black" points="226.74,-764.55 237.32,-764.08 228.76,-757.85 226.74,-764.55"/>
|
||||
</g>
|
||||
<!-- svc:crowdsec -->
|
||||
<g id="node2" class="node">
|
||||
<title>svc:crowdsec</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="130.5,-684 49.5,-684 49.5,-648 130.5,-648 130.5,-684"/>
|
||||
<text text-anchor="middle" x="90" y="-662.3" font-family="Helvetica,sans-Serif" font-size="14.00">crowdsec</text>
|
||||
</g>
|
||||
<!-- svc:crowdsec->net:traefik -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>svc:crowdsec->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M130.61,-674.06C146.59,-678.3 164.81,-684.44 180,-693 206.25,-707.78 231.35,-731.35 248.38,-749.26"/>
|
||||
<polygon fill="black" stroke="black" points="246.24,-752.1 255.62,-757.03 251.37,-747.33 246.24,-752.1"/>
|
||||
</g>
|
||||
<!-- svc:docker-socket-proxy -->
|
||||
<g id="node3" class="node">
|
||||
<title>svc:docker-socket-proxy</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="167.5,-954 12.5,-954 12.5,-918 167.5,-918 167.5,-954"/>
|
||||
<text text-anchor="middle" x="90" y="-932.3" font-family="Helvetica,sans-Serif" font-size="14.00">docker-socket-proxy</text>
|
||||
</g>
|
||||
<!-- net:monitor -->
|
||||
<g id="node30" class="node">
|
||||
<title>net:monitor</title>
|
||||
<ellipse fill="#f4f4f4" stroke="black" cx="271.25" cy="-1206" rx="46.29" ry="18"/>
|
||||
<text text-anchor="middle" x="271.25" y="-1202.3" font-family="Helvetica,sans-Serif" font-size="14.00">monitor</text>
|
||||
</g>
|
||||
<!-- svc:docker-socket-proxy->net:monitor -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>svc:docker-socket-proxy->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M167.53,-953.71C172.02,-956.38 176.24,-959.46 180,-963 242.3,-1021.6 261.83,-1127.12 267.77,-1177.6"/>
|
||||
<polygon fill="black" stroke="black" points="264.31,-1178.21 268.86,-1187.78 271.27,-1177.46 264.31,-1178.21"/>
|
||||
</g>
|
||||
<!-- svc:docker-socket-proxy->net:traefik -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>svc:docker-socket-proxy->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M165.31,-917.9C170.5,-915.32 175.46,-912.37 180,-909 218.01,-880.82 244.97,-831.56 259.03,-800.98"/>
|
||||
<polygon fill="black" stroke="black" points="262.27,-802.31 263.14,-791.76 255.87,-799.46 262.27,-802.31"/>
|
||||
</g>
|
||||
<!-- svc:docker-update-exporter -->
|
||||
<g id="node4" class="node">
|
||||
<title>svc:docker-update-exporter</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="180,-1494 0,-1494 0,-1458 180,-1458 180,-1494"/>
|
||||
<text text-anchor="middle" x="90" y="-1472.3" font-family="Helvetica,sans-Serif" font-size="14.00">docker-update-exporter</text>
|
||||
</g>
|
||||
<!-- svc:docker-update-exporter->net:monitor -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>svc:docker-update-exporter->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M168.37,-1457.79C172.55,-1455.23 176.47,-1452.32 180,-1449 242.3,-1390.4 261.83,-1284.88 267.77,-1234.4"/>
|
||||
<polygon fill="black" stroke="black" points="271.27,-1234.54 268.86,-1224.22 264.31,-1233.79 271.27,-1234.54"/>
|
||||
</g>
|
||||
<!-- svc:error-pages -->
|
||||
<g id="node5" class="node">
|
||||
<title>svc:error-pages</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="137.5,-630 42.5,-630 42.5,-594 137.5,-594 137.5,-630"/>
|
||||
<text text-anchor="middle" x="90" y="-608.3" font-family="Helvetica,sans-Serif" font-size="14.00">error-pages</text>
|
||||
</g>
|
||||
<!-- svc:error-pages->net:traefik -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>svc:error-pages->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M137.71,-619.76C152.25,-623.79 167.68,-629.86 180,-639 218.01,-667.18 244.97,-716.44 259.03,-747.02"/>
|
||||
<polygon fill="black" stroke="black" points="255.87,-748.54 263.14,-756.24 262.27,-745.69 255.87,-748.54"/>
|
||||
</g>
|
||||
<!-- svc:gitea -->
|
||||
<g id="node6" class="node">
|
||||
<title>svc:gitea</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="117,-576 63,-576 63,-540 117,-540 117,-576"/>
|
||||
<text text-anchor="middle" x="90" y="-554.3" font-family="Helvetica,sans-Serif" font-size="14.00">gitea</text>
|
||||
</g>
|
||||
<!-- svc:gitea->net:traefik -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>svc:gitea->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M117.07,-560.28C136.41,-563.2 162.37,-569.85 180,-585 229.98,-627.95 254.42,-704.8 264.44,-746.04"/>
|
||||
<polygon fill="black" stroke="black" points="261.07,-747 266.73,-755.95 267.88,-745.42 261.07,-747"/>
|
||||
</g>
|
||||
<!-- svc:gitea-runner -->
|
||||
<g id="node7" class="node">
|
||||
<title>svc:gitea-runner</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="142,-522 38,-522 38,-486 142,-486 142,-522"/>
|
||||
<text text-anchor="middle" x="90" y="-500.3" font-family="Helvetica,sans-Serif" font-size="14.00">gitea-runner</text>
|
||||
</g>
|
||||
<!-- svc:gitea-runner->net:traefik -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>svc:gitea-runner->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M142.31,-511.04C155.9,-515.03 169.65,-521.26 180,-531 242.3,-589.6 261.83,-695.12 267.77,-745.6"/>
|
||||
<polygon fill="black" stroke="black" points="264.31,-746.21 268.86,-755.78 271.27,-745.46 264.31,-746.21"/>
|
||||
</g>
|
||||
<!-- svc:gotify -->
|
||||
<g id="node8" class="node">
|
||||
<title>svc:gotify</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="118,-468 62,-468 62,-432 118,-432 118,-468"/>
|
||||
<text text-anchor="middle" x="90" y="-446.3" font-family="Helvetica,sans-Serif" font-size="14.00">gotify</text>
|
||||
</g>
|
||||
<!-- svc:gotify->net:traefik -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>svc:gotify->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M118.17,-451.6C137.81,-454.16 163.67,-460.68 180,-477 254.99,-551.96 268.02,-687.13 270.03,-745.69"/>
|
||||
<polygon fill="black" stroke="black" points="266.53,-745.79 270.29,-755.69 273.53,-745.61 266.53,-745.79"/>
|
||||
</g>
|
||||
<!-- svc:grafana -->
|
||||
<g id="node9" class="node">
|
||||
<title>svc:grafana</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="125.5,-1278 54.5,-1278 54.5,-1242 125.5,-1242 125.5,-1278"/>
|
||||
<text text-anchor="middle" x="90" y="-1256.3" font-family="Helvetica,sans-Serif" font-size="14.00">grafana</text>
|
||||
</g>
|
||||
<!-- svc:grafana->net:monitor -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>svc:grafana->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M125.56,-1249.59C153.74,-1241.1 193.78,-1229.04 224.6,-1219.75"/>
|
||||
<polygon fill="black" stroke="black" points="225.69,-1223.08 234.26,-1216.84 223.67,-1216.38 225.69,-1223.08"/>
|
||||
</g>
|
||||
<!-- svc:grafana->net:traefik -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>svc:grafana->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M125.54,-1257.93C144.23,-1254.97 166.25,-1248.21 180,-1233 238.17,-1168.67 262.1,-892.17 268.43,-802.32"/>
|
||||
<polygon fill="black" stroke="black" points="271.93,-802.3 269.13,-792.08 264.95,-801.82 271.93,-802.3"/>
|
||||
</g>
|
||||
<!-- svc:gramps-redis -->
|
||||
<g id="node10" class="node">
|
||||
<title>svc:gramps-redis</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="144.5,-360 35.5,-360 35.5,-324 144.5,-324 144.5,-360"/>
|
||||
<text text-anchor="middle" x="90" y="-338.3" font-family="Helvetica,sans-Serif" font-size="14.00">gramps-redis</text>
|
||||
</g>
|
||||
<!-- net:gramps -->
|
||||
<g id="node29" class="node">
|
||||
<title>net:gramps</title>
|
||||
<ellipse fill="#f4f4f4" stroke="black" cx="271.25" cy="-342" rx="45.49" ry="18"/>
|
||||
<text text-anchor="middle" x="271.25" y="-338.3" font-family="Helvetica,sans-Serif" font-size="14.00">gramps</text>
|
||||
</g>
|
||||
<!-- svc:gramps-redis->net:gramps -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>svc:gramps-redis->net:gramps</title>
|
||||
<path fill="none" stroke="black" d="M144.78,-342C167.14,-342 193.05,-342 215.51,-342"/>
|
||||
<polygon fill="black" stroke="black" points="215.56,-345.5 225.56,-342 215.56,-338.5 215.56,-345.5"/>
|
||||
</g>
|
||||
<!-- svc:grampsweb -->
|
||||
<g id="node11" class="node">
|
||||
<title>svc:grampsweb</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="139,-414 41,-414 41,-378 139,-378 139,-414"/>
|
||||
<text text-anchor="middle" x="90" y="-392.3" font-family="Helvetica,sans-Serif" font-size="14.00">grampsweb</text>
|
||||
</g>
|
||||
<!-- svc:grampsweb->net:gramps -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>svc:grampsweb->net:gramps</title>
|
||||
<path fill="none" stroke="black" d="M139.03,-381.53C165.7,-373.5 198.68,-363.56 224.9,-355.66"/>
|
||||
<polygon fill="black" stroke="black" points="226.03,-358.98 234.59,-352.74 224.01,-352.27 226.03,-358.98"/>
|
||||
</g>
|
||||
<!-- svc:grampsweb->net:traefik -->
|
||||
<g id="edge14" class="edge">
|
||||
<title>svc:grampsweb->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M139.27,-401.34C154.08,-405.21 169.28,-411.81 180,-423 225.12,-470.09 256.34,-671.08 266.59,-745.84"/>
|
||||
<polygon fill="black" stroke="black" points="263.14,-746.48 267.95,-755.92 270.08,-745.55 263.14,-746.48"/>
|
||||
</g>
|
||||
<!-- svc:grampsweb_celery -->
|
||||
<g id="node12" class="node">
|
||||
<title>svc:grampsweb_celery</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="163.5,-306 16.5,-306 16.5,-270 163.5,-270 163.5,-306"/>
|
||||
<text text-anchor="middle" x="90" y="-284.3" font-family="Helvetica,sans-Serif" font-size="14.00">grampsweb_celery</text>
|
||||
</g>
|
||||
<!-- svc:grampsweb_celery->net:gramps -->
|
||||
<g id="edge15" class="edge">
|
||||
<title>svc:grampsweb_celery->net:gramps</title>
|
||||
<path fill="none" stroke="black" d="M151.18,-306.13C175.28,-313.39 202.57,-321.61 224.94,-328.35"/>
|
||||
<polygon fill="black" stroke="black" points="223.94,-331.71 234.52,-331.24 225.96,-325 223.94,-331.71"/>
|
||||
</g>
|
||||
<!-- svc:influxdb -->
|
||||
<g id="node13" class="node">
|
||||
<title>svc:influxdb</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="127,-1224 53,-1224 53,-1188 127,-1188 127,-1224"/>
|
||||
<text text-anchor="middle" x="90" y="-1202.3" font-family="Helvetica,sans-Serif" font-size="14.00">influxdb</text>
|
||||
</g>
|
||||
<!-- svc:influxdb->net:monitor -->
|
||||
<g id="edge16" class="edge">
|
||||
<title>svc:influxdb->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M127.27,-1206C152.33,-1206 186.13,-1206 214.57,-1206"/>
|
||||
<polygon fill="black" stroke="black" points="214.79,-1209.5 224.79,-1206 214.79,-1202.5 214.79,-1209.5"/>
|
||||
</g>
|
||||
<!-- svc:influxdb->net:traefik -->
|
||||
<g id="edge17" class="edge">
|
||||
<title>svc:influxdb->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M127.17,-1203.5C145.42,-1200.36 166.5,-1193.56 180,-1179 231.57,-1123.4 259.36,-885.3 267.6,-802.51"/>
|
||||
<polygon fill="black" stroke="black" points="271.1,-802.62 268.59,-792.33 264.14,-801.94 271.1,-802.62"/>
|
||||
</g>
|
||||
<!-- svc:monitor-kuma -->
|
||||
<g id="node14" class="node">
|
||||
<title>svc:monitor-kuma</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="146.5,-1170 33.5,-1170 33.5,-1134 146.5,-1134 146.5,-1170"/>
|
||||
<text text-anchor="middle" x="90" y="-1148.3" font-family="Helvetica,sans-Serif" font-size="14.00">monitor-kuma</text>
|
||||
</g>
|
||||
<!-- svc:monitor-kuma->net:monitor -->
|
||||
<g id="edge18" class="edge">
|
||||
<title>svc:monitor-kuma->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M146.73,-1168.79C171.73,-1176.32 200.85,-1185.1 224.54,-1192.23"/>
|
||||
<polygon fill="black" stroke="black" points="223.75,-1195.65 234.33,-1195.18 225.77,-1188.94 223.75,-1195.65"/>
|
||||
</g>
|
||||
<!-- svc:monitor-kuma->net:traefik -->
|
||||
<g id="edge19" class="edge">
|
||||
<title>svc:monitor-kuma->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M146.69,-1144.49C159.02,-1140.46 171.06,-1134.33 180,-1125 225.12,-1077.91 256.34,-876.92 266.59,-802.16"/>
|
||||
<polygon fill="black" stroke="black" points="270.08,-802.45 267.95,-792.08 263.14,-801.52 270.08,-802.45"/>
|
||||
</g>
|
||||
<!-- svc:mtls-bridge -->
|
||||
<g id="node15" class="node">
|
||||
<title>svc:mtls-bridge</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="138.5,-1116 41.5,-1116 41.5,-1080 138.5,-1080 138.5,-1116"/>
|
||||
<text text-anchor="middle" x="90" y="-1094.3" font-family="Helvetica,sans-Serif" font-size="14.00">mtls-bridge</text>
|
||||
</g>
|
||||
<!-- svc:mtls-bridge->net:monitor -->
|
||||
<g id="edge20" class="edge">
|
||||
<title>svc:mtls-bridge->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M138.76,-1108.34C152.58,-1112.41 167.34,-1117.87 180,-1125 206.25,-1139.78 231.35,-1163.35 248.38,-1181.26"/>
|
||||
<polygon fill="black" stroke="black" points="246.24,-1184.1 255.62,-1189.03 251.37,-1179.33 246.24,-1184.1"/>
|
||||
</g>
|
||||
<!-- svc:mtls-bridge->net:traefik -->
|
||||
<g id="edge21" class="edge">
|
||||
<title>svc:mtls-bridge->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M138.53,-1092.51C153.46,-1088.63 168.92,-1082.07 180,-1071 254.99,-996.04 268.02,-860.87 270.03,-802.31"/>
|
||||
<polygon fill="black" stroke="black" points="273.53,-802.39 270.29,-792.31 266.53,-802.21 273.53,-802.39"/>
|
||||
</g>
|
||||
<!-- svc:nextcloud-db -->
|
||||
<g id="node16" class="node">
|
||||
<title>svc:nextcloud-db</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="144,-90 36,-90 36,-54 144,-54 144,-90"/>
|
||||
<text text-anchor="middle" x="90" y="-68.3" font-family="Helvetica,sans-Serif" font-size="14.00">nextcloud-db</text>
|
||||
</g>
|
||||
<!-- net:nextcloud -->
|
||||
<g id="node31" class="node">
|
||||
<title>net:nextcloud</title>
|
||||
<ellipse fill="#f4f4f4" stroke="black" cx="271.25" cy="-180" rx="55.49" ry="18"/>
|
||||
<text text-anchor="middle" x="271.25" y="-176.3" font-family="Helvetica,sans-Serif" font-size="14.00">nextcloud</text>
|
||||
</g>
|
||||
<!-- svc:nextcloud-db->net:nextcloud -->
|
||||
<g id="edge22" class="edge">
|
||||
<title>svc:nextcloud-db->net:nextcloud</title>
|
||||
<path fill="none" stroke="black" d="M144.33,-84.04C156.48,-87.9 169.03,-92.82 180,-99 206.09,-113.7 231.04,-137.06 248.07,-154.93"/>
|
||||
<polygon fill="black" stroke="black" points="245.93,-157.77 255.31,-162.7 251.06,-153 245.93,-157.77"/>
|
||||
</g>
|
||||
<!-- svc:nextcloud-redis -->
|
||||
<g id="node17" class="node">
|
||||
<title>svc:nextcloud-redis</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="152,-198 28,-198 28,-162 152,-162 152,-198"/>
|
||||
<text text-anchor="middle" x="90" y="-176.3" font-family="Helvetica,sans-Serif" font-size="14.00">nextcloud-redis</text>
|
||||
</g>
|
||||
<!-- svc:nextcloud-redis->net:nextcloud -->
|
||||
<g id="edge23" class="edge">
|
||||
<title>svc:nextcloud-redis->net:nextcloud</title>
|
||||
<path fill="none" stroke="black" d="M152.18,-180C169.48,-180 188.35,-180 205.83,-180"/>
|
||||
<polygon fill="black" stroke="black" points="205.94,-183.5 215.94,-180 205.94,-176.5 205.94,-183.5"/>
|
||||
</g>
|
||||
<!-- svc:nextcloud-webapp -->
|
||||
<g id="node18" class="node">
|
||||
<title>svc:nextcloud-webapp</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="162.5,-252 17.5,-252 17.5,-216 162.5,-216 162.5,-252"/>
|
||||
<text text-anchor="middle" x="90" y="-230.3" font-family="Helvetica,sans-Serif" font-size="14.00">nextcloud-webapp</text>
|
||||
</g>
|
||||
<!-- svc:nextcloud-webapp->net:nextcloud -->
|
||||
<g id="edge24" class="edge">
|
||||
<title>svc:nextcloud-webapp->net:nextcloud</title>
|
||||
<path fill="none" stroke="black" d="M151.18,-215.87C173.57,-209.12 198.72,-201.55 220.11,-195.1"/>
|
||||
<polygon fill="black" stroke="black" points="221.4,-198.37 229.97,-192.13 219.38,-191.67 221.4,-198.37"/>
|
||||
</g>
|
||||
<!-- svc:nextcloud-webapp->net:traefik -->
|
||||
<g id="edge25" class="edge">
|
||||
<title>svc:nextcloud-webapp->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M162.89,-247.71C169.31,-251.2 175.18,-255.56 180,-261 212.66,-297.85 255.07,-643.36 267,-745.62"/>
|
||||
<polygon fill="black" stroke="black" points="263.55,-746.27 268.18,-755.8 270.51,-745.47 263.55,-746.27"/>
|
||||
</g>
|
||||
<!-- svc:node-exporter -->
|
||||
<g id="node19" class="node">
|
||||
<title>svc:node-exporter</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="148,-1440 32,-1440 32,-1404 148,-1404 148,-1440"/>
|
||||
<text text-anchor="middle" x="90" y="-1418.3" font-family="Helvetica,sans-Serif" font-size="14.00">node-exporter</text>
|
||||
</g>
|
||||
<!-- svc:node-exporter->net:monitor -->
|
||||
<g id="edge26" class="edge">
|
||||
<title>svc:node-exporter->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M148.25,-1412.27C159.68,-1408.33 170.94,-1402.79 180,-1395 229.98,-1352.05 254.42,-1275.2 264.44,-1233.96"/>
|
||||
<polygon fill="black" stroke="black" points="267.88,-1234.58 266.73,-1224.05 261.07,-1233 267.88,-1234.58"/>
|
||||
</g>
|
||||
<!-- svc:node-red -->
|
||||
<g id="node20" class="node">
|
||||
<title>svc:node-red</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="129.5,-1062 50.5,-1062 50.5,-1026 129.5,-1026 129.5,-1062"/>
|
||||
<text text-anchor="middle" x="90" y="-1040.3" font-family="Helvetica,sans-Serif" font-size="14.00">node-red</text>
|
||||
</g>
|
||||
<!-- svc:node-red->net:monitor -->
|
||||
<g id="edge27" class="edge">
|
||||
<title>svc:node-red->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M129.57,-1049.69C146.29,-1053.6 165.34,-1060.13 180,-1071 218.01,-1099.18 244.97,-1148.44 259.03,-1179.02"/>
|
||||
<polygon fill="black" stroke="black" points="255.87,-1180.54 263.14,-1188.24 262.27,-1177.69 255.87,-1180.54"/>
|
||||
</g>
|
||||
<!-- svc:node-red->net:traefik -->
|
||||
<g id="edge28" class="edge">
|
||||
<title>svc:node-red->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M129.95,-1040.03C147.14,-1036.46 166.48,-1029.72 180,-1017 242.3,-958.4 261.83,-852.88 267.77,-802.4"/>
|
||||
<polygon fill="black" stroke="black" points="271.27,-802.54 268.86,-792.22 264.31,-801.79 271.27,-802.54"/>
|
||||
</g>
|
||||
<!-- svc:passbolt-db -->
|
||||
<g id="node21" class="node">
|
||||
<title>svc:passbolt-db</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="139,-36 41,-36 41,0 139,0 139,-36"/>
|
||||
<text text-anchor="middle" x="90" y="-14.3" font-family="Helvetica,sans-Serif" font-size="14.00">passbolt-db</text>
|
||||
</g>
|
||||
<!-- net:passbolt -->
|
||||
<g id="node32" class="node">
|
||||
<title>net:passbolt</title>
|
||||
<ellipse fill="#f4f4f4" stroke="black" cx="271.25" cy="-72" rx="48.99" ry="18"/>
|
||||
<text text-anchor="middle" x="271.25" y="-68.3" font-family="Helvetica,sans-Serif" font-size="14.00">passbolt</text>
|
||||
</g>
|
||||
<!-- svc:passbolt-db->net:passbolt -->
|
||||
<g id="edge29" class="edge">
|
||||
<title>svc:passbolt-db->net:passbolt</title>
|
||||
<path fill="none" stroke="black" d="M139.03,-32.47C165.15,-40.34 197.32,-50.03 223.27,-57.85"/>
|
||||
<polygon fill="black" stroke="black" points="222.3,-61.21 232.88,-60.74 224.32,-54.51 222.3,-61.21"/>
|
||||
</g>
|
||||
<!-- svc:passbolt-webapp -->
|
||||
<g id="node22" class="node">
|
||||
<title>svc:passbolt-webapp</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="157.5,-144 22.5,-144 22.5,-108 157.5,-108 157.5,-144"/>
|
||||
<text text-anchor="middle" x="90" y="-122.3" font-family="Helvetica,sans-Serif" font-size="14.00">passbolt-webapp</text>
|
||||
</g>
|
||||
<!-- svc:passbolt-webapp->net:passbolt -->
|
||||
<g id="edge30" class="edge">
|
||||
<title>svc:passbolt-webapp->net:passbolt</title>
|
||||
<path fill="none" stroke="black" d="M151.18,-107.87C174.64,-100.8 201.13,-92.82 223.16,-86.19"/>
|
||||
<polygon fill="black" stroke="black" points="224.37,-89.48 232.94,-83.24 222.35,-82.77 224.37,-89.48"/>
|
||||
</g>
|
||||
<!-- svc:passbolt-webapp->net:traefik -->
|
||||
<g id="edge31" class="edge">
|
||||
<title>svc:passbolt-webapp->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M157.85,-136.93C166.26,-140.81 174,-146.02 180,-153 189.88,-164.49 250.79,-625.33 266.53,-745.56"/>
|
||||
<polygon fill="black" stroke="black" points="263.1,-746.33 267.87,-755.8 270.04,-745.43 263.1,-746.33"/>
|
||||
</g>
|
||||
<!-- svc:pihole-exporter -->
|
||||
<g id="node23" class="node">
|
||||
<title>svc:pihole-exporter</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="151.5,-1386 28.5,-1386 28.5,-1350 151.5,-1350 151.5,-1386"/>
|
||||
<text text-anchor="middle" x="90" y="-1364.3" font-family="Helvetica,sans-Serif" font-size="14.00">pihole-exporter</text>
|
||||
</g>
|
||||
<!-- svc:pihole-exporter->net:monitor -->
|
||||
<g id="edge32" class="edge">
|
||||
<title>svc:pihole-exporter->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M151.62,-1355.78C161.68,-1352.07 171.57,-1347.25 180,-1341 218.01,-1312.82 244.97,-1263.56 259.03,-1232.98"/>
|
||||
<polygon fill="black" stroke="black" points="262.27,-1234.31 263.14,-1223.76 255.87,-1231.46 262.27,-1234.31"/>
|
||||
</g>
|
||||
<!-- svc:portainer -->
|
||||
<g id="node24" class="node">
|
||||
<title>svc:portainer</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="130,-900 50,-900 50,-864 130,-864 130,-900"/>
|
||||
<text text-anchor="middle" x="90" y="-878.3" font-family="Helvetica,sans-Serif" font-size="14.00">portainer</text>
|
||||
</g>
|
||||
<!-- svc:portainer->net:traefik -->
|
||||
<g id="edge33" class="edge">
|
||||
<title>svc:portainer->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M130.17,-874.06C146.25,-869.82 164.67,-863.64 180,-855 206.25,-840.22 231.35,-816.65 248.38,-798.74"/>
|
||||
<polygon fill="black" stroke="black" points="251.37,-800.67 255.62,-790.97 246.24,-795.9 251.37,-800.67"/>
|
||||
</g>
|
||||
<!-- svc:prometheus -->
|
||||
<g id="node25" class="node">
|
||||
<title>svc:prometheus</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="140,-1008 40,-1008 40,-972 140,-972 140,-1008"/>
|
||||
<text text-anchor="middle" x="90" y="-986.3" font-family="Helvetica,sans-Serif" font-size="14.00">prometheus</text>
|
||||
</g>
|
||||
<!-- svc:prometheus->net:monitor -->
|
||||
<g id="edge34" class="edge">
|
||||
<title>svc:prometheus->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M140.37,-997.26C154.39,-1001.24 168.86,-1007.42 180,-1017 229.98,-1059.95 254.42,-1136.8 264.44,-1178.04"/>
|
||||
<polygon fill="black" stroke="black" points="261.07,-1179 266.73,-1187.95 267.88,-1177.42 261.07,-1179"/>
|
||||
</g>
|
||||
<!-- svc:prometheus->net:traefik -->
|
||||
<g id="edge35" class="edge">
|
||||
<title>svc:prometheus->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M140.37,-982.74C154.39,-978.76 168.86,-972.58 180,-963 229.98,-920.05 254.42,-843.2 264.44,-801.96"/>
|
||||
<polygon fill="black" stroke="black" points="267.88,-802.58 266.73,-792.05 261.07,-801 267.88,-802.58"/>
|
||||
</g>
|
||||
<!-- svc:searxng-webapp -->
|
||||
<g id="node26" class="node">
|
||||
<title>svc:searxng-webapp</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="156,-846 24,-846 24,-810 156,-810 156,-846"/>
|
||||
<text text-anchor="middle" x="90" y="-824.3" font-family="Helvetica,sans-Serif" font-size="14.00">searxng-webapp</text>
|
||||
</g>
|
||||
<!-- svc:searxng-webapp->net:traefik -->
|
||||
<g id="edge36" class="edge">
|
||||
<title>svc:searxng-webapp->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M151.18,-809.87C176.26,-802.32 204.79,-793.72 227.63,-786.84"/>
|
||||
<polygon fill="black" stroke="black" points="228.81,-790.14 237.37,-783.9 226.79,-783.44 228.81,-790.14"/>
|
||||
</g>
|
||||
<!-- svc:telegraf -->
|
||||
<g id="node27" class="node">
|
||||
<title>svc:telegraf</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="125.5,-1332 54.5,-1332 54.5,-1296 125.5,-1296 125.5,-1332"/>
|
||||
<text text-anchor="middle" x="90" y="-1310.3" font-family="Helvetica,sans-Serif" font-size="14.00">telegraf</text>
|
||||
</g>
|
||||
<!-- svc:telegraf->net:monitor -->
|
||||
<g id="edge37" class="edge">
|
||||
<title>svc:telegraf->net:monitor</title>
|
||||
<path fill="none" stroke="black" d="M125.8,-1307.18C142.85,-1302.93 163.26,-1296.43 180,-1287 206.25,-1272.22 231.35,-1248.65 248.38,-1230.74"/>
|
||||
<polygon fill="black" stroke="black" points="251.37,-1232.67 255.62,-1222.97 246.24,-1227.9 251.37,-1232.67"/>
|
||||
</g>
|
||||
<!-- svc:traefik -->
|
||||
<g id="node28" class="node">
|
||||
<title>svc:traefik</title>
|
||||
<polygon fill="#dfefff" stroke="black" points="121,-792 59,-792 59,-756 121,-756 121,-792"/>
|
||||
<text text-anchor="middle" x="90" y="-770.3" font-family="Helvetica,sans-Serif" font-size="14.00">traefik</text>
|
||||
</g>
|
||||
<!-- svc:traefik->net:traefik -->
|
||||
<g id="edge38" class="edge">
|
||||
<title>svc:traefik->net:traefik</title>
|
||||
<path fill="none" stroke="black" d="M121,-774C148.16,-774 188.69,-774 220.66,-774"/>
|
||||
<polygon fill="black" stroke="black" points="220.71,-777.5 230.71,-774 220.71,-770.5 220.71,-777.5"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 24 KiB |
@@ -0,0 +1,611 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.43.0 (0)
|
||||
-->
|
||||
<!-- Title: DockerTraefikDynu Pages: 1 -->
|
||||
<svg width="1113pt" height="1536pt"
|
||||
viewBox="0.00 0.00 1113.39 1536.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1532)">
|
||||
<title>DockerTraefikDynu</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-1532 1109.39,-1532 1109.39,4 -4,4"/>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_networks</title>
|
||||
<path fill="none" stroke="#d1d5db" stroke-dasharray="5,2" d="M922,-650C922,-650 1093.39,-650 1093.39,-650 1099.39,-650 1105.39,-656 1105.39,-662 1105.39,-662 1105.39,-1117 1105.39,-1117 1105.39,-1123 1099.39,-1129 1093.39,-1129 1093.39,-1129 922,-1129 922,-1129 916,-1129 910,-1123 910,-1117 910,-1117 910,-662 910,-662 910,-656 916,-650 922,-650"/>
|
||||
<text text-anchor="middle" x="1007.69" y="-1113.8" font-family="Helvetica,sans-Serif" font-size="14.00">Docker backend networks</text>
|
||||
</g>
|
||||
<!-- dynu -->
|
||||
<g id="node1" class="node">
|
||||
<title>dynu</title>
|
||||
<path fill="#fde68a" stroke="black" d="M374,-789C374,-789 282,-789 282,-789 276,-789 270,-783 270,-777 270,-777 270,-765 270,-765 270,-759 276,-753 282,-753 282,-753 374,-753 374,-753 380,-753 386,-759 386,-765 386,-765 386,-777 386,-777 386,-783 380,-789 374,-789"/>
|
||||
<text text-anchor="middle" x="328" y="-768.2" font-family="Helvetica,sans-Serif" font-size="11.00">Dynu / Public DNS</text>
|
||||
</g>
|
||||
<!-- svc:traefik -->
|
||||
<g id="node2" class="node">
|
||||
<title>svc:traefik</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M559,-789C559,-789 513,-789 513,-789 507,-789 501,-783 501,-777 501,-777 501,-765 501,-765 501,-759 507,-753 513,-753 513,-753 559,-753 559,-753 565,-753 571,-759 571,-765 571,-765 571,-777 571,-777 571,-783 565,-789 559,-789"/>
|
||||
<text text-anchor="middle" x="536" y="-774.2" font-family="Helvetica,sans-Serif" font-size="11.00">traefik</text>
|
||||
<text text-anchor="middle" x="536" y="-762.2" font-family="Helvetica,sans-Serif" font-size="11.00">[authelia]</text>
|
||||
</g>
|
||||
<!-- dynu->svc:traefik -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>dynu->svc:traefik</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.6" d="M386.11,-771C419.13,-771 460.06,-771 490.64,-771"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.6" points="491,-774.5 501,-771 491,-767.5 491,-774.5"/>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:traefik -->
|
||||
<g id="edge30" class="edge">
|
||||
<title>svc:traefik->svc:traefik</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M511.86,-789.35C485.91,-817.82 493.95,-854 536,-854 574.1,-854 584.29,-824.29 566.55,-797.52"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="569.07,-795.06 560.14,-789.35 563.55,-799.38 569.07,-795.06"/>
|
||||
</g>
|
||||
<!-- svc:authelia -->
|
||||
<g id="node3" class="node">
|
||||
<title>svc:authelia</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M763,-789C763,-789 726,-789 726,-789 720,-789 714,-783 714,-777 714,-777 714,-765 714,-765 714,-759 720,-753 726,-753 726,-753 763,-753 763,-753 769,-753 775,-759 775,-765 775,-765 775,-777 775,-777 775,-783 769,-789 763,-789"/>
|
||||
<text text-anchor="middle" x="744.5" y="-774.2" font-family="Helvetica,sans-Serif" font-size="11.00">authelia</text>
|
||||
<text text-anchor="middle" x="744.5" y="-762.2" font-family="Helvetica,sans-Serif" font-size="11.00">[TLS]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:authelia -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>svc:traefik->svc:authelia</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M571.1,-771C607.43,-771 664.91,-771 703.39,-771"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="703.71,-774.5 713.71,-771 703.71,-767.5 703.71,-774.5"/>
|
||||
</g>
|
||||
<!-- svc:gitea -->
|
||||
<g id="node5" class="node">
|
||||
<title>svc:gitea</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M759.5,-688C759.5,-688 729.5,-688 729.5,-688 723.5,-688 717.5,-682 717.5,-676 717.5,-676 717.5,-656 717.5,-656 717.5,-650 723.5,-644 729.5,-644 729.5,-644 759.5,-644 759.5,-644 765.5,-644 771.5,-650 771.5,-656 771.5,-656 771.5,-676 771.5,-676 771.5,-682 765.5,-688 759.5,-688"/>
|
||||
<text text-anchor="middle" x="744.5" y="-675.2" font-family="Helvetica,sans-Serif" font-size="11.00">gitea</text>
|
||||
<text text-anchor="middle" x="744.5" y="-663.2" font-family="Helvetica,sans-Serif" font-size="11.00">:3000</text>
|
||||
<text text-anchor="middle" x="744.5" y="-651.2" font-family="Helvetica,sans-Serif" font-size="11.00">[TLS]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:gitea -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>svc:traefik->svc:gitea</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M571.1,-753.66C608.91,-734.44 669.61,-703.57 707.98,-684.06"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="709.89,-687.01 717.22,-679.36 706.72,-680.77 709.89,-687.01"/>
|
||||
</g>
|
||||
<!-- svc:gotify -->
|
||||
<g id="node7" class="node">
|
||||
<title>svc:gotify</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M759.5,-579C759.5,-579 729.5,-579 729.5,-579 723.5,-579 717.5,-573 717.5,-567 717.5,-567 717.5,-555 717.5,-555 717.5,-549 723.5,-543 729.5,-543 729.5,-543 759.5,-543 759.5,-543 765.5,-543 771.5,-549 771.5,-555 771.5,-555 771.5,-567 771.5,-567 771.5,-573 765.5,-579 759.5,-579"/>
|
||||
<text text-anchor="middle" x="744.5" y="-564.2" font-family="Helvetica,sans-Serif" font-size="11.00">gotify</text>
|
||||
<text text-anchor="middle" x="744.5" y="-552.2" font-family="Helvetica,sans-Serif" font-size="11.00">:80</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:gotify -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>svc:traefik->svc:gotify</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M553.8,-752.96C592.77,-711.11 686,-611 686,-611 686,-611 700.43,-598.45 714.83,-585.93"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="717.49,-588.25 722.74,-579.05 712.9,-582.97 717.49,-588.25"/>
|
||||
</g>
|
||||
<!-- svc:grafana -->
|
||||
<g id="node9" class="node">
|
||||
<title>svc:grafana</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M762,-999C762,-999 727,-999 727,-999 721,-999 715,-993 715,-987 715,-987 715,-975 715,-975 715,-969 721,-963 727,-963 727,-963 762,-963 762,-963 768,-963 774,-969 774,-975 774,-975 774,-987 774,-987 774,-993 768,-999 762,-999"/>
|
||||
<text text-anchor="middle" x="744.5" y="-984.2" font-family="Helvetica,sans-Serif" font-size="11.00">grafana</text>
|
||||
<text text-anchor="middle" x="744.5" y="-972.2" font-family="Helvetica,sans-Serif" font-size="11.00">:3000</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:grafana -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>svc:traefik->svc:grafana</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M553.8,-789.04C592.77,-830.89 686,-931 686,-931 686,-931 700.43,-943.55 714.83,-956.07"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="712.9,-959.03 722.74,-962.95 717.49,-953.75 712.9,-959.03"/>
|
||||
</g>
|
||||
<!-- svc:grampsweb -->
|
||||
<g id="node11" class="node">
|
||||
<title>svc:grampsweb</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M772.5,-1528C772.5,-1528 716.5,-1528 716.5,-1528 710.5,-1528 704.5,-1522 704.5,-1516 704.5,-1516 704.5,-1504 704.5,-1504 704.5,-1498 710.5,-1492 716.5,-1492 716.5,-1492 772.5,-1492 772.5,-1492 778.5,-1492 784.5,-1498 784.5,-1504 784.5,-1504 784.5,-1516 784.5,-1516 784.5,-1522 778.5,-1528 772.5,-1528"/>
|
||||
<text text-anchor="middle" x="744.5" y="-1507.2" font-family="Helvetica,sans-Serif" font-size="11.00">grampsweb</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:grampsweb -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>svc:traefik->svc:grampsweb</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M540.91,-789.07C564.42,-897.78 686,-1460 686,-1460 686,-1460 700.43,-1472.55 714.83,-1485.07"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="712.9,-1488.03 722.74,-1491.95 717.49,-1482.75 712.9,-1488.03"/>
|
||||
</g>
|
||||
<!-- svc:influxdb -->
|
||||
<g id="node13" class="node">
|
||||
<title>svc:influxdb</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M767.5,-898C767.5,-898 721.5,-898 721.5,-898 715.5,-898 709.5,-892 709.5,-886 709.5,-886 709.5,-866 709.5,-866 709.5,-860 715.5,-854 721.5,-854 721.5,-854 767.5,-854 767.5,-854 773.5,-854 779.5,-860 779.5,-866 779.5,-866 779.5,-886 779.5,-886 779.5,-892 773.5,-898 767.5,-898"/>
|
||||
<text text-anchor="middle" x="744.5" y="-885.2" font-family="Helvetica,sans-Serif" font-size="11.00">influxdb</text>
|
||||
<text text-anchor="middle" x="744.5" y="-873.2" font-family="Helvetica,sans-Serif" font-size="11.00">:8086</text>
|
||||
<text text-anchor="middle" x="744.5" y="-861.2" font-family="Helvetica,sans-Serif" font-size="11.00">[authelia]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:influxdb -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>svc:traefik->svc:influxdb</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M571.1,-788.34C606.37,-806.27 661.57,-834.34 699.97,-853.87"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="698.85,-857.22 709.35,-858.64 702.02,-850.98 698.85,-857.22"/>
|
||||
</g>
|
||||
<!-- svc:monitor-kuma -->
|
||||
<g id="node15" class="node">
|
||||
<title>svc:monitor-kuma</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M778.5,-1427C778.5,-1427 710.5,-1427 710.5,-1427 704.5,-1427 698.5,-1421 698.5,-1415 698.5,-1415 698.5,-1403 698.5,-1403 698.5,-1397 704.5,-1391 710.5,-1391 710.5,-1391 778.5,-1391 778.5,-1391 784.5,-1391 790.5,-1397 790.5,-1403 790.5,-1403 790.5,-1415 790.5,-1415 790.5,-1421 784.5,-1427 778.5,-1427"/>
|
||||
<text text-anchor="middle" x="744.5" y="-1412.2" font-family="Helvetica,sans-Serif" font-size="11.00">monitor-kuma</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1400.2" font-family="Helvetica,sans-Serif" font-size="11.00">[TLS]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:monitor-kuma -->
|
||||
<g id="edge14" class="edge">
|
||||
<title>svc:traefik->svc:monitor-kuma</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M541.62,-789.24C566.77,-888.49 686,-1359 686,-1359 686,-1359 700.43,-1371.55 714.83,-1384.07"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="712.9,-1387.03 722.74,-1390.95 717.49,-1381.75 712.9,-1387.03"/>
|
||||
</g>
|
||||
<!-- svc:mtls-bridge -->
|
||||
<g id="node17" class="node">
|
||||
<title>svc:mtls-bridge</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M772,-1326C772,-1326 717,-1326 717,-1326 711,-1326 705,-1320 705,-1314 705,-1314 705,-1294 705,-1294 705,-1288 711,-1282 717,-1282 717,-1282 772,-1282 772,-1282 778,-1282 784,-1288 784,-1294 784,-1294 784,-1314 784,-1314 784,-1320 778,-1326 772,-1326"/>
|
||||
<text text-anchor="middle" x="744.5" y="-1313.2" font-family="Helvetica,sans-Serif" font-size="11.00">mtls-bridge</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1301.2" font-family="Helvetica,sans-Serif" font-size="11.00">:8080</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1289.2" font-family="Helvetica,sans-Serif" font-size="11.00">[mTLS]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:mtls-bridge -->
|
||||
<g id="edge16" class="edge">
|
||||
<title>svc:traefik->svc:mtls-bridge</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M542.66,-789.19C569.88,-876.69 686,-1250 686,-1250 686,-1250 698.77,-1262 712.28,-1274.68"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="710.1,-1277.43 719.78,-1281.72 714.89,-1272.33 710.1,-1277.43"/>
|
||||
</g>
|
||||
<!-- svc:nextcloud-webapp -->
|
||||
<g id="node19" class="node">
|
||||
<title>svc:nextcloud-webapp</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M791,-137C791,-137 698,-137 698,-137 692,-137 686,-131 686,-125 686,-125 686,-113 686,-113 686,-107 692,-101 698,-101 698,-101 791,-101 791,-101 797,-101 803,-107 803,-113 803,-113 803,-125 803,-125 803,-131 797,-137 791,-137"/>
|
||||
<text text-anchor="middle" x="744.5" y="-116.2" font-family="Helvetica,sans-Serif" font-size="11.00">nextcloud-webapp</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:nextcloud-webapp -->
|
||||
<g id="edge18" class="edge">
|
||||
<title>svc:traefik->svc:nextcloud-webapp</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M541.62,-752.85C566.77,-654.11 686,-186 686,-186 686,-186 704.96,-163.91 721.1,-145.1"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="723.93,-147.18 727.79,-137.31 718.62,-142.62 723.93,-147.18"/>
|
||||
</g>
|
||||
<!-- svc:node-red -->
|
||||
<g id="node21" class="node">
|
||||
<title>svc:node-red</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M767.5,-1217C767.5,-1217 721.5,-1217 721.5,-1217 715.5,-1217 709.5,-1211 709.5,-1205 709.5,-1205 709.5,-1185 709.5,-1185 709.5,-1179 715.5,-1173 721.5,-1173 721.5,-1173 767.5,-1173 767.5,-1173 773.5,-1173 779.5,-1179 779.5,-1185 779.5,-1185 779.5,-1205 779.5,-1205 779.5,-1211 773.5,-1217 767.5,-1217"/>
|
||||
<text text-anchor="middle" x="744.5" y="-1204.2" font-family="Helvetica,sans-Serif" font-size="11.00">node-red</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1192.2" font-family="Helvetica,sans-Serif" font-size="11.00">:1880</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1180.2" font-family="Helvetica,sans-Serif" font-size="11.00">[authelia]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:node-red -->
|
||||
<g id="edge20" class="edge">
|
||||
<title>svc:traefik->svc:node-red</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M544.29,-789.1C574.2,-863.38 686,-1141 686,-1141 686,-1141 698.77,-1153 712.28,-1165.68"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="710.1,-1168.43 719.78,-1172.72 714.89,-1163.33 710.1,-1168.43"/>
|
||||
</g>
|
||||
<!-- svc:passbolt-webapp -->
|
||||
<g id="node23" class="node">
|
||||
<title>svc:passbolt-webapp</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M787.5,-36C787.5,-36 701.5,-36 701.5,-36 695.5,-36 689.5,-30 689.5,-24 689.5,-24 689.5,-12 689.5,-12 689.5,-6 695.5,0 701.5,0 701.5,0 787.5,0 787.5,0 793.5,0 799.5,-6 799.5,-12 799.5,-12 799.5,-24 799.5,-24 799.5,-30 793.5,-36 787.5,-36"/>
|
||||
<text text-anchor="middle" x="744.5" y="-15.2" font-family="Helvetica,sans-Serif" font-size="11.00">passbolt-webapp</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:passbolt-webapp -->
|
||||
<g id="edge22" class="edge">
|
||||
<title>svc:traefik->svc:passbolt-webapp</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M540.83,-752.92C564.15,-642.88 686,-68 686,-68 686,-68 700.43,-55.45 714.83,-42.93"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="717.49,-45.25 722.74,-36.05 712.9,-39.97 717.49,-45.25"/>
|
||||
</g>
|
||||
<!-- svc:portainer -->
|
||||
<g id="node25" class="node">
|
||||
<title>svc:portainer</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M766,-478C766,-478 723,-478 723,-478 717,-478 711,-472 711,-466 711,-466 711,-446 711,-446 711,-440 717,-434 723,-434 723,-434 766,-434 766,-434 772,-434 778,-440 778,-446 778,-446 778,-466 778,-466 778,-472 772,-478 766,-478"/>
|
||||
<text text-anchor="middle" x="744.5" y="-465.2" font-family="Helvetica,sans-Serif" font-size="11.00">portainer</text>
|
||||
<text text-anchor="middle" x="744.5" y="-453.2" font-family="Helvetica,sans-Serif" font-size="11.00">:9000</text>
|
||||
<text text-anchor="middle" x="744.5" y="-441.2" font-family="Helvetica,sans-Serif" font-size="11.00">[TLS]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:portainer -->
|
||||
<g id="edge24" class="edge">
|
||||
<title>svc:traefik->svc:portainer</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M547.48,-752.65C581.39,-693.24 686,-510 686,-510 686,-510 698.77,-498 712.28,-485.32"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="714.89,-487.67 719.78,-478.28 710.1,-482.57 714.89,-487.67"/>
|
||||
</g>
|
||||
<!-- svc:prometheus -->
|
||||
<g id="node27" class="node">
|
||||
<title>svc:prometheus</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M774,-1108C774,-1108 715,-1108 715,-1108 709,-1108 703,-1102 703,-1096 703,-1096 703,-1076 703,-1076 703,-1070 709,-1064 715,-1064 715,-1064 774,-1064 774,-1064 780,-1064 786,-1070 786,-1076 786,-1076 786,-1096 786,-1096 786,-1102 780,-1108 774,-1108"/>
|
||||
<text text-anchor="middle" x="744.5" y="-1095.2" font-family="Helvetica,sans-Serif" font-size="11.00">prometheus</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1083.2" font-family="Helvetica,sans-Serif" font-size="11.00">:9090</text>
|
||||
<text text-anchor="middle" x="744.5" y="-1071.2" font-family="Helvetica,sans-Serif" font-size="11.00">[authelia]</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:prometheus -->
|
||||
<g id="edge26" class="edge">
|
||||
<title>svc:traefik->svc:prometheus</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M547.48,-789.35C581.39,-848.76 686,-1032 686,-1032 686,-1032 698.77,-1044 712.28,-1056.68"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="710.1,-1059.43 719.78,-1063.72 714.89,-1054.33 710.1,-1059.43"/>
|
||||
</g>
|
||||
<!-- svc:searxng-webapp -->
|
||||
<g id="node29" class="node">
|
||||
<title>svc:searxng-webapp</title>
|
||||
<path fill="#dcfce7" stroke="black" d="M786,-369C786,-369 703,-369 703,-369 697,-369 691,-363 691,-357 691,-357 691,-345 691,-345 691,-339 697,-333 703,-333 703,-333 786,-333 786,-333 792,-333 798,-339 798,-345 798,-345 798,-357 798,-357 798,-363 792,-369 786,-369"/>
|
||||
<text text-anchor="middle" x="744.5" y="-348.2" font-family="Helvetica,sans-Serif" font-size="11.00">searxng-webapp</text>
|
||||
</g>
|
||||
<!-- svc:traefik->svc:searxng-webapp -->
|
||||
<g id="edge28" class="edge">
|
||||
<title>svc:traefik->svc:searxng-webapp</title>
|
||||
<path fill="none" stroke="#334155" stroke-width="1.4" d="M544.29,-752.9C574.2,-678.62 686,-401 686,-401 686,-401 700.43,-388.45 714.83,-375.93"/>
|
||||
<polygon fill="#334155" stroke="#334155" stroke-width="1.4" points="717.49,-378.25 722.74,-369.05 712.9,-372.97 717.49,-378.25"/>
|
||||
</g>
|
||||
<!-- net:traefik -->
|
||||
<g id="node36" class="node">
|
||||
<title>net:traefik</title>
|
||||
<ellipse fill="#f8fafc" stroke="black" cx="1007.69" cy="-878" rx="31.04" ry="18"/>
|
||||
<text text-anchor="middle" x="1007.69" y="-875.2" font-family="Helvetica,sans-Serif" font-size="11.00">traefik</text>
|
||||
</g>
|
||||
<!-- svc:traefik->net:traefik -->
|
||||
<g id="edge55" class="edge">
|
||||
<title>svc:traefik->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M542.75,-752.82C570.13,-666.27 686,-300 686,-300 686,-300 803,-300 803,-300 803,-300 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- svc:authelia->net:traefik -->
|
||||
<g id="edge32" class="edge">
|
||||
<title>svc:authelia->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M775.21,-783.17C824.86,-803.51 924.25,-844.23 975.12,-865.06"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="974.26,-867.36 981.67,-867.75 976.12,-862.83 974.26,-867.36"/>
|
||||
</g>
|
||||
<!-- dns:auth.<domain> -->
|
||||
<g id="node4" class="node">
|
||||
<title>dns:auth.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="123.5,-1496 25.5,-1496 25.5,-1460 129.5,-1460 129.5,-1490 123.5,-1496"/>
|
||||
<polyline fill="none" stroke="black" points="123.5,-1496 123.5,-1490 "/>
|
||||
<polyline fill="none" stroke="black" points="129.5,-1490 123.5,-1490 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-1475.2" font-family="Helvetica,sans-Serif" font-size="11.00">auth.<domain></text>
|
||||
</g>
|
||||
<!-- dns:auth.<domain>->dynu -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>dns:auth.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-1459.95C128.03,-1445.63 155,-1428 155,-1428 155,-1428 286.65,-925.11 319.6,-799.28"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="323.07,-799.82 322.22,-789.26 316.3,-798.05 323.07,-799.82"/>
|
||||
</g>
|
||||
<!-- svc:gitea->net:traefik -->
|
||||
<g id="edge33" class="edge">
|
||||
<title>svc:gitea->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M768.56,-688.05C784.55,-703.36 803,-721 803,-721 803,-721 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- dns:gitea.<domain> -->
|
||||
<g id="node6" class="node">
|
||||
<title>dns:gitea.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="125,-1395 24,-1395 24,-1359 131,-1359 131,-1389 125,-1395"/>
|
||||
<polyline fill="none" stroke="black" points="125,-1395 125,-1389 "/>
|
||||
<polyline fill="none" stroke="black" points="131,-1389 125,-1389 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-1374.2" font-family="Helvetica,sans-Serif" font-size="11.00">gitea.<domain></text>
|
||||
</g>
|
||||
<!-- dns:gitea.<domain>->dynu -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>dns:gitea.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-1358.95C128.03,-1344.63 155,-1327 155,-1327 155,-1327 283.58,-911.36 318.4,-798.82"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="321.76,-799.77 321.38,-789.18 315.08,-797.7 321.76,-799.77"/>
|
||||
</g>
|
||||
<!-- svc:gotify->net:traefik -->
|
||||
<g id="edge34" class="edge">
|
||||
<title>svc:gotify->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-579.05C782.73,-593.37 803,-611 803,-611 803,-611 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- dns:gotify.<domain> -->
|
||||
<g id="node8" class="node">
|
||||
<title>dns:gotify.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="126,-1294 23,-1294 23,-1258 132,-1258 132,-1288 126,-1294"/>
|
||||
<polyline fill="none" stroke="black" points="126,-1294 126,-1288 "/>
|
||||
<polyline fill="none" stroke="black" points="132,-1288 126,-1288 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-1273.2" font-family="Helvetica,sans-Serif" font-size="11.00">gotify.<domain></text>
|
||||
</g>
|
||||
<!-- dns:gotify.<domain>->dynu -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>dns:gotify.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-1257.95C128.03,-1243.63 155,-1226 155,-1226 155,-1226 279.21,-897.41 316.53,-798.71"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="319.89,-799.71 320.15,-789.12 313.34,-797.23 319.89,-799.71"/>
|
||||
</g>
|
||||
<!-- net:monitor -->
|
||||
<g id="node33" class="node">
|
||||
<title>net:monitor</title>
|
||||
<ellipse fill="#f8fafc" stroke="black" cx="1007.69" cy="-979" rx="35.46" ry="18"/>
|
||||
<text text-anchor="middle" x="1007.69" y="-976.2" font-family="Helvetica,sans-Serif" font-size="11.00">monitor</text>
|
||||
</g>
|
||||
<!-- svc:grafana->net:monitor -->
|
||||
<g id="edge35" class="edge">
|
||||
<title>svc:grafana->net:monitor</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M774.2,-980.78C820.4,-980.43 911.47,-979.73 964.89,-979.32"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="965.19,-981.77 972.17,-979.26 965.15,-976.87 965.19,-981.77"/>
|
||||
</g>
|
||||
<!-- svc:grafana->net:traefik -->
|
||||
<g id="edge36" class="edge">
|
||||
<title>svc:grafana->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M774.2,-969.68C823.41,-950.28 923.53,-910.8 974.83,-890.57"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="975.82,-892.81 981.44,-887.96 974.03,-888.25 975.82,-892.81"/>
|
||||
</g>
|
||||
<!-- dns:grafana.<domain> -->
|
||||
<g id="node10" class="node">
|
||||
<title>dns:grafana.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="132,-1193 17,-1193 17,-1157 138,-1157 138,-1187 132,-1193"/>
|
||||
<polyline fill="none" stroke="black" points="132,-1193 132,-1187 "/>
|
||||
<polyline fill="none" stroke="black" points="138,-1187 132,-1187 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-1172.2" font-family="Helvetica,sans-Serif" font-size="11.00">grafana.<domain></text>
|
||||
</g>
|
||||
<!-- dns:grafana.<domain>->dynu -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>dns:grafana.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-1156.95C128.03,-1142.63 155,-1125 155,-1125 155,-1125 273.61,-880.89 313.84,-798.09"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="317.01,-799.57 318.23,-789.04 310.72,-796.51 317.01,-799.57"/>
|
||||
</g>
|
||||
<!-- net:gramps -->
|
||||
<g id="node32" class="node">
|
||||
<title>net:gramps</title>
|
||||
<ellipse fill="#f8fafc" stroke="black" cx="1007.69" cy="-1080" rx="34.76" ry="18"/>
|
||||
<text text-anchor="middle" x="1007.69" y="-1077.2" font-family="Helvetica,sans-Serif" font-size="11.00">gramps</text>
|
||||
</g>
|
||||
<!-- svc:grampsweb->net:gramps -->
|
||||
<g id="edge37" class="edge">
|
||||
<title>svc:grampsweb->net:gramps</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-1491.95C782.73,-1477.63 803,-1460 803,-1460 803,-1460 949.23,-1187.21 993.89,-1103.88"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="996.27,-1104.64 997.41,-1097.32 991.95,-1102.33 996.27,-1104.64"/>
|
||||
</g>
|
||||
<!-- svc:grampsweb->net:traefik -->
|
||||
<g id="edge38" class="edge">
|
||||
<title>svc:grampsweb->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-1491.95C782.73,-1477.63 803,-1460 803,-1460 803,-1460 910,-929 910,-929 910,-929 949.05,-908.4 977.52,-893.39"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="978.73,-895.52 983.78,-890.09 976.45,-891.18 978.73,-895.52"/>
|
||||
</g>
|
||||
<!-- dns:familytree.<domain> -->
|
||||
<g id="node12" class="node">
|
||||
<title>dns:familytree.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="139,-1092 10,-1092 10,-1056 145,-1056 145,-1086 139,-1092"/>
|
||||
<polyline fill="none" stroke="black" points="139,-1092 139,-1086 "/>
|
||||
<polyline fill="none" stroke="black" points="145,-1086 139,-1086 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-1071.2" font-family="Helvetica,sans-Serif" font-size="11.00">familytree.<domain></text>
|
||||
</g>
|
||||
<!-- dns:familytree.<domain>->dynu -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>dns:familytree.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-1055.95C128.03,-1041.63 155,-1024 155,-1024 155,-1024 264.64,-862.73 308.84,-797.71"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="311.9,-799.43 314.63,-789.2 306.11,-795.5 311.9,-799.43"/>
|
||||
</g>
|
||||
<!-- svc:influxdb->net:monitor -->
|
||||
<g id="edge39" class="edge">
|
||||
<title>svc:influxdb->net:monitor</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M779.65,-889.47C829.7,-909.2 922.46,-945.78 972.53,-965.53"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="971.89,-967.91 979.3,-968.2 973.69,-963.35 971.89,-967.91"/>
|
||||
</g>
|
||||
<!-- svc:influxdb->net:traefik -->
|
||||
<g id="edge40" class="edge">
|
||||
<title>svc:influxdb->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M779.65,-876.26C828.54,-876.64 918.2,-877.32 968.99,-877.71"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="969.17,-880.16 976.19,-877.77 969.21,-875.26 969.17,-880.16"/>
|
||||
</g>
|
||||
<!-- dns:influxdb.<domain> -->
|
||||
<g id="node14" class="node">
|
||||
<title>dns:influxdb.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="132.5,-991 16.5,-991 16.5,-955 138.5,-955 138.5,-985 132.5,-991"/>
|
||||
<polyline fill="none" stroke="black" points="132.5,-991 132.5,-985 "/>
|
||||
<polyline fill="none" stroke="black" points="138.5,-985 132.5,-985 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-970.2" font-family="Helvetica,sans-Serif" font-size="11.00">influxdb.<domain></text>
|
||||
</g>
|
||||
<!-- dns:influxdb.<domain>->dynu -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>dns:influxdb.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-954.95C128.03,-940.63 155,-923 155,-923 155,-923 250.14,-838.92 298.91,-795.83"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="301.42,-798.28 306.59,-789.03 296.78,-793.03 301.42,-798.28"/>
|
||||
</g>
|
||||
<!-- svc:monitor-kuma->net:monitor -->
|
||||
<g id="edge41" class="edge">
|
||||
<title>svc:monitor-kuma->net:monitor</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-1390.95C782.73,-1376.63 803,-1359 803,-1359 803,-1359 910,-1030 910,-1030 910,-1030 947.73,-1010.1 976.05,-995.16"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="977.25,-997.3 982.29,-991.87 974.96,-992.97 977.25,-997.3"/>
|
||||
</g>
|
||||
<!-- svc:monitor-kuma->net:traefik -->
|
||||
<g id="edge42" class="edge">
|
||||
<title>svc:monitor-kuma->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-1390.95C782.73,-1376.63 803,-1359 803,-1359 803,-1359 910,-929 910,-929 910,-929 949.05,-908.4 977.52,-893.39"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="978.73,-895.52 983.78,-890.09 976.45,-891.18 978.73,-895.52"/>
|
||||
</g>
|
||||
<!-- dns:monitor-kuma.<domain> -->
|
||||
<g id="node16" class="node">
|
||||
<title>dns:monitor-kuma.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="149,-890 0,-890 0,-854 155,-854 155,-884 149,-890"/>
|
||||
<polyline fill="none" stroke="black" points="149,-890 149,-884 "/>
|
||||
<polyline fill="none" stroke="black" points="155,-884 149,-884 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-869.2" font-family="Helvetica,sans-Serif" font-size="11.00">monitor-kuma.<domain></text>
|
||||
</g>
|
||||
<!-- dns:monitor-kuma.<domain>->dynu -->
|
||||
<g id="edge15" class="edge">
|
||||
<title>dns:monitor-kuma.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M122.93,-853.94C165.02,-836.83 228.32,-811.11 273.25,-792.85"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="274.59,-796.08 282.54,-789.07 271.96,-789.59 274.59,-796.08"/>
|
||||
</g>
|
||||
<!-- svc:mtls-bridge->net:monitor -->
|
||||
<g id="edge43" class="edge">
|
||||
<title>svc:mtls-bridge->net:monitor</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M769.22,-1281.72C785.06,-1266.85 803,-1250 803,-1250 803,-1250 910,-1030 910,-1030 910,-1030 947.73,-1010.1 976.05,-995.16"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="977.25,-997.3 982.29,-991.87 974.96,-992.97 977.25,-997.3"/>
|
||||
</g>
|
||||
<!-- svc:mtls-bridge->net:traefik -->
|
||||
<g id="edge44" class="edge">
|
||||
<title>svc:mtls-bridge->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M769.22,-1281.72C785.06,-1266.85 803,-1250 803,-1250 803,-1250 910,-929 910,-929 910,-929 949.05,-908.4 977.52,-893.39"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="978.73,-895.52 983.78,-890.09 976.45,-891.18 978.73,-895.52"/>
|
||||
</g>
|
||||
<!-- dns:mtls-bridge.<domain> -->
|
||||
<g id="node18" class="node">
|
||||
<title>dns:mtls-bridge.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="142,-789 7,-789 7,-753 148,-753 148,-783 142,-789"/>
|
||||
<polyline fill="none" stroke="black" points="142,-789 142,-783 "/>
|
||||
<polyline fill="none" stroke="black" points="148,-783 142,-783 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-768.2" font-family="Helvetica,sans-Serif" font-size="11.00">mtls-bridge.<domain></text>
|
||||
</g>
|
||||
<!-- dns:mtls-bridge.<domain>->dynu -->
|
||||
<g id="edge17" class="edge">
|
||||
<title>dns:mtls-bridge.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M148.05,-771C182.94,-771 225.03,-771 259.61,-771"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="259.62,-774.5 269.62,-771 259.62,-767.5 259.62,-774.5"/>
|
||||
</g>
|
||||
<!-- net:nextcloud -->
|
||||
<g id="node34" class="node">
|
||||
<title>net:nextcloud</title>
|
||||
<ellipse fill="#f8fafc" stroke="black" cx="1007.69" cy="-777" rx="42.89" ry="18"/>
|
||||
<text text-anchor="middle" x="1007.69" y="-774.2" font-family="Helvetica,sans-Serif" font-size="11.00">nextcloud</text>
|
||||
</g>
|
||||
<!-- svc:nextcloud-webapp->net:nextcloud -->
|
||||
<g id="edge45" class="edge">
|
||||
<title>svc:nextcloud-webapp->net:nextcloud</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M761.21,-137.31C778.24,-157.15 803,-186 803,-186 803,-186 910,-727 910,-727 910,-727 945.48,-745.35 973.46,-759.81"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="972.67,-762.17 980.02,-763.2 974.92,-757.81 972.67,-762.17"/>
|
||||
</g>
|
||||
<!-- svc:nextcloud-webapp->net:traefik -->
|
||||
<g id="edge46" class="edge">
|
||||
<title>svc:nextcloud-webapp->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M761.21,-137.31C778.24,-157.15 803,-186 803,-186 803,-186 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- dns:nextcloud.<domain> -->
|
||||
<g id="node20" class="node">
|
||||
<title>dns:nextcloud.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="138,-688 11,-688 11,-652 144,-652 144,-682 138,-688"/>
|
||||
<polyline fill="none" stroke="black" points="138,-688 138,-682 "/>
|
||||
<polyline fill="none" stroke="black" points="144,-682 138,-682 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-667.2" font-family="Helvetica,sans-Serif" font-size="11.00">nextcloud.<domain></text>
|
||||
</g>
|
||||
<!-- dns:nextcloud.<domain>->dynu -->
|
||||
<g id="edge19" class="edge">
|
||||
<title>dns:nextcloud.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M122.93,-688.06C165.02,-705.17 228.32,-730.89 273.25,-749.15"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="271.96,-752.41 282.54,-752.93 274.59,-745.92 271.96,-752.41"/>
|
||||
</g>
|
||||
<!-- svc:node-red->net:monitor -->
|
||||
<g id="edge47" class="edge">
|
||||
<title>svc:node-red->net:monitor</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M769.22,-1172.72C785.06,-1157.85 803,-1141 803,-1141 803,-1141 910,-1030 910,-1030 910,-1030 947.73,-1010.1 976.05,-995.16"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="977.25,-997.3 982.29,-991.87 974.96,-992.97 977.25,-997.3"/>
|
||||
</g>
|
||||
<!-- svc:node-red->net:traefik -->
|
||||
<g id="edge48" class="edge">
|
||||
<title>svc:node-red->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M769.22,-1172.72C785.06,-1157.85 803,-1141 803,-1141 803,-1141 910,-929 910,-929 910,-929 949.05,-908.4 977.52,-893.39"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="978.73,-895.52 983.78,-890.09 976.45,-891.18 978.73,-895.52"/>
|
||||
</g>
|
||||
<!-- dns:node-red.<domain> -->
|
||||
<g id="node22" class="node">
|
||||
<title>dns:node-red.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="135.5,-587 13.5,-587 13.5,-551 141.5,-551 141.5,-581 135.5,-587"/>
|
||||
<polyline fill="none" stroke="black" points="135.5,-587 135.5,-581 "/>
|
||||
<polyline fill="none" stroke="black" points="141.5,-581 135.5,-581 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-566.2" font-family="Helvetica,sans-Serif" font-size="11.00">node-red.<domain></text>
|
||||
</g>
|
||||
<!-- dns:node-red.<domain>->dynu -->
|
||||
<g id="edge21" class="edge">
|
||||
<title>dns:node-red.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-587.05C128.03,-601.37 155,-619 155,-619 155,-619 250.14,-703.08 298.91,-746.17"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="296.78,-748.97 306.59,-752.97 301.42,-743.72 296.78,-748.97"/>
|
||||
</g>
|
||||
<!-- net:passbolt -->
|
||||
<g id="node35" class="node">
|
||||
<title>net:passbolt</title>
|
||||
<ellipse fill="#f8fafc" stroke="black" cx="1007.69" cy="-676" rx="37.77" ry="18"/>
|
||||
<text text-anchor="middle" x="1007.69" y="-673.2" font-family="Helvetica,sans-Serif" font-size="11.00">passbolt</text>
|
||||
</g>
|
||||
<!-- svc:passbolt-webapp->net:passbolt -->
|
||||
<g id="edge49" class="edge">
|
||||
<title>svc:passbolt-webapp->net:passbolt</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-36.05C782.73,-50.37 803,-68 803,-68 803,-68 960.4,-537.83 998.48,-651.47"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="996.16,-652.27 1000.71,-658.13 1000.81,-650.72 996.16,-652.27"/>
|
||||
</g>
|
||||
<!-- svc:passbolt-webapp->net:traefik -->
|
||||
<g id="edge50" class="edge">
|
||||
<title>svc:passbolt-webapp->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-36.05C782.73,-50.37 803,-68 803,-68 803,-68 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- dns:passbolt.<domain> -->
|
||||
<g id="node24" class="node">
|
||||
<title>dns:passbolt.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="134,-486 15,-486 15,-450 140,-450 140,-480 134,-486"/>
|
||||
<polyline fill="none" stroke="black" points="134,-486 134,-480 "/>
|
||||
<polyline fill="none" stroke="black" points="140,-480 134,-480 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-465.2" font-family="Helvetica,sans-Serif" font-size="11.00">passbolt.<domain></text>
|
||||
</g>
|
||||
<!-- dns:passbolt.<domain>->dynu -->
|
||||
<g id="edge23" class="edge">
|
||||
<title>dns:passbolt.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-486.05C128.03,-500.37 155,-518 155,-518 155,-518 264.64,-679.27 308.84,-744.29"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="306.11,-746.5 314.63,-752.8 311.9,-742.57 306.11,-746.5"/>
|
||||
</g>
|
||||
<!-- svc:portainer->net:traefik -->
|
||||
<g id="edge51" class="edge">
|
||||
<title>svc:portainer->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M769.22,-478.28C785.06,-493.15 803,-510 803,-510 803,-510 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- dns:portainer.<domain> -->
|
||||
<g id="node26" class="node">
|
||||
<title>dns:portainer.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="135.5,-385 13.5,-385 13.5,-349 141.5,-349 141.5,-379 135.5,-385"/>
|
||||
<polyline fill="none" stroke="black" points="135.5,-385 135.5,-379 "/>
|
||||
<polyline fill="none" stroke="black" points="141.5,-379 135.5,-379 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-364.2" font-family="Helvetica,sans-Serif" font-size="11.00">portainer.<domain></text>
|
||||
</g>
|
||||
<!-- dns:portainer.<domain>->dynu -->
|
||||
<g id="edge25" class="edge">
|
||||
<title>dns:portainer.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-385.05C128.03,-399.37 155,-417 155,-417 155,-417 273.61,-661.11 313.84,-743.91"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="310.72,-745.49 318.23,-752.96 317.01,-742.43 310.72,-745.49"/>
|
||||
</g>
|
||||
<!-- svc:prometheus->net:monitor -->
|
||||
<g id="edge52" class="edge">
|
||||
<title>svc:prometheus->net:monitor</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M786.03,-1069.4C837.48,-1048.32 925.31,-1012.34 973.18,-992.73"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="974.11,-995 979.66,-990.07 972.26,-990.46 974.11,-995"/>
|
||||
</g>
|
||||
<!-- svc:prometheus->net:traefik -->
|
||||
<g id="edge53" class="edge">
|
||||
<title>svc:prometheus->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M769.22,-1063.72C785.06,-1048.85 803,-1032 803,-1032 803,-1032 910,-929 910,-929 910,-929 949.05,-908.4 977.52,-893.39"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="978.73,-895.52 983.78,-890.09 976.45,-891.18 978.73,-895.52"/>
|
||||
</g>
|
||||
<!-- dns:prometheus.<domain> -->
|
||||
<g id="node28" class="node">
|
||||
<title>dns:prometheus.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="144,-284 5,-284 5,-248 150,-248 150,-278 144,-284"/>
|
||||
<polyline fill="none" stroke="black" points="144,-284 144,-278 "/>
|
||||
<polyline fill="none" stroke="black" points="150,-278 144,-278 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-263.2" font-family="Helvetica,sans-Serif" font-size="11.00">prometheus.<domain></text>
|
||||
</g>
|
||||
<!-- dns:prometheus.<domain>->dynu -->
|
||||
<g id="edge27" class="edge">
|
||||
<title>dns:prometheus.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-284.05C128.03,-298.37 155,-316 155,-316 155,-316 279.21,-644.59 316.53,-743.29"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="313.34,-744.77 320.15,-752.88 319.89,-742.29 313.34,-744.77"/>
|
||||
</g>
|
||||
<!-- svc:searxng-webapp->net:traefik -->
|
||||
<g id="edge54" class="edge">
|
||||
<title>svc:searxng-webapp->net:traefik</title>
|
||||
<path fill="none" stroke="#94a3b8" stroke-dasharray="5,2" d="M766.26,-369.05C782.73,-383.37 803,-401 803,-401 803,-401 910,-828 910,-828 910,-828 949.05,-848.19 977.52,-862.92"/>
|
||||
<polygon fill="#94a3b8" stroke="#94a3b8" points="976.44,-865.11 983.78,-866.15 978.69,-860.76 976.44,-865.11"/>
|
||||
</g>
|
||||
<!-- dns:searxng.<domain> -->
|
||||
<g id="node30" class="node">
|
||||
<title>dns:searxng.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="133,-183 16,-183 16,-147 139,-147 139,-177 133,-183"/>
|
||||
<polyline fill="none" stroke="black" points="133,-183 133,-177 "/>
|
||||
<polyline fill="none" stroke="black" points="139,-177 133,-177 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-162.2" font-family="Helvetica,sans-Serif" font-size="11.00">searxng.<domain></text>
|
||||
</g>
|
||||
<!-- dns:searxng.<domain>->dynu -->
|
||||
<g id="edge29" class="edge">
|
||||
<title>dns:searxng.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-183.05C128.03,-197.37 155,-215 155,-215 155,-215 283.58,-630.64 318.4,-743.18"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="315.08,-744.3 321.38,-752.82 321.76,-742.23 315.08,-744.3"/>
|
||||
</g>
|
||||
<!-- dns:traefik.<domain> -->
|
||||
<g id="node31" class="node">
|
||||
<title>dns:traefik.<domain></title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="128.5,-82 20.5,-82 20.5,-46 134.5,-46 134.5,-76 128.5,-82"/>
|
||||
<polyline fill="none" stroke="black" points="128.5,-82 128.5,-76 "/>
|
||||
<polyline fill="none" stroke="black" points="134.5,-76 128.5,-76 "/>
|
||||
<text text-anchor="middle" x="77.5" y="-61.2" font-family="Helvetica,sans-Serif" font-size="11.00">traefik.<domain></text>
|
||||
</g>
|
||||
<!-- dns:traefik.<domain>->dynu -->
|
||||
<g id="edge31" class="edge">
|
||||
<title>dns:traefik.<domain>->dynu</title>
|
||||
<path fill="none" stroke="#334155" d="M106.12,-82.05C128.03,-96.37 155,-114 155,-114 155,-114 286.65,-616.89 319.6,-742.72"/>
|
||||
<polygon fill="#334155" stroke="#334155" points="316.3,-743.95 322.22,-752.74 323.07,-742.18 316.3,-743.95"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 41 KiB |
@@ -0,0 +1,21 @@
|
||||
# Public Infrastructure Summary
|
||||
|
||||
This documentation is generated from the infrastructure repository. Sensitive values are redacted.
|
||||
|
||||
> Generated docs are sanitised/redacted before publishing to GitHub Pages.
|
||||
|
||||
## Infrastructure diagrams
|
||||
|
||||
### Physical / virtual topology
|
||||
|
||||

|
||||
|
||||
### Docker, Traefik and Dynu routing
|
||||
|
||||

|
||||
|
||||
## Documents
|
||||
|
||||
- [Diagrams](diagrams.md)
|
||||
- [Compose Inventory](compose-inventory.md)
|
||||
- [Traefik Routes](traefik-routes.md)
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.43.0 (0)
|
||||
-->
|
||||
<!-- Title: PhysicalTopology Pages: 1 -->
|
||||
<svg width="514pt" height="61pt"
|
||||
viewBox="0.00 0.00 514.00 61.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 57)">
|
||||
<title>PhysicalTopology</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-57 510,-57 510,4 -4,4"/>
|
||||
<!-- placeholder:inventory -->
|
||||
<g id="node1" class="node">
|
||||
<title>placeholder:inventory</title>
|
||||
<polygon fill="#fef3c7" stroke="black" points="500,-53 0,-53 0,0 506,0 506,-47 500,-53"/>
|
||||
<polyline fill="none" stroke="black" points="500,-53 500,-47 "/>
|
||||
<polyline fill="none" stroke="black" points="506,-47 500,-47 "/>
|
||||
<text text-anchor="middle" x="253" y="-37.8" font-family="Times,serif" font-size="14.00">Host inventory JSON not found.</text>
|
||||
<text text-anchor="middle" x="253" y="-22.8" font-family="Times,serif" font-size="14.00">Generate terraform inventory and rerun scripts/docs/generate-all.sh</text>
|
||||
<text text-anchor="middle" x="253" y="-7.8" font-family="Times,serif" font-size="14.00">(--host-inventory <path>).</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,23 @@
|
||||
.md-content img, article img {
|
||||
max-width: 100%;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.diagram-wrap {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
margin: 1rem 0 2rem;
|
||||
}
|
||||
|
||||
.diagram-wrap img {
|
||||
max-width: none;
|
||||
width: 1400px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.diagram-wrap img {
|
||||
width: 1200px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# Traefik Routes
|
||||
|
||||
| Service | Router | Rule | Entrypoints | TLS | Middlewares | Target Port |
|
||||
|---|---|---|---|---|---|---|
|
||||
| authelia | authelia | Host(`auth.<domain>`) | websecure | true | | |
|
||||
| error-pages | error-pages-router | HostRegexp(`{host:.+}`) | web | | error-pages-middleware | |
|
||||
| gitea | gitea | Host(`gitea.<domain>`) | websecure | true | | 3000 |
|
||||
| gotify | gotify | Host(`gotify.<domain>`) | websecure | | | 80 |
|
||||
| grafana | grafana | Host(`grafana.<domain>`) | websecure | | | 3000 |
|
||||
| grampsweb | gramps | Host(`familytree.<domain>`) | websecure | | | 5000 |
|
||||
| influxdb | influxdb | Host(`influxdb.<domain>`) | websecure | | authelia | 8086 |
|
||||
| monitor-kuma | monitor | Host(`monitor-kuma.<domain>`) | websecure | true | | 3001 |
|
||||
| mtls-bridge | mtls-bridge | Host(`mtls-bridge.<domain>`) | websecure | | mtls-bridge-auth,mtls-bridge-cors | 8080 |
|
||||
| mtls-bridge | mtls-bridge-preflight | Host(`mtls-bridge.<domain>`) && Method(`OPTIONS`) | websecure | | mtls-bridge-cors | |
|
||||
| nextcloud-webapp | nextcloud | Host(`nextcloud.<domain>`) | websecure | | nextcloud-dav, nextcloud-webfinger | |
|
||||
| node-red | node-red | Host(`node-red.<domain>`) | websecure | | authelia | 1880 |
|
||||
| passbolt-webapp | passbolt | Host(`passbolt.<domain>`) | websecure | | | |
|
||||
| portainer | portainer | Host(`portainer.<domain>`) | websecure | true | | 9000 |
|
||||
| prometheus | prometheus | Host(`prometheus.<domain>`) | websecure | | authelia | 9090 |
|
||||
| searxng-webapp | searxng | Host(`searxng.<domain>`) | websecure | | | 8080 |
|
||||
| traefik | traefik | Host(`traefik.<domain>`) | websecure | | authelia | |
|
||||
@@ -0,0 +1,42 @@
|
||||
# Repository Structure
|
||||
|
||||
This page explains where to find authoritative files quickly.
|
||||
|
||||
## Top-level directories
|
||||
|
||||
- `core/` — core platform/security services (Traefik, Authelia, CrowdSec, error pages).
|
||||
- `apps/` — user/business applications (Nextcloud, Passbolt, Gitea, Gramps, SearXNG).
|
||||
- `monitoring/` — observability and operational tooling (Prometheus, Grafana, InfluxDB, Node-RED, etc.).
|
||||
- `infrastructure/terraform/` — brownfield Terraform inventory/reconciliation layers.
|
||||
- `infrastructure/ansible/` — phase-1 Ansible inventory/configuration scaffold and validation playbooks.
|
||||
- `docs/` — repository-level architecture and workflow documentation.
|
||||
- `archive/` — historical compose/config artifacts not part of active runtime composition.
|
||||
- `secrets/` — local secret material and templates; never commit real values.
|
||||
|
||||
## Key top-level files
|
||||
|
||||
- `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.
|
||||
- `scripts/codex-setup.sh` — Codex/bootstrap helper to install validation tooling and prepare dummy secret material.
|
||||
- `scripts/codex-maintenance.sh` — Codex maintenance helper to refresh tooling, reconcile dummy secret material, and run safe Ansible validation checks.
|
||||
- `docs/deployment-prerequisites.md` — prerequisite setup before runtime operations.
|
||||
- `docs/security-secrets.md` — secrets documentation and inventory model.
|
||||
|
||||
## Terraform layout
|
||||
|
||||
- `infrastructure/terraform/README.md` — Terraform purpose and boundaries in this repo.
|
||||
- `infrastructure/terraform/proxmox/` — imported/reconciled Proxmox VM resources and host metadata.
|
||||
- `infrastructure/terraform/docker/` — selective Docker container documentation mirrors.
|
||||
- `infrastructure/terraform/bootstrap/` — backend/provider bootstrap scaffolding.
|
||||
- `infrastructure/terraform/scripts/reconcile_from_plan.sh` — helper for `terraform plan -generate-config-out` reconciliation workflow.
|
||||
|
||||
## Fast path for future Codex runs
|
||||
|
||||
1. Read [README.md](https://github.com/beatz174-bit/docker/blob/main/README.md).
|
||||
2. Read [docs/source-of-truth.md](source-of-truth.md).
|
||||
3. Read [docs/docker-environment.md](docker-environment.md).
|
||||
4. Read [docs/terraform-workflows.md](terraform-workflows.md).
|
||||
5. Only then edit Compose/Terraform files.
|
||||
|
||||
6. For Ansible bootstrap changes, validate inventory and playbook syntax checks only.
|
||||
@@ -0,0 +1,56 @@
|
||||
# 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`](https://github.com/beatz174-bit/docker/blob/main/secrets/inventory.json).
|
||||
|
||||
## Scope and authority
|
||||
|
||||
- Canonical example template: [`secrets/.env.secrets.example`](https://github.com/beatz174-bit/docker/blob/main/secrets/.env.secrets.example)
|
||||
- Runtime-loaded secret env file (local, non-committed): `../secrets/stack-secrets.env`
|
||||
- Dynu DNS inventory env file (local, non-committed): `../secrets/dynu.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 Dynu env file (`dynu.env`)**
|
||||
- Holds `DYNU_*` values used by read-only Dynu DNS inventory scripts.
|
||||
4. **Local Docker secret files (`*.txt`)**
|
||||
- Hold password/token material consumed via `*_FILE` style configuration.
|
||||
5. **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`](https://github.com/beatz174-bit/docker/blob/main/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`
|
||||
- `secrets/dynu.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)
|
||||
@@ -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.
|
||||
@@ -0,0 +1,63 @@
|
||||
# Source-of-Truth Boundaries
|
||||
|
||||
This repository has multiple layers. Knowing the authority for each layer prevents accidental drift.
|
||||
|
||||
## Boundary summary
|
||||
|
||||
| Layer | Primary authority | Purpose |
|
||||
|---|---|---|
|
||||
| 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 | `docs/security-secrets.md` + `secrets/inventory.json` + local secret files in `secrets/` | What secrets exist, where they are expected, and what automation should parse. |
|
||||
| Host/device configuration bootstrap (emerging) | Ansible under `infrastructure/ansible/` | Gradual inventory/configuration layer for hosts/devices; validation-first at current stage. |
|
||||
|
||||
## Practical meaning
|
||||
|
||||
### Docker runtime decisions
|
||||
|
||||
Change Compose files and `services-up.sh` when changing runtime behavior.
|
||||
|
||||
Do **not** assume Terraform Docker resources are the deployment source for day-to-day service runtime.
|
||||
|
||||
### Infrastructure inventory decisions
|
||||
|
||||
Use Terraform when documenting/reconciling existing:
|
||||
|
||||
- Proxmox VM config and identifiers.
|
||||
- Physical host metadata.
|
||||
- Select Docker container details that are intentionally mirrored.
|
||||
|
||||
Do **not** treat Terraform as a full replacement for Compose operations in this repo.
|
||||
|
||||
- Dynu public DNS records remain authoritative at Dynu.
|
||||
- Terraform Dynu configuration mirrors/reconciles Dynu DNS state for documentation and controlled drift management.
|
||||
- Imported Dynu Terraform state reflects actual provider-side DNS state at import time.
|
||||
|
||||
|
||||
### Ansible bootstrap decisions
|
||||
|
||||
Use Ansible under `infrastructure/ansible/` to build inventory and configuration structure incrementally.
|
||||
|
||||
At the current stage:
|
||||
|
||||
- Do **not** treat Ansible as replacement authority for Docker runtime operations.
|
||||
- Do **not** treat Ansible as replacement authority for Terraform inventory/reconciliation.
|
||||
- NixOS remains outside Ansible authority unless explicitly adopted in a later phase.
|
||||
|
||||
## Declared config vs observed/runtime state
|
||||
|
||||
- **Declared config**: files in this repository (Compose, Terraform, docs).
|
||||
- **Observed/runtime state**: live Docker/Proxmox reality and Terraform state snapshots.
|
||||
|
||||
Brownfield workflows reconcile these two safely and incrementally.
|
||||
|
||||
## Guardrails for contributors and Codex
|
||||
|
||||
- Do not mass-import or mass-reconcile everything at once.
|
||||
- Keep imports/reconciliation scoped to one object (or small set) at a time.
|
||||
- Keep `ignore_changes` surgical and justified.
|
||||
- Prefer shaped outputs (inventory-ready) over raw provider object dumps.
|
||||
- Do not commit `.tfstate`, real `.tfvars`, or real secret files.
|
||||
|
||||
See [docs/terraform-workflows.md](terraform-workflows.md) for step-by-step procedures.
|
||||
@@ -0,0 +1,93 @@
|
||||
# Terraform Workflows (Brownfield / Reconciliation)
|
||||
|
||||
Terraform in this repository is primarily used for **importing and reconciling existing infrastructure**.
|
||||
|
||||
This is a brownfield workflow: real infrastructure exists first, then code/state are brought into alignment.
|
||||
|
||||
## Core workflow pattern
|
||||
|
||||
1. Define/import one existing object.
|
||||
2. Inspect current provider state.
|
||||
3. Reconcile hand-maintained `.tf` configuration.
|
||||
4. Use targeted `ignore_changes` only when necessary.
|
||||
5. Iterate until plan is sane/no-op for intended scope.
|
||||
6. Avoid casual apply operations.
|
||||
|
||||
## Docker mirror workflow (documentation-oriented)
|
||||
|
||||
Directory: `infrastructure/terraform/docker/`
|
||||
|
||||
Use when intentionally mirroring selected running containers as structured documentation.
|
||||
|
||||
### Steps
|
||||
|
||||
1. Add minimal `docker_container` resource block (or uncomment/import-ready block).
|
||||
2. Add `import {}` block or run `terraform import` for the container.
|
||||
3. Run plan and inspect generated/state values.
|
||||
4. Keep only meaningful, maintainable arguments in hand-edited files.
|
||||
5. Use generated files as draft input, not final truth.
|
||||
6. Re-run plan until intended scope is clean.
|
||||
|
||||
## Proxmox VM workflow
|
||||
|
||||
Directory: `infrastructure/terraform/proxmox/`
|
||||
|
||||
Use for existing Proxmox VMs and metadata reconciliation.
|
||||
|
||||
### Steps
|
||||
|
||||
1. Add/import one VM resource at a time.
|
||||
2. Confirm provider import ID format and vm/node mapping.
|
||||
3. Inspect with `terraform state show` / plan output.
|
||||
4. Move useful arguments into stable hand-maintained files.
|
||||
5. Keep lifecycle ignore rules narrow and explicit.
|
||||
6. Iterate per VM until plan stabilizes.
|
||||
|
||||
|
||||
## Dynu DNS workflow
|
||||
|
||||
Directory: `infrastructure/terraform/dynu/`
|
||||
|
||||
Use for existing Dynu domains and DNS records.
|
||||
|
||||
1. Add or confirm the documentation catalog entry for one hostname.
|
||||
2. Confirm the provider resource type and import ID format.
|
||||
3. Import one existing domain or DNS record at a time.
|
||||
4. Inspect state with `terraform state show`.
|
||||
5. Reconcile only stable, meaningful attributes into hand-maintained `.tf`.
|
||||
6. Keep record IDs, dynamic DNS targets, and provider-computed values out unless intentionally required.
|
||||
7. Re-run plan until intended scope is clean.
|
||||
|
||||
## Physical host metadata workflow
|
||||
|
||||
Physical host metadata currently lives in Proxmox Terraform locals/outputs and is used as documentation inventory context.
|
||||
|
||||
When updating:
|
||||
|
||||
1. update locals with factual host metadata,
|
||||
2. ensure outputs remain documentation-friendly,
|
||||
3. avoid leaking sensitive internal data not needed for repository goals.
|
||||
|
||||
## Generated config guidance
|
||||
|
||||
`infrastructure/terraform/scripts/reconcile_from_plan.sh` can generate Terraform draft configuration via `-generate-config-out`.
|
||||
|
||||
Treat generated files as:
|
||||
|
||||
- a starting point,
|
||||
- reviewed manually,
|
||||
- reduced to meaningful attributes,
|
||||
- reformatted and split into maintainable files.
|
||||
|
||||
## Safety reminders
|
||||
|
||||
- Do not commit `.tfstate*` or real `.tfvars`.
|
||||
- Do not commit credentials.
|
||||
- Do not run `terraform apply`/`destroy` casually.
|
||||
- Keep changes incremental and reviewable.
|
||||
|
||||
## Related docs
|
||||
|
||||
- [docs/source-of-truth.md](source-of-truth.md)
|
||||
- [docs/infrastructure-inventory.md](infrastructure-inventory.md)
|
||||
- [infrastructure/terraform/README.md](https://github.com/beatz174-bit/docker/blob/main/infrastructure/terraform/README.md)
|
||||
@@ -0,0 +1,32 @@
|
||||
# Terraform working dir
|
||||
**/.terraform/*
|
||||
|
||||
# Terraform state
|
||||
*.tfstate
|
||||
*.tfstate.*
|
||||
**/terraform.tfstate
|
||||
**/terraform.tfstate.*
|
||||
|
||||
# Crash logs
|
||||
crash.log
|
||||
crash.*.log
|
||||
|
||||
# Variable files with real values
|
||||
*.tfvars
|
||||
*.tfvars.json
|
||||
|
||||
# CLI config / overrides
|
||||
override.tf
|
||||
override.tf.json
|
||||
*_override.tf
|
||||
*_override.tf.json
|
||||
.terraformrc
|
||||
terraform.rc
|
||||
|
||||
# Plan files
|
||||
*.tfplan
|
||||
plan.out
|
||||
|
||||
# Local backend/state folders if you make them
|
||||
state/
|
||||
artifacts/
|
||||
@@ -0,0 +1,48 @@
|
||||
# Ansible Foundation (Phase 1)
|
||||
|
||||
This directory provides a minimal Ansible bootstrap for this repository.
|
||||
|
||||
## Purpose
|
||||
|
||||
- Establish a maintainable inventory/configuration foundation for hosts and devices.
|
||||
- Support gradual host onboarding and validation workflows.
|
||||
- Keep boundaries clear with existing Compose and Terraform authorities.
|
||||
|
||||
This is intentionally a **foundation stage**, not full production automation.
|
||||
|
||||
## Boundaries
|
||||
|
||||
- Docker runtime authority remains in Compose files and `services-up.sh`.
|
||||
- Terraform remains the primary structured infrastructure inventory/reconciliation layer.
|
||||
- Ansible here is a complementary configuration/inventory layer.
|
||||
- NixOS and network gear management are not authoritative through Ansible yet.
|
||||
|
||||
## Structure
|
||||
|
||||
- `ansible.cfg` - local defaults for inventory, collections, and output behavior.
|
||||
- `inventory/hosts.yml` - YAML inventory scaffold with starter groups.
|
||||
- `inventory/group_vars/` - shared/group variables.
|
||||
- `inventory/host_vars/` - per-host variables.
|
||||
- `playbooks/ping.yml` - minimal syntax/connection test playbook.
|
||||
- `playbooks/dns-inventory.yml` - local-only Dynu DNS read-only inventory wrapper.
|
||||
- `collections/requirements.yml` - lightweight baseline collections.
|
||||
- `roles/` - reserved for future incremental role adoption.
|
||||
|
||||
## Basic commands
|
||||
|
||||
Run from repository root:
|
||||
|
||||
```bash
|
||||
ansible --version
|
||||
ansible-lint --version
|
||||
ansible-galaxy collection install -r infrastructure/ansible/collections/requirements.yml -p infrastructure/ansible/collections
|
||||
ansible-inventory -i infrastructure/ansible/inventory/hosts.yml --list
|
||||
ansible-playbook -i infrastructure/ansible/inventory/hosts.yml infrastructure/ansible/playbooks/ping.yml --syntax-check
|
||||
ansible-playbook -i infrastructure/ansible/inventory/hosts.yml infrastructure/ansible/playbooks/dns-inventory.yml --syntax-check
|
||||
```
|
||||
|
||||
## Secrets and safety
|
||||
|
||||
- Do not commit real credentials or private keys.
|
||||
- Put sensitive per-host variables in local, untracked files or a future vault approach.
|
||||
- Keep host and device entries factual; avoid speculative production entries.
|
||||
@@ -0,0 +1,9 @@
|
||||
[defaults]
|
||||
inventory = ./inventory/hosts.yml
|
||||
collections_path = ./collections
|
||||
retry_files_enabled = False
|
||||
stdout_callback = yaml
|
||||
host_key_checking = True
|
||||
|
||||
[inventory]
|
||||
enable_plugins = yaml
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
collections:
|
||||
- name: ansible.posix
|
||||
- name: community.general
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
# Bootstrap defaults for the Ansible foundation in this repository.
|
||||
# Keep secrets and environment-specific auth details out of version control.
|
||||
|
||||
# Common interpreter hint for modern Linux hosts. Override per-host if needed.
|
||||
ansible_python_interpreter: /usr/bin/python3
|
||||
|
||||
# Placeholders for future connection/auth settings:
|
||||
# ansible_user: ""
|
||||
# ansible_port: 22
|
||||
# ansible_ssh_private_key_file: ""
|
||||
|
||||
# Add group-specific settings under inventory/group_vars/<group>.yml
|
||||
# and host-specific settings under inventory/host_vars/<host>.yml.
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
all:
|
||||
children:
|
||||
linux:
|
||||
hosts: {}
|
||||
network:
|
||||
hosts: {}
|
||||
virtualization:
|
||||
hosts: {}
|
||||
nixos:
|
||||
hosts: {}
|
||||
examples:
|
||||
hosts:
|
||||
example-managed-host:
|
||||
ansible_host: example-host.local
|
||||
ansible_connection: ssh
|
||||
# Example only: replace/remove before real operations.
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
# This integration is intentionally read-only.
|
||||
# No Dynu mutations are permitted in this repo at this stage.
|
||||
- name: Build Dynu DNS read-only inventory artifacts
|
||||
hosts: localhost
|
||||
connection: local
|
||||
gather_facts: false
|
||||
vars:
|
||||
repo_root: "{{ playbook_dir }}/../../.."
|
||||
|
||||
tasks:
|
||||
- name: Assert read-only guard variable is set
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- lookup('ansible.builtin.env', 'DYNU_READ_ONLY') == 'true'
|
||||
fail_msg: "Refusing to run: DYNU_READ_ONLY must be exactly 'true'."
|
||||
|
||||
- name: Fetch Dynu DNS (GET-only script)
|
||||
ansible.builtin.command: python3 scripts/dynu/fetch_dynu_dns.py
|
||||
args:
|
||||
chdir: "{{ repo_root }}"
|
||||
|
||||
- name: Correlate Dynu with Traefik and generate docs
|
||||
ansible.builtin.command: python3 scripts/dynu/correlate_dynu_with_traefik.py
|
||||
args:
|
||||
chdir: "{{ repo_root }}"
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Basic inventory and connectivity check
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- name: Ping managed hosts
|
||||
ansible.builtin.ping:
|
||||
@@ -0,0 +1,14 @@
|
||||
.terraform/
|
||||
*.tfstate
|
||||
*.tfstate.*
|
||||
*.tfvars
|
||||
*.tfvars.json
|
||||
crash.log
|
||||
override.tf
|
||||
override.tf.json
|
||||
*_override.tf
|
||||
*_override.tf.json
|
||||
*.tfplan
|
||||
plan.out
|
||||
state/
|
||||
artifacts/
|
||||
@@ -0,0 +1,64 @@
|
||||
# Terraform in This Repository
|
||||
|
||||
Terraform here is used as a **structured inventory + reconciliation layer** for existing infrastructure.
|
||||
|
||||
It does **not** replace Docker Compose as runtime deployment authority.
|
||||
|
||||
## What Terraform is currently used for
|
||||
|
||||
- Proxmox VM import/reconciliation for existing VMs.
|
||||
- Physical host metadata represented in Terraform locals/outputs.
|
||||
- Select Docker container mirror resources for documentation-oriented tracking.
|
||||
- Outputs that can support documentation and later downstream tooling.
|
||||
- Dynu DNS domain/record import and documentation inventory.
|
||||
|
||||
## What Terraform is not used for (today)
|
||||
|
||||
- Replacing `services-up.sh` / Compose for day-to-day app runtime orchestration.
|
||||
- Broad, immediate greenfield provisioning of the whole stack.
|
||||
- Casual `apply` operations across all infrastructure.
|
||||
- Replacing Dynu as DNS authority.
|
||||
- Blindly recreating production DNS records without import/reconciliation.
|
||||
|
||||
## Directory map
|
||||
|
||||
- `proxmox/` — imported/reconciled VM resources and host metadata outputs.
|
||||
- `docker/` — selective Docker container import/mirror resources.
|
||||
- `dynu/` — Dynu DNS brownfield import/reconciliation and DNS documentation outputs.
|
||||
- `bootstrap/` — backend/provider bootstrap scaffolding.
|
||||
- `modules/` — placeholder module directories for future stable abstractions.
|
||||
- `scripts/reconcile_from_plan.sh` — helper to convert generated plan config into reviewable draft files.
|
||||
|
||||
## Brownfield workflow standard
|
||||
|
||||
1. Import one existing object.
|
||||
2. Inspect state/plan output.
|
||||
3. Reconcile hand-maintained Terraform code.
|
||||
4. Keep `ignore_changes` narrowly scoped.
|
||||
5. Iterate to no-op/sane plan for intended scope.
|
||||
6. Avoid casual apply.
|
||||
|
||||
See detailed steps in [../../docs/terraform-workflows.md](../../docs/terraform-workflows.md).
|
||||
|
||||
## Safe validation commands
|
||||
|
||||
From Terraform directories, preferred checks are:
|
||||
|
||||
```bash
|
||||
terraform fmt -check -recursive
|
||||
terraform init -backend=false -input=false
|
||||
terraform validate
|
||||
```
|
||||
|
||||
## Secrets and state safety
|
||||
|
||||
- Do not commit `.tfstate*`.
|
||||
- Do not commit real `.tfvars` values.
|
||||
- Keep credentials in local, untracked inputs only.
|
||||
|
||||
## Related docs
|
||||
|
||||
- [../../docs/source-of-truth.md](../../docs/source-of-truth.md)
|
||||
- [../../docs/infrastructure-inventory.md](../../docs/infrastructure-inventory.md)
|
||||
- [docker/README.md](docker/README.md)
|
||||
- [proxmox/README.md](proxmox/README.md)
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/kreuzwerker/docker" {
|
||||
version = "3.0.2"
|
||||
constraints = "3.0.2"
|
||||
hashes = [
|
||||
"h1:cT2ccWOtlfKYBUE60/v2/4Q6Stk1KYTNnhxSck+VPlU=",
|
||||
"zh:15b0a2b2b563d8d40f62f83057d91acb02cd0096f207488d8b4298a59203d64f",
|
||||
"zh:23d919de139f7cd5ebfd2ff1b94e6d9913f0977fcfc2ca02e1573be53e269f95",
|
||||
"zh:38081b3fe317c7e9555b2aaad325ad3fa516a886d2dfa8605ae6a809c1072138",
|
||||
"zh:4a9c5065b178082f79ad8160243369c185214d874ff5048556d48d3edd03c4da",
|
||||
"zh:5438ef6afe057945f28bce43d76c4401254073de01a774760169ac1058830ac2",
|
||||
"zh:60b7fadc287166e5c9873dfe53a7976d98244979e0ab66428ea0dea1ebf33e06",
|
||||
"zh:61c5ec1cb94e4c4a4fb1e4a24576d5f39a955f09afb17dab982de62b70a9bdd1",
|
||||
"zh:a38fe9016ace5f911ab00c88e64b156ebbbbfb72a51a44da3c13d442cd214710",
|
||||
"zh:c2c4d2b1fd9ebb291c57f524b3bf9d0994ff3e815c0cd9c9bcb87166dc687005",
|
||||
"zh:d567bb8ce483ab2cf0602e07eae57027a1a53994aba470fa76095912a505533d",
|
||||
"zh:e83bf05ab6a19dd8c43547ce9a8a511f8c331a124d11ac64687c764ab9d5a792",
|
||||
"zh:e90c934b5cd65516fbcc454c89a150bfa726e7cf1fe749790c7480bbeb19d387",
|
||||
"zh:f05f167d2eaf913045d8e7b88c13757e3cf595dd5cd333057fdafc7c4b7fed62",
|
||||
"zh:fcc9c1cea5ce85e8bcb593862e699a881bd36dffd29e2e367f82d15368659c3d",
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
# Terraform Docker Mirror Layer
|
||||
|
||||
This directory tracks selected existing Docker containers in Terraform for inventory/documentation purposes.
|
||||
|
||||
## Purpose
|
||||
|
||||
- Mirror specific running containers as Terraform resources.
|
||||
- Reconcile imported state into maintainable code.
|
||||
- Produce structured outputs/reminders that support documentation workflows.
|
||||
|
||||
## Boundary with Docker Compose
|
||||
|
||||
Docker Compose + `services-up.sh` remain runtime composition authority.
|
||||
|
||||
Terraform resources here are **not** the primary day-to-day deployment mechanism for app services.
|
||||
|
||||
## Current contents
|
||||
|
||||
- `main.tf` — import-first workflow notes and minimal scaffolding.
|
||||
- `searxng-webapp.tf` — generated/reconciled example container resource.
|
||||
- `outputs.tf` — documentation-oriented reminders/outputs.
|
||||
- `terraform.tfvars.example` — safe template for local values.
|
||||
|
||||
## Import/reconciliation workflow
|
||||
|
||||
1. Start with one existing container.
|
||||
2. Import with `import {}` block or `terraform import`.
|
||||
3. Inspect state / generated config.
|
||||
4. Reduce generated attributes to meaningful, stable arguments.
|
||||
5. Keep lifecycle `ignore_changes` narrow and justified.
|
||||
6. Iterate until plan is clean for the intended resource.
|
||||
|
||||
## Guardrails
|
||||
|
||||
- Do not attempt to mirror all containers in one pass.
|
||||
- Do not commit local state or real credentials.
|
||||
- Treat generated config as draft input that needs review.
|
||||
|
||||
## Related docs
|
||||
|
||||
- [../README.md](../README.md)
|
||||
- [../../../docs/source-of-truth.md](../../../docs/source-of-truth.md)
|
||||
- [../../../docs/terraform-workflows.md](../../../docs/terraform-workflows.md)
|
||||
@@ -0,0 +1,14 @@
|
||||
resource "docker_container" "authelia" {
|
||||
name = local.docker_containers["authelia"].container_name
|
||||
image = local.docker_containers["authelia"].image
|
||||
|
||||
restart = local.docker_containers["authelia"].restart_policy
|
||||
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
env,
|
||||
labels,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,613 @@
|
||||
locals {
|
||||
docker_containers = {
|
||||
"authelia" = {
|
||||
terraform_resource = "docker_container.authelia"
|
||||
compose_project = "core"
|
||||
compose_service = "authelia"
|
||||
compose_file = "core/authelia/docker-compose.yml"
|
||||
container_name = "authelia"
|
||||
image = "authelia/authelia"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/core/authelia->/config"]
|
||||
published_ports = []
|
||||
build_context = "/home/nixos/docker/core/authelia"
|
||||
build_dockerfile = "Dockerfile"
|
||||
useful_labels = {
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.middlewares.authelia.forwardauth.address" = "http://authelia:9091/api/verify?rd=https://auth.lan.ddnsgeek.com/"
|
||||
"traefik.http.middlewares.authelia.forwardauth.authResponseHeaders" = "Remote-User,Remote-Groups"
|
||||
"traefik.http.middlewares.authelia.forwardauth.maxResponseBodySize" = "2097152"
|
||||
"traefik.http.middlewares.authelia.forwardauth.trustForwardHeader" = "true"
|
||||
"traefik.http.routers.authelia.entrypoints" = "websecure"
|
||||
"traefik.http.routers.authelia.rule" = "Host(`auth.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.authelia.tls" = "true"
|
||||
"traefik.http.routers.authelia.tls.certresolver" = "myresolver"
|
||||
}
|
||||
}
|
||||
"crowdsec" = {
|
||||
terraform_resource = "docker_container.crowdsec"
|
||||
compose_project = "core"
|
||||
compose_service = "crowdsec"
|
||||
compose_file = "core/crowdsec/docker-compose.yml"
|
||||
container_name = "crowdsec"
|
||||
image = "core-crowdsec"
|
||||
image_source = "compose_build_inferred"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/core/crowdsec/logs->/logs:ro", "bind:/home/nixos/docker/core/crowdsec/data->/var/lib/crowdsec/data", "bind:/home/nixos/docker/core/crowdsec/config->/etc/crowdsec"]
|
||||
published_ports = []
|
||||
build_context = "/home/nixos/docker/core/crowdsec"
|
||||
build_dockerfile = "Dockerfile"
|
||||
useful_labels = {}
|
||||
}
|
||||
"docker-socket-proxy" = {
|
||||
terraform_resource = "docker_container.docker_socket_proxy"
|
||||
compose_project = "core"
|
||||
compose_service = "docker-socket-proxy"
|
||||
compose_file = "monitoring/docker-socket-proxy/docker-compose.yml"
|
||||
container_name = "docker-socket-proxy"
|
||||
image = "tecnativa/docker-socket-proxy:latest"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "unless-stopped"
|
||||
network_mode = null
|
||||
networks = ["monitor", "traefik"]
|
||||
mounts = ["bind:/var/run/docker.sock->/var/run/docker.sock:ro"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {}
|
||||
}
|
||||
"docker-update-exporter" = {
|
||||
terraform_resource = "docker_container.docker_update_exporter"
|
||||
compose_project = "core"
|
||||
compose_service = "docker-update-exporter"
|
||||
compose_file = "monitoring/docker-exporter/docker-compose.yml"
|
||||
container_name = "docker-update-exporter"
|
||||
image = "core-docker-update-exporter"
|
||||
image_source = "compose_build_inferred"
|
||||
restart_policy = "unless-stopped"
|
||||
network_mode = null
|
||||
networks = ["monitor"]
|
||||
mounts = ["bind:/root/.docker/config.json->/root/.docker/config.json:ro", "bind:/home/nixos/docker/monitoring/docker-exporter/data->/data", "bind:/home/nixos/docker->/compose:ro"]
|
||||
published_ports = []
|
||||
build_context = "/home/nixos/docker/monitoring/docker-exporter"
|
||||
build_dockerfile = "Dockerfile"
|
||||
useful_labels = {}
|
||||
}
|
||||
"error-pages" = {
|
||||
terraform_resource = "docker_container.error_pages"
|
||||
compose_project = "core"
|
||||
compose_service = "error-pages"
|
||||
compose_file = "core/error-pages/docker-compose.yml"
|
||||
container_name = "error-pages"
|
||||
image = "tarampampam/error-pages:3"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["traefik"]
|
||||
mounts = []
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.middlewares.error-pages-middleware.errors.query" = "/{status}.html"
|
||||
"traefik.http.middlewares.error-pages-middleware.errors.service" = "error-pages-service"
|
||||
"traefik.http.middlewares.error-pages-middleware.errors.status" = "400-599"
|
||||
"traefik.http.routers.error-pages-router.entrypoints" = "web"
|
||||
"traefik.http.routers.error-pages-router.middlewares" = "error-pages-middleware"
|
||||
"traefik.http.routers.error-pages-router.rule" = "HostRegexp(`{host:.+}`)"
|
||||
"traefik.http.services.error-pages-service.loadbalancer.server.port" = "8080"
|
||||
}
|
||||
}
|
||||
"gitea" = {
|
||||
terraform_resource = "docker_container.gitea"
|
||||
compose_project = "core"
|
||||
compose_service = "gitea"
|
||||
compose_file = "apps/gitea/docker-compose.yml"
|
||||
container_name = "gitea"
|
||||
image = "gitea/gitea:latest"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/apps/gitea/data->/data"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {
|
||||
"traefik.docker.network" = "core_traefik"
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.routers.gitea.entrypoints" = "websecure"
|
||||
"traefik.http.routers.gitea.rule" = "Host(`gitea.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.gitea.tls" = "true"
|
||||
"traefik.http.routers.gitea.tls.certresolver" = "myresolver"
|
||||
"traefik.http.services.gitea.loadbalancer.server.port" = "3000"
|
||||
}
|
||||
}
|
||||
"gotify" = {
|
||||
terraform_resource = "docker_container.gotify"
|
||||
compose_project = "core"
|
||||
compose_service = "gotify"
|
||||
compose_file = "monitoring/gotify/docker-compose.yml"
|
||||
container_name = "gotify"
|
||||
image = "gotify/server:latest"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/monitoring/gotify/data->/app/data"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {
|
||||
"traefik.docker.network" = "core_traefik"
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.routers.gotify.entrypoints" = "websecure"
|
||||
"traefik.http.routers.gotify.rule" = "Host(`gotify.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.gotify.tls.certresolver" = "myresolver"
|
||||
"traefik.http.routers.gotify.tls.options" = "mtls-private-admin@file"
|
||||
"traefik.http.services.gotify.loadbalancer.server.port" = "80"
|
||||
}
|
||||
}
|
||||
"grafana" = {
|
||||
terraform_resource = "docker_container.grafana"
|
||||
compose_project = "core"
|
||||
compose_service = "grafana"
|
||||
compose_file = "monitoring/grafana/docker-compose.yml"
|
||||
container_name = "grafana"
|
||||
image = "grafana/grafana:latest"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "unless-stopped"
|
||||
network_mode = null
|
||||
networks = ["monitor", "traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/monitoring/grafana/data->/var/lib/grafana"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {
|
||||
"traefik.docker.network" = "core_traefik"
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.routers.grafana.entrypoints" = "websecure"
|
||||
"traefik.http.routers.grafana.rule" = "Host(`grafana.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.grafana.tls.certresolver" = "myresolver"
|
||||
"traefik.http.routers.grafana.tls.options" = "mtls-private-admin@file"
|
||||
"traefik.http.services.grafana.loadbalancer.server.port" = "3000"
|
||||
}
|
||||
}
|
||||
"gramps-redis" = {
|
||||
terraform_resource = "docker_container.gramps_redis"
|
||||
compose_project = "core"
|
||||
compose_service = "gramps-redis"
|
||||
compose_file = "apps/gramps/docker-compose.yml"
|
||||
container_name = "gramps-redis"
|
||||
image = "valkey/valkey:8-alpine"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["gramps"]
|
||||
mounts = []
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {}
|
||||
}
|
||||
"gramps-web" = {
|
||||
terraform_resource = "docker_container.gramps_web"
|
||||
compose_project = "core"
|
||||
compose_service = "grampsweb"
|
||||
compose_file = "apps/gramps/docker-compose.yml"
|
||||
container_name = "gramps-web"
|
||||
image = "ghcr.io/gramps-project/grampsweb:latest"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["gramps", "traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/apps/gramps/data/users->/app/users", "bind:/home/nixos/docker/apps/gramps/data/index->/app/indexdir", "bind:/home/nixos/docker/apps/gramps/data/thumbnail_cache->/app/thumbnail_cache", "bind:/home/nixos/docker/apps/gramps/data/cache->/app/cache", "bind:/home/nixos/docker/apps/gramps/data/secret->/app/secret", "bind:/home/nixos/docker/apps/gramps/data/db->/root/.gramps/grampsdb", "bind:/home/nixos/docker/apps/gramps/data/media->/app/media", "bind:/home/nixos/docker/apps/gramps/data/tmp->/tmp"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {
|
||||
"traefik.docker.network" = "core_traefik"
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.routers.gramps.entrypoints" = "websecure"
|
||||
"traefik.http.routers.gramps.rule" = "Host(`familytree.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.gramps.tls.certresolver" = "myresolver"
|
||||
"traefik.http.services.gramps.loadbalancer.server.port" = "5000"
|
||||
}
|
||||
}
|
||||
"gramps-web-celery" = {
|
||||
terraform_resource = "docker_container.gramps_web_celery"
|
||||
compose_project = "core"
|
||||
compose_service = "grampsweb_celery"
|
||||
compose_file = "apps/gramps/docker-compose.yml"
|
||||
container_name = "gramps-web-celery"
|
||||
image = "ghcr.io/gramps-project/grampsweb:latest"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["gramps"]
|
||||
mounts = ["bind:/home/nixos/docker/apps/gramps/data/users->/app/users", "bind:/home/nixos/docker/apps/gramps/data/index->/app/indexdir", "bind:/home/nixos/docker/apps/gramps/data/thumbnail_cache->/app/thumbnail_cache", "bind:/home/nixos/docker/apps/gramps/data/cache->/app/cache", "bind:/home/nixos/docker/apps/gramps/data/secret->/app/secret", "bind:/home/nixos/docker/apps/gramps/data/db->/root/.gramps/grampsdb", "bind:/home/nixos/docker/apps/gramps/data/media->/app/media", "bind:/home/nixos/docker/apps/gramps/data/tmp->/tmp"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {}
|
||||
}
|
||||
"influxdb" = {
|
||||
terraform_resource = "docker_container.influxdb"
|
||||
compose_project = "core"
|
||||
compose_service = "influxdb"
|
||||
compose_file = "monitoring/influxdb/docker-compose.yml"
|
||||
container_name = "influxdb"
|
||||
image = "influxdb:2.7"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "unless-stopped"
|
||||
network_mode = null
|
||||
networks = ["monitor", "traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/monitoring/influxdb->/var/lib/influxdb2"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {
|
||||
"traefik.docker.network" = "core_traefik"
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.routers.influxdb.entrypoints" = "websecure"
|
||||
"traefik.http.routers.influxdb.middlewares" = "authelia"
|
||||
"traefik.http.routers.influxdb.rule" = "Host(`influxdb.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.influxdb.tls.certresolver" = "myresolver"
|
||||
"traefik.http.routers.influxdb.tls.options" = "mtls-private-admin@file"
|
||||
"traefik.http.services.influxdb.loadbalancer.server.port" = "8086"
|
||||
}
|
||||
}
|
||||
"monitor-kuma" = {
|
||||
terraform_resource = "docker_container.monitor_kuma"
|
||||
compose_project = "core"
|
||||
compose_service = "monitor-kuma"
|
||||
compose_file = "monitoring/uptime-kuma/docker-compose.yml"
|
||||
container_name = "monitor-kuma"
|
||||
image = "louislam/uptime-kuma:2.1.1"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["monitor", "traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/monitoring/uptime-kuma/data->/app/data"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {
|
||||
"traefik.docker.network" = "core_traefik"
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.routers.monitor.entrypoints" = "websecure"
|
||||
"traefik.http.routers.monitor.rule" = "Host(`monitor-kuma.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.monitor.tls" = "true"
|
||||
"traefik.http.routers.monitor.tls.certresolver" = "myresolver"
|
||||
"traefik.http.routers.monitor.tls.options" = "mtls-private-admin@file"
|
||||
"traefik.http.services.monitor.loadbalancer.server.port" = "3001"
|
||||
}
|
||||
}
|
||||
"mtls-bridge" = {
|
||||
terraform_resource = "docker_container.mtls_bridge"
|
||||
compose_project = "core"
|
||||
compose_service = "mtls-bridge"
|
||||
compose_file = "monitoring/mtls-bridge/docker-compose.yml"
|
||||
container_name = "mtls-bridge"
|
||||
image = "core-mtls-bridge"
|
||||
image_source = "compose_build_inferred"
|
||||
restart_policy = "unless-stopped"
|
||||
network_mode = null
|
||||
networks = ["monitor", "traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/core/traefik/certs->/certs:ro"]
|
||||
published_ports = []
|
||||
build_context = "/home/nixos/docker/monitoring/mtls-bridge"
|
||||
build_dockerfile = "Dockerfile"
|
||||
useful_labels = {
|
||||
"traefik.docker.network" = "core_traefik"
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.middlewares.mtls-bridge-auth.basicauth.users" = ""
|
||||
"traefik.http.middlewares.mtls-bridge-cors.headers.accesscontrolallowcredentials" = "true"
|
||||
"traefik.http.middlewares.mtls-bridge-cors.headers.accesscontrolallowheaders" = "authorization,content-type,x-grafana-action,x-grafana-device-id"
|
||||
"traefik.http.middlewares.mtls-bridge-cors.headers.accesscontrolallowmethods" = "GET,POST,PUT,PATCH,DELETE,OPTIONS"
|
||||
"traefik.http.middlewares.mtls-bridge-cors.headers.accesscontrolalloworiginlist" = "https://grafana.lan.ddnsgeek.com"
|
||||
"traefik.http.middlewares.mtls-bridge-cors.headers.addvaryheader" = "true"
|
||||
"traefik.http.routers.mtls-bridge-preflight.entrypoints" = "websecure"
|
||||
"traefik.http.routers.mtls-bridge-preflight.middlewares" = "mtls-bridge-cors"
|
||||
"traefik.http.routers.mtls-bridge-preflight.priority" = "100"
|
||||
"traefik.http.routers.mtls-bridge-preflight.rule" = "Host(`mtls-bridge.lan.ddnsgeek.com`) && Method(`OPTIONS`)"
|
||||
"traefik.http.routers.mtls-bridge-preflight.service" = "mtls-bridge"
|
||||
"traefik.http.routers.mtls-bridge-preflight.tls.certresolver" = "myresolver"
|
||||
"traefik.http.routers.mtls-bridge.entrypoints" = "websecure"
|
||||
"traefik.http.routers.mtls-bridge.middlewares" = "mtls-bridge-auth,mtls-bridge-cors"
|
||||
"traefik.http.routers.mtls-bridge.rule" = "Host(`mtls-bridge.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.mtls-bridge.tls.certresolver" = "myresolver"
|
||||
"traefik.http.services.mtls-bridge.loadbalancer.server.port" = "8080"
|
||||
}
|
||||
}
|
||||
"nextcloud-db" = {
|
||||
terraform_resource = "docker_container.nextcloud_db"
|
||||
compose_project = "core"
|
||||
compose_service = "nextcloud-db"
|
||||
compose_file = "apps/nextcloud/docker-compose.yml"
|
||||
container_name = "nextcloud-db"
|
||||
image = "mariadb:11.4"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["nextcloud"]
|
||||
mounts = ["bind:/home/nixos/docker/apps/nextcloud/database->/var/lib/mysql"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {}
|
||||
}
|
||||
"nextcloud-redis" = {
|
||||
terraform_resource = "docker_container.nextcloud_redis"
|
||||
compose_project = "core"
|
||||
compose_service = "nextcloud-redis"
|
||||
compose_file = "apps/nextcloud/docker-compose.yml"
|
||||
container_name = "nextcloud-redis"
|
||||
image = "redis"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["nextcloud"]
|
||||
mounts = ["bind:/home/nixos/docker/apps/nextcloud/data/redis->/data"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {}
|
||||
}
|
||||
"nextcloud-webapp" = {
|
||||
terraform_resource = "docker_container.nextcloud_webapp"
|
||||
compose_project = "core"
|
||||
compose_service = "nextcloud-webapp"
|
||||
compose_file = "apps/nextcloud/docker-compose.yml"
|
||||
container_name = "nextcloud-webapp"
|
||||
image = "core-nextcloud-webapp"
|
||||
image_source = "compose_build_inferred"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["nextcloud", "traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/apps/nextcloud/data->/var/www/html/data", "bind:/home/nixos/docker/apps/nextcloud/config->/var/www/html/config", "tmpfs:->/tmp:exec"]
|
||||
published_ports = []
|
||||
build_context = "/home/nixos/docker/apps/nextcloud"
|
||||
build_dockerfile = "Dockerfile"
|
||||
useful_labels = {
|
||||
"traefik.docker.network" = "core_traefik"
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.middlewares.nextcloud-dav.replacepathregex.regex" = "^/.well-known/ca(l|rd)dav"
|
||||
"traefik.http.middlewares.nextcloud-dav.replacepathregex.replacement" = "/remote.php/dav/"
|
||||
"traefik.http.middlewares.nextcloud-nodeinfo.replacepathregex.regex" = "^/.well-known/nodeinfo"
|
||||
"traefik.http.middlewares.nextcloud-nodeinfo.replacepathregex.replacement" = "/nextcloud/index.php/.well-known/nodeinfo/"
|
||||
"traefik.http.middlewares.nextcloud-webfinger.redirectregex.permanent" = "true"
|
||||
"traefik.http.middlewares.nextcloud-webfinger.redirectregex.regex" = "https://(.*)/.well-known/webfinger"
|
||||
"traefik.http.middlewares.nextcloud-webfinger.redirectregex.replacement" = "https://$${1}/nextcloud/index.php/.well-known/webfinger"
|
||||
"traefik.http.routers.nextcloud.entrypoints" = "websecure"
|
||||
"traefik.http.routers.nextcloud.middlewares" = "nextcloud-dav, nextcloud-webfinger"
|
||||
"traefik.http.routers.nextcloud.rule" = "Host(`nextcloud.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.nextcloud.tls.certresolver" = "myresolver"
|
||||
}
|
||||
}
|
||||
"node-exporter" = {
|
||||
terraform_resource = "docker_container.node_exporter"
|
||||
compose_project = "core"
|
||||
compose_service = "node-exporter"
|
||||
compose_file = "monitoring/node-exporter/docker-compose.yml"
|
||||
container_name = "node-exporter"
|
||||
image = "prom/node-exporter:latest"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "unless-stopped"
|
||||
network_mode = null
|
||||
networks = ["monitor"]
|
||||
mounts = ["bind:/proc->/host/proc:ro", "bind:/sys->/host/sys:ro", "bind:/->/rootfs:ro"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {}
|
||||
}
|
||||
"node-red" = {
|
||||
terraform_resource = "docker_container.node_red"
|
||||
compose_project = "core"
|
||||
compose_service = "node-red"
|
||||
compose_file = "monitoring/node-red/docker-compose.yml"
|
||||
container_name = "node-red"
|
||||
image = "core-node-red"
|
||||
image_source = "compose_build_inferred"
|
||||
restart_policy = "unless-stopped"
|
||||
network_mode = null
|
||||
networks = ["monitor", "traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/monitoring/node-red/data->/data", "bind:/home/nixos/docker->/compose/docker:ro", "bind:/home/nixos/raspi->/compose/raspi:ro"]
|
||||
published_ports = []
|
||||
build_context = "/home/nixos/docker/monitoring/node-red"
|
||||
build_dockerfile = "Dockerfile"
|
||||
useful_labels = {
|
||||
"traefik.docker.network" = "core_traefik"
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.routers.node-red.entrypoints" = "websecure"
|
||||
"traefik.http.routers.node-red.middlewares" = "authelia"
|
||||
"traefik.http.routers.node-red.rule" = "Host(`node-red.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.node-red.tls.certresolver" = "myresolver"
|
||||
"traefik.http.routers.node-red.tls.options" = "mtls-private-admin@file"
|
||||
"traefik.http.services.node-red.loadbalancer.server.port" = "1880"
|
||||
}
|
||||
}
|
||||
"passbolt-db" = {
|
||||
terraform_resource = "docker_container.passbolt_db"
|
||||
compose_project = "core"
|
||||
compose_service = "passbolt-db"
|
||||
compose_file = "apps/passbolt/docker-compose.yml"
|
||||
container_name = "passbolt-db"
|
||||
image = "mariadb:12"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["passbolt"]
|
||||
mounts = ["bind:/home/nixos/docker/apps/passbolt/data/database->/var/lib/mysql"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {}
|
||||
}
|
||||
"passbolt-webapp" = {
|
||||
terraform_resource = "docker_container.passbolt_webapp"
|
||||
compose_project = "core"
|
||||
compose_service = "passbolt-webapp"
|
||||
compose_file = "apps/passbolt/docker-compose.yml"
|
||||
container_name = "passbolt-webapp"
|
||||
image = "passbolt/passbolt:latest-ce"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["passbolt", "traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/apps/passbolt/data/gpg->/etc/passbolt/gpg", "bind:/home/nixos/docker/apps/passbolt/data/jwt->/etc/passbolt/jwt"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {
|
||||
"traefik.docker.network" = "core_traefik"
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.routers.passbolt.entrypoints" = "websecure"
|
||||
"traefik.http.routers.passbolt.rule" = "Host(`passbolt.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.passbolt.tls.certresolver" = "myresolver"
|
||||
}
|
||||
}
|
||||
"pihole-exporter" = {
|
||||
terraform_resource = "docker_container.pihole_exporter"
|
||||
compose_project = "core"
|
||||
compose_service = "pihole-exporter"
|
||||
compose_file = "monitoring/pihole-exporter/docker-compose.yml"
|
||||
container_name = "pihole-exporter"
|
||||
image = "ekofr/pihole-exporter:latest"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "unless-stopped"
|
||||
network_mode = null
|
||||
networks = ["monitor"]
|
||||
mounts = []
|
||||
published_ports = ["9617:9617/tcp"]
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {}
|
||||
}
|
||||
"portainer" = {
|
||||
terraform_resource = "docker_container.portainer"
|
||||
compose_project = "core"
|
||||
compose_service = "portainer"
|
||||
compose_file = "monitoring/portainer/docker-compose.yml"
|
||||
container_name = "portainer"
|
||||
image = "portainer/portainer-ce:latest"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "unless-stopped"
|
||||
network_mode = null
|
||||
networks = ["traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/monitoring/portainer/data->/data"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.routers.portainer.entrypoints" = "websecure"
|
||||
"traefik.http.routers.portainer.rule" = "Host(`portainer.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.portainer.tls" = "true"
|
||||
"traefik.http.routers.portainer.tls.certresolver" = "myresolver"
|
||||
"traefik.http.routers.portainer.tls.options" = "mtls-private-admin@file"
|
||||
"traefik.http.services.portainer.loadbalancer.server.port" = "9000"
|
||||
}
|
||||
}
|
||||
"prometheus" = {
|
||||
terraform_resource = "docker_container.prometheus"
|
||||
compose_project = "core"
|
||||
compose_service = "prometheus"
|
||||
compose_file = "monitoring/prometheus/docker-compose.yml"
|
||||
container_name = "prometheus"
|
||||
image = "prom/prometheus:latest"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "unless-stopped"
|
||||
network_mode = null
|
||||
networks = ["monitor", "traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/monitoring/prometheus/prometheus.yml->/etc/prometheus/prometheus.yml:ro", "bind:/home/nixos/docker/monitoring/prometheus/data->/prometheus", "bind:/home/nixos/docker/monitoring/prometheus/rules->/etc/prometheus/rules:ro", "bind:/home/nixos/docker/secrets/prometheus_kuma_basic_auth_password.txt->/run/secrets/prometheus_kuma_basic_auth_password:ro"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {
|
||||
"traefik.docker.network" = "core_traefik"
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.routers.prometheus.entrypoints" = "websecure"
|
||||
"traefik.http.routers.prometheus.middlewares" = "authelia"
|
||||
"traefik.http.routers.prometheus.rule" = "Host(`prometheus.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.prometheus.tls.certresolver" = "myresolver"
|
||||
"traefik.http.routers.prometheus.tls.options" = "mtls-private-admin@file"
|
||||
"traefik.http.services.prometheus.loadbalancer.server.port" = "9090"
|
||||
}
|
||||
}
|
||||
"searxng-webapp" = {
|
||||
terraform_resource = "docker_container.searxng-webapp"
|
||||
compose_project = "core"
|
||||
compose_service = "searxng-webapp"
|
||||
compose_file = "apps/searxng/docker-compose.yml"
|
||||
container_name = "searxng-webapp"
|
||||
image = "searxng/searxng"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["traefik"]
|
||||
mounts = []
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.routers.searxng.entrypoints" = "websecure"
|
||||
"traefik.http.routers.searxng.rule" = "Host(`searxng.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.searxng.tls.certresolver" = "myresolver"
|
||||
"traefik.http.services.searxng.loadbalancer.server.port" = "8080"
|
||||
}
|
||||
}
|
||||
"telegraf" = {
|
||||
terraform_resource = "docker_container.telegraf"
|
||||
compose_project = "core"
|
||||
compose_service = "telegraf"
|
||||
compose_file = "monitoring/telegraf/docker-compose.yml"
|
||||
container_name = "telegraf"
|
||||
image = "telegraf:latest"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "unless-stopped"
|
||||
network_mode = null
|
||||
networks = ["monitor"]
|
||||
mounts = ["bind:/home/nixos/docker/monitoring/telegraf/telegraf.conf->/etc/telegraf/telegraf.conf:ro", "bind:/home/nixos/docker/monitoring/node-red/data->/var/log/node-red:ro"]
|
||||
published_ports = []
|
||||
build_context = null
|
||||
build_dockerfile = null
|
||||
useful_labels = {}
|
||||
}
|
||||
"traefik" = {
|
||||
terraform_resource = "docker_container.traefik"
|
||||
compose_project = "core"
|
||||
compose_service = "traefik"
|
||||
compose_file = "core/traefik/docker-compose.yml"
|
||||
container_name = "traefik"
|
||||
image = "traefik:3"
|
||||
image_source = "declared_image"
|
||||
restart_policy = "always"
|
||||
network_mode = null
|
||||
networks = ["traefik"]
|
||||
mounts = ["bind:/home/nixos/docker/core/traefik/data/letsencrypt->/letsencrypt", "bind:/home/nixos/docker/core/traefik/data/logs->/logs", "bind:/home/nixos/docker/core/traefik/certs->/etc/traefik/certs:ro", "bind:/home/nixos/docker/core/traefik/dynamic.yml->/etc/traefik/dynamic.yml:ro", "bind:/home/nixos/docker/core/traefik/traefik.yml->/etc/traefik/traefik.yml:ro", "bind:/home/nixos/docker/core/traefik/data/plugins->/plugins-storage"]
|
||||
published_ports = ["80:80/tcp", "443:443/tcp"]
|
||||
build_context = "/home/nixos/docker/core"
|
||||
build_dockerfile = "Dockerfile"
|
||||
useful_labels = {
|
||||
"traefik.docker.network" = "core_traefik"
|
||||
"traefik.enable" = "true"
|
||||
"traefik.http.routers.traefik.entrypoints" = "websecure"
|
||||
"traefik.http.routers.traefik.middlewares" = "authelia"
|
||||
"traefik.http.routers.traefik.observability.tracing" = "true"
|
||||
"traefik.http.routers.traefik.rule" = "Host(`traefik.lan.ddnsgeek.com`)"
|
||||
"traefik.http.routers.traefik.service" = "api@internal"
|
||||
"traefik.http.routers.traefik.tls.certresolver" = "myresolver"
|
||||
"traefik.http.routers.traefik.tls.options" = "mtls-private-admin@file"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
resource "docker_container" "crowdsec" {
|
||||
name = local.docker_containers["crowdsec"].container_name
|
||||
image = local.docker_containers["crowdsec"].image
|
||||
|
||||
restart = local.docker_containers["crowdsec"].restart_policy
|
||||
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
env,
|
||||
labels,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
resource "docker_container" "docker_socket_proxy" {
|
||||
name = local.docker_containers["docker-socket-proxy"].container_name
|
||||
image = local.docker_containers["docker-socket-proxy"].image
|
||||
|
||||
restart = local.docker_containers["docker-socket-proxy"].restart_policy
|
||||
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
env,
|
||||
labels,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
resource "docker_container" "docker_update_exporter" {
|
||||
name = local.docker_containers["docker-update-exporter"].container_name
|
||||
image = local.docker_containers["docker-update-exporter"].image
|
||||
|
||||
restart = local.docker_containers["docker-update-exporter"].restart_policy
|
||||
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
env,
|
||||
labels,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
resource "docker_container" "error_pages" {
|
||||
name = local.docker_containers["error-pages"].container_name
|
||||
image = local.docker_containers["error-pages"].image
|
||||
|
||||
restart = local.docker_containers["error-pages"].restart_policy
|
||||
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
env,
|
||||
labels,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
resource "docker_container" "gitea" {
|
||||
name = local.docker_containers["gitea"].container_name
|
||||
image = local.docker_containers["gitea"].image
|
||||
|
||||
restart = local.docker_containers["gitea"].restart_policy
|
||||
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
env,
|
||||
labels,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
resource "docker_container" "gotify" {
|
||||
name = local.docker_containers["gotify"].container_name
|
||||
image = local.docker_containers["gotify"].image
|
||||
|
||||
restart = local.docker_containers["gotify"].restart_policy
|
||||
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
env,
|
||||
labels,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
resource "docker_container" "grafana" {
|
||||
name = local.docker_containers["grafana"].container_name
|
||||
image = local.docker_containers["grafana"].image
|
||||
|
||||
restart = local.docker_containers["grafana"].restart_policy
|
||||
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
env,
|
||||
labels,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
resource "docker_container" "gramps_redis" {
|
||||
name = local.docker_containers["gramps-redis"].container_name
|
||||
image = local.docker_containers["gramps-redis"].image
|
||||
|
||||
restart = local.docker_containers["gramps-redis"].restart_policy
|
||||
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
env,
|
||||
labels,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
resource "docker_container" "gramps_web_celery" {
|
||||
name = local.docker_containers["gramps-web-celery"].container_name
|
||||
image = local.docker_containers["gramps-web-celery"].image
|
||||
|
||||
restart = local.docker_containers["gramps-web-celery"].restart_policy
|
||||
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [
|
||||
env,
|
||||
labels,
|
||||
]
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user