1
0
Files
docker-compose-templates/docker-compose.yml
T
2026-01-16 11:45:51 +01:00

966 lines
28 KiB
YAML

---
secrets:
gitea_runner_token:
file: secrets/gitea_runner_token.txt
authentik_secret_key:
file: secrets/authentik_secret_key
email_host:
file: secrets/email_host
email_username:
file: secrets/email_username
email_password:
file: secrets/email_password
postgres_general_username:
file: secrets/postgres_general_username
postgres_general_password:
file: secrets/postgres_general_password
mariadb_root_password:
file: secrets/mariadb_root_password
configs:
caddyfile:
content: |
notes-old.${DOMAIN_LOCAL} {
handle {
root * /srv/notes
file_server
}
}
mimi.kucharczyk.xyz {
handle {
root * /etc/caddy/sites-enabled
file_server {
index mimikong.html
}
}
}
files.kucharczyk.xyz {
reverse_proxy 192.168.0.106:3923
}
photos.kucharczyk.xyz {
reverse_proxy 192.168.0.167:2283
}
http://ca.home.arpa {
root * /data/caddy/pki/authorities/local/
file_server browse
}
dnsmasq:
content: |
log-facility=-
log-queries
no-resolv
server=8.8.4.4
server=8.8.8.8
# This ensures local lookups from /etc/hosts or host-record are logged
log-async
address=/home.arpa/192.168.0.106
ptr-record=106.0.168.192.in-addr.arpa,nas.home.arpa
host-record=suma.home.arpa,192.168.0.217
host-record=suma-proxy.home.arpa,192.168.0.122
include:
- services/bazarr.yml
- services/jellyfin.yml
- services/komga.yml
- services/radarr.yml
- services/miniflux.yml
- services/jelu.yml
- services/sonarr.yml
- services/postgres.yml
- services/nextcloud.yml
- services/sabnzbd.yml
- services/openldap.yml
- services/prowlarr.yml
- services/netbootxyz.yml
- services/registry.yml
- services/portainer.yml
- services/drone/drone.yml
- services/enshrouded.yml
- services/7dtdserver.yml
- services/gluetun.yml
- services/handbrake-server.yml
- services/redlib.yml
- services/calibre-web.yml
- services/calibre-web-automated.yml
- services/kavita.yml
services:
caddy:
image: lucaslorentz/caddy-docker-proxy:2.10-alpine
container_name: caddy
ports:
- "${TIMETRACKER_EXTERNAL_PORT}:${TIMETRACKER_INTERNAL_PORT}"
- "${DENDRON_NOTES_EXTERNAL_PORT}:${DENDRON_NOTES_INTERNAL_PORT}"
- 80:80
- 443:443
environment:
- CADDY_INGRESS_NETWORKS=docker-compose-templates_public
- CADDY_DOCKER_CADDYFILE_PATH=/Caddyfile
configs:
- source: caddyfile
target: /Caddyfile
volumes:
- "${DOCKER_STORAGE_PATH}/caddy/etc:/etc/caddy"
- "${DOCKER_STORAGE_PATH}/caddy/data:/data"
- "${DOCKER_STORAGE_PATH}/caddy/config:/config"
- "/var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock"
- "/www/notes:/srv/notes"
- "timetracker-static:/srv/timetracker"
- /var/run/docker.sock:/var/run/docker.sock
networks:
public:
ipv4_address: 192.168.240.2
restart: unless-stopped
# cap_drop:
# - ALL
# cap_add:
# - NET_BIND_SERVICE
timetracker:
image: ${REGISTRY_URL}/timetracker
container_name: timetracker
environment:
- TZ=${TZ}
- "CSRF_TRUSTED_ORIGINS=https://tracker.kucharczyk.xyz"
user: ${PUID}
volumes:
- "${DOCKER_STORAGE_PATH}/timetracker/db.sqlite3:/home/timetracker/app/db.sqlite3"
- "${DOCKER_STORAGE_PATH}/timetracker/backups:/home/timetracker/app/games/fixtures/backups"
- "timetracker-static:/var/www/django/static"
depends_on:
- caddy
networks:
public:
ipv4_address: 192.168.240.3
labels:
caddy: tracker.${DOMAIN}
caddy.reverse_proxy: "{{ upstreams 8001 }}"
caddy.handle_path: "/static/*"
caddy.handle_path.root: "* /srv/timetracker"
caddy.handle_path.file_server:
caddy.handle: /robots.txt
caddy.handle.root: "* /srv/timetracker"
caddy.handle.file_server:
restart: unless-stopped
trilium:
image: triliumnext/notes:v0.95.0
container_name: trilium
restart: always
environment:
- TRILIUM_DATA_DIR=/home/node/trilium-data
volumes:
- ${DOCKER_STORAGE_PATH}/trilium:/home/node/trilium-data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
labels:
caddy: trilium.${DOMAIN}
caddy.reverse_proxy: "{{ upstreams $TRILIUM_INTERNAL_PORT }}"
ports:
- "${TRILIUM_EXTERNAL_PORT}:${TRILIUM_INTERNAL_PORT}"
networks:
public:
ipv4_address: 192.168.240.4
ntfy:
image: binwiederhier/ntfy:v2.15.0
container_name: ntfy
command:
- serve
user: ${PUID}:${PGID}
environment:
- TZ=${TZ}
- NTFY_LOG_LEVEL=debug
volumes:
- "${DOCKER_STORAGE_PATH}/ntfy/cache:/var/cache/ntfy"
- "${DOCKER_STORAGE_PATH}/ntfy/config:/etc/ntfy"
ports:
- "${NTFY_EXTERNAL_PORT}:${NTFY_INTERNAL_PORT}"
networks:
public:
ipv4_address: 192.168.240.5
labels:
caddy: "notify.${DOMAIN}, http://notify.${DOMAIN}"
caddy.reverse_proxy: "{{ upstreams $NTFY_INTERNAL_PORT }}"
caddy.@httpget.protocol: http
caddy.@httpget.method: get
caddy.@httpget.path_regexp: "^/([-_a-z0-9]{0,64}$|docs/|static/)"
caddy.redir: "@httpget https://{host}{uri}"
restart: unless-stopped
audiobookshelf:
image: ghcr.io/advplyr/audiobookshelf:2.20.0
container_name: audiobookshelf
environment:
- AUDIOBOOKSHELF_UID=${PUID}
- AUDIOBOOKSHELF_GID=${PGID}
- TZ=${TZ}
volumes:
- "${DOCKER_STORAGE_PATH}/audiobookshelf/audiobooks:/audiobooks"
- "${DOCKER_STORAGE_PATH}/audiobookshelf/podcasts:/podcasts"
- "${DOCKER_STORAGE_PATH}/audiobookshelf/config:/config"
- "${DOCKER_STORAGE_PATH}/audiobookshelf/metadata:/metadata"
ports:
- "${AUDIOBOOKSHELF_EXTERNAL_PORT}:${AUDIOBOOKSHELF_INTERNAL_PORT}"
networks:
public:
ipv4_address: 192.168.240.6
restart: unless-stopped
beets:
image: lscr.io/linuxserver/beets:2.5.1
container_name: beets
user: 1000:100
environment:
- TZ=${TZ}
volumes:
- "${DOCKER_STORAGE_PATH}/beets:/config"
- "${STORAGE_PATH}/media/music2:/music"
- "${STORAGE_PATH}/download/music:/downloads"
ports:
- 8337:8337
networks:
public:
ipv4_address: 192.168.240.7
restart: unless-stopped
mealie:
container_name: mealie
image: hkotel/mealie:v3.5.0
depends_on:
- authentik-server
environment:
PUID: ${PUID}
PGID: ${PGID}
TZ: ${TZ}
OIDC_AUTH_ENABLED: true
OIDC_PROVIDER_NAME: Authentik
OIDC_CONFIGURATION_URL: https://authentik.kucharczyk.xyz/application/o/mealie/.well-known/openid-configuration
OIDC_CLIENT_ID: asDhzvutfxxpgwaaz0Jjr6SNpEtZo8GKjjs1WzUU
OIDC_CLIENT_SECRET: iIgP3aaF1t0sTd8JPwXrCYmd3Ycc5hhfQROdHN7ByDU81gFJiNbRQ1OrTU7e9yzuPAyqLShRQ2Ve7ov03maHpQtyZzZ2FBdb0OHCkoS4brVuV8uZ4cnVPCzwLEO9bk9U
OIDC_SIGNUP_ENABLED: false
OIDC_USER_GROUP: mealie-users
OIDC_ADMIN_GROUP: mealie-admins
OIDC_AUTO_REDIRECT: false # Optional: The login page will be bypassed and you will be sent directly to your Identity Provider.
OIDC_REMEMBER_ME: true # Option
ALLOW_PASSWORD_LOGIN: false
env_file:
- mealie.env
volumes:
- "${DOCKER_STORAGE_PATH}/mealie/data/:/app/data"
networks:
public:
ipv4_address: 192.168.240.8
labels:
caddy: recipes.${DOMAIN}
caddy.reverse_proxy: "{{ upstreams 9000 }}"
restart: unless-stopped
webhook:
image: ${REGISTRY_URL}/webhook
container_name: webhook
build: https://git.kucharczyk.xyz/containers/webhook.git#main
user: ${PUID}:${PGID}
environment:
- TZ=${TZ}
volumes:
- "${DOCKER_STORAGE_PATH}/webhook/config:/config"
- "${DOCKER_STORAGE_PATH}/webhook/scripts:/var/webhook"
ports:
- "${WEBHOOK_EXTERNAL_PORT}:${WEBHOOK_INTERNAL_PORT}"
networks:
public:
ipv4_address: 192.168.240.10
restart: unless-stopped
valheim:
image: ghcr.io/lloesche/valheim-server
container_name: valheim
volumes:
- ${DOCKER_STORAGE_PATH}/valheim/config:/config
- ${DOCKER_STORAGE_PATH}/valheim/data:/opt/valheim
env_file:
- valheim.env
ports:
- ${VALHEIM_EXTERNAL_PORT}:${VALHEIM_INTERNAL_PORT}
cap_add:
- SYS_NICE
networks:
public:
ipv4_address: 192.168.240.11
restart: unless-stopped
stash:
image: stashapp/stash:v0.30.0
container_name: stash
ports:
- "${STASH_EXTERNAL_PORT}:${STASH_INTERNAL_PORT}"
logging:
driver: "json-file"
options:
max-file: "10"
max-size: "2m"
environment:
- STASH_STASH=/data/
- STASH_GENERATED=/generated/
- STASH_METADATA=/metadata/
- STASH_CACHE=/cache/
- STASH_PORT=${STASH_INTERNAL_PORT}
volumes:
- /etc/localtime:/etc/localtime:ro
## Adjust below paths (the left part) to your liking.
## E.g. you can change ./config:/root/.stash to ./stash:/root/.stash
## Keep configs, scrapers, and plugins here.
- "${DOCKER_STORAGE_PATH}/stash/config:/root/.stash"
## Point this at your collection.
- "${STORAGE_PATH}/xxx:/data/"
## This is where your stash's metadata lives
- "${DOCKER_STORAGE_PATH}/stash/metadata:/metadata"
## Any other cache content.
- "${DOCKER_STORAGE_PATH}/stash/cache:/cache"
## Where to store generated content (screenshots,previews,transcodes,sprites)
- "${DOCKER_STORAGE_PATH}/stash/generated:/generated"
## Where to store binary blob data (scene covers, images)
- "${DOCKER_STORAGE_PATH}/stash/blobs:/blobs"
networks:
public:
ipv4_address: 192.168.240.13
restart: unless-stopped
navidrome:
image: deluan/navidrome:0.59.0
container_name: navidrome
ports:
- "${NAVIDROME_EXTERNAL_PORT}:${NAVIDROME_INTERNAL_PORT}"
env_file:
- navidrome.env
user: "${PUID}:${PGID}"
volumes:
- "${DOCKER_STORAGE_PATH}/navidrome:/data"
- "${STORAGE_PATH}/media/music2:/music"
networks:
public:
ipv4_address: 192.168.240.14
labels:
caddy: music.${DOMAIN}
caddy.reverse_proxy: "{{ upstreams $NAVIDROME_INTERNAL_PORT }}"
restart: unless-stopped
maloja:
image: krateng/maloja
container_name: maloja
ports:
- "${MALOJA_EXTERNAL_PORT}:${MALOJA_INTERNAL_PORT}"
env_file:
- maloja.env
user: "${PUID}:${PGID}"
volumes:
- "${DOCKER_STORAGE_PATH}/maloja:/data"
networks:
public:
ipv4_address: 192.168.240.15
restart: unless-stopped
redis:
container_name: redis
image: docker.io/library/redis:7
networks:
public:
ipv4_address: 192.168.240.30
restart: unless-stopped
volumes:
- "${DOCKER_STORAGE_PATH}/redis:/data"
paperless-ngx:
container_name: paperless-ngx
image: ghcr.io/paperless-ngx/paperless-ngx:2.0.1
restart: unless-stopped
depends_on:
- redis
- gotenberg
- tika
ports:
- "${PAPERLESS_EXTERNAL_PORT}:${PAPERLESS_INTERNAL_PORT}"
networks:
public:
ipv4_address: 192.168.240.16
healthcheck:
test:
[
"CMD",
"curl",
"-fs",
"-S",
"--max-time",
"2",
"http://localhost:8000"
]
interval: 30s
timeout: 10s
retries: 5
volumes:
- "${DOCKER_STORAGE_PATH}/paperless-ngx/data:/usr/src/paperless/data"
- "${DOCKER_STORAGE_PATH}/paperless-ngx/media:/usr/src/paperless/media"
- "${DOCKER_STORAGE_PATH}/paperless-ngx/export:/usr/src/paperless/export"
- "${DOCKER_STORAGE_PATH}/paperless-ngx/consume:/usr/src/paperless/consume"
env_file: paperless-ngx.env
environment:
PAPERLESS_REDIS: redis://redis:6379
PAPERLESS_TIKA_ENABLED: 1
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
PAPERLESS_URL: "https://paperless.${DOMAIN}"
gotenberg:
image: docker.io/gotenberg/gotenberg:7.6
restart: unless-stopped
networks:
public:
ipv4_address: 192.168.240.17
# 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/.*"
tika:
image: ghcr.io/paperless-ngx/tika:latest
networks:
public:
ipv4_address: 192.168.240.18
restart: unless-stopped
homer:
image: b4bz/homer:v25.11.1
container_name: homer
ports:
- "${HOMER_EXTERNAL_PORT}:${HOMER_INTERNAL_PORT}"
labels:
caddy: dashboard.home.arpa
caddy.reverse_proxy: "{{ upstreams $HOMER_INTERNAL_PORT }}"
networks:
public:
ipv4_address: 192.168.240.19
volumes:
- "${DOCKER_STORAGE_PATH}/homer:/www/assets"
environment:
UID: ${PUID}
GID: ${PGID}
restart: unless-stopped
syncthing:
image: lscr.io/linuxserver/syncthing:1.28.1
container_name: syncthing
volumes:
- "${DOCKER_STORAGE_PATH_SLOW}/syncthing:/config"
- "${DOCKER_STORAGE_PATH_SLOW}/syncthing/shares:/shares"
- "${STORAGE_PATH}:/storage"
ports:
- "${SYNCTHING_EXTERNAL_PORT1}:${SYNCTHING_INTERNAL_PORT1}"
- "${SYNCTHING_EXTERNAL_PORT2}:${SYNCTHING_INTERNAL_PORT2}"
- "${SYNCTHING_EXTERNAL_PORT3}:${SYNCTHING_INTERNAL_PORT3}"
- "${SYNCTHING_EXTERNAL_PORT4}:${SYNCTHING_INTERNAL_PORT4}"
environment:
- "PUID=${PUID}"
- "PGID=${PGID}"
restart: unless-stopped
networks:
public:
ipv4_address: 192.168.240.20
mediawiki:
container_name: mediawiki
image: mediawiki
networks:
public:
ipv4_address: 192.168.240.21
labels:
caddy: wiki.${DOMAIN}
caddy.reverse_proxy: "{{ upstreams $MEDIAWIKI_INTERNAL_PORT }}"
depends_on:
- mariadb
ports:
- "${MEDIAWIKI_EXTERNAL_PORT}:${MEDIAWIKI_INTERNAL_PORT}"
volumes:
- "${DOCKER_STORAGE_PATH}/mediawiki/images:/var/www/html/images"
- "${DOCKER_STORAGE_PATH}/mediawiki/extensions:/var/www/html/extensions"
- "${DOCKER_STORAGE_PATH}/mediawiki/LocalSettings.php:/var/www/html/LocalSettings.php"
restart: unless-stopped
photoprism:
container_name: photoprism
image: docker.io/photoprism/photoprism
networks:
public:
ipv4_address: 192.168.240.22
ports:
- "${PHOTOPRISM_EXTERNAL_PORT}:${PHOTOPRISM_INTERNAL_PORT}"
labels:
caddy: photoprism.home.arpa
caddy.reverse_proxy: "{{ upstreams 2342 }}"
depends_on:
- mariadb
env_file:
- photoprism.env
volumes:
- "${PHOTOS_STORAGE_PATH}/import:/photoprism/import"
- "${PHOTOS_STORAGE_PATH}/originals:/photoprism/originals"
- "${PHOTOS_STORAGE_PATH}/storage:/photoprism/storage"
restart: unless-stopped
mariadb:
container_name: mariadb
image: linuxserver/mariadb:11.4.5
networks:
public:
ipv4_address: 192.168.240.23
ports:
- "${MARIADB_EXTERNAL_PORT}:${MARIADB_INTERNAL_PORT}"
secrets:
- mariadb_root_password
environment:
- MARIADB_AUTO_UPGRADE=true
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- FILE__MYSQL_ROOT_PASSWORD=/run/secrets/mariadb_root_password
volumes:
- "${DOCKER_STORAGE_PATH}/mariadb:/config"
- sockets:/run/mysqld/
restart: unless-stopped
healthcheck:
test: [ "CMD", "mariadb-admin", "ping", "-h", "localhost" ]
interval: 5s
timeout: 5s
retries: 10
baserow:
container_name: baserow
image: baserow/baserow:latest
networks:
public:
ipv4_address: 192.168.240.24
labels:
caddy: baserow.${DOMAIN}
caddy.reverse_proxy: "{{ upstreams 80 }}"
depends_on:
- postgres
env_file:
- baserow.env
volumes:
- "${DOCKER_STORAGE_PATH}/baserow:/baserow/data"
restart: unless-stopped
gitea:
container_name: gitea
image: gitea/gitea:1.25.3
networks:
public:
ipv4_address: 192.168.240.26
depends_on:
- postgres
- authentik-server
ports:
- "${GITEA_WEBUI_EXTERNAL_PORT}:${GITEA_WEBUI_INTERNAL_PORT}"
- "${GITEA_SSH_EXTERNAL_PORT}:${GITEA_SSH_INTERNAL_PORT}"
labels:
caddy: git.${DOMAIN}
caddy.reverse_proxy: "{{ upstreams $GITEA_WEBUI_INTERNAL_PORT }}"
volumes:
- "${DOCKER_STORAGE_PATH}/gitea:/data"
restart: unless-stopped
gitearunner:
container_name: gitearunner
image: gitea/act_runner
depends_on:
- gitea
volumes:
- "${DOCKER_STORAGE_PATH}/gitearunner/config:/config"
- "${DOCKER_STORAGE_PATH}/gitearunner/data:/data"
- /var/run/docker.sock:/var/run/docker.sock
networks:
public:
ipv4_address: 192.168.240.27
environment:
- GITEA_INSTANCE_URL=https://git.${DOMAIN}
- CONFIG_FILE=/config/config.yaml
- GITEA_RUNNER_REGISTRATION_TOKEN_FILE=/run/secrets/gitea_runner_token
- GITEA_RUNNER_LABELS="ubuntu-latest:docker://catthehacker/ubuntu:act-latest"
- GITEA_RUNNER_NAME="NAS_CONTAINER"
secrets:
- gitea_runner_token
restart: unless-stopped
# ghost:
# image: "ghost:latest"
# container_name: ghost
# environment:
# - url=http://blog.kucharczyk.xyz
# labels:
# - "traefik.enable=true"
# - "traefik.http.routers.ghost.rule=Host(`blog.kucharczyk.xyz`)"
# - "traefik.http.routers.ghost.entrypoints=https"
# - "traefik.http.routers.ghost.tls.certresolver=myresolver"
# volumes:
# - ${DOCKER_STORAGE_PATH}/ghost/content:/var/lib/ghost/content
# networks:
# - public
vaultwarden:
image: vaultwarden/server:1.32.1
container_name: vaultwarden
networks:
public:
ipv4_address: 192.168.240.29
ports:
- "${VAULTWARDEN_EXTERNAL_PORT}:${VAULTWARDEN_INTERNAL_PORT}"
labels:
caddy: bw.${DOMAIN}
caddy.reverse_proxy: "{{ upstreams 80 }}"
env_file:
- ./secrets/vaultwarden.env
environment:
- PUSH_ENABLED=true
# PUSH_INSTALLATION_ID=
# PUSH_INSTALLATION_KEY=
- PUSH_RELAY_URI=https://api.bitwarden.eu
- PUSH_IDENTITY_URI=https://identity.bitwarden.eu
- ADMIN_TOKEN=$$argon2id$$v=19$$m=65540,t=3,p=4$$aWJ2cVRvYUsySkM3M01TMTJJMnZqbUF0Wm1qRWhvd1B6Sk50Q1hwck96dz0$$FKjZ36E54pX2e0AE9OaDpiH43TyAyfVwr3IvracbqEA
- SMTP_HOST=${EMAIL_HOST}
- SMTP_FROM=${EMAIL_FROM}
- SMTP_FROM_NAME="Bitwarden (bw.kucharczyk.xyz)"
- SMTP_PORT=${EMAIL_PORT}
- SMTP_USERNAME=${EMAIL_FROM}
- SMTP_PASSWORD=${EMAIL_PASSWORD}
volumes:
- ${DOCKER_STORAGE_PATH}/vaultwarden:/data
restart: unless-stopped
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:5.1.4-r1-ls431
container_name: qbittorrent
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
- WEBUI_PORT=${QBITTORRENT_WEBUI_PORT}
- TORRENTING_PORT=6881
- DOCKER_MODS=ghcr.io/vuetorrent/vuetorrent-lsio-mod|linuxserver/mods:universal-apprise
volumes:
- ${DOCKER_STORAGE_PATH}/qbittorrent/appdata:/config
- "${DOWNLOADS_PATH}/sabnzbd:/downloads"
- "${TORRENTS_SEED_PATH}:/seed"
- ${TORRENTS_WATCH_PATH}:/watch
- /etc/localtime:/etc/localtime:ro
networks:
public:
ipv4_address: 192.168.240.55
ports:
- ${QBITTORRENT_WEBUI_EXTERNAL_PORT}:${QBITTORRENT_WEBUI_INTERNAL_PORT}
- 6881:6881
- 6881:6881/udp
labels:
caddy: qbt.home.arpa
caddy.reverse_proxy: "{{ upstreams $QBITTORRENT_WEBUI_INTERNAL_PORT }}"
restart: unless-stopped
# see https://github.com/FarisZR/Privacy-OCI
breezewiki:
container_name: breezewiki
image: oci.fariszr.com/fariszr/breezewiki:latest
restart: always
networks:
public:
ipv4_address: 192.168.240.56
ports:
- 8005:8000
labels:
caddy: bwiki.${DOMAIN} bwiki.home.arpa
caddy.reverse_proxy: "{{ upstreams 8000 }}"
environment:
- bw_canonical_origin=bwiki.kucharczyk.xyz
- bw_feature_search_suggestions=true
- bw_port=8000
rss-bridge:
container_name: rss-bridge
image: rssbridge/rss-bridge:latest
networks:
public:
ipv4_address: 192.168.240.57
volumes:
- ./config:/config
ports:
- 3002:80
restart: unless-stopped
karakeep:
container_name: karakeep
image: ghcr.io/karakeep-app/karakeep:0.29.0
restart: unless-stopped
volumes:
# By default, the data is stored in a docker volume called "data".
# If you want to mount a custom directory, change the volume mapping to:
# - /path/to/your/directory:/data
- ${DOCKER_STORAGE_PATH}/karakeep:/data
ports:
- 3003:3000
env_file:
- .env
environment:
MEILI_ADDR: http://meilisearch:7700
BROWSER_WEB_URL: http://chrome:9222
NEXTAUTH_SECRET: lB5mx3t9mdKclELtt+cs2pVBefB+8vD4dKuzhvUP+JzR9bL1
MEILI_MASTER_KEY: Cvu7m/RIGYQPiYcIrxacHFhbfLKfKq3wwSAWJPKVWQEauiIX
NEXTAUTH_URL: https://karakeep.kucharczykx.xyz
DISABLE_SIGNUPS: TRUE
CRAWLER_VIDEO_DOWNLOAD: TRUE
BROWSER_COOKIE_PATH: /data/yt-cookies.json
CRAWLER_FULL_PAGE_SCREENSHOT: TRUE
CRAWLER_FULL_PAGE_ARCHIVE: TRUE
OLLAMA_BASE_URL: http://100.84.157.12:11434
INFERENCE_TEXT_MODEL: gemma3:27b-it-qat
INFERENCE_IMAGE_MODEL: llava
INFERENCE_ENABLE_AUTO_TAGGING: TRUE
INFERENCE_ENABLE_AUTO_SUMMARIZATION: TRUE
INFERENCE_CONTEXT_LENGTH: 32000
# OPENAI_API_KEY: ...
# You almost never want to change the value of the DATA_DIR variable.
# If you want to mount a custom directory, change the volume mapping above instead.
DATA_DIR: /data # DON'T CHANGE THIS
networks:
public:
ipv4_address: 192.168.240.58
labels:
caddy: karakeep.${DOMAIN}
caddy.reverse_proxy: "{{ upstreams 3000 }}"
chrome:
image: gcr.io/zenika-hub/alpine-chrome:124
restart: unless-stopped
command:
- --no-sandbox
- --disable-gpu
- --disable-dev-shm-usage
- --remote-debugging-address=0.0.0.0
- --remote-debugging-port=9222
- --hide-scrollbars
networks:
public:
ipv4_address: 192.168.240.59
ports:
- 9222:9222
meilisearch:
image: getmeili/meilisearch:v1.13.3
restart: unless-stopped
env_file:
- .env
environment:
MEILI_NO_ANALYTICS: "true"
MEILI_MASTER_KEY: Cvu7m/RIGYQPiYcIrxacHFhbfLKfKq3wwSAWJPKVWQEauiIX
volumes:
- meilisearch:/meili_data
networks:
public:
ipv4_address: 192.168.240.60
authentik-server:
command: server
depends_on:
postgres:
condition: service_healthy
secrets:
- authentik_secret_key
- postgres_general_username
- postgres_general_password
environment:
AUTHENTIK_POSTGRESQL__HOST: postgres
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: file:///run/secrets/postgres_general_password
AUTHENTIK_POSTGRESQL__USER: file:///run/secrets/postgres_general_username
AUTHENTIK_SECRET_KEY: file:///run/secrets/authentik_secret_key
AUTHENTIK_EMAIL__HOST: smtp.protonmail.ch
AUTHENTIK_EMAIL__PORT: 587
AUTHENTIK_EMAIL__USERNAME: lukas@kucharczyk.xyz
AUTHENTIK_EMAIL__PASSWORD: CQHMWAUWQG5FBJ2V
AUTHENTIK_EMAIL__USE_TLS: true
AUTHENTIK_EMAIL__USE_SSL: false
AUTHENTIK_EMAIL__TIMEOUT: 60
AUTHENTIK_EMAIL__FROM: lukas@kucharczyk.xyz
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.10.0}
ports:
- 9002:9000
- 9443:9443
networks:
public:
ipv4_address: 192.168.240.61
restart: unless-stopped
volumes:
- ${DOCKER_STORAGE_PATH}/authentik/media:/media
- ${DOCKER_STORAGE_PATH}/authentik/custom-templates:/templates
labels:
caddy: authentik.${DOMAIN}
caddy.reverse_proxy: "{{ upstreams 9000 }}"
authentik-worker:
command: worker
depends_on:
postgres:
condition: service_healthy
networks:
public:
ipv4_address: 192.168.240.62
secrets:
- authentik_secret_key
- email_host
- email_username
- email_password
- postgres_general_username
- postgres_general_password
environment:
AUTHENTIK_POSTGRESQL__HOST: postgres
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: file:///run/secrets/postgres_general_password
AUTHENTIK_POSTGRESQL__USER: file:///run/secrets/postgres_general_username
AUTHENTIK_SECRET_KEY: file:///run/secrets/authentik_secret_key
AUTHENTIK_EMAIL__HOST: file:///run/secrets/email_host
AUTHENTIK_EMAIL__PORT: 587
AUTHENTIK_EMAIL__USERNAME: file:///run/secrets/email_username
AUTHENTIK_EMAIL__PASSWORD: file:///run/secrets/email_password
AUTHENTIK_EMAIL__USE_TLS: true
AUTHENTIK_EMAIL__USE_SSL: false
AUTHENTIK_EMAIL__TIMEOUT: 60
AUTHENTIK_EMAIL__FROM: file:///run/secrets/email_username
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.10.0}
restart: unless-stopped
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ${DOCKER_STORAGE_PATH}/authentik/media:/media
- ${DOCKER_STORAGE_PATH}/authentik/certs:/certs
- ${DOCKER_STORAGE_PATH}/authentik/custom-templates:/templates
dnsmasq:
restart: always
image: strm/dnsmasq
configs:
- source: dnsmasq
target: /etc/dnsmasq.conf
ports:
- "53:53/udp"
cap_add:
- NET_ADMIN
ersatztv:
image: jasongdove/ersatztv:latest
container_name: ersatztv
networks:
public:
ipv4_address: 192.168.240.63
ports:
- 8409:8409
labels:
caddy: tv.kucharczyk.xyz
caddy.reverse_proxy: "{{ upstreams 8409 }}"
volumes:
- ${DOCKER_STORAGE_PATH}/ersatztv/config:/config
- ${MEDIA_PATH}:/media:ro
restart: unless-stopped
environment:
TZ: ${TZ}
slskd:
image: slskd/slskd:0.24.0
container_name: slskd
user: 1000:100
networks:
public:
ipv4_address: 192.168.240.67
ports:
- "5030:5030"
# - "5031:5031"
- "50300:50300"
env_file:
- secrets/slskd_secrets.env
environment:
- SLSKD_REMOTE_CONFIGURATION=true
- SLSKD_DOWNLOADS_DIR=/downloads
- SLSKD_INCOMPLETE_DIR=/app/incomplete
- SLSKD_SHARED_DIR=/shares
- SLSKD_SLSK_ADDRESS=server.slsknet.org
- SLSKD_SLSK_PORT=2242
# from slskd_secrets.env
# - SLSKD_USERNAME
# - SLSKD_PASSWORD
# - SLSKD_SLSK_USERNAME
# - SLSKD_SLSK_PASSWORD
- SLSKD_NO_HTTPS=TRUE
volumes:
- ${DOCKER_STORAGE_PATH}/slskd:/app
- ${DOWNLOADS_PATH}/music/autoimport:/downloads
- ${MUSIC_PATH}:/shares/music:ro
restart: always
booklore:
image: booklore/booklore:v1.16.2
container_name: booklore
env_file: secrets/booklore.env
environment:
- USER_ID=${PUID}
- GROUP_ID=${PGID}
- TZ=${TZ}
- DATABASE_URL_FILE=jdbc:mariadb://mariadb:3306/booklore
- DATABASE_USERNAME=booklore
- BOOKLORE_PORT=6060
depends_on:
mariadb:
condition: service_healthy
networks:
public:
ipv4_address: 192.168.240.66
ports:
- "6060:6060"
labels:
caddy: books.kucharczyk.xyz
caddy.reverse_proxy: "{{ upstreams 6060 }}"
caddy_config.servers.protocol.max_header_size: "32kb"
volumes:
- ${DOCKER_STORAGE_PATH}/booklore/data:/app/data
- "${DOCKER_STORAGE_PATH_SLOW}/books-calibre:/books-calibre"
- ${DOWNLOADS_PATH}/bookdrop:/bookdrop
restart: unless-stopped
adminer:
image: adminer:latest
container_name: adminer
depends_on:
mariadb:
condition: service_healthy
networks:
public:
ipv4_address: 192.168.240.65
ports:
- 8087:8080
restart: unless-stopped
networks:
public:
attachable: true
ipam:
config:
# 192.168.240.1 - 192.168.240.254
- subnet: "192.168.240.0/24"
volumes:
timetracker-static:
sockets:
meilisearch: