Refactor: Reorganize services into standalone structure
This commit is contained in:
32
services/standalone/AI/docker-compose.yml
Normal file
32
services/standalone/AI/docker-compose.yml
Normal file
@@ -0,0 +1,32 @@
|
||||
version: '3.8'
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
openwebui_data:
|
||||
|
||||
services:
|
||||
openwebui:
|
||||
image: ghcr.io/open-webui/open-webui:main
|
||||
container_name: openwebui
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- openwebui_data:/app/backend/data
|
||||
networks:
|
||||
- traefik-public
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.openwebui.rule=Host(`ai.sterl.xyz`)"
|
||||
- "traefik.http.routers.openwebui.entrypoints=websecure"
|
||||
- "traefik.http.routers.openwebui.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.openwebui.loadbalancer.server.port=8080"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=openwebui"
|
||||
- "docktail.container_port=8080"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
1
services/standalone/Gitea/.env.example
Normal file
1
services/standalone/Gitea/.env.example
Normal file
@@ -0,0 +1 @@
|
||||
GITEA_DB_PASSWORD=replace_me
|
||||
63
services/standalone/Gitea/docker-compose.yml
Normal file
63
services/standalone/Gitea/docker-compose.yml
Normal file
@@ -0,0 +1,63 @@
|
||||
version: '3.8'
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
gitea-internal:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
gitea_data:
|
||||
gitea_db_data:
|
||||
|
||||
services:
|
||||
gitea:
|
||||
image: gitea/gitea:latest
|
||||
container_name: gitea
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- gitea_data:/data
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
networks:
|
||||
- traefik-public
|
||||
- gitea-internal
|
||||
ports:
|
||||
- "2222:22"
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
- GITEA__database__DB_TYPE=postgres
|
||||
- GITEA__database__HOST=gitea-db:5432
|
||||
- GITEA__database__NAME=gitea
|
||||
- GITEA__database__USER=gitea
|
||||
- GITEA__database__PASSWD=${GITEA_DB_PASSWORD}
|
||||
- GITEA__server__DOMAIN=git.sterl.xyz
|
||||
- GITEA__server__ROOT_URL=https://git.sterl.xyz
|
||||
- GITEA__server__SSH_DOMAIN=git.sterl.xyz
|
||||
- GITEA__server__SSH_PORT=2222
|
||||
- GITEA__service__DISABLE_REGISTRATION=false
|
||||
depends_on:
|
||||
- gitea-db
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.gitea.rule=Host(`git.sterl.xyz`)"
|
||||
- "traefik.http.routers.gitea.entrypoints=websecure"
|
||||
- "traefik.http.routers.gitea.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=gitea"
|
||||
- "docktail.container_port=3000"
|
||||
|
||||
gitea-db:
|
||||
image: postgres:15-alpine
|
||||
container_name: gitea-db
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- gitea_db_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- gitea-internal
|
||||
environment:
|
||||
- POSTGRES_USER=gitea
|
||||
- POSTGRES_PASSWORD=${GITEA_DB_PASSWORD}
|
||||
- POSTGRES_DB=gitea
|
||||
67
services/standalone/Infrastructure/docker-compose.yml
Normal file
67
services/standalone/Infrastructure/docker-compose.yml
Normal file
@@ -0,0 +1,67 @@
|
||||
version: '3.8'
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
homelab-backend:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
komodo_data:
|
||||
komodo_mongo_data:
|
||||
|
||||
services:
|
||||
komodo-mongo:
|
||||
image: mongo:7
|
||||
container_name: komodo-mongo
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- komodo_mongo_data:/data/db
|
||||
networks:
|
||||
- homelab-backend
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
komodo-core:
|
||||
image: ghcr.io/moghtech/komodo:latest
|
||||
container_name: komodo-core
|
||||
depends_on:
|
||||
- komodo-mongo
|
||||
environment:
|
||||
- KOMODO_DATABASE_ADDRESS=komodo-mongo:27017
|
||||
volumes:
|
||||
- komodo_data:/config
|
||||
networks:
|
||||
- traefik-public
|
||||
- homelab-backend
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.komodo.rule=Host(`komodo.sterl.xyz`)"
|
||||
- "traefik.http.routers.komodo.entrypoints=websecure"
|
||||
- "traefik.http.routers.komodo.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.komodo.loadbalancer.server.port=9120"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=komodo"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
komodo-periphery:
|
||||
image: ghcr.io/moghtech/komodo-periphery:latest
|
||||
container_name: komodo-periphery
|
||||
environment:
|
||||
- PERIPHERY_Id=periphery-standalone
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
restart: unless-stopped
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
198
services/standalone/Media/docker-compose.yml
Normal file
198
services/standalone/Media/docker-compose.yml
Normal file
@@ -0,0 +1,198 @@
|
||||
version: '3.8'
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
media-backend:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
homarr_config:
|
||||
jellyfin_config:
|
||||
immich_upload:
|
||||
immich_model_cache:
|
||||
immich_db:
|
||||
immich_redis:
|
||||
|
||||
services:
|
||||
homarr:
|
||||
image: ghcr.io/ajnart/homarr:latest
|
||||
container_name: homarr
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- homarr_config:/app/data
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
environment:
|
||||
- TZ=America/Chicago
|
||||
networks:
|
||||
- traefik-public
|
||||
- media-backend
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.homarr.rule=Host(`homarr.sterl.xyz`)"
|
||||
- "traefik.http.routers.homarr.entrypoints=websecure"
|
||||
- "traefik.http.routers.homarr.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.homarr-svc.loadbalancer.server.port=7575"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=homarr"
|
||||
- "docktail.container_port=7575"
|
||||
|
||||
jellyfin:
|
||||
image: jellyfin/jellyfin:latest
|
||||
container_name: jellyfin
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.hostname == fedora
|
||||
volumes:
|
||||
- jellyfin_config:/config
|
||||
- /mnt/media:/media:ro
|
||||
environment:
|
||||
- TZ=America/Chicago
|
||||
networks:
|
||||
- traefik-public
|
||||
- media-backend
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.jellyfin.rule=Host(`jellyfin.sterl.xyz`)"
|
||||
- "traefik.http.routers.jellyfin.entrypoints=websecure"
|
||||
- "traefik.http.routers.jellyfin.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.jellyfin-svc.loadbalancer.server.port=8096"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=jellyfin"
|
||||
- "docktail.container_port=8096"
|
||||
|
||||
immich-server:
|
||||
image: ghcr.io/immich-app/immich-server:release
|
||||
container_name: immich-server
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.role == photo
|
||||
depends_on:
|
||||
- immich-redis
|
||||
- immich-db
|
||||
volumes:
|
||||
- immich_upload:/usr/src/app/upload
|
||||
- /mnt/media/Photos:/usr/src/app/upload/library:rw
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
environment:
|
||||
- DB_HOSTNAME=immich-db
|
||||
- DB_USERNAME=immich
|
||||
- DB_PASSWORD=immich
|
||||
- DB_DATABASE_NAME=immich
|
||||
- REDIS_HOSTNAME=immich-redis
|
||||
- TZ=America/Chicago
|
||||
- IMMICH_MEDIA_LOCATION=/usr/src/app/upload/library
|
||||
networks:
|
||||
- traefik-public
|
||||
- media-backend
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.immich.rule=Host(`immich.sterl.xyz`)"
|
||||
- "traefik.http.routers.immich.entrypoints=websecure"
|
||||
- "traefik.http.routers.immich.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.immich-svc.loadbalancer.server.port=2283"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=immich"
|
||||
- "docktail.container_port=2283"
|
||||
- "traefik.http.routers.immich.middlewares=immich-headers"
|
||||
- "traefik.http.middlewares.immich-headers.headers.customrequestheaders.X-Forwarded-Proto=https"
|
||||
immich-server-haos:
|
||||
image: ghcr.io/immich-app/immich-server:release
|
||||
container_name: immich-server
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.hostname == homeassistant
|
||||
- node.labels.role == photo
|
||||
depends_on:
|
||||
- immich-redis
|
||||
- immich-db
|
||||
volumes:
|
||||
- immich_upload:/usr/src/app/upload
|
||||
- /mnt/data/supervisor/media/Media/Photos:/usr/src/app/upload/library:rw
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
environment:
|
||||
- DB_HOSTNAME=immich-db
|
||||
- DB_USERNAME=immich
|
||||
- DB_PASSWORD=immich
|
||||
- DB_DATABASE_NAME=immich
|
||||
- REDIS_HOSTNAME=immich-redis
|
||||
- TZ=America/Chicago
|
||||
- IMMICH_MEDIA_LOCATION=/usr/src/app/upload/library
|
||||
networks:
|
||||
- traefik-public
|
||||
- media-backend
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.immich.rule=Host(`immich.sterl.xyz`)"
|
||||
- "traefik.http.routers.immich.entrypoints=websecure"
|
||||
- "traefik.http.routers.immich.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.immich-svc.loadbalancer.server.port=2283"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=immich"
|
||||
- "docktail.container_port=2283"
|
||||
- "traefik.http.routers.immich.middlewares=immich-headers"
|
||||
- "traefik.http.middlewares.immich-headers.headers.customrequestheaders.X-Forwarded-Proto=https"
|
||||
|
||||
immich-machine-learning:
|
||||
image: ghcr.io/immich-app/immich-machine-learning:release
|
||||
container_name: immich-machine-learning
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.ai == true
|
||||
- node.labels.role == photo
|
||||
volumes:
|
||||
- immich_model_cache:/cache
|
||||
environment:
|
||||
- TZ=America/Chicago
|
||||
networks:
|
||||
- media-backend
|
||||
|
||||
immich-redis:
|
||||
image: redis:7-alpine
|
||||
container_name: immich-redis
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.role == photo
|
||||
volumes:
|
||||
- immich_redis:/data
|
||||
networks:
|
||||
- media-backend
|
||||
|
||||
immich-db:
|
||||
image: tensorchord/pgvecto-rs:pg14-v0.2.0
|
||||
container_name: immich-db
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.role == photo
|
||||
volumes:
|
||||
- immich_db:/var/lib/postgresql/data
|
||||
environment:
|
||||
- POSTGRES_PASSWORD=immich
|
||||
- POSTGRES_USER=immich
|
||||
- POSTGRES_DB=immich
|
||||
networks:
|
||||
- media-backend
|
||||
1
services/standalone/Monitoring/.env.example
Normal file
1
services/standalone/Monitoring/.env.example
Normal file
@@ -0,0 +1 @@
|
||||
GRAFANA_ADMIN_PASSWORD=replace_me
|
||||
6
services/standalone/Monitoring/config/alertmanager.yml
Normal file
6
services/standalone/Monitoring/config/alertmanager.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
route:
|
||||
receiver: "web.hook"
|
||||
receivers:
|
||||
- name: "web.hook"
|
||||
webhook_configs:
|
||||
- url: "http://127.0.0.1:5001/"
|
||||
15
services/standalone/Monitoring/config/prometheus.yml
Normal file
15
services/standalone/Monitoring/config/prometheus.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: "prometheus"
|
||||
static_configs:
|
||||
- targets: ["localhost:9090"]
|
||||
|
||||
- job_name: "node-exporter"
|
||||
static_configs:
|
||||
- targets: ["node-exporter:9100"]
|
||||
|
||||
- job_name: "cadvisor"
|
||||
static_configs:
|
||||
- targets: ["cadvisor:8080"]
|
||||
110
services/standalone/Monitoring/docker-compose.yml
Normal file
110
services/standalone/Monitoring/docker-compose.yml
Normal file
@@ -0,0 +1,110 @@
|
||||
version: '3.8'
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
monitoring:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
prometheus_data:
|
||||
grafana_data:
|
||||
alertmanager_data:
|
||||
|
||||
services:
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
container_name: prometheus
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- prometheus_data:/prometheus
|
||||
- ./config/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
||||
networks:
|
||||
- monitoring
|
||||
- traefik-public
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.prometheus.rule=Host(`prometheus.sterl.xyz`)"
|
||||
- "traefik.http.routers.prometheus.entrypoints=websecure"
|
||||
- "traefik.http.routers.prometheus.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.prometheus.loadbalancer.server.port=9090"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=prometheus"
|
||||
- "docktail.container_port=9090"
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
container_name: grafana
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- grafana_data:/var/lib/grafana
|
||||
environment:
|
||||
- GF_SERVER_ROOT_URL=https://grafana.sterl.xyz
|
||||
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
|
||||
networks:
|
||||
- monitoring
|
||||
- traefik-public
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.grafana.rule=Host(`grafana.sterl.xyz`)"
|
||||
- "traefik.http.routers.grafana.entrypoints=websecure"
|
||||
- "traefik.http.routers.grafana.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.grafana.loadbalancer.server.port=3000"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=grafana"
|
||||
- "docktail.container_port=3000"
|
||||
|
||||
alertmanager:
|
||||
image: prom/alertmanager:latest
|
||||
container_name: alertmanager
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- alertmanager_data:/alertmanager
|
||||
- ./config/alertmanager.yml:/etc/alertmanager/config.yml:ro
|
||||
command:
|
||||
- '--config.file=/etc/alertmanager/config.yml'
|
||||
- '--storage.path=/alertmanager'
|
||||
networks:
|
||||
- monitoring
|
||||
- traefik-public
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.alertmanager.rule=Host(`alertmanager.sterl.xyz`)"
|
||||
- "traefik.http.routers.alertmanager.entrypoints=websecure"
|
||||
- "traefik.http.routers.alertmanager.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.alertmanager.loadbalancer.server.port=9093"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=alertmanager"
|
||||
- "docktail.container_port=9093"
|
||||
|
||||
node-exporter:
|
||||
image: prom/node-exporter:latest
|
||||
container_name: node-exporter
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /proc:/host/proc:ro
|
||||
- /sys:/host/sys:ro
|
||||
- /:/rootfs:ro
|
||||
command:
|
||||
- '--path.procfs=/host/proc'
|
||||
- '--path.rootfs=/rootfs'
|
||||
- '--path.sysfs=/host/sys'
|
||||
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
|
||||
networks:
|
||||
- monitoring
|
||||
|
||||
cadvisor:
|
||||
image: gcr.io/cadvisor/cadvisor:latest
|
||||
container_name: cadvisor
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /:/rootfs:ro
|
||||
- /var/run:/var/run:ro
|
||||
- /sys:/sys:ro
|
||||
- /var/lib/docker/:/var/lib/docker:ro
|
||||
- /dev/disk/:/dev/disk:ro
|
||||
command:
|
||||
- '--docker_only=true'
|
||||
- '--housekeeping_interval=30s'
|
||||
networks:
|
||||
- monitoring
|
||||
123
services/standalone/Networking/docker-compose.yml
Normal file
123
services/standalone/Networking/docker-compose.yml
Normal file
@@ -0,0 +1,123 @@
|
||||
version: '3.8'
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:latest
|
||||
container_name: traefik
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- traefik_letsencrypt:/letsencrypt
|
||||
networks:
|
||||
- traefik-public
|
||||
environment:
|
||||
# Cloudflare API Token (with DNS edit permissions for your domain)
|
||||
- CF_DNS_API_TOKEN=WI8HAmOJhvDdhmm3XMpYPZs1o4uSG9gp4l66ncjr
|
||||
|
||||
# Optional: your Pi-hole DNS can stay
|
||||
dns:
|
||||
- 192.168.1.1
|
||||
- 192.168.1.245
|
||||
- 1.1.1.1
|
||||
|
||||
command:
|
||||
# Entrypoints
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
|
||||
# Docker Provider (Standalone)
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.network=traefik-public"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
# Watch for changes in Docker events
|
||||
- "--providers.docker.watch=true"
|
||||
|
||||
# Dashboard
|
||||
- "--api.dashboard=true"
|
||||
- "--api.insecure=false"
|
||||
|
||||
# HTTP -> HTTPS
|
||||
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
|
||||
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
|
||||
|
||||
# Let's Encrypt / ACME Cloudflare DNS Challenge
|
||||
- "--certificatesresolvers.cfresolver.acme.email=sterlenjohnson6@gmail.com"
|
||||
- "--certificatesresolvers.cfresolver.acme.storage=/letsencrypt/acme.json"
|
||||
- "--certificatesresolvers.cfresolver.acme.dnschallenge=true"
|
||||
- "--certificatesresolvers.cfresolver.acme.dnschallenge.provider=cloudflare"
|
||||
|
||||
# Optional: increase delay for propagation
|
||||
- "--certificatesresolvers.cfresolver.acme.dnschallenge.propagation.delayBeforeChecks=60"
|
||||
# Logging
|
||||
- "--log.level=INFO"
|
||||
|
||||
labels:
|
||||
# Dashboard Router
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.traefik.rule=Host(`traefik.sterl.xyz`)"
|
||||
- "traefik.http.routers.traefik.entrypoints=websecure"
|
||||
- "traefik.http.routers.traefik.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
|
||||
- "traefik.http.routers.traefik.service=api@internal"
|
||||
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
container_name: whoami
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- traefik-public
|
||||
labels:
|
||||
# Whoami Router
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.whoami.rule=Host(`whoami.sterl.xyz`)"
|
||||
- "traefik.http.routers.whoami.entrypoints=websecure"
|
||||
- "traefik.http.routers.whoami.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.whoami.loadbalancer.server.port=80"
|
||||
|
||||
docktail:
|
||||
image: ghcr.io/marvinvr/docktail:latest
|
||||
container_name: docktail
|
||||
restart: on-failure:3
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
networks:
|
||||
- traefik-public
|
||||
environment:
|
||||
# Optional: Your Tailscale Auth Key if not using tag approval flow
|
||||
- TAILSCALE_AUTH_KEY=tskey-auth-ksGqv9DLDZ11CNTRL-TPrRcTiHWYUyuVskzy4nYUGwm2bxPM2d
|
||||
# Optional: Set log level
|
||||
# - DOCKTAIL_LOG_LEVEL=info
|
||||
# Optional: Specify a Tailnet IP for the container itself if needed
|
||||
# - DOCKTAIL_TAILNET_IP=100.x.y.z
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 128M
|
||||
cpus: '0.2'
|
||||
reservations:
|
||||
memory: 32M
|
||||
cpus: '0.05'
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 15s
|
||||
|
||||
volumes:
|
||||
traefik_letsencrypt:
|
||||
external: true
|
||||
@@ -0,0 +1,47 @@
|
||||
# =============================================================================
|
||||
# DNS Chain: Router(:53) → AdGuard(:53,DOH,DOT) → Pi-hole(:5353) → Unbound(:5335)
|
||||
# =============================================================================
|
||||
# NOTE: For HAOS, use the run_command file instead - compose doesn't work there
|
||||
# NOTE: Post-install: Configure AdGuard upstream to <host-ip>:5053
|
||||
# NOTE: Pi-hole handles blocking/caching, AdGuard handles DOH/DOT encryption
|
||||
# =============================================================================
|
||||
|
||||
services:
|
||||
pihole:
|
||||
image: pihole/pihole:latest
|
||||
container_name: pihole
|
||||
network_mode: host
|
||||
environment:
|
||||
TZ: "America/Chicago"
|
||||
WEBPASSWORD: "YOURPASSWORD"
|
||||
FTLCONF_webserver_enabled: "true"
|
||||
FTLCONF_webserver_port: "7300"
|
||||
WEB_BIND_ADDR: "0.0.0.0"
|
||||
FTLCONF_dns_port: "5053"
|
||||
# DNS1/DNS2 are deprecated in Pi-hole v6+, use FTLCONF_dns_upstreams
|
||||
FTLCONF_dns_upstreams: "127.0.0.1#5335"
|
||||
volumes:
|
||||
- pihole_etc:/etc/pihole:rw
|
||||
- pihole_dnsmasq:/etc/dnsmasq.d:rw
|
||||
restart: unless-stopped
|
||||
|
||||
adguardhome:
|
||||
image: adguard/adguardhome:latest
|
||||
container_name: adguardhome
|
||||
network_mode: host
|
||||
environment:
|
||||
TZ: "America/Chicago"
|
||||
volumes:
|
||||
- adguard_conf:/opt/adguardhome/conf:rw
|
||||
- adguard_work:/opt/adguardhome/work:rw
|
||||
- adguard_certs:/opt/adguardhome/conf/certs:ro
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- pihole
|
||||
|
||||
volumes:
|
||||
pihole_etc:
|
||||
pihole_dnsmasq:
|
||||
adguard_conf:
|
||||
adguard_work:
|
||||
adguard_certs:
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
# =============================================================================
|
||||
# DNS Chain: Router(:53) → AdGuard(:53,DOH,DOT) → Pi-hole(:5353) → Unbound(:5335)
|
||||
# =============================================================================
|
||||
# BE9300 router points to this host on port 53
|
||||
# AdGuard handles DOH(443), DOT(853), and standard DNS(53)
|
||||
# Pi-hole runs on port 5353 to avoid conflict with AdGuard
|
||||
# Unbound provides recursive DNS on 5335 (installed locally)
|
||||
# =============================================================================
|
||||
|
||||
# Step 1: Start Pi-hole on port 5053 (5353 is used by mDNS/Avahi, 53 is AdGuard)
|
||||
# Configure upstream to Unbound on 127.0.0.1#5335
|
||||
# NOTE: DNS1/DNS2 are deprecated in Pi-hole v6+, use FTLCONF_dns_upstreams instead
|
||||
docker run -d \
|
||||
--name pihole \
|
||||
--network host \
|
||||
@@ -6,18 +18,24 @@ docker run -d \
|
||||
-e FTLCONF_webserver_enabled=true \
|
||||
-e FTLCONF_webserver_port=7300 \
|
||||
-e WEB_BIND_ADDR=0.0.0.0 \
|
||||
-e DNS1=127.0.0.1#5335 \
|
||||
-e DNS2=0.0.0.0 \
|
||||
-e FTLCONF_dns_port=5053 \
|
||||
-e FTLCONF_dns_upstreams=127.0.0.1#5335 \
|
||||
-v pihole_etc:/etc/pihole:rw \
|
||||
-v pihole_dnsmasq:/etc/dnsmasq.d:rw \
|
||||
--restart=unless-stopped \
|
||||
pihole/pihole:latest
|
||||
|
||||
# Step 2: Start AdGuard Home on port 53 (what router sees)
|
||||
# After first run, access http://<host-ip>:3000 to configure:
|
||||
# - Upstream DNS: 127.0.0.1:5353 (Pi-hole)
|
||||
# - DNS listen: 0.0.0.0:53
|
||||
# - Enable DOH (port 443) and DOT (port 853)
|
||||
docker run -d \
|
||||
--name adguardhome \
|
||||
--network host \
|
||||
-e TZ=America/Chicago \
|
||||
-v adguard_conf:/opt/adguardhome/conf:rw \
|
||||
-v adguard_work:/opt/adguardhome/work:rw \
|
||||
-v adguard_certs:/opt/adguardhome/conf/certs:ro \
|
||||
--restart=unless-stopped \
|
||||
adguard/adguardhome:latest
|
||||
37
services/standalone/Portainer/docker-compose.yml
Normal file
37
services/standalone/Portainer/docker-compose.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
version: '3.8'
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
portainer_data:
|
||||
|
||||
services:
|
||||
portainer:
|
||||
image: portainer/portainer-ce:latest
|
||||
container_name: portainer
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9443:9443"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- portainer_data:/data
|
||||
networks:
|
||||
- traefik-public
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.portainer.rule=Host(`portainer.sterl.xyz`)"
|
||||
- "traefik.http.routers.portainer.entrypoints=websecure"
|
||||
- "traefik.http.routers.portainer.tls.certresolver=cfresolver"
|
||||
- "traefik.http.routers.portainer.service=portainer"
|
||||
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=portainer"
|
||||
- "docktail.container_port=9000"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
3
services/standalone/Productivity/.env.example
Normal file
3
services/standalone/Productivity/.env.example
Normal file
@@ -0,0 +1,3 @@
|
||||
POSTGRES_PASSWORD=replace_me
|
||||
NEXTCLOUD_ADMIN_USER=admin
|
||||
NEXTCLOUD_ADMIN_PASSWORD=replace_me
|
||||
83
services/standalone/Productivity/docker-compose.yml
Normal file
83
services/standalone/Productivity/docker-compose.yml
Normal file
@@ -0,0 +1,83 @@
|
||||
version: '3.8'
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
productivity-backend:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
nextcloud_data:
|
||||
nextcloud_db:
|
||||
nextcloud_redis:
|
||||
|
||||
services:
|
||||
nextcloud-db:
|
||||
image: postgres:15-alpine
|
||||
container_name: nextcloud-db
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- nextcloud_db:/var/lib/postgresql/data
|
||||
environment:
|
||||
- POSTGRES_DB=nextcloud
|
||||
- POSTGRES_USER=nextcloud
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD} # Set in .env
|
||||
networks:
|
||||
- productivity-backend
|
||||
|
||||
nextcloud-redis:
|
||||
image: redis:7-alpine
|
||||
container_name: nextcloud-redis
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- nextcloud_redis:/data
|
||||
networks:
|
||||
- productivity-backend
|
||||
|
||||
nextcloud:
|
||||
image: nextcloud:latest
|
||||
container_name: nextcloud
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- nextcloud_data:/var/www/html
|
||||
environment:
|
||||
- POSTGRES_HOST=nextcloud-db
|
||||
- POSTGRES_DB=nextcloud
|
||||
- POSTGRES_USER=nextcloud
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- REDIS_HOST=nextcloud-redis
|
||||
- NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER}
|
||||
- NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD}
|
||||
- NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.sterl.xyz
|
||||
- OVERWRITEPROTOCOL=https
|
||||
- OVERWRITEHOST=nextcloud.sterl.xyz
|
||||
- TRUSTED_PROXIES=172.16.0.0/12
|
||||
depends_on:
|
||||
- nextcloud-db
|
||||
- nextcloud-redis
|
||||
networks:
|
||||
- traefik-public
|
||||
- productivity-backend
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.nextcloud.rule=Host(`nextcloud.sterl.xyz`)"
|
||||
- "traefik.http.routers.nextcloud.entrypoints=websecure"
|
||||
- "traefik.http.routers.nextcloud.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.nextcloud.loadbalancer.server.port=80"
|
||||
# Nextcloud-specific middlewares
|
||||
- "traefik.http.routers.nextcloud.middlewares=nextcloud-chain"
|
||||
- "traefik.http.middlewares.nextcloud-chain.chain.middlewares=nextcloud-caldav,nextcloud-headers"
|
||||
# CalDAV/CardDAV redirect
|
||||
- "traefik.http.middlewares.nextcloud-caldav.redirectregex.regex=^https://(.*)/.well-known/(card|cal)dav"
|
||||
- "traefik.http.middlewares.nextcloud-caldav.redirectregex.replacement=https://$$1/remote.php/dav/"
|
||||
- "traefik.http.middlewares.nextcloud-caldav.redirectregex.permanent=true"
|
||||
# Security headers
|
||||
- "traefik.http.middlewares.nextcloud-headers.headers.stsSeconds=31536000"
|
||||
- "traefik.http.middlewares.nextcloud-headers.headers.stsIncludeSubdomains=true"
|
||||
- "traefik.http.middlewares.nextcloud-headers.headers.stsPreload=true"
|
||||
- "traefik.http.middlewares.nextcloud-headers.headers.forceSTSHeader=true"
|
||||
- "traefik.http.middlewares.nextcloud-headers.headers.customFrameOptionsValue=SAMEORIGIN"
|
||||
- "traefik.http.middlewares.nextcloud-headers.headers.customResponseHeaders.X-Robots-Tag=noindex,nofollow"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=nextcloud"
|
||||
- "docktail.container_port=80"
|
||||
47
services/standalone/Technitium/docker-compose.yml
Normal file
47
services/standalone/Technitium/docker-compose.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
version: "3"
|
||||
services:
|
||||
dns-server:
|
||||
container_name: technitium-dns
|
||||
hostname: technitium-dns
|
||||
image: technitium/dns-server:latest
|
||||
ports:
|
||||
- "5380:5380/tcp" # Web Console
|
||||
- "53:53/udp" # DNS
|
||||
- "53:53/tcp" # DNS
|
||||
- "853:853/tcp" # DNS-over-TLS
|
||||
- "8443:443/tcp" # DNS-over-HTTPS
|
||||
# Uncomment if using DHCP
|
||||
# - "67:67/udp"
|
||||
environment:
|
||||
- DNS_SERVER_DOMAIN=dns-server
|
||||
# - DNS_SERVER_ADMIN_PASSWORD=password # Set via UI on first login
|
||||
volumes:
|
||||
- ./config:/etc/dns/config
|
||||
# Mount AdGuard certs for migration/usage
|
||||
# Path in container: /etc/dns/certs
|
||||
- adguard_certs:/etc/dns/certs:ro
|
||||
restart: unless-stopped
|
||||
sysctls:
|
||||
- net.ipv4.ip_local_port_range=1024 65000
|
||||
networks:
|
||||
- traefik-public
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# Web Console
|
||||
- "traefik.http.routers.technitium.rule=Host(`dns.sterl.xyz`)"
|
||||
- "traefik.http.routers.technitium.entrypoints=websecure"
|
||||
- "traefik.http.routers.technitium.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.technitium.loadbalancer.server.port=5380"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=technitium"
|
||||
- "docktail.container_port=5380"
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
adguard_certs:
|
||||
external: true
|
||||
# Volume created by docker run
|
||||
name: adguard_certs
|
||||
27
services/standalone/Tools/docker-compose.yml
Normal file
27
services/standalone/Tools/docker-compose.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
version: '3.8'
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
|
||||
services:
|
||||
dozzle:
|
||||
image: amir20/dozzle:latest
|
||||
container_name: dozzle
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
networks:
|
||||
- traefik-public
|
||||
environment:
|
||||
- DOZZLE_LEVEL=debug
|
||||
- DOZZLE_NO_ANALYTICS=true
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.dozzle.rule=Host(`dozzle.sterl.xyz`)"
|
||||
- "traefik.http.routers.dozzle.entrypoints=websecure"
|
||||
- "traefik.http.routers.dozzle.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.dozzle.loadbalancer.server.port=8080"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=logs"
|
||||
- "docktail.container_port=8080"
|
||||
57
services/standalone/n8n/docker-compose.yml
Normal file
57
services/standalone/n8n/docker-compose.yml
Normal file
@@ -0,0 +1,57 @@
|
||||
version: '3.8'
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
n8n_data:
|
||||
|
||||
services:
|
||||
n8n:
|
||||
image: n8nio/n8n:latest
|
||||
container_name: n8n
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- n8n_data:/home/node/.n8n
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- traefik-public
|
||||
extra_hosts:
|
||||
- "gateway:192.168.1.1"
|
||||
- "proxmox:192.168.1.57"
|
||||
- "omv:192.168.1.70"
|
||||
- "swarm-manager:192.168.1.196"
|
||||
- "swarm-leader:192.168.1.245"
|
||||
- "swarm-worker-light:192.168.1.62"
|
||||
- "lm-studio:192.168.1.81"
|
||||
- "fedora:192.168.1.81"
|
||||
- "n8n.sterl.xyz:127.0.0.1" # Mapped to localhost since it's standalone
|
||||
environment:
|
||||
- N8N_HOST=n8n.sterl.xyz
|
||||
- N8N_PROTOCOL=https
|
||||
- NODE_ENV=production
|
||||
- WEBHOOK_URL=https://n8n.sterl.xyz/
|
||||
- N8N_EDITOR_BASE_URL=https://n8n.sterl.xyz/
|
||||
- N8N_PUSH_BACKEND=websocket
|
||||
- N8N_PROXY_HOPS=1
|
||||
- N8N_SECURE_COOKIE=false
|
||||
- N8N_METRICS=false
|
||||
- N8N_SKIP_WEBHOOK_CSRF_CHECK=true
|
||||
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
|
||||
- DB_SQLITE_POOL_SIZE=10
|
||||
- N8N_RUNNERS_ENABLED=true
|
||||
- N8N_BLOCK_ENV_ACCESS_IN_NODE=false
|
||||
- N8N_GIT_NODE_DISABLE_BARE_REPOS=true
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.n8n.rule=Host(`n8n.sterl.xyz`)"
|
||||
- "traefik.http.routers.n8n.entrypoints=websecure"
|
||||
- "traefik.http.routers.n8n.tls.certresolver=cfresolver"
|
||||
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
|
||||
- "traefik.http.services.n8n.loadbalancer.sticky.cookie=true"
|
||||
- "traefik.http.services.n8n.loadbalancer.sticky.cookie.name=n8n_sticky"
|
||||
- "traefik.http.services.n8n.loadbalancer.sticky.cookie.secure=true"
|
||||
- "docktail.enable=true"
|
||||
- "docktail.name=n8n"
|
||||
- "docktail.container_port=5678"
|
||||
@@ -41,9 +41,8 @@ services:
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
deploy:
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
replicas: 2
|
||||
|
||||
resources:
|
||||
limits:
|
||||
memory: 2G
|
||||
@@ -94,9 +93,8 @@ services:
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
deploy:
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
replicas: 2
|
||||
|
||||
resources:
|
||||
limits:
|
||||
memory: 1G
|
||||
@@ -148,9 +146,8 @@ services:
|
||||
retries: 3
|
||||
start_period: 15s
|
||||
deploy:
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
replicas: 2
|
||||
|
||||
resources:
|
||||
limits:
|
||||
memory: 256M
|
||||
|
||||
Reference in New Issue
Block a user