Restructure into one folder per private repo/host, not a flat Docker/ dump

rocky-docker-lxc/, caddy-vm/, monitoring-vm/ (was missing entirely -
Grafana+Loki+Prometheus stack, refreshed and CA mount stripped same as
everything else), and automation/{ansible,automation-vm,iac}/ for the
three repos that live on the automation VM. Hawser is genuinely
deployed on all three of caddy-vm/monitoring-vm/automation-vm so it's
duplicated in each rather than picking one canonical home.

Old Ansible/ and "Infrastrucutre as Code/" content moved under
automation/ansible/old-playbooks and automation/iac/old-content as-is
for now - contents still need refreshing against the current repos and
a per-folder README, that's the next pass.
This commit is contained in:
thesabear committed 2026-07-06 02:41:53 +03:00
1 parent 08f705ffd7
commit c05c7164c8
146 files changed
+101 -84

No files matched your search

@@ -0,0 +1,19 @@
services:
actual_server:
image: actualbudget/actual-server:latest
container_name: actual
ports:
- ${HTTP_PORT}:5006
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
volumes:
- /path/to/actual/actual-data:/data
restart: unless-stopped
networks:
- actual-net
networks:
actual-net:
external: true
@@ -0,0 +1,27 @@
services:
audiobookshelf:
image: ghcr.io/advplyr/audiobookshelf:latest
container_name: audiobookshelf
user: "${PUID}:${PGID}"
environment:
- TZ=${TZ}
ports:
- ${HTTP_PORT}:80
volumes:
- /path/to/audiobookshelf/config:/config
- /path/to/audiobookshelf/metadata:/metadata
- /path/to/data/media/audiobooks:/audiobooks
- /path/to/data/media/podcasts:/podcasts
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:80/ || exit 1"]
interval: 15s
timeout: 5s
retries: 5
start_period: 20s
networks:
- audiobookshelf-net
networks:
audiobookshelf-net:
external: true
@@ -0,0 +1,108 @@
services:
postgresql:
env_file:
- .env
container_name: authentik-postgres
environment:
POSTGRES_DB: ${PG_DB}
POSTGRES_PASSWORD: ${PG_PASS}
POSTGRES_USER: ${PG_USER}
command: >
postgres
-c max_connections=400
-c shared_buffers=256MB
-c work_mem=8MB
-c maintenance_work_mem=128MB
-c effective_cache_size=1GB
healthcheck:
interval: 30s
retries: 5
start_period: 20s
test:
- CMD-SHELL
- pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}
timeout: 5s
image: docker.io/library/postgres:16-alpine
restart: unless-stopped
volumes:
- /path/to/authentik/database:/var/lib/postgresql/data
networks:
- authentik-net
redis:
image: redis:7-alpine
container_name: authentik-redis
restart: unless-stopped
command: redis-server --appendonly yes
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- /path/to/authentik/redis:/data
networks:
- authentik-net
server:
command: server
container_name: authentik-server
depends_on:
postgresql:
condition: service_healthy
redis:
condition: service_healthy
env_file:
- .env
environment:
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB}
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
AUTHENTIK_POSTGRESQL__USER: ${PG_USER}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_URL: ${AUTHENTIK_URL}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.5.3}
ports:
- ${COMPOSE_PORT_HTTP}:9000
restart: unless-stopped
shm_size: 512mb
volumes:
- /path/to/authentik/data:/data
- /path/to/authentik/custom-templates:/templates
networks:
- authentik-net
worker:
command: worker
container_name: authentik-worker
depends_on:
postgresql:
condition: service_healthy
redis:
condition: service_healthy
env_file:
- .env
environment:
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB}
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
AUTHENTIK_POSTGRESQL__USER: ${PG_USER}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_URL: ${AUTHENTIK_URL}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.5.3}
restart: unless-stopped
shm_size: 512mb
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /path/to/authentik/data:/data
- /path/to/authentik/certs:/certs
- /path/to/authentik/custom-templates:/templates
networks:
- authentik-net
networks:
authentik-net:
external: true
@@ -0,0 +1,27 @@
services:
bazarr:
image: lscr.io/linuxserver/bazarr:latest
container_name: bazarr
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- UMASK=${UMASK}
ports:
- ${HTTP_PORT}:6767
volumes:
- /path/to/bazarr:/config
- /path/to/media:/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:6767/ || exit 1"]
interval: 15s
timeout: 5s
retries: 5
start_period: 20s
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,28 @@
services:
beets:
image: linuxserver/beets:2.8.0-ls323
container_name: beets
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
volumes:
- /path/to/beets:/config
- /path/to/media/music:/music
- /path/to/media/music_untagged:/music_untagged
- /path/to/torrents/beets:/downloads
ports:
- ${HTTP_PORT}:8337
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8337/ || exit 1"]
interval: 15s
timeout: 5s
retries: 5
start_period: 20s
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,63 @@
---
services:
bookstack:
image: lscr.io/linuxserver/bookstack:latest
container_name: bookstack
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- APP_URL=https://subdomain.example.com
- DB_HOST=bookstack_db
- DB_PORT=${DB_PORT}
- DB_USER=${DB_USER}
- DB_PASS=${DB_PASS}
- DB_DATABASE=${DB_DATABASE}
- APP_DEFAULT_DARK_MODE=true
volumes:
- /path/to/bookstack/bookstack_app_data:/config
ports:
- ${HTTP_PORT}:80
restart: unless-stopped
depends_on:
bookstack_db:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:80/ || exit 1"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
networks:
- bookstack-net
bookstack_db:
image: lscr.io/linuxserver/mariadb:latest
container_name: bookstack_db
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
- MYSQL_DATABASE=${DB_DATABASE}
- MYSQL_USER=${DB_USER}
- MYSQL_PASSWORD=${DB_PASSWORD}
volumes:
- /path/to/bookstack/bookstack_db_data:/config
restart: unless-stopped
healthcheck:
test:
[
"CMD-SHELL",
"mysqladmin ping -h localhost -u${DB_USER} -p${DB_PASSWORD} || exit 1",
]
interval: 10s
timeout: 5s
retries: 10
start_period: 20s
networks:
- bookstack-net
networks:
bookstack-net:
external: true
@@ -0,0 +1,21 @@
services:
calibre-web-automated:
image: crocodilestick/calibre-web-automated:latest
container_name: calibre-web-automated
environment:
- TZ=${TZ}
- DOCKER_MODS=linuxserver/mods:universal-calibre
volumes:
- /path/to/calibre-web:/config
- /path/to/media/calibre:/calibre-library
- /path/to/calibre-web/ingest:/cwa-book-ingest
# This is an ingest dir, NOT a library one. Anything added here will be automatically added to your library according to the settings you have configured in CWA Settings page. All files placed here are REMOVED AFTER PROCESSING
ports:
- ${HTTP_PORT}:8083
restart: unless-stopped
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,25 @@
services:
calibre:
image: lscr.io/linuxserver/calibre:latest
container_name: calibre
security_opt:
- seccomp:unconfined #optional
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
volumes:
- /path/to/calibre:/config
- /path/to/books:/books
ports:
- ${HTTP_PORT}:8080 # Calibre desktop gui.
restart: unless-stopped
networks:
- media-net
- notif-net
networks:
media-net:
external: true
notif-net:
external: true
@@ -0,0 +1,27 @@
services:
cloudcmd:
image: coderaiser/cloudcmd:latest
container_name: cloudcommander
ports:
- ${HTTP_PORT}:8000
volumes:
- ~:/root
- /:/mnt/fs
user: "1000:1000"
restart: unless-stopped
healthcheck:
test:
[
"CMD-SHELL",
"curl -fsS http://localhost:8000 | grep -qi cloudcmd || exit 1",
]
interval: 20s
timeout: 5s
retries: 5
start_period: 25s
networks:
- cloudcommander-net
networks:
cloudcommander-net:
external: true
@@ -0,0 +1,40 @@
services:
dashy:
image: lissy93/dashy
container_name: dashy
volumes:
# Conf file
- /path/to/dashy/conf.yml:/app/user-data/conf.yml
# Icons folder
- /path/to/dashy/public/assets:/app/user-data/item-icons/
# Pages, one by one
- /path/to/dashy/control-plane.yml:/app/user-data/control-plane.yml
- /path/to/dashy/observability.yml:/app/user-data/observability.yml
- /path/to/dashy/media.yml:/app/user-data/media.yml
- /path/to/dashy/automation.yml:/app/user-data/automation.yml
- /path/to/dashy/dev-platform-tools.yml:/app/user-data/dev-platform-tools.yml
- /path/to/dashy/identity-security.yml:/app/user-data/identity-security.yml
- /path/to/dashy/data-knowledge.yml:/app/user-data/data-knowledge.yml
- /path/to/dashy/personal-apps.yml:/app/user-data/personal-apps.yml
ports:
- ${HTTP_PORT}:8080
environment:
- NODE_ENV=production
- PUID=${PUID}
- PGID=${PGID}
restart: unless-stopped
healthcheck:
test: ["CMD", "node", "/app/services/healthcheck"]
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- media-net
- caddy-net
networks:
media-net:
external: true
caddy-net:
external: true
@@ -0,0 +1,23 @@
services:
socket-proxy:
image: tecnativa/docker-socket-proxy
container_name: socket-proxy
restart: always
environment:
- CONTAINERS=1
- IMAGES=0
- NETWORKS=0
- VOLUMES=0
- EVENTS=0
- POST=0
- DELETE=0
- INFO=1
- EXEC=0
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- docker-proxy-net
networks:
docker-proxy-net:
external: true
@@ -0,0 +1,49 @@
services:
socket-proxy:
image: tecnativa/docker-socket-proxy
container_name: dockhand-socket-proxy
restart: always
environment:
# Required for Dockhand core functionality
- CONTAINERS=1
- IMAGES=1
- NETWORKS=1
- VOLUMES=1
- EVENTS=1
- POST=1
- DELETE=1
# Required for dashboard host info and disk usage
- INFO=1
- SYSTEM=1
# Required for vulnerability scanning
- ALLOW_START=1
- ALLOW_STOP=1
- ALLOW_RESTARTS=1
# Optional: enable for terminal access
- EXEC=1
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- dockhand-net
dockhand:
image: fnsys/dockhand:latest
container_name: dockhand
restart: always
depends_on:
- socket-proxy
environment:
- PUID=1000
- PGID=1000
group_add:
- "996"
ports:
- ${HTTP_PORT}:3000
volumes:
- /path/to/dockhand/dockhand_data:/app/data
networks:
- dockhand-net
networks:
dockhand-net:
external: true
+19
View File
@@ -0,0 +1,19 @@
services:
emby:
image: emby/embyserver:latest
container_name: emby
environment:
- TZ=${TZ}
volumes:
- /path/to/emby:/config
- /path/to/media:/data
- /path/to/transcodes/emby:/transcode
ports:
- ${HTTP_PORT}:8096
restart: unless-stopped
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,82 @@
services:
ghost:
image: ghost:latest
container_name: ghost_blog
restart: unless-stopped
ports:
- "${HTTP_PORT}:2368"
depends_on:
- ghost_db
environment:
NODE_ENV: production
TZ: ${TZ}
# Ghost URL
url: ${GHOST_URL}
# SMTP
mail__transport: ${SMTP_TRANSPORT}
mail__options__host: ${SMTP_HOST}
mail__options__port: ${SMTP_PORT}
mail__options__secure: "false"
mail__options__auth__user: ${SMTP_USER}
mail__options__auth__pass: ${SMTP_PASSWORD}
# Database
database__client: mysql
database__connection__host: ${DB_HOST}
database__connection__user: ${DB_USER}
database__connection__password: ${DB_PASSWORD}
database__connection__database: ${DB_NAME}
volumes:
- /path/to/ghost/content:/var/lib/ghost/content
networks:
- blog-net
ghost_db:
image: mysql:8
container_name: ghost_mysql
restart: unless-stopped
environment:
TZ: ${TZ}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- /path/to/ghost/db_data:/var/lib/mysql
- /path/to/ghost/init:/docker-entrypoint-initdb.d:ro
networks:
- blog-net
umami:
image: ghcr.io/umami-software/umami:postgresql-latest
container_name: umami_analytics
restart: unless-stopped
ports:
- "${UMAMI_PORT}:3000"
depends_on:
- umami-db
environment:
TZ: ${TZ}
DATABASE_URL: postgresql://${UMAMI_DB_USER}:${UMAMI_DB_PASSWORD}@umami-db:5432/${UMAMI_DB_NAME}
DATABASE_TYPE: postgresql
APP_SECRET: ${UMAMI_APP_SECRET}
IGNORE_IP: ${UMAMI_IGNORE_IP}
networks:
- blog-net
umami-db:
image: postgres:15-alpine
container_name: umami_postgres
restart: unless-stopped
environment:
TZ: ${TZ}
POSTGRES_DB: ${UMAMI_DB_NAME}
POSTGRES_USER: ${UMAMI_DB_USER}
POSTGRES_PASSWORD: ${UMAMI_DB_PASSWORD}
volumes:
- /path/to/umami/db_data:/var/lib/postgresql/data
networks:
- blog-net
networks:
blog-net:
external: true
@@ -0,0 +1,19 @@
services:
it-tools:
image: corentinth/it-tools:latest
restart: unless-stopped
container_name: it-tools
ports:
- ${HTTP_PORT}:80
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost/ > /dev/null || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
networks:
- it-tools-net
networks:
it-tools-net:
external: true
@@ -0,0 +1,75 @@
services:
immich-server:
container_name: immich_server
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
volumes:
- /path/to/immich/data:/data
- /path/to/immich/upload:/usr/src/app/upload
- /path/to/external-library-1:/path/to/external-library-1:ro
- /path/to/external-library-2:/path/to/external-library-2:ro
env_file:
- .env
ports:
- ${HTTP_PORT}:2283
depends_on:
- redis
- database
restart: unless-stopped
networks:
- immich-net
immich-machine-learning:
container_name: immich_machine_learning
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
volumes:
- /path/to/immich/model-cache:/cache
env_file:
- .env
restart: unless-stopped
networks:
- immich-net
redis:
container_name: immich_redis
image: redis:6.2-alpine
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
volumes:
- /path/to/immich/redis:/data
restart: unless-stopped
networks:
- immich-net
database:
container_name: immich_postgres
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
env_file:
- .env
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_USER=${DB_USERNAME}
- POSTGRES_DB=${DB_DATABASE_NAME}
- POSTGRES_INITDB_ARGS='--data-checksums'
volumes:
- /path/to/immich/pgdata:/var/lib/postgresql/data
shm_size: 128mb
restart: unless-stopped
networks:
- immich-net
networks:
immich-net:
external: true
@@ -0,0 +1,32 @@
services:
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
volumes:
- /path/to/jellyfin/config:/config
- /path/to/jellyfin/cache:/cache
- /path/to/media:/data
- /path/to/transcodes/jellyfin:/transcodes
ports:
- ${HTTP_PORT}:8096
restart: unless-stopped
healthcheck:
test:
[
"CMD-SHELL",
"curl -fsS http://localhost:8096/health | grep -q Healthy",
]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,56 @@
services:
joplin-db:
image: postgres:latest
container_name: joplin-db
volumes:
- /path/to/joplin:/var/lib/postgresql
ports:
- "${POSTGRES_PORT}:5432"
restart: unless-stopped
environment:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_DB=${POSTGRES_DB}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 10
start_period: 15s
networks:
- joplin-net
joplin:
image: joplin/server:latest
container_name: joplin-server
depends_on:
- joplin-db
ports:
- "${HTTP_PORT}:22300"
restart: unless-stopped
environment:
- APP_PORT=${HTTP_PORT}
- APP_BASE_URL=${APP_BASE_URL}
- DB_CLIENT=pg
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DATABASE=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PORT=${POSTGRES_PORT}
- POSTGRES_HOST=joplin-db
- MAILER_ENABLED=1
- MAILER_HOST=${MAILER_HOST}
- MAILER_PORT=${MAILER_PORT}
- MAILER_SECURITY=${MAILER_SECURITY}
- MAILER_AUTH_USER=${MAILER_AUTH_USER}
- MAILER_AUTH_PASSWORD=${MAILER_AUTH_PASSWORD}
- MAILER_NOREPLY_NAME=${MAILER_NOREPLY_NAME}
- MAILER_NOREPLY_EMAIL=${MAILER_NOREPLY_EMAIL}
- APP_ADMIN_EMAIL=${APP_ADMIN_EMAIL}
- APP_ADMIN_PASSWORD=${APP_ADMIN_PASSWORD}
- APP_ADMIN_NAME=${APP_ADMIN_NAME}
networks:
- joplin-net
networks:
joplin-net:
external: true
@@ -0,0 +1,32 @@
services:
mariadb:
image: lscr.io/linuxserver/mariadb:latest
container_name: kodi-mariadb
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
volumes:
- /path/to/kodi-mariadb:/config
ports:
- ${HTTP_PORT}:3306
restart: unless-stopped
healthcheck:
test:
[
"CMD-SHELL",
"mysqladmin ping -h 127.0.0.1 -u root -p${MYSQL_ROOT_PASSWORD} --silent",
]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,34 @@
services:
kopia:
image: kopia/kopia:latest
container_name: kopia
restart: unless-stopped
user: "0:0"
hostname: "docker-host"
ports:
- "${HTTP_PORT}:51515"
command:
- server
- start
- --address=0.0.0.0:51515
- --tls-cert-file=/tls/kopia.crt
- --tls-key-file=/tls/kopia.key
- --server-username=${USERNAME}
- --server-password=${SECRET_PASSWORD}
- --disable-csrf-token-checks
environment:
TZ: ${TZ}
KOPIA_PASSWORD: ${SECRET_PASSWORD}
volumes:
- /path/to/backup-drive/kopia-repo:/repository # External drive for repository
- /path/to/backup-drive/kopia-cache:/cache
- /path/to/backup-drive/kopia-config:/app/config
- /path/to/backup-drive/kopia-tls:/tls:ro
- /path/to/docker-volumes:/apps:ro # Read-only access to docker volumes
- /path/to/docker-volumes:/restore
networks:
- kopia-net
networks:
kopia-net:
external: true
@@ -0,0 +1,23 @@
services:
lidarr:
image: ghcr.io/linuxserver/lidarr:latest
container_name: lidarr
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- UMASK=${UMASK}
- DOCKER_MODS=ghcr.io/gilbn/theme.park:lidarr
- TP_ADDON=lidarr-alt-calendar
ports:
- ${HTTP_PORT}:8686
volumes:
- /path/to/lidarr:/config
- /path/to/media:/data
restart: unless-stopped
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,27 @@
services:
music-assistant-server:
image: ghcr.io/music-assistant/server:latest
container_name: music-assistant
restart: unless-stopped
volumes:
- /path/to/music-assistant-server/data:/data/
- /path/to/data/media/music:/music:ro
ports:
- "${PORT1}:8095"
- "${PORT2}:3483"
- "${PORT3}:5353/udp"
- "${PORT4}:21064/tcp"
- "${PORT5}:21064/udp"
environment:
- LOG_LEVEL=info
cap_add:
- SYS_ADMIN
- DAC_READ_SEARCH
security_opt:
- apparmor:unconfined
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,82 @@
name: nextcloud
services:
db:
image: lscr.io/linuxserver/mariadb:latest
container_name: nextcloud_db
volumes:
- /path/to/nextcloud/data/db:/var/lib/mysql
- /path/to/nextcloud/data/db-config:/config
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- TZ=${TZ}
restart: unless-stopped
networks:
- nextcloud-net
redis:
image: redis:alpine
container_name: nextcloud_redis
environment:
- "TZ"
volumes:
- /path/to/nextcloud/data/redis:/data
restart: unless-stopped
networks:
- nextcloud-net
# Main Nextcloud container (custom image with SMB + cert trust)
nextcloud:
build:
context: ./nextcloud
dockerfile: Dockerfile
container_name: nextcloud
depends_on:
- db
- redis
volumes:
- /path/to/nextcloud/html:/var/www/html
- /path/to/nextcloud/html/data:/var/www/html/data
- /path/to/nextcloud/html/config:/var/www/html/config
- /path/to/nextcloud/html/custom_apps:/var/www/html/custom_apps
- /path/to/nextcloud/html/themes:/var/www/html/themes
env_file:
- ".env"
environment:
- "TZ"
- "DB_TYPE=mysql"
- "DB_HOST=db"
- "DB_NAME=${MYSQL_DATABASE}"
- "DB_USER=${MYSQL_USER}"
- "DB_PASSWORD=${MYSQL_PASSWORD}"
restart: unless-stopped
networks:
- nextcloud-net
- caddy-net
euro-office:
build:
context: ./euro-office
dockerfile: Dockerfile
container_name: nextcloud_euro-office
restart: unless-stopped
ports:
- "8080:80"
environment:
- JWT_ENABLED=true
- JWT_SECRET=${ONLYOFFICE_JWT_SECRET}
volumes:
- /path/to/nextcloud/euro-office/data:/var/lib/euro-office/documentserver
- /path/to/nextcloud/euro-office/logs:/var/log/euro-office/documentserver
- /path/to/nextcloud/euro-office/config:/etc/euro-office/documentserver
networks:
- nextcloud-net
- caddy-net
networks:
nextcloud-net:
external: true
caddy-net:
external: true
@@ -0,0 +1,42 @@
services:
nocodb:
image: nocodb/nocodb:latest
container_name: nocodb
restart: unless-stopped
ports:
- "${HTTP_PORT}:8080"
depends_on:
nocodb_db:
condition: service_healthy
environment:
TZ: ${TZ}
NC_DB: pg://nocodb_db:5432?u=${POSTGRES_USER}&p=${POSTGRES_PASSWORD}&d=${POSTGRES_DB}
NC_AUTH_JWT_SECRET: ${JWT_SECRET}
volumes:
- /path/to/nocodb/nc_data:/usr/app/data
networks:
- nocodb-net
nocodb_db:
image: postgres:16-alpine
container_name: nocodb_postgres
restart: unless-stopped
environment:
TZ: ${TZ}
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- /path/to/nocodb/db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 10
start_period: 20s
networks:
- nocodb-net
networks:
nocodb-net:
external: true
@@ -0,0 +1,44 @@
services:
ollama:
# Uncomment below for GPU support
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: 1
# capabilities:
# - gpu
volumes:
- /path/to/ollama:/root/.ollama
# Uncomment below to expose Ollama API outside the container stack
ports:
- "${HTTP_PORT2}:11434"
container_name: ollama
pull_policy: always
tty: true
restart: unless-stopped
image: ollama/ollama:latest
networks:
- openai-net
open-webui:
image: ghcr.io/open-webui/open-webui:latest
container_name: open-webui
volumes:
- /path/to/open-webui:/app/backend/data
depends_on:
- ollama
ports:
- "${HTTP_PORT}:8080"
environment:
- "OLLAMA_BASE_URL=http://ollama:11434"
extra_hosts:
- host.docker.internal:host-gateway
restart: unless-stopped
networks:
- openai-net
networks:
openai-net:
external: true
@@ -0,0 +1,76 @@
services:
broker:
image: docker.io/library/redis:7
container_name: paperless-redis
restart: unless-stopped
volumes:
- /path/to/paperless/redisdata:/data
networks:
- paperless-net
db:
image: docker.io/library/postgres:15
container_name: paperless-postgres
restart: unless-stopped
volumes:
- /path/to/paperless/pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
networks:
- paperless-net
webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
container_name: paperless
restart: unless-stopped
depends_on:
- db
- broker
- gotenberg
- tika
ports:
- "${HTTP_PORT}:8000"
volumes:
- /path/to/paperless/data:/usr/src/paperless/data
- /path/to/paperless/media:/usr/src/paperless/media
- /path/to/paperless/export:/usr/src/paperless/export
- /path/to/paperless/consume:/usr/src/paperless/consume
env_file: .env
environment:
PAPERLESS_REDIS: redis://broker:6379
PAPERLESS_DBHOST: db
PAPERLESS_DBPASS: ${PAPERLESS_DBPASS}
PAPERLESS_TIKA_ENABLED: 1
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
PAPERLESS_URL: ${PAPERLESS_URL}
PAPERLESS_ADMIN_USER: ${PAPERLESS_ADMIN_USER}
PAPERLESS_ADMIN_PASSWORD: ${PAPERLESS_ADMIN_PASSWORD}
networks:
- paperless-net
gotenberg:
image: docker.io/gotenberg/gotenberg:7.10
container_name: paperless-gotenberg
restart: unless-stopped
# The gotenberg chromium route is used to convert .eml files. We do not
# want to allow external content like tracking pixels or even javascript.
command:
- "gotenberg"
- "--chromium-disable-javascript=true"
- "--chromium-allow-list=file:///tmp/.*"
networks:
- paperless-net
tika:
image: docker.io/apache/tika:latest
container_name: paperless-tika
restart: unless-stopped
networks:
- paperless-net
networks:
paperless-net:
external: true
@@ -0,0 +1,27 @@
services:
prowlarr:
container_name: prowlarr
image: lscr.io/linuxserver/prowlarr:latest
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- UMASK=${UMASK}
ports:
- ${HTTP_PORT}:9696
volumes:
- /path/to/prowlarr:/config
- /path/to/media:/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:9696 || exit 1"]
interval: 15s
timeout: 5s
retries: 5
start_period: 20s
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,31 @@
services:
radarr:
image: ghcr.io/linuxserver/radarr:latest
container_name: radarr
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- UMASK=${UMASK}
- DOCKER_MODS=ghcr.io/gilbn/theme.park:radarr
- TP_THEME=dark
- TP_ADDON=radarr-4k-logo
- TP_ADDON=radarr-alt-calendar
ports:
- ${HTTP_PORT}:7878
volumes:
- /path/to/radarr:/config
- /path/to/media:/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:7878 || exit 1"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,27 @@
services:
seerr:
image: ghcr.io/seerr-team/seerr:latest
init: true
container_name: seerr
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- LOG_LEVEL=debug
ports:
- ${HTTP_PORT}:5055
volumes:
- /path/to/seerr:/app/config
healthcheck:
test: wget --no-verbose --tries=1 --spider http://localhost:5055/api/v1/status || exit 1
start_period: 20s
timeout: 3s
interval: 15s
retries: 3
restart: unless-stopped
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,30 @@
services:
sonarr:
image: ghcr.io/linuxserver/sonarr:latest
container_name: sonarr
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- UMASK=${UMASK}
- DOCKER_MODS=ghcr.io/gilbn/theme.park:sonarr
- TP_THEME=dark
- TP_ADDON=sonarr-4k-logo
ports:
- ${HTTP_PORT}:8989
volumes:
- /path/to/sonarr:/config
- /path/to/media:/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8989 || exit 1"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,24 @@
services:
speedtest-tracker:
container_name: speedtest-tracker
image: lscr.io/linuxserver/speedtest-tracker:latest
ports:
- "${HTTPS_PORT}:443"
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- APP_KEY=${APP_KEY}
- APP_URL=${APP_URL}
- DB_CONNECTION=sqlite
- SPEEDTEST_SCHEDULE="0 */3 * * *" # Cron schedule, runs every 3 hours.
- DISPLAY_TIMEZONE=${DISPLAY_TIMEZONE}
volumes:
- /path/to/speedtest-tracker/data:/config
restart: unless-stopped
networks:
- speedtest-net
networks:
speedtest-net:
external: true
@@ -0,0 +1,38 @@
services:
tdarr:
container_name: tdarr
image: ghcr.io/haveagitgat/tdarr:2.82.01
restart: unless-stopped
ports:
- ${HTTP_PORT}:8265
- ${HTTP_PORT1}:8266
- ${HTTP_PORT2}:8267
- ${HTTP_PORT3}:8268
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- UMASK=${UMASK}
- serverIP=${serverIP}
- serverPort=${serverPort}
- webUIPort=${webUIPort}
- internalNode=${internalNode}
- nodeName=${nodeName}
volumes:
- /path/to/tdarr/server:/app/server
- /path/to/tdarr/configs:/app/configs
- /path/to/tdarr/logs:/app/logs
- /path/to/media:/media
- /path/to/transcodes/transcodes_tdarr:/temp
healthcheck:
test: ["CMD-SHELL", "curl -f http://127.0.0.1:8265 || exit 1"]
interval: 30s
timeout: 5s
retries: 5
start_period: 20s
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,25 @@
services:
tinymediamanager:
image: tinymediamanager/tinymediamanager:latest
container_name: tinymediamanager
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
ports:
- ${HTTP_PORT}:4000
volumes:
- /path/to/tinymediamanager/data:/data
- /path/to/tinymediamanager/config/launcher-extra.yml:/app/launcher-extra.yml
- /path/to/media/movies:/media/movies
- /path/to/media/moviesetsartwork:/media/moviesetsartwork
- /path/to/media/tv:/media/tv shows
- /path/to/media/documentaries:/media/documentaries
- /path/to/media/stand-up comedy:/media/stand-up comedy
restart: unless-stopped
networks:
- media-net
networks:
media-net:
external: true
@@ -0,0 +1,20 @@
services:
trilium-sync:
image: triliumnext/trilium:latest
container_name: trilium-sync
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- TRILIUM_SYNC_SERVER=true
volumes:
- /path/to/trilium-sync:/home/node/trilium-data
ports:
- ${HTTP_PORT}:8080
restart: unless-stopped
networks:
- trillium-net
networks:
trillium-net:
external: true
@@ -0,0 +1,22 @@
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: always
ports:
- ${HTTP_PORT}:80
volumes:
- /path/to/vaultwarden/bw-data:/data
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- ICON_CACHE_TTL=0
- WEBSOCKET_ENABLED='true' # Required to use websockets
- SIGNUPS_ALLOWED='true' # set to false to disable signups
networks:
- vaultwarden-net
networks:
vaultwarden-net:
external: true
@@ -0,0 +1,30 @@
services:
qbittorrent:
image: ghcr.io/hotio/qbittorrent:release-5.1.4
container_name: qbittorrent
privileged: true
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- UMASK=${UMASK}
volumes:
- /path/to/qbittorrent:/config
- /path/to/media/torrents:/data/torrents
ports:
- ${HTTP_PORT}:8080
- ${HTTP_PORT1}:8999
- ${HTTP_PORT1}:8999/udp
restart: always
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080 || exit 1"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
networks:
- media-net
networks:
media-net:
external: true