-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.edge.yml
More file actions
122 lines (116 loc) · 4.34 KB
/
Copy pathdocker-compose.edge.yml
File metadata and controls
122 lines (116 loc) · 4.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
services:
# ── Infisical (self-hosted secrets manager) ──────────────────────────────────
# Tailscale-only — no public ingress, no Caddy vhost (see UFW rules in
# group_vars/edge.yml and docs/NETWORK.md "Tailscale-only routing"). High
# blast-radius control plane: holds every application secret.
# Dedicated Postgres + Redis — keeps edge self-contained.
# .env rendered by roles/infisical to /opt/infisical/.env (mode 0600) — deliberately
# OUTSIDE the repo dir so repo git operations never touch node-generated secrets.
# All three containers share /opt/infisical/.env (env_file) — it carries both the
# Infisical-named vars (ENCRYPTION_KEY, AUTH_SECRET, DB_CONNECTION_URI, REDIS_URL)
# and the POSTGRES_*/REDIS_PASSWORD vars consumed by the DB/cache images. Each
# image picks out only the keys it recognises. Single source of truth — no shell-
# level ${VAR} substitution, so `docker compose up` needs no extra environment.
infisical-db:
image: postgres:16-alpine
container_name: infisical-db
restart: unless-stopped
env_file:
- /opt/infisical/.env
volumes:
- infisical_db_data:/var/lib/postgresql/data
networks:
- infisical_net
security_opt:
- no-new-privileges:true
infisical-redis:
image: redis:7-alpine
container_name: infisical-redis
restart: unless-stopped
env_file:
- /opt/infisical/.env
entrypoint: ["sh", "-c", "exec redis-server --requirepass \"$$REDIS_PASSWORD\""]
volumes:
- infisical_redis_data:/data
networks:
- infisical_net
security_opt:
- no-new-privileges:true
infisical:
image: infisical/infisical:v0.161.9
container_name: infisical
restart: unless-stopped
env_file:
- /opt/infisical/.env
ports:
- "8222:8080" # Tailscale-only — bound 0.0.0.0 but firewalled to the Tailscale CGNAT range
networks:
- infisical_net
- edge_net # so semaphore can reach it as http://infisical:8080
depends_on:
- infisical-db
- infisical-redis
security_opt:
- no-new-privileges:true
# ── Semaphore (web UI over the existing Ansible playbooks) ───────────────────
# Tailscale-only — same routing rationale as Infisical (runs privileged playbooks).
# Repo bind-mounted READ-ONLY at /repo; playbook execution dir is the separate
# writable semaphore_workspace volume (/tmp/workspace) — facts/temp/inventory
# writes never touch the repo, and a Semaphore compromise can't rewrite playbooks.
# .env rendered by roles/semaphore to /opt/semaphore/.env (mode 0600), same
# rationale as Infisical's — outside the repo dir, shared via env_file. Carries
# the admin account, DB credentials, and the READ-ONLY Infisical "runtime"
# identity's token — loaded straight from the node-local file
# bootstrap_instance.yml writes it to; there is no write-capable identity
# anywhere in this design (see CLAUDE.md "Secrets").
semaphore-db:
image: postgres:16-alpine
container_name: semaphore-db
restart: unless-stopped
env_file:
- /opt/semaphore/.env
volumes:
- semaphore_db_data:/var/lib/postgresql/data
networks:
- semaphore_net
security_opt:
- no-new-privileges:true
semaphore:
image: semaphoreui/semaphore:latest
container_name: semaphore
restart: unless-stopped
env_file:
- /opt/semaphore/.env
environment:
SEMAPHORE_DB_DIALECT: postgres
SEMAPHORE_DB_HOST: semaphore-db
SEMAPHORE_DB_PORT: "5432"
SEMAPHORE_DB: semaphore
SEMAPHORE_ADMIN_NAME: "Homelab Admin"
SEMAPHORE_RUNNER_TMP_PATH: /tmp/workspace
INFISICAL_API_URL: "http://infisical:8080/api"
ports:
- "3010:3000" # Tailscale-only — bound 0.0.0.0 but firewalled to the Tailscale CGNAT range
volumes:
- ".:/repo:ro"
- semaphore_workspace:/tmp/workspace
networks:
- semaphore_net
- edge_net # so semaphore can reach infisical
depends_on:
- semaphore-db
- infisical
security_opt:
- no-new-privileges:true
networks:
edge_net:
driver: bridge
infisical_net:
driver: bridge
semaphore_net:
driver: bridge
volumes:
infisical_db_data: {}
infisical_redis_data: {}
semaphore_db_data: {}
semaphore_workspace: {}