Update docker-compose files to use configurable environment variables
- Replace hardcoded paths with variables: STACKS_DIR, PROJECTS_DIR, MEDIA_DIR, DOWNLOAD_DIR - Update .env.example with new variable definitions - Remove unused .template files - Enable configurable directory paths for stacks, media, and downloads
This commit is contained in:
265
.env.example
265
.env.example
@@ -1,138 +1,116 @@
|
|||||||
# EZ-Homelab .env template file - Copy to .env and fill in your values
|
########################################################
|
||||||
|
#### EZ-Homelab .env template file ####
|
||||||
|
#### EZ MODE: just run ez-homelab.sh ####
|
||||||
|
########################################################
|
||||||
|
|
||||||
# ################################
|
########################################################
|
||||||
# #### REQUIRED CONFIGURATION ####
|
# #### REQUIRED CONFIGURATION ####
|
||||||
|
|
||||||
# User and Group IDs for file permissions (get with: id -u and id -g)
|
# Required for file permissions (get with: id -u and id -g)
|
||||||
PUID=1000
|
PUID=1000
|
||||||
PGID=1000
|
PGID=1000
|
||||||
TZ=America/New_York
|
TZ=America/New_York
|
||||||
|
|
||||||
# Servers configuration
|
# This Server's IP and Hostname
|
||||||
SERVER_IP=192.168.1.100 # This server
|
SERVER_IP=
|
||||||
SERVER_HOSTNAME=debian
|
SERVER_HOSTNAME=
|
||||||
|
|
||||||
# Domain Configuration
|
# Domain Configuration
|
||||||
DUCKDNS_SUBDOMAINS=yourdomain # Without .duckdns.org
|
DUCKDNS_SUBDOMAINS=
|
||||||
DUCKDNS_TOKEN=your-duckdns-token
|
DUCKDNS_TOKEN=
|
||||||
DOMAIN=${DUCKDNS_SUBDOMAINS}.duckdns.org
|
DOMAIN=${DUCKDNS_SUBDOMAINS}.duckdns.org
|
||||||
|
|
||||||
# Default credentials (used by multiple services for easier setup)
|
# Default credentials (used by multiple services)
|
||||||
DEFAULT_USER=admin
|
# For better security: replace each ${DEFAULT_PASSWORD} with unique values
|
||||||
DEFAULT_PASSWORD=changeme
|
DEFAULT_USER=
|
||||||
DEFAULT_EMAIL=admin@example.com
|
DEFAULT_PASSWORD=
|
||||||
|
DEFAULT_EMAIL=
|
||||||
# ADMIN_SSH_PUB_KEY=
|
|
||||||
|
|
||||||
# FOLDER PATHS
|
# FOLDER PATHS
|
||||||
USERDIR=/opt/stacks # all docker-compose stacks
|
STACKS_DIR=/opt/stacks # for Dockge
|
||||||
MEDIADIR=/mnt/media # Large media files on separate drive
|
PROJECTS_DIR=${STACKS_DIR} # for Arcane
|
||||||
DOWNLOADDIR=/mnt/downloads # Downloads on separate drive
|
MEDIA_DIR=/mnt/media # Large media files on separate drive
|
||||||
PROJECTDIR=~/projects # User's projects folder
|
DOWNLOAD_DIR=/mnt/downloads # Downloads on separate drive
|
||||||
|
|
||||||
# If selecting option 3: Deploy Additional Server
|
# PROJECTDIR=~/projects # User's projects folder
|
||||||
# the CORE_SERVER is where the Core Traefik is running
|
|
||||||
CORE_SERVER_IP=192.168.1.101
|
# ########## END REQUIRED CONFIGURATION ####
|
||||||
CORE_SERVER_HOSTNAME=debian2
|
########################################################
|
||||||
|
|
||||||
|
########################################################
|
||||||
|
# #### OPTION 3: ADDITIONAL SERVER ####
|
||||||
|
CORE_SERVER_IP=
|
||||||
|
CORE_SERVER_HOSTNAME=
|
||||||
CORE_SERVER_USER=${DEFAULT_USER}
|
CORE_SERVER_USER=${DEFAULT_USER}
|
||||||
CORE_SERVER_PASSWORD=${DEFAULT_PASSWORD}
|
CORE_SERVER_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
|
# #### END ADDITIONAL SERVER ####
|
||||||
|
########################################################
|
||||||
|
|
||||||
# ##########################################
|
########################################################
|
||||||
# #### NOTEABLE OPTIONAL CONFIGURATIONS ####
|
# #### VPN CONFIGURATIONS ####
|
||||||
|
SURFSHARK_USERNAME=
|
||||||
# Surfshark OpenVPN (RECOMMENDED)
|
SURFSHARK_PASSWORD=
|
||||||
# Wireguard options are below and commented out
|
|
||||||
SURFSHARK_USERNAME=your-surfshark-username
|
|
||||||
SURFSHARK_PASSWORD=your-surfshark-password
|
|
||||||
VPN_SERVER_COUNTRIES=Netherlands # Preferred VPN server location
|
VPN_SERVER_COUNTRIES=Netherlands # Preferred VPN server location
|
||||||
|
# #### END VPN CONFIGURATIONS ####
|
||||||
|
########################################################
|
||||||
|
|
||||||
# Email credentials for services that need SMTP
|
########################################################
|
||||||
SMTP_EMAIL_PASSWORD=your-email-app-password
|
# #### EMAIL CONFIGURATIONS ####
|
||||||
SMTP_EMAIL_SERVER=smtp.gmail.com # change if not using Gmail
|
SMTP_EMAIL_PASSWORD=
|
||||||
|
SMTP_EMAIL_SERVER=smtp.gmail.com
|
||||||
SMTP_EMAIL_PORT=587
|
SMTP_EMAIL_PORT=587
|
||||||
SMTP_EMAIL_FROM=${DEFAULT_EMAIL}
|
SMTP_EMAIL_FROM=${DEFAULT_EMAIL}
|
||||||
SMTP_EMAIL_SECURITY=starttls
|
SMTP_EMAIL_SECURITY=starttls
|
||||||
|
|
||||||
# ACME Email for Let's Encrypt certificates
|
|
||||||
ACME_EMAIL=${DEFAULT_EMAIL}
|
ACME_EMAIL=${DEFAULT_EMAIL}
|
||||||
|
SMTP_USERNAME=${SMTP_EMAIL_FROM}
|
||||||
|
SMTP_PASSWORD=${SMTP_EMAIL_PASSWORD}
|
||||||
|
# #### END EMAIL CONFIGURATIONS ####
|
||||||
|
########################################################
|
||||||
|
|
||||||
# Authelia Admin Account
|
########################################################
|
||||||
# These 4 Used by ez-homelab.sh for easy deployment
|
# ########### DELETE AFTER DEPLOYMENT ###########
|
||||||
# Not used by the Authelia container directly
|
# #### Used by ez-homelab.sh & deploy scripts ####
|
||||||
ADMIN_EMAIL=${DEFAULT_EMAIL} # Used for admin user account
|
# #### Unused by the actual containers ####
|
||||||
|
|
||||||
|
# Public SSH key from the pc used to access the homelab
|
||||||
|
# Will be added to the admin user's authorized_keys
|
||||||
|
# #### DO NOT INCLUDE YOUR PRIVATE KEY ####
|
||||||
|
ADMIN_SSH_PUB_KEY=
|
||||||
|
|
||||||
|
# Authelia Admin Credentials
|
||||||
|
ADMIN_EMAIL=${DEFAULT_EMAIL}
|
||||||
AUTHELIA_ADMIN_USER=${DEFAULT_USER}
|
AUTHELIA_ADMIN_USER=${DEFAULT_USER}
|
||||||
AUTHELIA_ADMIN_EMAIL=${DEFAULT_EMAIL}
|
AUTHELIA_ADMIN_EMAIL=${DEFAULT_EMAIL}
|
||||||
AUTHELIA_ADMIN_PASSWORD=${DEFAULT_PASSWORD}
|
AUTHELIA_ADMIN_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
AUTHELIA_ADMIN_PASSWORD_HASH=generate-with-openssl-rand-hex-64
|
|
||||||
|
|
||||||
# SMTP for Authelia Notifications
|
# Use this command to generate AUTHELIA_ADMIN_PASSWORD_HASH:
|
||||||
SMTP_USERNAME=${SMTP_EMAIL_FROM}
|
# docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password "YOUR_PASSWORD_HERE"
|
||||||
SMTP_PASSWORD=${SMTP_EMAIL_PASSWORD}
|
AUTHELIA_ADMIN_PASSWORD_HASH=
|
||||||
|
|
||||||
# Let ez-homelab.sh generate these 3 unless you know what your doing
|
# Use this command to generate each secret
|
||||||
AUTHELIA_JWT_SECRET=generate-with-openssl-rand-hex-64
|
# openssl rand -hex 64
|
||||||
AUTHELIA_SESSION_SECRET=generate-with-openssl-rand-hex-64
|
AUTHELIA_JWT_SECRET=
|
||||||
AUTHELIA_STORAGE_ENCRYPTION_KEY=generate-with-openssl-rand-hex-64
|
AUTHELIA_SESSION_SECRET=
|
||||||
|
AUTHELIA_STORAGE_ENCRYPTION_KEY=
|
||||||
|
|
||||||
# ARCANE Secrets - Let ez-homelab.sh generate these unless you know what your doing
|
# Arcane secrets
|
||||||
ARCANE_ENCRYPTION_KEY=generate-with-openssl-rand-hex-64
|
ARCANE_ENCRYPTION_KEY=
|
||||||
ARCANE_JWT_SECRET=generate-with-openssl-rand-hex-64
|
ARCANE_JWT_SECRET=
|
||||||
|
# ########## END DELETE AFTER DEPLOYMENT ####
|
||||||
|
########################################################
|
||||||
|
|
||||||
|
|
||||||
# Surfshark WireGuard (OPTIONAL - Advanced users only)
|
########################################################
|
||||||
# Get WireGuard details from Surfshark dashboard
|
# #####################################################
|
||||||
# SURFSHARK_PRIVATE_KEY=your-wireguard-private-key
|
# #### Application Specific Configurations ####
|
||||||
# SURFSHARK_ADDRESSES=10.14.0.2/16
|
# #####################################################
|
||||||
|
|
||||||
# What domains Homepage will accept requests from
|
# #####################################################
|
||||||
# comma separated list NO SPACES!!!
|
# #### Bitwarden #####
|
||||||
HOMEPAGE_ALLOWED_HOSTS=homepage.${DOMAIN},${SERVER_IP}:3003
|
# #### SET TO FALSE AFTER CREATING USERS ####
|
||||||
|
|
||||||
# #######################################
|
BITWARDEN_SIGNUPS_ALLOWED=true
|
||||||
# #### OTHER OPTIONAL CONFIGURATIONS ####
|
|
||||||
|
|
||||||
# BookStack
|
|
||||||
BOOKSTACK_DB_PASSWORD=${DEFAULT_PASSWORD}
|
|
||||||
BOOKSTACK_DB_ROOT_PASSWORD=${DEFAULT_PASSWORD}
|
|
||||||
|
|
||||||
# DATABASES - GENERAL
|
|
||||||
POSTGRES_USER=${DEFAULT_USER}
|
|
||||||
POSTGRES_PASSWORD=${DEFAULT_PASSWORD}
|
|
||||||
POSTGRES_DB=homelab
|
|
||||||
PGADMIN_EMAIL=${DEFAULT_EMAIL}
|
|
||||||
PGADMIN_PASSWORD=${DEFAULT_PASSWORD}
|
|
||||||
|
|
||||||
# Form.io
|
|
||||||
FORMIO_JWT_SECRET=${DEFAULT_PASSWORD}
|
|
||||||
FORMIO_DB_SECRET=${DEFAULT_PASSWORD}
|
|
||||||
|
|
||||||
# Gitea
|
|
||||||
GITEA_DB_PASSWORD=${DEFAULT_PASSWORD}
|
|
||||||
|
|
||||||
# GRAFANA
|
|
||||||
GRAFANA_ADMIN_PASSWORD=${DEFAULT_PASSWORD}
|
|
||||||
|
|
||||||
# Jupyter Notebook
|
|
||||||
JUPYTER_TOKEN=${DEFAULT_PASSWORD}
|
|
||||||
|
|
||||||
# MediaWiki
|
|
||||||
MEDIAWIKI_DB_PASSWORD=${DEFAULT_PASSWORD}
|
|
||||||
MEDIAWIKI_DB_ROOT_PASSWORD=${DEFAULT_PASSWORD}
|
|
||||||
|
|
||||||
# Nextcloud
|
|
||||||
NEXTCLOUD_ADMIN_USER=${DEFAULT_USER}
|
|
||||||
NEXTCLOUD_ADMIN_PASSWORD=${DEFAULT_PASSWORD}
|
|
||||||
NEXTCLOUD_DB_PASSWORD=${DEFAULT_PASSWORD}
|
|
||||||
NEXTCLOUD_DB_ROOT_PASSWORD=${DEFAULT_PASSWORD}
|
|
||||||
|
|
||||||
# Pi-hole
|
|
||||||
PIHOLE_PASSWORD=${DEFAULT_PASSWORD}
|
|
||||||
|
|
||||||
# qBittorrent
|
|
||||||
QBITTORRENT_USER=admin
|
|
||||||
QBITTORRENT_PASS=${DEFAULT_PASSWORD}
|
|
||||||
|
|
||||||
# Vaultwarden
|
|
||||||
BITWARDEN_ADMIN_TOKEN=${DEFAULT_PASSWORD}
|
BITWARDEN_ADMIN_TOKEN=${DEFAULT_PASSWORD}
|
||||||
BITWARDEN_INVITATIONS_ALLOWED=true
|
BITWARDEN_INVITATIONS_ALLOWED=true
|
||||||
SMTP_HOST=${SMTP_EMAIL_SERVER}
|
SMTP_HOST=${SMTP_EMAIL_SERVER}
|
||||||
@@ -140,17 +118,90 @@ SMTP_FROM=${SMTP_EMAIL_FROM}
|
|||||||
SMTP_PORT=${SMTP_EMAIL_PORT}
|
SMTP_PORT=${SMTP_EMAIL_PORT}
|
||||||
SMTP_SECURITY=${SMTP_EMAIL_SECURITY}
|
SMTP_SECURITY=${SMTP_EMAIL_SECURITY}
|
||||||
|
|
||||||
# #### IMPORTANT ****************************
|
# #####################################################
|
||||||
# #### SET TO FALSE AFTER CREATING USERS ####
|
# #### Bookstack #####
|
||||||
BITWARDEN_SIGNUPS_ALLOWED=true
|
|
||||||
|
BOOKSTACK_DB_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
|
BOOKSTACK_DB_ROOT_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
|
|
||||||
|
# #####################################################
|
||||||
|
# #### Code Server #####
|
||||||
|
|
||||||
# VS Code Server
|
|
||||||
CODE_SERVER_PASSWORD=${DEFAULT_PASSWORD}
|
CODE_SERVER_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
CODE_SERVER_SUDO_PASSWORD=${DEFAULT_PASSWORD}
|
CODE_SERVER_SUDO_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
|
|
||||||
# Watchtower Notifications (optional)
|
# #####################################################
|
||||||
|
# #### Form.io #####
|
||||||
|
|
||||||
|
FORMIO_JWT_SECRET=${DEFAULT_PASSWORD}
|
||||||
|
FORMIO_DB_SECRET=${DEFAULT_PASSWORD}
|
||||||
|
|
||||||
|
# #####################################################
|
||||||
|
# #### Gitea #####
|
||||||
|
|
||||||
|
GITEA_DB_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
|
|
||||||
|
# #####################################################
|
||||||
|
# #### Grafana #####
|
||||||
|
|
||||||
|
GRAFANA_ADMIN_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
|
|
||||||
|
# #####################################################
|
||||||
|
# #### Homepage #####
|
||||||
|
|
||||||
|
# comma separated list NO SPACES!!!
|
||||||
|
HOMEPAGE_ALLOWED_HOSTS=homepage.${DOMAIN},${SERVER_IP}:3003
|
||||||
|
|
||||||
|
# #####################################################
|
||||||
|
# #### Jupyter #####
|
||||||
|
|
||||||
|
JUPYTER_TOKEN=${DEFAULT_PASSWORD}
|
||||||
|
|
||||||
|
# #####################################################
|
||||||
|
# #### MediaWiki #####
|
||||||
|
|
||||||
|
MEDIAWIKI_DB_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
|
MEDIAWIKI_DB_ROOT_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
|
|
||||||
|
# #####################################################
|
||||||
|
# #### Nextcloud #####
|
||||||
|
|
||||||
|
NEXTCLOUD_ADMIN_USER=${DEFAULT_USER}
|
||||||
|
NEXTCLOUD_ADMIN_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
|
NEXTCLOUD_DB_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
|
NEXTCLOUD_DB_ROOT_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
|
NEXTCLOUD_DIR=./nextcloud/data
|
||||||
|
# #####################################################
|
||||||
|
# #### Pi-hole #####
|
||||||
|
|
||||||
|
PIHOLE_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
|
|
||||||
|
# #####################################################
|
||||||
|
# #### qBittorrent #####
|
||||||
|
|
||||||
|
QBITTORRENT_USER=admin
|
||||||
|
QBITTORRENT_PASS=${DEFAULT_PASSWORD}
|
||||||
|
|
||||||
|
# #####################################################
|
||||||
|
# #### SURFSHARK OPTIONAL CONFIGURATIONS ####
|
||||||
|
|
||||||
|
# Surfshark WireGuard (OPTIONAL - Advanced users only)
|
||||||
|
# Get WireGuard details from Surfshark dashboard
|
||||||
|
# SURFSHARK_PRIVATE_KEY=your-wireguard-private-key
|
||||||
|
# SURFSHARK_ADDRESSES=10.14.0.2/16
|
||||||
|
|
||||||
|
# #####################################################
|
||||||
|
# #### Watchtower #####
|
||||||
|
|
||||||
# WATCHTOWER_NOTIFICATION_URL=
|
# WATCHTOWER_NOTIFICATION_URL=
|
||||||
|
|
||||||
# WordPress
|
# #####################################################
|
||||||
|
# #### WordPress #####
|
||||||
|
|
||||||
WORDPRESS_DB_PASSWORD=${DEFAULT_PASSWORD}
|
WORDPRESS_DB_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
WORDPRESS_DB_ROOT_PASSWORD=${DEFAULT_PASSWORD}
|
WORDPRESS_DB_ROOT_PASSWORD=${DEFAULT_PASSWORD}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TDARR_TRANSCODE_DIR=./tdarr/transcode_cache
|
||||||
|
UNMANIC_TRANSCODE_DIR=./unmanic/cache
|
||||||
@@ -19,7 +19,7 @@ services:
|
|||||||
- '9000:9000'
|
- '9000:9000'
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- portainer-data:/data
|
- ./portainer/data:/data
|
||||||
security_opt:
|
security_opt:
|
||||||
- no-new-privileges:true
|
- no-new-privileges:true
|
||||||
labels:
|
labels:
|
||||||
@@ -52,8 +52,8 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- '9000:9000'
|
- '9000:9000'
|
||||||
volumes:
|
volumes:
|
||||||
- /opt/stacks/authentik/media:/media
|
- ./authentik/media:/media
|
||||||
- /opt/stacks/authentik/custom-templates:/templates
|
- ./authentik/custom-templates:/templates
|
||||||
environment:
|
environment:
|
||||||
- AUTHENTIK_REDIS__HOST=authentik-redis
|
- AUTHENTIK_REDIS__HOST=authentik-redis
|
||||||
- AUTHENTIK_POSTGRESQL__HOST=authentik-db
|
- AUTHENTIK_POSTGRESQL__HOST=authentik-db
|
||||||
@@ -89,9 +89,9 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- homelab-network
|
- homelab-network
|
||||||
volumes:
|
volumes:
|
||||||
- /opt/stacks/authentik/media:/media
|
- ./authentik/media:/media
|
||||||
- /opt/stacks/authentik/certs:/certs
|
- ./authentik/certs:/certs
|
||||||
- /opt/stacks/authentik/custom-templates:/templates
|
- ./authentik/custom-templates:/templates
|
||||||
environment:
|
environment:
|
||||||
- AUTHENTIK_REDIS__HOST=authentik-redis
|
- AUTHENTIK_REDIS__HOST=authentik-redis
|
||||||
- AUTHENTIK_POSTGRESQL__HOST=authentik-db
|
- AUTHENTIK_POSTGRESQL__HOST=authentik-db
|
||||||
@@ -119,7 +119,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- homelab-network
|
- homelab-network
|
||||||
volumes:
|
volumes:
|
||||||
- authentik-db-data:/var/lib/postgresql/data
|
- ./authentik/db:/var/lib/postgresql/data
|
||||||
environment:
|
environment:
|
||||||
- POSTGRES_USER=${AUTHENTIK_DB_USER}
|
- POSTGRES_USER=${AUTHENTIK_DB_USER}
|
||||||
- POSTGRES_PASSWORD=${AUTHENTIK_DB_PASSWORD}
|
- POSTGRES_PASSWORD=${AUTHENTIK_DB_PASSWORD}
|
||||||
@@ -145,7 +145,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- homelab-network
|
- homelab-network
|
||||||
volumes:
|
volumes:
|
||||||
- authentik-redis-data:/data
|
- ./authentik/redis:/data
|
||||||
command: --save 60 1 --loglevel warning
|
command: --save 60 1 --loglevel warning
|
||||||
labels:
|
labels:
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
@@ -173,7 +173,7 @@ services:
|
|||||||
- '32400:32400'
|
- '32400:32400'
|
||||||
volumes:
|
volumes:
|
||||||
- ./plex/config:/config
|
- ./plex/config:/config
|
||||||
- /mnt/media:/media:ro # Large media files on separate drive
|
- ${MEDIA_DIR}:/media:ro # Large media files on separate drive
|
||||||
- plex-transcode:/transcode
|
- plex-transcode:/transcode
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=1000
|
||||||
@@ -211,18 +211,6 @@ services:
|
|||||||
- 'traefik.http.routers.plex.entrypoints=websecure'
|
- 'traefik.http.routers.plex.entrypoints=websecure'
|
||||||
- 'traefik.http.routers.plex.tls.certresolver=letsencrypt'
|
- 'traefik.http.routers.plex.tls.certresolver=letsencrypt'
|
||||||
- 'traefik.http.services.plex.loadbalancer.server.port=32400'
|
- 'traefik.http.services.plex.loadbalancer.server.port=32400'
|
||||||
- 'x-dockge.url=https://plex.${DOMAIN}'
|
|
||||||
- 'x-dockge.url=https://plex.${DOMAIN}'
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
portainer-data:
|
|
||||||
driver: local
|
|
||||||
authentik-db-data:
|
|
||||||
driver: local
|
|
||||||
authentik-redis-data:
|
|
||||||
driver: local
|
|
||||||
plex-transcode:
|
|
||||||
driver: local
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
homelab-network:
|
homelab-network:
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ services:
|
|||||||
- '3552:3552'
|
- '3552:3552'
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- arcane-data:/app/data
|
- ./arcane/data:/app/data
|
||||||
- /opt/stacks:/opt/stacks
|
- ${PROJECTS_DIR}:${PROJECTS_DIR}
|
||||||
environment:
|
environment:
|
||||||
- APP_URL=http://${SERVER_IP}:3552
|
- APP_URL=http://${SERVER_IP}:3552
|
||||||
- PROJECTS_DIRECTORY=/opt/stacks
|
- PROJECTS_DIRECTORY=${PROJECTS_DIR}
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PGID}
|
||||||
- ENCRYPTION_KEY=${ARCANE_ENCRYPTION_KEY}
|
- ENCRYPTION_KEY=${ARCANE_ENCRYPTION_KEY}
|
||||||
- JWT_SECRET=${ARCANE_JWT_SECRET}
|
- JWT_SECRET=${ARCANE_JWT_SECRET}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -31,7 +31,7 @@ services:
|
|||||||
# - "3553:3553"
|
# - "3553:3553"
|
||||||
# volumes:
|
# volumes:
|
||||||
# - /var/run/docker.sock:/var/run/docker.sock
|
# - /var/run/docker.sock:/var/run/docker.sock
|
||||||
# - arcane-data:/app/data
|
# - ./arcane/data:/app/data
|
||||||
# networks:
|
# networks:
|
||||||
# - traefik-network
|
# - traefik-network
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ services:
|
|||||||
container_name: duckdns
|
container_name: duckdns
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PGID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
- SUBDOMAINS=${DUCKDNS_SUBDOMAINS}
|
- SUBDOMAINS=${DUCKDNS_SUBDOMAINS}
|
||||||
- TOKEN=${DUCKDNS_TOKEN}
|
- TOKEN=${DUCKDNS_TOKEN}
|
||||||
volumes:
|
volumes:
|
||||||
@@ -60,7 +60,7 @@ services:
|
|||||||
container_name: authelia
|
container_name: authelia
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
ports:
|
ports:
|
||||||
- '9091:9091'
|
- '9091:9091'
|
||||||
volumes:
|
volumes:
|
||||||
@@ -112,7 +112,7 @@ services:
|
|||||||
- ./pihole/etc-pihole:/etc/pihole
|
- ./pihole/etc-pihole:/etc/pihole
|
||||||
- ./pihole/etc-dnsmasq.d:/etc/dnsmasq.d
|
- ./pihole/etc-dnsmasq.d:/etc/dnsmasq.d
|
||||||
environment:
|
environment:
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
- WEBPASSWORD=${PIHOLE_PASSWORD}
|
- WEBPASSWORD=${PIHOLE_PASSWORD}
|
||||||
- FTLCONF_LOCAL_IPV4=192.168.4.4
|
- FTLCONF_LOCAL_IPV4=192.168.4.4
|
||||||
dns:
|
dns:
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
/config/duck.log {
|
|
||||||
rotate 5
|
|
||||||
size 100k
|
|
||||||
compress
|
|
||||||
}
|
|
||||||
@@ -28,7 +28,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./homepage:/app/config
|
- ./homepage:/app/config
|
||||||
- /var/run/docker.sock:/var/run/docker.sock # For Docker integration do not mount RO
|
- /var/run/docker.sock:/var/run/docker.sock # For Docker integration do not mount RO
|
||||||
- /opt/stacks:/opt/stacks # To discover other stacks
|
- ${STACKS_DIR}:${STACKS_DIR} # To discover other stacks
|
||||||
environment:
|
environment:
|
||||||
- PUID=${PUID} # Must be set to the docker user ID
|
- PUID=${PUID} # Must be set to the docker user ID
|
||||||
- PGID=${PGID} # Must be set to the docker group ID
|
- PGID=${PGID} # Must be set to the docker group ID
|
||||||
@@ -83,7 +83,7 @@ services:
|
|||||||
- ./homarr/icons:/app/public/icons
|
- ./homarr/icons:/app/public/icons
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
environment:
|
environment:
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
- SECRET_ENCRYPTION_KEY=8830c9434b05ebfe3e31340c685fea63446ab3f635c4fad68370006949ed30df
|
- SECRET_ENCRYPTION_KEY=8830c9434b05ebfe3e31340c685fea63446ab3f635c4fad68370006949ed30df
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ['CMD', 'curl', '-f', 'http://localhost:7575/']
|
test: ['CMD', 'curl', '-f', 'http://localhost:7575/']
|
||||||
|
|||||||
@@ -1,127 +0,0 @@
|
|||||||
# Dashboard Services
|
|
||||||
# Homepage and Homarr for homelab dashboards
|
|
||||||
|
|
||||||
# SABLIER SESSION DURATION: Set to 5m for testing. Increase to 30m for production in config-templates/traefik/dynamic/sablier.yml
|
|
||||||
|
|
||||||
# Service Access URLs:
|
|
||||||
# - Homepage: https://homepage.${DOMAIN}
|
|
||||||
# - Homarr: https://homarr.${DOMAIN}
|
|
||||||
|
|
||||||
services:
|
|
||||||
# Homepage - Default Application Dashboard
|
|
||||||
homepage:
|
|
||||||
image: ghcr.io/gethomepage/homepage:latest
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.50'
|
|
||||||
memory: 256M
|
|
||||||
pids: 512
|
|
||||||
reservations:
|
|
||||||
cpus: '0.25'
|
|
||||||
memory: 128M
|
|
||||||
container_name: homepage
|
|
||||||
restart: unless-stopped # change to 'no' to enable Sablier lazy loading
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "3003:3000"
|
|
||||||
volumes:
|
|
||||||
- ./homepage:/app/config
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock # For Docker integration do not mount RO
|
|
||||||
- /opt/stacks:/opt/stacks # To discover other stacks
|
|
||||||
environment:
|
|
||||||
- PUID=995 # Must be set to the docker user ID
|
|
||||||
- PGID=995 # Must be set to the docker group ID
|
|
||||||
- TZ=${TZ}
|
|
||||||
- HOMEPAGE_ALLOWED_HOSTS=homepage.${DOMAIN}
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=dashboard"
|
|
||||||
- "homelab.description=Application dashboard"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# IMPORTANT: On REMOTE SERVERS (where Traefik runs elsewhere):
|
|
||||||
# - COMMENT OUT all traefik.* labels below (don't delete them)
|
|
||||||
# - Routes are configured via external YAML files on the core server
|
|
||||||
# - This prevents conflicts between Docker labels and file provider
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.homepage.rule=Host(`homepage.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.homepage.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.homepage.tls=true"
|
|
||||||
- "traefik.http.routers.homepage.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.homepage.loadbalancer.server.port=3003"
|
|
||||||
# Sablier lazy loading (disabled by default - uncomment to enable)
|
|
||||||
# - "sablier.enable=true"
|
|
||||||
# - "sablier.group=${SERVER_HOSTNAME}-homarr"
|
|
||||||
# - "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Homarr - Modern dashboard
|
|
||||||
# Uses Sablier lazy loading - starts on-demand, stops after 5min inactivity
|
|
||||||
|
|
||||||
homarr:
|
|
||||||
image: ghcr.io/ajnart/homarr:latest
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.50'
|
|
||||||
memory: 256M
|
|
||||||
pids: 512
|
|
||||||
reservations:
|
|
||||||
cpus: '0.25'
|
|
||||||
memory: 128M
|
|
||||||
container_name: homarr
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "7575:7575"
|
|
||||||
volumes:
|
|
||||||
- ./homarr/config:/app/config/configs
|
|
||||||
- ./homarr/data:/data
|
|
||||||
- ./homarr/icons:/app/public/icons
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
environment:
|
|
||||||
- TZ=${TZ}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:7575/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=dashboard"
|
|
||||||
- "homelab.description=Modern homelab dashboard"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.homarr.rule=Host(`homarr.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.homarr.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.homarr.tls=true"
|
|
||||||
- "traefik.http.routers.homarr.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.homarr.loadbalancer.server.port=7575"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-homarr"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# DOCKGE URL CONFIGURATION
|
|
||||||
x-dockge:
|
|
||||||
urls:
|
|
||||||
# Proxied URLs (through Traefik)
|
|
||||||
- https://homepage.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:3003
|
|
||||||
- https://homarr.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:7575
|
|
||||||
|
|
||||||
networks:
|
|
||||||
homelab-network:
|
|
||||||
external: true
|
|
||||||
traefik-network:
|
|
||||||
external: true
|
|
||||||
@@ -27,11 +27,11 @@ services:
|
|||||||
- '5001:5001' # Optional: direct access
|
- '5001:5001' # Optional: direct access
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- /opt/stacks:/opt/stacks # Dockge manages stacks in this directory
|
- ${STACKS_DIR}:${STACKS_DIR} # Dockge manages stacks in this directory
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
- /usr/bin/docker:/usr/bin/docker:ro # Mount docker binary for CLI access
|
- /usr/bin/docker:/usr/bin/docker:ro # Mount docker binary for CLI access
|
||||||
environment:
|
environment:
|
||||||
- DOCKGE_STACKS_DIR=/opt/stacks
|
- DOCKGE_STACKS_DIR=${STACKS_DIR}
|
||||||
- DOCKGE_ENABLE_CONSOLE=true
|
- DOCKGE_ENABLE_CONSOLE=true
|
||||||
labels:
|
labels:
|
||||||
- 'homelab.category=infrastructure'
|
- 'homelab.category=infrastructure'
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ services:
|
|||||||
- ./homeassistant/config:/config
|
- ./homeassistant/config:/config
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
environment:
|
environment:
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
privileged: true
|
privileged: true
|
||||||
labels:
|
labels:
|
||||||
- 'homelab.category=iot'
|
- 'homelab.category=iot'
|
||||||
@@ -56,7 +56,7 @@ services:
|
|||||||
- ./esphome/config:/config
|
- ./esphome/config:/config
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
environment:
|
environment:
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
- ESPHOME_DASHBOARD_USE_PING=true
|
- ESPHOME_DASHBOARD_USE_PING=true
|
||||||
privileged: true # For USB device access
|
privileged: true # For USB device access
|
||||||
labels:
|
labels:
|
||||||
@@ -87,9 +87,9 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- '8084:80'
|
- '8084:80'
|
||||||
volumes:
|
volumes:
|
||||||
- /opt/stacks/tasmoadmin/data:/data
|
- ./tasmoadmin/data:/data
|
||||||
environment:
|
environment:
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
labels:
|
labels:
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
# ==========================================
|
# ==========================================
|
||||||
@@ -118,10 +118,10 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- '8765:8765'
|
- '8765:8765'
|
||||||
volumes:
|
volumes:
|
||||||
- ./$(basename $file .yml)/config:/etc/motioneye
|
- ./motioneye/config:/etc/motioneye
|
||||||
- /mnt/surveillance:/var/lib/motioneye # Large video files on separate drive
|
- ./motioneye/video:/var/lib/motioneye
|
||||||
environment:
|
environment:
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
labels:
|
labels:
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
# ==========================================
|
# ==========================================
|
||||||
@@ -159,9 +159,9 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- '1880:1880'
|
- '1880:1880'
|
||||||
volumes:
|
volumes:
|
||||||
- /opt/stacks/nodered/data:/data
|
- ./nodered/data:/data
|
||||||
environment:
|
environment:
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
labels:
|
labels:
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
# ==========================================
|
# ==========================================
|
||||||
@@ -217,7 +217,7 @@ services:
|
|||||||
# # Common paths: /dev/ttyACM0, /dev/ttyUSB0, /dev/serial/by-id/...
|
# # Common paths: /dev/ttyACM0, /dev/ttyUSB0, /dev/serial/by-id/...
|
||||||
# # Run 'ls -l /dev/serial/by-id/' to find your adapter
|
# # Run 'ls -l /dev/serial/by-id/' to find your adapter
|
||||||
# environment:
|
# environment:
|
||||||
# - TZ=America/New_York
|
# - TZ=${TZ}
|
||||||
# labels:
|
# labels:
|
||||||
# - 'homelab.category=iot'
|
# - 'homelab.category=iot'
|
||||||
# - 'homelab.description=Zigbee to MQTT bridge'
|
# - 'homelab.description=Zigbee to MQTT bridge'
|
||||||
|
|||||||
@@ -1,258 +0,0 @@
|
|||||||
# Home Assistant and IoT Services
|
|
||||||
# Home automation platform and related tools
|
|
||||||
# Place in /opt/stacks/homeassistant/docker-compose.yml
|
|
||||||
|
|
||||||
# Service Access URLs:
|
|
||||||
# - Home Assistant: https://ha.${DOMAIN} (configure via Traefik file provider - uses host network)
|
|
||||||
# - ESPHome: https://esphome.${DOMAIN}
|
|
||||||
# - Node-RED: https://nodered.${DOMAIN}
|
|
||||||
# - Mosquitto MQTT: mqtt://server-ip:1883 (no web UI)
|
|
||||||
# - Zigbee2MQTT: https://zigbee2mqtt.${DOMAIN} (requires USB adapter)
|
|
||||||
|
|
||||||
services:
|
|
||||||
# Home Assistant - Home automation platform
|
|
||||||
# Access at: https://ha.${DOMAIN}
|
|
||||||
# NOTE: No Authelia - HA has its own authentication
|
|
||||||
homeassistant:
|
|
||||||
image: ghcr.io/home-assistant/home-assistant:2024.1
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '1.5'
|
|
||||||
memory: 1G
|
|
||||||
pids: 2048
|
|
||||||
reservations:
|
|
||||||
cpus: '0.75'
|
|
||||||
memory: 512M
|
|
||||||
container_name: homeassistant
|
|
||||||
restart: unless-stopped
|
|
||||||
network_mode: host # Required for device discovery
|
|
||||||
volumes:
|
|
||||||
- ./homeassistant/config:/config
|
|
||||||
- /etc/localtime:/etc/localtime:ro
|
|
||||||
environment:
|
|
||||||
- TZ=${TZ}
|
|
||||||
privileged: true
|
|
||||||
labels:
|
|
||||||
- "homelab.category=iot"
|
|
||||||
- "homelab.description=Home automation platform"
|
|
||||||
# Note: network_mode: host means Traefik can't proxy this directly
|
|
||||||
# Use Traefik's file provider or external host routing
|
|
||||||
|
|
||||||
# ESPHome - ESP8266/ESP32 firmware manager
|
|
||||||
# Access at: https://esphome.${DOMAIN}
|
|
||||||
esphome:
|
|
||||||
image: ghcr.io/esphome/esphome:latest
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.50'
|
|
||||||
memory: 256M
|
|
||||||
pids: 512
|
|
||||||
reservations:
|
|
||||||
cpus: '0.25'
|
|
||||||
memory: 128M
|
|
||||||
container_name: esphome
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "6052:6052"
|
|
||||||
volumes:
|
|
||||||
- ./esphome/config:/config
|
|
||||||
- /etc/localtime:/etc/localtime:ro
|
|
||||||
environment:
|
|
||||||
- TZ=${TZ}
|
|
||||||
- ESPHOME_DASHBOARD_USE_PING=true
|
|
||||||
privileged: true # For USB device access
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=iot"
|
|
||||||
- "homelab.description=ESP8266/ESP32 firmware manager"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.esphome.rule=Host(`esphome.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.esphome.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.esphome.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.esphome.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.esphome.loadbalancer.server.port=6052"
|
|
||||||
|
|
||||||
# TasmoAdmin - Tasmota device manager
|
|
||||||
# Access at: https://tasmoadmin.${DOMAIN}
|
|
||||||
tasmoadmin:
|
|
||||||
image: ghcr.io/tasmoadmin/tasmoadmin:latest
|
|
||||||
container_name: tasmoadmin
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8084:80"
|
|
||||||
volumes:
|
|
||||||
- /opt/stacks/tasmoadmin/data:/data
|
|
||||||
environment:
|
|
||||||
- TZ=${TZ}
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=iot"
|
|
||||||
- "homelab.description=Tasmota device management"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.tasmoadmin.rule=Host(`tasmoadmin.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.tasmoadmin.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.tasmoadmin.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.tasmoadmin.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.tasmoadmin.loadbalancer.server.port=80"
|
|
||||||
|
|
||||||
# MotionEye - Video surveillance
|
|
||||||
# Access at: https://motioneye.${DOMAIN}
|
|
||||||
motioneye:
|
|
||||||
image: ccrisan/motioneye:master-amd64
|
|
||||||
container_name: motioneye
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8765:8765" # Optional: direct access
|
|
||||||
volumes:
|
|
||||||
- ./$(basename $file .yml)/config:/etc/motioneye
|
|
||||||
- /mnt/surveillance:/var/lib/motioneye # Large video files on separate drive
|
|
||||||
environment:
|
|
||||||
- TZ=${TZ}
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=iot"
|
|
||||||
- "homelab.description=Video surveillance system"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.motioneye.rule=Host(`motioneye.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.motioneye.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.motioneye.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.motioneye.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.motioneye.loadbalancer.server.port=8765"
|
|
||||||
|
|
||||||
# Node-RED - Flow-based automation (Home Assistant addon alternative)
|
|
||||||
# Access at: https://nodered.${DOMAIN}
|
|
||||||
nodered:
|
|
||||||
image: nodered/node-red:latest
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.50'
|
|
||||||
memory: 256M
|
|
||||||
pids: 512
|
|
||||||
reservations:
|
|
||||||
cpus: '0.25'
|
|
||||||
memory: 128M
|
|
||||||
container_name: nodered
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "1880:1880"
|
|
||||||
volumes:
|
|
||||||
- /opt/stacks/nodered/data:/data
|
|
||||||
environment:
|
|
||||||
- TZ=${TZ}
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=iot"
|
|
||||||
- "homelab.description=Flow-based automation programming"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.nodered.rule=Host(`nodered.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.nodered.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.nodered.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.nodered.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.nodered.loadbalancer.server.port=1880"
|
|
||||||
|
|
||||||
# Mosquitto - MQTT broker (Home Assistant addon alternative)
|
|
||||||
# Used by: Home Assistant, ESPHome, Tasmota devices
|
|
||||||
mosquitto:
|
|
||||||
image: eclipse-mosquitto:latest
|
|
||||||
container_name: mosquitto
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
ports:
|
|
||||||
- "1883:1883" # MQTT
|
|
||||||
- "9001:9001" # Websockets
|
|
||||||
volumes:
|
|
||||||
- ./mosquitto/config:/mosquitto/config
|
|
||||||
- ./mosquitto/data:/mosquitto/data
|
|
||||||
- ./mosquitto/log:/mosquitto/log
|
|
||||||
labels:
|
|
||||||
- "homelab.category=iot"
|
|
||||||
- "homelab.description=MQTT message broker"
|
|
||||||
|
|
||||||
# Zigbee2MQTT - Zigbee to MQTT bridge (DISABLED - requires USB adapter)
|
|
||||||
# Access at: https://zigbee2mqtt.${DOMAIN}
|
|
||||||
# NOTE: Requires USB Zigbee adapter (e.g., ConBee II, Sonoff ZBDongle)
|
|
||||||
# Uncomment after connecting adapter
|
|
||||||
# zigbee2mqtt:
|
|
||||||
# image: koenkk/zigbee2mqtt:1.35.1
|
|
||||||
# container_name: zigbee2mqtt
|
|
||||||
# restart: unless-stopped
|
|
||||||
# networks:
|
|
||||||
# - homelab-network
|
|
||||||
# - traefik-network
|
|
||||||
# volumes:
|
|
||||||
# - ./zigbee2mqtt/data:/app/data
|
|
||||||
# - /run/udev:/run/udev:ro
|
|
||||||
# # Uncomment and adjust device path after connecting USB adapter:
|
|
||||||
# # devices:
|
|
||||||
# # - /dev/ttyACM0:/dev/ttyACM0 # Adjust based on your adapter
|
|
||||||
# # Common paths: /dev/ttyACM0, /dev/ttyUSB0, /dev/serial/by-id/...
|
|
||||||
# # Run 'ls -l /dev/serial/by-id/' to find your adapter
|
|
||||||
# environment:
|
|
||||||
# - TZ=${TZ}
|
|
||||||
# labels:
|
|
||||||
# - "homelab.category=iot"
|
|
||||||
# - "homelab.description=Zigbee to MQTT bridge"
|
|
||||||
# - "traefik.enable=true"
|
|
||||||
# - "traefik.http.routers.zigbee2mqtt.rule=Host(`zigbee2mqtt.${DOMAIN}`)"
|
|
||||||
# - "traefik.http.routers.zigbee2mqtt.entrypoints=websecure"
|
|
||||||
# - "traefik.http.routers.zigbee2mqtt.tls.certresolver=letsencrypt"
|
|
||||||
# - "traefik.http.routers.zigbee2mqtt.middlewares=authelia@docker"
|
|
||||||
# - "traefik.http.services.zigbee2mqtt.loadbalancer.server.port=8080"
|
|
||||||
|
|
||||||
networks:
|
|
||||||
homelab-network:
|
|
||||||
external: true
|
|
||||||
traefik-network:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
x-dockge:
|
|
||||||
urls:
|
|
||||||
# Proxied URLs (through Traefik)
|
|
||||||
- https://ha.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:8123
|
|
||||||
- https://esphome.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:6052
|
|
||||||
- https://tasmoadmin.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:8084
|
|
||||||
- https://motioneye.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:8765
|
|
||||||
- https://nodered.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:1880
|
|
||||||
- mqtt://${SERVER_IP}:1883
|
|
||||||
- https://zigbee2mqtt.${DOMAIN}
|
|
||||||
@@ -8,12 +8,6 @@
|
|||||||
services:
|
services:
|
||||||
dockerproxy:
|
dockerproxy:
|
||||||
# Docker socket proxy for security - provides safe Docker API access, must always run
|
# Docker socket proxy for security - provides safe Docker API access, must always run
|
||||||
# REQUIREMENTS FOR SABLIER INTEGRATION:
|
|
||||||
# 1. Docker daemon must be configured to listen on TCP port 2375 (not just unix socket)
|
|
||||||
# 2. Firewall must allow access to port 2375 from Sablier service
|
|
||||||
# 3. Docker daemon config should include: 'hosts': ['tcp://0.0.0.0:2375', 'unix:///var/run/docker.sock']
|
|
||||||
# 4. For security, consider restricting access to specific IP ranges or using TLS
|
|
||||||
# 5. dockerproxy runs for additional security but doesn't expose port 2375 (handled by Docker daemon)
|
|
||||||
image: tecnativa/docker-socket-proxy:latest
|
image: tecnativa/docker-socket-proxy:latest
|
||||||
container_name: dockerproxy
|
container_name: dockerproxy
|
||||||
privileged: true
|
privileged: true
|
||||||
@@ -36,7 +30,6 @@ services:
|
|||||||
- homelab.category=infrastructure
|
- homelab.category=infrastructure
|
||||||
- homelab.description=Docker socket proxy for security
|
- homelab.description=Docker socket proxy for security
|
||||||
|
|
||||||
|
|
||||||
# Watchtower - Automatic container updates
|
# Watchtower - Automatic container updates
|
||||||
watchtower:
|
watchtower:
|
||||||
image: containrrr/watchtower:latest
|
image: containrrr/watchtower:latest
|
||||||
@@ -171,12 +164,12 @@ services:
|
|||||||
- '8079:8443'
|
- '8079:8443'
|
||||||
volumes:
|
volumes:
|
||||||
- ./code-server/config:/config
|
- ./code-server/config:/config
|
||||||
- /opt/stacks:/opt/stacks # Access to all stacks
|
- ${STACKS_DIR}:${STACKS_DIR} # Access to all stacks
|
||||||
- /mnt:/mnt:ro # Read-only access to data
|
- /mnt:/mnt:ro # Read-only access to data
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=1000
|
||||||
- PGID=1000
|
- PGID=1000
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
- PASSWORD=${CODE_SERVER_PASSWORD}
|
- PASSWORD=${CODE_SERVER_PASSWORD}
|
||||||
- SUDO_PASSWORD=${CODE_SERVER_SUDO_PASSWORD}
|
- SUDO_PASSWORD=${CODE_SERVER_SUDO_PASSWORD}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
|||||||
@@ -1,294 +0,0 @@
|
|||||||
# Infrastructure Services
|
|
||||||
# Core services that other services depend on
|
|
||||||
# Place in /opt/stacks/infrastructure/docker-compose.yml
|
|
||||||
|
|
||||||
# SABLIER SESSION DURATION: Set to 5m for testing. Increase to 30m for production in config-templates/traefik/dynamic/sablier.yml
|
|
||||||
|
|
||||||
# RESTART POLICY GUIDE:
|
|
||||||
# - unless-stopped: Core infrastructure services that should always run
|
|
||||||
# - no: Services with Sablier lazy loading (start on-demand)
|
|
||||||
# - See individual service comments for specific reasoning
|
|
||||||
|
|
||||||
services:
|
|
||||||
dockerproxy:
|
|
||||||
# Docker socket proxy for security - provides safe Docker API access, must always run
|
|
||||||
# REQUIREMENTS FOR SABLIER INTEGRATION:
|
|
||||||
# 1. Docker daemon must be configured to listen on TCP port 2375 (not just unix socket)
|
|
||||||
# 2. Firewall must allow access to port 2375 from Sablier service
|
|
||||||
# 3. Docker daemon config should include: "hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
|
|
||||||
# 4. For security, consider restricting access to specific IP ranges or using TLS
|
|
||||||
# 5. dockerproxy runs for additional security but doesn't expose port 2375 (handled by Docker daemon)
|
|
||||||
image: tecnativa/docker-socket-proxy:latest
|
|
||||||
container_name: dockerproxy
|
|
||||||
privileged: true
|
|
||||||
restart: unless-stopped
|
|
||||||
# Note: Port 2375 is handled directly by Docker daemon for Sablier access
|
|
||||||
# dockerproxy provides additional security features but doesn't expose the port
|
|
||||||
volumes:
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
environment:
|
|
||||||
- CONTAINERS=1
|
|
||||||
- SERVICES=1
|
|
||||||
- TASKS=1
|
|
||||||
- NETWORKS=1
|
|
||||||
- NODES=1
|
|
||||||
- EXEC=1
|
|
||||||
- IMAGES=1
|
|
||||||
- VOLUMES=1
|
|
||||||
- SWARM=1
|
|
||||||
labels:
|
|
||||||
- homelab.category=infrastructure
|
|
||||||
- homelab.description=Docker socket proxy for security
|
|
||||||
|
|
||||||
# Pi-hole - Network-wide ad blocker and DNS server
|
|
||||||
# Access at: https://pihole.${DOMAIN}
|
|
||||||
# DNS service must always run for network-wide ad blocking
|
|
||||||
pihole:
|
|
||||||
image: pihole/pihole:2024.01.0
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.25'
|
|
||||||
memory: 128M
|
|
||||||
pids: 256
|
|
||||||
reservations:
|
|
||||||
cpus: '0.10'
|
|
||||||
memory: 64M
|
|
||||||
container_name: pihole
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "53:53/tcp" # DNS TCP
|
|
||||||
- "53:53/udp" # DNS UDP
|
|
||||||
volumes:
|
|
||||||
- ./pihole/etc-pihole:/etc/pihole
|
|
||||||
- ./pihole/etc-dnsmasq.d:/etc/dnsmasq.d
|
|
||||||
environment:
|
|
||||||
- TZ=${TZ}
|
|
||||||
- WEBPASSWORD=${PIHOLE_PASSWORD}
|
|
||||||
- FTLCONF_LOCAL_IPV4=${SERVER_IP}
|
|
||||||
dns:
|
|
||||||
- 127.0.0.1
|
|
||||||
- 1.1.1.1
|
|
||||||
cap_add:
|
|
||||||
- NET_ADMIN
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=infrastructure"
|
|
||||||
- "homelab.description=Network-wide ad blocking and DNS"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# IMPORTANT: On REMOTE SERVERS (where Traefik runs elsewhere):
|
|
||||||
# - COMMENT OUT all traefik.* labels below (don't delete them)
|
|
||||||
# - Routes are configured via external YAML files on the core server
|
|
||||||
# - This prevents conflicts between Docker labels and file provider
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.pihole.rule=Host(`pihole.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.pihole.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.pihole.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.pihole.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.pihole.loadbalancer.server.port=80"
|
|
||||||
|
|
||||||
# Watchtower - Automatic container updates
|
|
||||||
# Monitors and updates Docker containers to latest versions
|
|
||||||
# Runs daily at 4 AM
|
|
||||||
watchtower:
|
|
||||||
image: containrrr/watchtower:latest
|
|
||||||
container_name: watchtower
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
volumes:
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
environment:
|
|
||||||
- DOCKER_API_VERSION=1.52
|
|
||||||
- WATCHTOWER_CLEANUP=true
|
|
||||||
- WATCHTOWER_INCLUDE_RESTARTING=true
|
|
||||||
- WATCHTOWER_SCHEDULE=0 0 4 * * * # 4 AM daily
|
|
||||||
- WATCHTOWER_NOTIFICATIONS=shoutrrr
|
|
||||||
- WATCHTOWER_NOTIFICATION_URL=${WATCHTOWER_NOTIFICATION_URL}
|
|
||||||
labels:
|
|
||||||
- "homelab.category=infrastructure"
|
|
||||||
- "homelab.description=Automatic Docker container updates"
|
|
||||||
|
|
||||||
# Dozzle - Real-time Docker log viewer
|
|
||||||
# Access at: https://dozzle.${DOMAIN}
|
|
||||||
# Uses Sablier lazy loading - starts on-demand, stops after 5min inactivity
|
|
||||||
dozzle:
|
|
||||||
image: amir20/dozzle:latest
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.50'
|
|
||||||
memory: 256M
|
|
||||||
pids: 512
|
|
||||||
reservations:
|
|
||||||
cpus: '0.25'
|
|
||||||
memory: 128M
|
|
||||||
container_name: dozzle
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8085:8080"
|
|
||||||
volumes:
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
||||||
environment:
|
|
||||||
- DOZZLE_LEVEL=info
|
|
||||||
- DOZZLE_TAILSIZE=300
|
|
||||||
- DOZZLE_FILTER=status=running
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "/dozzle", "healthcheck"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 30s
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=infrastructure"
|
|
||||||
- "homelab.description=Real-time Docker log viewer"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.dozzle.rule=Host(`dozzle.${SERVER_HOSTNAME}.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.dozzle.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.dozzle.tls=true"
|
|
||||||
- "traefik.http.routers.dozzle.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.dozzle.loadbalancer.server.port=8085"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-dozzle"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Glances - System monitoring
|
|
||||||
# Access at: https://glances.${DOMAIN}
|
|
||||||
# Uses Sablier lazy loading - starts on-demand, stops after 30min inactivity
|
|
||||||
glances:
|
|
||||||
image: nicolargo/glances:latest-full
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.50'
|
|
||||||
memory: 256M
|
|
||||||
pids: 512
|
|
||||||
reservations:
|
|
||||||
cpus: '0.25'
|
|
||||||
memory: 128M
|
|
||||||
container_name: glances
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "61208:61208"
|
|
||||||
pid: host
|
|
||||||
volumes:
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
||||||
- ./glances/config:/glances/conf
|
|
||||||
environment:
|
|
||||||
- GLANCES_OPT=-w
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:61208/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 30s
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=infrastructure"
|
|
||||||
- "homelab.description=System and Docker monitoring"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.glances.rule=Host(`glances.${SERVER_HOSTNAME}.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.glances.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.glances.tls=true"
|
|
||||||
- "traefik.http.routers.glances.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.glances.loadbalancer.server.port=61208"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-glances"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Code Server - VS Code in browser
|
|
||||||
# Access at: https://code.${DOMAIN}
|
|
||||||
# Uses Sablier lazy loading - starts on-demand, stops after 30min inactivity
|
|
||||||
code-server:
|
|
||||||
image: lscr.io/linuxserver/code-server:latest
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '1.5'
|
|
||||||
memory: 1G
|
|
||||||
pids: 2048
|
|
||||||
reservations:
|
|
||||||
cpus: '0.75'
|
|
||||||
memory: 512M
|
|
||||||
container_name: code-server
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8079:8443"
|
|
||||||
volumes:
|
|
||||||
- ./code-server/config:/config
|
|
||||||
- /opt/stacks:/opt/stacks # Access to all stacks
|
|
||||||
- /mnt:/mnt:ro # Read-only access to data
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
- PASSWORD=${CODE_SERVER_PASSWORD}
|
|
||||||
- SUDO_PASSWORD=${CODE_SERVER_SUDO_PASSWORD}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8443/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=infrastructure"
|
|
||||||
- "homelab.description=VS Code in browser"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.code-server.rule=Host(`code.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.code-server.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.code-server.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.code-server.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.code-server.loadbalancer.server.port=8443"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-code-server"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
x-dockge:
|
|
||||||
urls:
|
|
||||||
- https://pihole.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:53
|
|
||||||
- https://dozzle.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:8085
|
|
||||||
- https://glances.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:61208
|
|
||||||
- https://code.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:8079
|
|
||||||
- http://${SERVER_IP}:2375 # Docker Proxy
|
|
||||||
- http://${SERVER_IP}:19999 # Netdata
|
|
||||||
|
|
||||||
networks:
|
|
||||||
homelab-network:
|
|
||||||
external: true
|
|
||||||
traefik-network:
|
|
||||||
external: true
|
|
||||||
@@ -17,12 +17,12 @@ services:
|
|||||||
- '8989:8989'
|
- '8989:8989'
|
||||||
volumes:
|
volumes:
|
||||||
- ./sonarr/config:/config
|
- ./sonarr/config:/config
|
||||||
- /mnt/media:/media
|
- ${MEDIA_DIR}:/media
|
||||||
- /mnt/downloads:/downloads # Large downloads on separate drive
|
- ${DOWNLOADS_DIR}:/downloads # Large downloads on separate drive
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PUID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ['CMD', 'curl', '-f', 'http://localhost:8989/']
|
test: ['CMD', 'curl', '-f', 'http://localhost:8989/']
|
||||||
interval: 30s
|
interval: 30s
|
||||||
@@ -62,12 +62,12 @@ services:
|
|||||||
- '7878:7878'
|
- '7878:7878'
|
||||||
volumes:
|
volumes:
|
||||||
- ./radarr/config:/config
|
- ./radarr/config:/config
|
||||||
- /mnt/media:/media
|
- ${MEDIA_DIR}:/media
|
||||||
- /mnt/downloads:/downloads # Large downloads on separate drive
|
- ${DOWNLOADS_DIR}:/downloads # Large downloads on separate drive
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PUID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ['CMD', 'curl', '-f', 'http://localhost:7878/']
|
test: ['CMD', 'curl', '-f', 'http://localhost:7878/']
|
||||||
interval: 30s
|
interval: 30s
|
||||||
@@ -109,9 +109,9 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./prowlarr/config:/config
|
- ./prowlarr/config:/config
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PUID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ['CMD', 'curl', '-f', 'http://localhost:9696/']
|
test: ['CMD', 'curl', '-f', 'http://localhost:9696/']
|
||||||
interval: 30s
|
interval: 30s
|
||||||
@@ -151,12 +151,12 @@ services:
|
|||||||
- '8787:8787'
|
- '8787:8787'
|
||||||
volumes:
|
volumes:
|
||||||
- ./readarr/config:/config
|
- ./readarr/config:/config
|
||||||
- /mnt/media/books:/books
|
- ${MEDIA_DIR}/books:/books
|
||||||
- /mnt/downloads:/downloads
|
- ${DOWNLOADS_DIR}:/downloads
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PUID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
labels:
|
labels:
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
# ==========================================
|
# ==========================================
|
||||||
@@ -190,12 +190,12 @@ services:
|
|||||||
- '8686:8686'
|
- '8686:8686'
|
||||||
volumes:
|
volumes:
|
||||||
- ./lidarr/config:/config
|
- ./lidarr/config:/config
|
||||||
- /mnt/media/music:/music
|
- ${MEDIA_DIR}/music:/music
|
||||||
- /mnt/downloads:/downloads
|
- ${DOWNLOADS_DIR}:/downloads
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PUID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
labels:
|
labels:
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
# ==========================================
|
# ==========================================
|
||||||
@@ -229,12 +229,12 @@ services:
|
|||||||
- '5299:5299'
|
- '5299:5299'
|
||||||
volumes:
|
volumes:
|
||||||
- ./lazylibrarian/config:/config
|
- ./lazylibrarian/config:/config
|
||||||
- /mnt/media/books:/books
|
- ${MEDIA_DIR}/books:/books
|
||||||
- /mnt/downloads:/downloads
|
- ${DOWNLOADS_DIR}:/downloads
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PUID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
- DOCKER_MODS=linuxserver/mods:lazylibrarian-ffmpeg
|
- DOCKER_MODS=linuxserver/mods:lazylibrarian-ffmpeg
|
||||||
labels:
|
labels:
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
@@ -269,12 +269,12 @@ services:
|
|||||||
- '8090:8090'
|
- '8090:8090'
|
||||||
volumes:
|
volumes:
|
||||||
- ./mylar3/config:/config
|
- ./mylar3/config:/config
|
||||||
- /mnt/media/comics:/comics
|
- ${MEDIA_DIR}/comics:/comics
|
||||||
- /mnt/downloads:/downloads
|
- ${DOWNLOADS_DIR}:/downloads
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PUID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
labels:
|
labels:
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
# ==========================================
|
# ==========================================
|
||||||
@@ -310,7 +310,7 @@ services:
|
|||||||
- ./jellyseerr/config:/app/config
|
- ./jellyseerr/config:/app/config
|
||||||
environment:
|
environment:
|
||||||
- LOG_LEVEL=info
|
- LOG_LEVEL=info
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ['CMD', 'wget', '--quiet', '--tries=1', '--spider', 'http://localhost:5055/']
|
test: ['CMD', 'wget', '--quiet', '--tries=1', '--spider', 'http://localhost:5055/']
|
||||||
interval: 30s
|
interval: 30s
|
||||||
@@ -348,7 +348,7 @@ services:
|
|||||||
- homelab-network
|
- homelab-network
|
||||||
environment:
|
environment:
|
||||||
- LOG_LEVEL=info
|
- LOG_LEVEL=info
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
labels:
|
labels:
|
||||||
- homelab.category=media
|
- homelab.category=media
|
||||||
- homelab.description=Cloudflare bypass for indexers
|
- homelab.description=Cloudflare bypass for indexers
|
||||||
|
|||||||
@@ -1,384 +0,0 @@
|
|||||||
# Media Management Services
|
|
||||||
# Content automation and library management (*arr apps, transcoders, etc.)
|
|
||||||
# Place in /opt/stacks/media-management/docker-compose.yml
|
|
||||||
|
|
||||||
# RESTART POLICY GUIDE:
|
|
||||||
# - unless-stopped: Core infrastructure services that should always run
|
|
||||||
# - no: Services with Sablier lazy loading (start on-demand)
|
|
||||||
# - See individual service comments for specific reasoning
|
|
||||||
|
|
||||||
services:
|
|
||||||
# Sonarr - TV show automation
|
|
||||||
# Access at: https://sonarr.yourdomain.duckdns.org
|
|
||||||
sonarr:
|
|
||||||
image: linuxserver/sonarr:4.0.0
|
|
||||||
container_name: sonarr
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8989:8989"
|
|
||||||
volumes:
|
|
||||||
- ./sonarr/config:/config
|
|
||||||
- /mnt/media:/media
|
|
||||||
- /mnt/downloads:/downloads # Large downloads on separate drive
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8989/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=media"
|
|
||||||
- "homelab.description=TV show management and automation"
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.sonarr.rule=Host(`sonarr.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.sonarr.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.sonarr.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.sonarr.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.sonarr.loadbalancer.server.port=8989"
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-arr"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Radarr - Movie automation
|
|
||||||
# Access at: https://radarr.yourdomain.duckdns.org
|
|
||||||
radarr:
|
|
||||||
image: linuxserver/radarr:5.2.6
|
|
||||||
container_name: radarr
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "7878:7878"
|
|
||||||
volumes:
|
|
||||||
- ./radarr/config:/config
|
|
||||||
- /mnt/media:/media
|
|
||||||
- /mnt/downloads:/downloads # Large downloads on separate drive
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:7878/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=media"
|
|
||||||
- "homelab.description=Movie management and automation"
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.radarr.rule=Host(`radarr.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.radarr.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.radarr.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.radarr.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.radarr.loadbalancer.server.port=7878"
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-arr"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Prowlarr - Indexer manager
|
|
||||||
# Access at: https://prowlarr.yourdomain.duckdns.org
|
|
||||||
prowlarr:
|
|
||||||
image: linuxserver/prowlarr:1.11.4
|
|
||||||
container_name: prowlarr
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "9696:9696"
|
|
||||||
volumes:
|
|
||||||
- ./prowlarr/config:/config
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:9696/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=media"
|
|
||||||
- "homelab.description=Indexer manager for Sonarr/Radarr"
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.prowlarr.rule=Host(`prowlarr.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.prowlarr.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.prowlarr.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.prowlarr.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.prowlarr.loadbalancer.server.port=9696"
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-arr"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Readarr - Ebook and audiobook management
|
|
||||||
# Access at: https://readarr.${DOMAIN}
|
|
||||||
readarr:
|
|
||||||
image: linuxserver/readarr:0.4.19-nightly
|
|
||||||
container_name: readarr
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8787:8787"
|
|
||||||
volumes:
|
|
||||||
- ./readarr/config:/config
|
|
||||||
- /mnt/media/books:/books
|
|
||||||
- /mnt/downloads:/downloads
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=media"
|
|
||||||
- "homelab.description=Ebook and audiobook management"
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.readarr.rule=Host(`readarr.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.readarr.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.readarr.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.readarr.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.readarr.loadbalancer.server.port=8787"
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-arr"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Lidarr - Music collection manager
|
|
||||||
# Access at: https://lidarr.${DOMAIN}
|
|
||||||
lidarr:
|
|
||||||
image: linuxserver/lidarr:2.0.7
|
|
||||||
container_name: lidarr
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8686:8686"
|
|
||||||
volumes:
|
|
||||||
- ./lidarr/config:/config
|
|
||||||
- /mnt/media/music:/music
|
|
||||||
- /mnt/downloads:/downloads
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=media"
|
|
||||||
- "homelab.description=Music collection manager"
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.lidarr.rule=Host(`lidarr.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.lidarr.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.lidarr.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.lidarr.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.lidarr.loadbalancer.server.port=8686"
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-arr"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Lazy Librarian - Book manager
|
|
||||||
# Access at: https://lazylibrarian.${DOMAIN}
|
|
||||||
lazylibrarian:
|
|
||||||
image: linuxserver/lazylibrarian:latest
|
|
||||||
container_name: lazylibrarian
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "5299:5299"
|
|
||||||
volumes:
|
|
||||||
- ./lazylibrarian/config:/config
|
|
||||||
- /mnt/media/books:/books
|
|
||||||
- /mnt/downloads:/downloads
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
- DOCKER_MODS=linuxserver/mods:lazylibrarian-ffmpeg
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=media"
|
|
||||||
- "homelab.description=Book download automation"
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.lazylibrarian.rule=Host(`lazylibrarian.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.lazylibrarian.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.lazylibrarian.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.lazylibrarian.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.lazylibrarian.loadbalancer.server.port=5299"
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-arr"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Mylar3 - Comic book manager
|
|
||||||
# Access at: https://mylar.${DOMAIN}
|
|
||||||
mylar3:
|
|
||||||
image: linuxserver/mylar3:latest
|
|
||||||
container_name: mylar3
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8090:8090"
|
|
||||||
volumes:
|
|
||||||
- ./mylar3/config:/config
|
|
||||||
- /mnt/media/comics:/comics
|
|
||||||
- /mnt/downloads:/downloads
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=media"
|
|
||||||
- "homelab.description=Comic book collection manager"
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.mylar.rule=Host(`mylar.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.mylar.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.mylar.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.mylar.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.mylar.loadbalancer.server.port=8090"
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-arr"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Jellyseerr - Request management for Jellyfin/Plex
|
|
||||||
# Access at: https://jellyseerr.${DOMAIN}
|
|
||||||
jellyseerr:
|
|
||||||
image: fallenbagel/jellyseerr:latest
|
|
||||||
container_name: jellyseerr
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "5055:5055"
|
|
||||||
volumes:
|
|
||||||
- ./jellyseerr/config:/app/config
|
|
||||||
environment:
|
|
||||||
- LOG_LEVEL=info
|
|
||||||
- TZ=${TZ}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:5055/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=media"
|
|
||||||
- "homelab.description=Media request management"
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.jellyseerr.rule=Host(`jellyseerr.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.jellyseerr.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.jellyseerr.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.jellyseerr.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.jellyseerr.loadbalancer.server.port=5055"
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-arr"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# FlareSolverr - Cloudflare bypass for Prowlarr
|
|
||||||
# No web UI - used by Prowlarr
|
|
||||||
flaresolverr:
|
|
||||||
image: flaresolverr/flaresolverr:latest
|
|
||||||
container_name: flaresolverr
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
environment:
|
|
||||||
- LOG_LEVEL=info
|
|
||||||
- TZ=${TZ}
|
|
||||||
labels:
|
|
||||||
- homelab.category=media
|
|
||||||
- homelab.description=Cloudflare bypass for indexers
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-arr"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
x-dockge:
|
|
||||||
urls:
|
|
||||||
- https://sonarr.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:8989
|
|
||||||
- https://radarr.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:7878
|
|
||||||
- https://prowlarr.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:9696
|
|
||||||
- https://readarr.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:8787
|
|
||||||
- https://lidarr.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:8686
|
|
||||||
- https://lazylibrarian.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:5299
|
|
||||||
- https://mylar.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:8090
|
|
||||||
- https://jellyseerr.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:5055
|
|
||||||
|
|
||||||
networks:
|
|
||||||
homelab-network:
|
|
||||||
external: true
|
|
||||||
traefik-network:
|
|
||||||
external: true
|
|
||||||
@@ -32,11 +32,11 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./jellyfin/config:/config
|
- ./jellyfin/config:/config
|
||||||
- ./jellyfin/cache:/cache
|
- ./jellyfin/cache:/cache
|
||||||
- /mnt/media:/media:ro # Large media files on separate drive
|
- ${MEDIA_DIR}:/media:ro # Large media files on separate drive
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PUID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ['CMD', 'curl', '-f', 'http://localhost:8096/']
|
test: ['CMD', 'curl', '-f', 'http://localhost:8096/']
|
||||||
interval: 30s
|
interval: 30s
|
||||||
@@ -88,11 +88,11 @@ services:
|
|||||||
- '8083:8083'
|
- '8083:8083'
|
||||||
volumes:
|
volumes:
|
||||||
- ./calibre-web/config:/config
|
- ./calibre-web/config:/config
|
||||||
- /mnt/media/books:/books
|
- ${MEDIA_DIR}/books:/books
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PUID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
- DOCKER_MODS=linuxserver/mods:universal-calibre
|
- DOCKER_MODS=linuxserver/mods:universal-calibre
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
labels:
|
labels:
|
||||||
|
|||||||
@@ -1,139 +0,0 @@
|
|||||||
# Media Services
|
|
||||||
# Default Services for media management and streaming
|
|
||||||
# Place in /opt/stacks/media/docker-compose.yml
|
|
||||||
|
|
||||||
# SABLIER SESSION DURATION: Set to 5m for testing. Increase to 30m for production in config-templates/traefik/dynamic/sablier.yml
|
|
||||||
|
|
||||||
# RESTART POLICY GUIDE:
|
|
||||||
# - unless-stopped: Core infrastructure services that should always run
|
|
||||||
# - no: Services with Sablier lazy loading (start on-demand)
|
|
||||||
# - See individual service comments for specific reasoning
|
|
||||||
|
|
||||||
# Service Access URLs:
|
|
||||||
# - Jellyfin: https://jellyfin.${DOMAIN} (no SSO - app access)
|
|
||||||
# - Plex: https://plex.${DOMAIN} (no SSO - app access)
|
|
||||||
# - qBittorrent: https://qbit.${DOMAIN} (routed through Gluetun VPN)
|
|
||||||
|
|
||||||
services:
|
|
||||||
# Jellyfin - Open-source media streaming server
|
|
||||||
# Access at: https://jellyfin.yourdomain.duckdns.org
|
|
||||||
# NOTE: No Authelia - allows app access from Roku, Fire TV, mobile, etc.
|
|
||||||
# Uses Sablier lazy loading - starts on-demand, stops after 5min inactivity
|
|
||||||
jellyfin:
|
|
||||||
image: jellyfin/jellyfin:10.8.13
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '2.0'
|
|
||||||
memory: 2G
|
|
||||||
pids: 2048
|
|
||||||
reservations:
|
|
||||||
cpus: '1.0'
|
|
||||||
memory: 1G
|
|
||||||
container_name: jellyfin
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8096:8096"
|
|
||||||
volumes:
|
|
||||||
- ./jellyfin/config:/config
|
|
||||||
- ./jellyfin/cache:/cache
|
|
||||||
- /mnt/media:/media:ro # Large media files on separate drive
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8096/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 30s
|
|
||||||
# Uncomment for hardware transcoding
|
|
||||||
# devices:
|
|
||||||
# - /dev/dri:/dev/dri
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
labels:
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=media"
|
|
||||||
- "homelab.description=Open-source media streaming server"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.jellyfin.rule=Host(`jellyfin.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.jellyfin.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.jellyfin.tls=true"
|
|
||||||
- "traefik.http.routers.jellyfin.tls.certresolver=letsencrypt"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.jellyfin.loadbalancer.server.port=8096"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-jellyfin"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
- "sablier.theme=hacker-terminal"
|
|
||||||
|
|
||||||
# Calibre-Web - Ebook reader and server
|
|
||||||
# Access at: https://calibre.${DOMAIN}
|
|
||||||
calibre-web:
|
|
||||||
image: lscr.io/linuxserver/calibre-web:latest
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.50'
|
|
||||||
memory: 256M
|
|
||||||
pids: 512
|
|
||||||
reservations:
|
|
||||||
cpus: '0.25'
|
|
||||||
memory: 128M
|
|
||||||
container_name: calibre-web
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8083:8083"
|
|
||||||
volumes:
|
|
||||||
- ./calibre-web/config:/config
|
|
||||||
- /mnt/media/books:/books
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
- DOCKER_MODS=linuxserver/mods:universal-calibre
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
labels:
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=media"
|
|
||||||
- "homelab.description=Ebook reader and library management"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.calibre.rule=Host(`calibre.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.calibre.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.calibre.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.calibre.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.calibre.loadbalancer.server.port=8083"
|
|
||||||
# Sablier configuration (disabled by default)
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-calibre-web"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# ==========================================
|
|
||||||
# DOCKGE URL CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
x-dockge:
|
|
||||||
urls:
|
|
||||||
# Proxied URLs (through Traefik)
|
|
||||||
- https://jellyfin.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:8096
|
|
||||||
- https://calibre.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:8083
|
|
||||||
|
|
||||||
networks:
|
|
||||||
homelab-network:
|
|
||||||
external: true
|
|
||||||
traefik-network:
|
|
||||||
external: true
|
|
||||||
@@ -25,8 +25,8 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- '9090:9090'
|
- '9090:9090'
|
||||||
volumes:
|
volumes:
|
||||||
- ./config/prometheus:/etc/prometheus
|
- ./prometheus/config:/etc/prometheus
|
||||||
- prometheus-data:/prometheus
|
- ./prometheus/data:/prometheus
|
||||||
command:
|
command:
|
||||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||||
- '--storage.tsdb.path=/prometheus'
|
- '--storage.tsdb.path=/prometheus'
|
||||||
@@ -73,14 +73,14 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- '3000:3000'
|
- '3000:3000'
|
||||||
volumes:
|
volumes:
|
||||||
- grafana-data:/var/lib/grafana
|
- ./grafana/data:/var/lib/grafana
|
||||||
- ./config/grafana/provisioning:/etc/grafana/provisioning
|
- ./grafana/provisioning:/etc/grafana/provisioning
|
||||||
environment:
|
environment:
|
||||||
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
|
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
|
||||||
- GF_USERS_ALLOW_SIGN_UP=false
|
- GF_USERS_ALLOW_SIGN_UP=false
|
||||||
- GF_SERVER_ROOT_URL=https://grafana.${DOMAIN}
|
- GF_SERVER_ROOT_URL=https://grafana.${DOMAIN}
|
||||||
- GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource,grafana-piechart-panel
|
- GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource,grafana-piechart-panel
|
||||||
user: '1000:1000'
|
user: '${PUID}:${PGID}'
|
||||||
depends_on:
|
depends_on:
|
||||||
- prometheus
|
- prometheus
|
||||||
labels:
|
labels:
|
||||||
@@ -112,8 +112,8 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- '9100:9100'
|
- '9100:9100'
|
||||||
volumes:
|
volumes:
|
||||||
- /proc:/host/proc:ro
|
- ./node-exporter/proc:/host/proc:ro
|
||||||
- /sys:/host/sys:ro
|
- ./node-exporter/sys:/host/sys:ro
|
||||||
- /:/rootfs:ro
|
- /:/rootfs:ro
|
||||||
command:
|
command:
|
||||||
- '--path.procfs=/host/proc'
|
- '--path.procfs=/host/proc'
|
||||||
@@ -182,7 +182,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- '3001:3001'
|
- '3001:3001'
|
||||||
volumes:
|
volumes:
|
||||||
- uptime-kuma-data:/app/data
|
- ./uptime-kuma:/app/data
|
||||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
labels:
|
labels:
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
@@ -219,12 +219,11 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- homelab-network
|
- homelab-network
|
||||||
- traefik-network
|
|
||||||
ports:
|
ports:
|
||||||
- '3100:3100'
|
- '3100:3100'
|
||||||
volumes:
|
volumes:
|
||||||
- ./config/loki:/etc/loki
|
- ./loki/config:/etc/loki
|
||||||
- loki-data:/loki
|
- ./loki/data:/loki
|
||||||
command: -config.file=/etc/loki/loki-config.yml
|
command: -config.file=/etc/loki/loki-config.yml
|
||||||
labels:
|
labels:
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
@@ -253,7 +252,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- homelab-network
|
- homelab-network
|
||||||
volumes:
|
volumes:
|
||||||
- ./config/promtail:/etc/promtail
|
- ./promtail/config:/etc/promtail
|
||||||
- /var/log:/var/log:ro
|
- /var/log:/var/log:ro
|
||||||
- /var/lib/docker/containers:/var/lib/docker/containers:ro
|
- /var/lib/docker/containers:/var/lib/docker/containers:ro
|
||||||
command: -config.file=/etc/promtail/promtail-config.yml
|
command: -config.file=/etc/promtail/promtail-config.yml
|
||||||
@@ -263,16 +262,6 @@ services:
|
|||||||
- 'homelab.category=monitoring'
|
- 'homelab.category=monitoring'
|
||||||
- 'homelab.description=Log collector for Loki'
|
- 'homelab.description=Log collector for Loki'
|
||||||
|
|
||||||
volumes:
|
|
||||||
prometheus-data:
|
|
||||||
driver: local
|
|
||||||
grafana-data:
|
|
||||||
driver: local
|
|
||||||
uptime-kuma-data:
|
|
||||||
driver: local
|
|
||||||
loki-data:
|
|
||||||
driver: local
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
homelab-network:
|
homelab-network:
|
||||||
external: true
|
external: true
|
||||||
|
|||||||
@@ -1,301 +0,0 @@
|
|||||||
# Monitoring and Observability Services
|
|
||||||
# Services for monitoring your homelab infrastructure
|
|
||||||
# Place in /opt/stacks/monitoring/docker-compose.yml
|
|
||||||
|
|
||||||
# RESTART POLICY GUIDE:
|
|
||||||
# - unless-stopped: Core infrastructure services that should always run
|
|
||||||
# - no: Services with Sablier lazy loading (start on-demand)
|
|
||||||
# - See individual service comments for specific reasoning
|
|
||||||
|
|
||||||
# Service Access URLs:
|
|
||||||
# - Prometheus: http://${SERVER_IP}:9090 (or configure Traefik)
|
|
||||||
# - Grafana: http://${SERVER_IP}:3000 (or configure Traefik)
|
|
||||||
# - Uptime Kuma: https://status.${DOMAIN}
|
|
||||||
# - Node Exporter: http://${SERVER_IP}:9100/metrics
|
|
||||||
# - cAdvisor: http://${SERVER_IP}:8082
|
|
||||||
# - Loki: http://${SERVER_IP}:3100
|
|
||||||
# NOTE: Prometheus, Grafana, Loki use ports because they need to be accessible to other services
|
|
||||||
# Add Traefik labels if you want https://prometheus.${DOMAIN} access
|
|
||||||
|
|
||||||
services:
|
|
||||||
# Prometheus - Metrics collection and storage
|
|
||||||
# Access at: http://${SERVER_IP}:9090
|
|
||||||
prometheus:
|
|
||||||
image: prom/prometheus:v2.48.1
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.75'
|
|
||||||
memory: 512M
|
|
||||||
pids: 1024
|
|
||||||
reservations:
|
|
||||||
cpus: '0.25'
|
|
||||||
memory: 256M
|
|
||||||
container_name: prometheus
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "9090:9090"
|
|
||||||
volumes:
|
|
||||||
- ./config/prometheus:/etc/prometheus
|
|
||||||
- prometheus-data:/prometheus
|
|
||||||
command:
|
|
||||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
|
||||||
- '--storage.tsdb.path=/prometheus'
|
|
||||||
- '--storage.tsdb.retention.time=30d'
|
|
||||||
- '--web.console.libraries=/etc/prometheus/console_libraries'
|
|
||||||
- '--web.console.templates=/etc/prometheus/consoles'
|
|
||||||
- '--web.enable-lifecycle'
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=monitoring"
|
|
||||||
- "homelab.description=Metrics collection and time-series database"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.prometheus.rule=Host(`prometheus.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.prometheus.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.prometheus.tls=true"
|
|
||||||
- "traefik.http.routers.prometheus.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.prometheus.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.prometheus.loadbalancer.server.port=9090"
|
|
||||||
|
|
||||||
# Grafana - Metrics visualization
|
|
||||||
# Access at: http://${SERVER_IP}:3000
|
|
||||||
# Default credentials: admin / admin (change on first login)
|
|
||||||
grafana:
|
|
||||||
image: grafana/grafana:10.2.3
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.50'
|
|
||||||
memory: 256M
|
|
||||||
pids: 512
|
|
||||||
reservations:
|
|
||||||
cpus: '0.25'
|
|
||||||
memory: 128M
|
|
||||||
container_name: grafana
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
volumes:
|
|
||||||
- grafana-data:/var/lib/grafana
|
|
||||||
- ./config/grafana/provisioning:/etc/grafana/provisioning
|
|
||||||
environment:
|
|
||||||
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
|
|
||||||
- GF_USERS_ALLOW_SIGN_UP=false
|
|
||||||
- GF_SERVER_ROOT_URL=https://grafana.${DOMAIN}
|
|
||||||
- GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource,grafana-piechart-panel
|
|
||||||
user: "${PUID}:${PGID}"
|
|
||||||
depends_on:
|
|
||||||
- prometheus
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=monitoring"
|
|
||||||
- "homelab.description=Metrics visualization and dashboards"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.grafana.rule=Host(`grafana.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.grafana.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.grafana.tls=true"
|
|
||||||
- "traefik.http.routers.grafana.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.grafana.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.grafana.loadbalancer.server.port=3000"
|
|
||||||
|
|
||||||
# Node Exporter - Host metrics exporter
|
|
||||||
# Metrics at: http://${SERVER_IP}:9100/metrics
|
|
||||||
node-exporter:
|
|
||||||
image: prom/node-exporter:v1.7.0
|
|
||||||
container_name: node-exporter
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
ports:
|
|
||||||
- "9100:9100"
|
|
||||||
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)($$|/)'
|
|
||||||
labels:
|
|
||||||
- "homelab.category=monitoring"
|
|
||||||
- "homelab.description=Hardware and OS metrics exporter"
|
|
||||||
|
|
||||||
# cAdvisor - Container metrics exporter
|
|
||||||
# Access at: http://${SERVER_IP}:8082
|
|
||||||
cadvisor:
|
|
||||||
image: gcr.io/cadvisor/cadvisor:v0.47.2
|
|
||||||
container_name: cadvisor
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8082:8080"
|
|
||||||
volumes:
|
|
||||||
- /:/rootfs:ro
|
|
||||||
- /var/run:/var/run:ro
|
|
||||||
- /sys:/sys:ro
|
|
||||||
- /var/lib/docker:/var/lib/docker:ro
|
|
||||||
- /dev/disk:/dev/disk:ro
|
|
||||||
privileged: true
|
|
||||||
devices:
|
|
||||||
- /dev/kmsg
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=monitoring"
|
|
||||||
- "homelab.description=Container metrics and performance monitoring"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.cadvisor.rule=Host(`cadvisor.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.cadvisor.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.cadvisor.tls=true"
|
|
||||||
- "traefik.http.routers.cadvisor.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.cadvisor.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.cadvisor.loadbalancer.server.port=8080"
|
|
||||||
|
|
||||||
# Uptime Kuma - Uptime monitoring
|
|
||||||
# Access at: https://uptime-kuma.${DOMAIN}
|
|
||||||
uptime-kuma:
|
|
||||||
image: louislam/uptime-kuma:1
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.50'
|
|
||||||
memory: 256M
|
|
||||||
pids: 512
|
|
||||||
reservations:
|
|
||||||
cpus: '0.25'
|
|
||||||
memory: 128M
|
|
||||||
container_name: uptime-kuma
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "3001:3001"
|
|
||||||
volumes:
|
|
||||||
- uptime-kuma-data:/app/data
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=monitoring"
|
|
||||||
- "homelab.description=Service uptime monitoring and alerts"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.uptime-kuma.rule=Host(`uptime-kuma.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.uptime-kuma.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.uptime-kuma.tls=true"
|
|
||||||
- "traefik.http.routers.uptime-kuma.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.uptime-kuma.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.uptime-kuma.loadbalancer.server.port=3001"
|
|
||||||
|
|
||||||
# Loki - Log aggregation
|
|
||||||
# Access at: http://${SERVER_IP}:3100
|
|
||||||
loki:
|
|
||||||
image: grafana/loki:2.9.3
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.75'
|
|
||||||
memory: 512M
|
|
||||||
pids: 1024
|
|
||||||
reservations:
|
|
||||||
cpus: '0.25'
|
|
||||||
memory: 256M
|
|
||||||
container_name: loki
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "3100:3100"
|
|
||||||
volumes:
|
|
||||||
- ./config/loki:/etc/loki
|
|
||||||
- loki-data:/loki
|
|
||||||
command: -config.file=/etc/loki/loki-config.yml
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=monitoring"
|
|
||||||
- "homelab.description=Log aggregation system"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.loki.rule=Host(`loki.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.loki.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.loki.tls=true"
|
|
||||||
- "traefik.http.routers.loki.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.loki.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.loki.loadbalancer.server.port=3100"
|
|
||||||
|
|
||||||
# Promtail - Log shipper for Loki
|
|
||||||
# Ships Docker container logs to Loki
|
|
||||||
promtail:
|
|
||||||
image: grafana/promtail:2.9.3
|
|
||||||
container_name: promtail
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
volumes:
|
|
||||||
- ./config/promtail:/etc/promtail
|
|
||||||
- /var/log:/var/log:ro
|
|
||||||
- /var/lib/docker/containers:/var/lib/docker/containers:ro
|
|
||||||
command: -config.file=/etc/promtail/promtail-config.yml
|
|
||||||
depends_on:
|
|
||||||
- loki
|
|
||||||
labels:
|
|
||||||
- "homelab.category=monitoring"
|
|
||||||
- "homelab.description=Log collector for Loki"
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
prometheus-data:
|
|
||||||
driver: local
|
|
||||||
grafana-data:
|
|
||||||
driver: local
|
|
||||||
uptime-kuma-data:
|
|
||||||
driver: local
|
|
||||||
loki-data:
|
|
||||||
driver: local
|
|
||||||
|
|
||||||
networks:
|
|
||||||
homelab-network:
|
|
||||||
external: true
|
|
||||||
traefik-network:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
x-dockge:
|
|
||||||
urls:
|
|
||||||
# Proxied URLs (through Traefik)
|
|
||||||
- http://${SERVER_IP}:9090
|
|
||||||
- http://${SERVER_IP}:3000
|
|
||||||
- https://uptime-kuma.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:9100/metrics
|
|
||||||
- http://${SERVER_IP}:8082
|
|
||||||
- http://${SERVER_IP}:3100
|
|
||||||
@@ -28,7 +28,7 @@ services:
|
|||||||
- '8089:80'
|
- '8089:80'
|
||||||
volumes:
|
volumes:
|
||||||
- ./nextcloud/html:/var/www/html
|
- ./nextcloud/html:/var/www/html
|
||||||
- /mnt/nextcloud-data:/var/www/html/data # Large data on separate drive
|
- ${NEXTCLOUD_DIR}:/var/www/html/data
|
||||||
environment:
|
environment:
|
||||||
- MYSQL_HOST=nextcloud-db
|
- MYSQL_HOST=nextcloud-db
|
||||||
- MYSQL_DATABASE=nextcloud
|
- MYSQL_DATABASE=nextcloud
|
||||||
@@ -75,7 +75,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- homelab-network
|
- homelab-network
|
||||||
volumes:
|
volumes:
|
||||||
- nextcloud-db-data:/var/lib/mysql
|
- ./nextcloud/db:/var/lib/mysql
|
||||||
environment:
|
environment:
|
||||||
- MYSQL_ROOT_PASSWORD=${NEXTCLOUD_DB_ROOT_PASSWORD}
|
- MYSQL_ROOT_PASSWORD=${NEXTCLOUD_DB_ROOT_PASSWORD}
|
||||||
- MYSQL_DATABASE=nextcloud
|
- MYSQL_DATABASE=nextcloud
|
||||||
@@ -99,9 +99,9 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./mealie/data:/app/data
|
- ./mealie/data:/app/data
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PGID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
- BASE_URL=https://mealie.${DOMAIN}
|
- BASE_URL=https://mealie.${DOMAIN}
|
||||||
- DB_ENGINE=sqlite
|
- DB_ENGINE=sqlite
|
||||||
labels:
|
labels:
|
||||||
@@ -176,7 +176,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- homelab-network
|
- homelab-network
|
||||||
volumes:
|
volumes:
|
||||||
- wordpress-db-data:/var/lib/mysql
|
- ./wordpress/db:/var/lib/mysql
|
||||||
environment:
|
environment:
|
||||||
- MYSQL_ROOT_PASSWORD=${WORDPRESS_DB_ROOT_PASSWORD}
|
- MYSQL_ROOT_PASSWORD=${WORDPRESS_DB_ROOT_PASSWORD}
|
||||||
- MYSQL_DATABASE=wordpress
|
- MYSQL_DATABASE=wordpress
|
||||||
@@ -210,8 +210,8 @@ services:
|
|||||||
- /etc/timezone:/etc/timezone:ro
|
- /etc/timezone:/etc/timezone:ro
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
environment:
|
environment:
|
||||||
- USER_UID=1000
|
- USER_UID=${PUID}
|
||||||
- USER_GID=1000
|
- USER_GID=${PGID}
|
||||||
- GITEA__database__DB_TYPE=postgres
|
- GITEA__database__DB_TYPE=postgres
|
||||||
- GITEA__database__HOST=gitea-db:5432
|
- GITEA__database__HOST=gitea-db:5432
|
||||||
- GITEA__database__NAME=gitea
|
- GITEA__database__NAME=gitea
|
||||||
@@ -252,7 +252,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- homelab-network
|
- homelab-network
|
||||||
volumes:
|
volumes:
|
||||||
- gitea-db-data:/var/lib/postgresql/data
|
- ./gitea/db:/var/lib/postgresql/data
|
||||||
environment:
|
environment:
|
||||||
- POSTGRES_USER=gitea
|
- POSTGRES_USER=gitea
|
||||||
- POSTGRES_PASSWORD=${GITEA_DB_PASSWORD}
|
- POSTGRES_PASSWORD=${GITEA_DB_PASSWORD}
|
||||||
@@ -309,11 +309,6 @@ services:
|
|||||||
- 'sablier.group=jasper-jupyter'
|
- 'sablier.group=jasper-jupyter'
|
||||||
- 'sablier.start-on-demand=true'
|
- 'sablier.start-on-demand=true'
|
||||||
|
|
||||||
volumes:
|
|
||||||
nextcloud-db-data:
|
|
||||||
wordpress-db-data:
|
|
||||||
gitea-db-data:
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
homelab-network:
|
homelab-network:
|
||||||
external: true
|
external: true
|
||||||
|
|||||||
@@ -1,338 +0,0 @@
|
|||||||
# Productivity and Content Management Services
|
|
||||||
# Place in /opt/stacks/productivity/docker-compose.yml
|
|
||||||
|
|
||||||
# SABLIER SESSION DURATION: Set to 5m for testing. Increase to 30m for production in config-templates/traefik/dynamic/sablier.yml
|
|
||||||
|
|
||||||
# RESTART POLICY GUIDE:
|
|
||||||
# - unless-stopped: Core infrastructure services that should always run
|
|
||||||
# - no: Services with Sablier lazy loading (start on-demand)
|
|
||||||
# - See individual service comments for specific reasoning
|
|
||||||
|
|
||||||
services:
|
|
||||||
# Nextcloud - File sync and collaboration
|
|
||||||
# Access at: https://nextcloud.${DOMAIN}
|
|
||||||
# Uses Sablier lazy loading - starts on-demand, stops after 5min inactivity
|
|
||||||
nextcloud:
|
|
||||||
image: nextcloud:28
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '1.5'
|
|
||||||
memory: 1G
|
|
||||||
pids: 2048
|
|
||||||
reservations:
|
|
||||||
cpus: '0.75'
|
|
||||||
memory: 512M
|
|
||||||
container_name: nextcloud
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8089:80"
|
|
||||||
volumes:
|
|
||||||
- ./nextcloud/html:/var/www/html
|
|
||||||
- /mnt/nextcloud-data:/var/www/html/data # Large data on separate drive
|
|
||||||
environment:
|
|
||||||
- MYSQL_HOST=nextcloud-db
|
|
||||||
- MYSQL_DATABASE=nextcloud
|
|
||||||
- MYSQL_USER=nextcloud
|
|
||||||
- MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD}
|
|
||||||
- NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER}
|
|
||||||
- NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD}
|
|
||||||
- NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.${DOMAIN}
|
|
||||||
- TRUSTED_PROXIES=172.18.0.0/16
|
|
||||||
- OVERWRITEPROTOCOL=https
|
|
||||||
- OVERWRITEHOST=nextcloud.${DOMAIN}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost/status.php"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
depends_on:
|
|
||||||
- nextcloud-db
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=productivity"
|
|
||||||
- "homelab.description=File sync and collaboration"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.nextcloud.rule=Host(`nextcloud.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.nextcloud.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.nextcloud.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.nextcloud.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.nextcloud.loadbalancer.server.port=8089"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-nextcloud"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
nextcloud-db:
|
|
||||||
image: mariadb:10.11
|
|
||||||
container_name: nextcloud-db
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
volumes:
|
|
||||||
- nextcloud-db-data:/var/lib/mysql
|
|
||||||
environment:
|
|
||||||
- MYSQL_ROOT_PASSWORD=${NEXTCLOUD_DB_ROOT_PASSWORD}
|
|
||||||
- MYSQL_DATABASE=nextcloud
|
|
||||||
- MYSQL_USER=nextcloud
|
|
||||||
- MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD}
|
|
||||||
command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
|
|
||||||
labels:
|
|
||||||
- "homelab.category=productivity"
|
|
||||||
- "homelab.description=Nextcloud database"
|
|
||||||
|
|
||||||
# Mealie - Recipe manager
|
|
||||||
# Access at: https://mealie.${DOMAIN}
|
|
||||||
mealie:
|
|
||||||
image: ghcr.io/mealie-recipes/mealie:latest
|
|
||||||
container_name: mealie
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "9000:9000"
|
|
||||||
volumes:
|
|
||||||
- ./mealie/data:/app/data
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
- BASE_URL=https://mealie.${DOMAIN}
|
|
||||||
- DB_ENGINE=sqlite
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=productivity"
|
|
||||||
- "homelab.description=Recipe manager and meal planner"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.mealie.rule=Host(`mealie.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.mealie.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.mealie.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.mealie.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.mealie.loadbalancer.server.port=9000"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-mealie"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# WordPress - Blog/website platform
|
|
||||||
# Access at: https://blog.${DOMAIN}
|
|
||||||
wordpress:
|
|
||||||
image: wordpress:latest
|
|
||||||
container_name: wordpress
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8088:80"
|
|
||||||
volumes:
|
|
||||||
- ./wordpress/html:/var/www/html
|
|
||||||
environment:
|
|
||||||
- WORDPRESS_DB_HOST=wordpress-db
|
|
||||||
- WORDPRESS_DB_USER=wordpress
|
|
||||||
- WORDPRESS_DB_PASSWORD=${WORDPRESS_DB_PASSWORD}
|
|
||||||
- WORDPRESS_DB_NAME=wordpress
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
depends_on:
|
|
||||||
- wordpress-db
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=productivity"
|
|
||||||
- "homelab.description=Blog and website platform"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.wordpress.rule=Host(`wordpress.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.wordpress.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.wordpress.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.wordpress.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.wordpress.loadbalancer.server.port=8088"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-wordpress"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
wordpress-db:
|
|
||||||
image: mariadb:10.11
|
|
||||||
container_name: wordpress-db
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
volumes:
|
|
||||||
- wordpress-db-data:/var/lib/mysql
|
|
||||||
environment:
|
|
||||||
- MYSQL_ROOT_PASSWORD=${WORDPRESS_DB_ROOT_PASSWORD}
|
|
||||||
- MYSQL_DATABASE=wordpress
|
|
||||||
- MYSQL_USER=wordpress
|
|
||||||
- MYSQL_PASSWORD=${WORDPRESS_DB_PASSWORD}
|
|
||||||
labels:
|
|
||||||
- "homelab.category=productivity"
|
|
||||||
- "homelab.description=WordPress database"
|
|
||||||
|
|
||||||
# Gitea - Self-hosted Git service
|
|
||||||
# Access at: https://git.${DOMAIN}
|
|
||||||
gitea:
|
|
||||||
image: gitea/gitea:latest
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '0.50'
|
|
||||||
memory: 256M
|
|
||||||
pids: 512
|
|
||||||
reservations:
|
|
||||||
cpus: '0.25'
|
|
||||||
memory: 128M
|
|
||||||
container_name: gitea
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "3010:3000"
|
|
||||||
volumes:
|
|
||||||
- ./gitea/data:/data
|
|
||||||
- /etc/timezone:/etc/timezone:ro
|
|
||||||
- /etc/localtime:/etc/localtime:ro
|
|
||||||
environment:
|
|
||||||
- USER_UID=${PUID}
|
|
||||||
- USER_GID=${PGID}
|
|
||||||
- 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}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:3000/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
depends_on:
|
|
||||||
- gitea-db
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=productivity"
|
|
||||||
- "homelab.description=Self-hosted Git service"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.gitea.rule=Host(`gitea.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.gitea.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.gitea.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.gitea.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.gitea.loadbalancer.server.port=3010"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-gitea"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
gitea-db:
|
|
||||||
image: postgres:14-alpine
|
|
||||||
container_name: gitea-db
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
volumes:
|
|
||||||
- gitea-db-data:/var/lib/postgresql/data
|
|
||||||
environment:
|
|
||||||
- POSTGRES_USER=gitea
|
|
||||||
- POSTGRES_PASSWORD=${GITEA_DB_PASSWORD}
|
|
||||||
- POSTGRES_DB=gitea
|
|
||||||
labels:
|
|
||||||
- "homelab.category=productivity"
|
|
||||||
- "homelab.description=Gitea database"
|
|
||||||
|
|
||||||
|
|
||||||
# Jupyter Lab - Interactive computing notebooks
|
|
||||||
# Access at: https://jupyter.${DOMAIN}
|
|
||||||
# Token displayed in logs on first start
|
|
||||||
jupyter:
|
|
||||||
image: jupyter/scipy-notebook:latest
|
|
||||||
container_name: jupyter
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8890:8888"
|
|
||||||
volumes:
|
|
||||||
- ./config/jupyter:/home/jovyan/work
|
|
||||||
environment:
|
|
||||||
- JUPYTER_ENABLE_LAB=yes
|
|
||||||
- GRANT_SUDO=yes
|
|
||||||
user: root
|
|
||||||
command: start-notebook.sh --NotebookApp.token='${JUPYTER_TOKEN}'
|
|
||||||
# Uncomment for GPU support (NVIDIA, requires nvidia-container-toolkit)
|
|
||||||
# runtime: nvidia
|
|
||||||
# devices:
|
|
||||||
# - /dev/nvidia0:/dev/nvidia0
|
|
||||||
# - /dev/nvidiactl:/dev/nvidiactl
|
|
||||||
# Add these to environment above:
|
|
||||||
# - NVIDIA_VISIBLE_DEVICES=all
|
|
||||||
# - NVIDIA_DRIVER_CAPABILITIES=compute,utility
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=productivity"
|
|
||||||
- "homelab.description=Jupyter Lab for data science and ML"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.jupyter.rule=Host(`jupyter.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.jupyter.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.jupyter.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.jupyter.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.jupyter.loadbalancer.server.port=8890"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-jupyter"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
nextcloud-db-data:
|
|
||||||
wordpress-db-data:
|
|
||||||
gitea-db-data:
|
|
||||||
|
|
||||||
networks:
|
|
||||||
homelab-network:
|
|
||||||
external: true
|
|
||||||
traefik-network:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
x-dockge:
|
|
||||||
urls:
|
|
||||||
# Proxied URLs (through Traefik)
|
|
||||||
- https://nextcloud.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:8089
|
|
||||||
- https://mealie.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:9000
|
|
||||||
- https://wordpress.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:8088
|
|
||||||
- https://gitea.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:3010
|
|
||||||
- https://jupyter.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:8890
|
|
||||||
@@ -20,12 +20,12 @@ services:
|
|||||||
- ./tdarr/server:/app/server
|
- ./tdarr/server:/app/server
|
||||||
- ./tdarr/configs:/app/configs
|
- ./tdarr/configs:/app/configs
|
||||||
- ./tdarr/logs:/app/logs
|
- ./tdarr/logs:/app/logs
|
||||||
- /mnt/media:/media
|
- ${MEDIA_DIR}:/media
|
||||||
- /mnt/tdarr-transcode:/temp # Transcode cache on separate drive
|
- ${TDARR_TRANSCODE_DIR}:/temp # Transcode cache on separate drive
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PGID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
- serverIP=0.0.0.0
|
- serverIP=0.0.0.0
|
||||||
- serverPort=8266
|
- serverPort=8266
|
||||||
- webUIPort=8265
|
- webUIPort=8265
|
||||||
@@ -61,12 +61,12 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./tdarr/configs:/app/configs
|
- ./tdarr/configs:/app/configs
|
||||||
- ./tdarr/logs:/app/logs
|
- ./tdarr/logs:/app/logs
|
||||||
- /mnt/media:/media
|
- ${MEDIA_DIR}:/media
|
||||||
- /mnt/tdarr-transcode:/temp
|
- ${TDARR_TRANSCODE_DIR}:/temp
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PGID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
- nodeID=MainNode
|
- nodeID=MainNode
|
||||||
- nodeIP=0.0.0.0
|
- nodeIP=0.0.0.0
|
||||||
- nodePort=8267
|
- nodePort=8267
|
||||||
@@ -91,12 +91,12 @@ services:
|
|||||||
- '8889:8888'
|
- '8889:8888'
|
||||||
volumes:
|
volumes:
|
||||||
- ./unmanic/config:/config
|
- ./unmanic/config:/config
|
||||||
- /mnt/media:/library
|
- ${MEDIA_DIR}:/library
|
||||||
- /mnt/unmanic-cache:/tmp/unmanic # Transcode cache on separate drive
|
- ${UNMANIC_TRANSCODE_DIR}:/tmp/unmanic # Transcode cache on separate drive
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PGID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
labels:
|
labels:
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
# ==========================================
|
# ==========================================
|
||||||
|
|||||||
@@ -1,126 +0,0 @@
|
|||||||
services:
|
|
||||||
# Tdarr Server - Distributed transcoding server
|
|
||||||
# Access at: https://tdarr.${DOMAIN}
|
|
||||||
tdarr-server:
|
|
||||||
image: ghcr.io/haveagitgat/tdarr:latest
|
|
||||||
container_name: tdarr-server
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- 8265:8265 # Web UI port
|
|
||||||
- 8266:8266 # Server port
|
|
||||||
volumes:
|
|
||||||
- ./tdarr/server:/app/server
|
|
||||||
- ./tdarr/configs:/app/configs
|
|
||||||
- ./tdarr/logs:/app/logs
|
|
||||||
- /mnt/media:/media
|
|
||||||
- /mnt/tdarr-transcode:/temp # Transcode cache on separate drive
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
- serverIP=0.0.0.0
|
|
||||||
- serverPort=8266
|
|
||||||
- webUIPort=8265
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=media"
|
|
||||||
- "homelab.description=Distributed transcoding server"
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.tdarr.rule=Host(`tdarr.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.tdarr.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.tdarr.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.tdarr.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.tdarr.loadbalancer.server.port=8265"
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-tdarr"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Tdarr Node - Transcoding worker
|
|
||||||
# No web UI - controlled by server
|
|
||||||
tdarr-node:
|
|
||||||
image: ghcr.io/haveagitgat/tdarr_node:latest
|
|
||||||
container_name: tdarr-node
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
volumes:
|
|
||||||
- ./tdarr/configs:/app/configs
|
|
||||||
- ./tdarr/logs:/app/logs
|
|
||||||
- /mnt/media:/media
|
|
||||||
- /mnt/tdarr-transcode:/temp
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
- nodeID=MainNode
|
|
||||||
- nodeIP=0.0.0.0
|
|
||||||
- nodePort=8267
|
|
||||||
- serverIP=tdarr-server
|
|
||||||
- serverPort=8266
|
|
||||||
labels:
|
|
||||||
- homelab.category=media
|
|
||||||
- homelab.description=Tdarr transcoding worker node
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-tdarr"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Unmanic - Another transcoding option
|
|
||||||
# Access at: https://unmanic.${DOMAIN}
|
|
||||||
unmanic:
|
|
||||||
image: josh5/unmanic:latest
|
|
||||||
container_name: unmanic
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8889:8888"
|
|
||||||
volumes:
|
|
||||||
- ./unmanic/config:/config
|
|
||||||
- /mnt/media:/library
|
|
||||||
- /mnt/unmanic-cache:/tmp/unmanic # Transcode cache on separate drive
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=media"
|
|
||||||
- "homelab.description=Library optimization and transcoding"
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.unmanic.rule=Host(`unmanic.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.unmanic.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.unmanic.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.unmanic.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.unmanic.loadbalancer.server.port=8889"
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-unmanic"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
networks:
|
|
||||||
homelab-network:
|
|
||||||
external: true
|
|
||||||
traefik-network:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
x-dockge:
|
|
||||||
urls:
|
|
||||||
- https://tdarr.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:8265
|
|
||||||
- https://unmanic.${DOMAIN}
|
|
||||||
- http://${SERVER_IP}:8888
|
|
||||||
@@ -19,13 +19,13 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./backrest/data:/data
|
- ./backrest/data:/data
|
||||||
- ./backrest/config:/config
|
- ./backrest/config:/config
|
||||||
- /opt/stacks:/opt/stacks:ro # Backup source
|
- ${STACKS_DIR}:${STACKS_DIR}:ro # Backup source
|
||||||
- /mnt:/mnt:ro # Backup additional drives
|
- /mnt:/mnt:ro # Backup additional drives
|
||||||
- backrest-cache:/cache
|
- ./backrest/cache:/cache
|
||||||
environment:
|
environment:
|
||||||
- BACKREST_DATA=/data
|
- BACKREST_DATA=/data
|
||||||
- BACKREST_CONFIG=/config/config.json
|
- BACKREST_CONFIG=/config/config.json
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ['CMD', 'wget', '--quiet', '--tries=1', '--spider', 'http://localhost:9898/']
|
test: ['CMD', 'wget', '--quiet', '--tries=1', '--spider', 'http://localhost:9898/']
|
||||||
interval: 30s
|
interval: 30s
|
||||||
@@ -64,13 +64,13 @@ services:
|
|||||||
- '8200:8200'
|
- '8200:8200'
|
||||||
volumes:
|
volumes:
|
||||||
- ./duplicati/config:/config
|
- ./duplicati/config:/config
|
||||||
- /opt/stacks:/source/stacks:ro
|
- ${STACKS_DIR}:${STACKS_DIR}:ro
|
||||||
- /mnt:/source/mnt:ro
|
- /mnt:/source/mnt:ro
|
||||||
- /mnt/backups:/backups
|
- /mnt/backups:/backups
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PGID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ['CMD', 'curl', '-f', 'http://localhost:8200/']
|
test: ['CMD', 'curl', '-f', 'http://localhost:8200/']
|
||||||
interval: 30s
|
interval: 30s
|
||||||
@@ -151,7 +151,7 @@ services:
|
|||||||
- 'homelab.category=utilities'
|
- 'homelab.category=utilities'
|
||||||
- 'homelab.description=Form.io database'
|
- 'homelab.description=Form.io database'
|
||||||
|
|
||||||
# Bitwarden (Vaultwarden) - Password manager
|
# Vaultwarden - Password manager
|
||||||
# Note: SSO disabled for browser extension and mobile app compatibility
|
# Note: SSO disabled for browser extension and mobile app compatibility
|
||||||
|
|
||||||
vaultwarden:
|
vaultwarden:
|
||||||
@@ -205,25 +205,8 @@ services:
|
|||||||
- 'sablier.group=jasper-vaultwarden'
|
- 'sablier.group=jasper-vaultwarden'
|
||||||
- 'sablier.start-on-demand=true'
|
- 'sablier.start-on-demand=true'
|
||||||
|
|
||||||
# Authelia Redis - Session storage for Authelia
|
|
||||||
# No web UI - backend service
|
|
||||||
# authelia-redis:
|
|
||||||
# image: redis:7-alpine
|
|
||||||
# container_name: authelia-redis
|
|
||||||
# restart: unless-stopped
|
|
||||||
# networks:
|
|
||||||
# - homelab-network
|
|
||||||
# volumes:
|
|
||||||
# - authelia-redis-data:/data
|
|
||||||
# command: redis-server --save 60 1 --loglevel warning
|
|
||||||
# labels:
|
|
||||||
# - homelab.category=utilities
|
|
||||||
# - homelab.description=Session storage for Authelia
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
backrest-cache: null
|
|
||||||
formio-mongo-data: null
|
formio-mongo-data: null
|
||||||
authelia-redis-data: null
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
homelab-network:
|
homelab-network:
|
||||||
|
|||||||
@@ -1,246 +0,0 @@
|
|||||||
# Backup and Utility Services
|
|
||||||
# Place in /opt/stacks/utilities/docker-compose.yml
|
|
||||||
|
|
||||||
# RESTART POLICY GUIDE:
|
|
||||||
# - unless-stopped: Core infrastructure services that should always run
|
|
||||||
# - no: Services with Sablier lazy loading (start on-demand)
|
|
||||||
# - See individual service comments for specific reasoning
|
|
||||||
|
|
||||||
services:
|
|
||||||
# Backrest - Backup solution for restic
|
|
||||||
# Access at: https://backrest.${DOMAIN}
|
|
||||||
# Uses Sablier lazy loading - starts on-demand, stops after 5min inactivity
|
|
||||||
backrest:
|
|
||||||
image: garethgeorge/backrest:latest
|
|
||||||
container_name: backrest
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "9898:9898"
|
|
||||||
volumes:
|
|
||||||
- ./backrest/data:/data
|
|
||||||
- ./backrest/config:/config
|
|
||||||
- /opt/stacks:/opt/stacks:ro # Backup source
|
|
||||||
- /mnt:/mnt:ro # Backup additional drives
|
|
||||||
- backrest-cache:/cache
|
|
||||||
environment:
|
|
||||||
- BACKREST_DATA=/data
|
|
||||||
- BACKREST_CONFIG=/config/config.json
|
|
||||||
- TZ=${TZ}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:9898/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 30s
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=utilities"
|
|
||||||
- "homelab.description=Backup management with restic"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.backrest.rule=Host(`backrest.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.backrest.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.backrest.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.backrest.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.backrest.loadbalancer.server.port=9898"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-backrest"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Duplicati - Backup solution
|
|
||||||
# Access at: https://duplicati.${DOMAIN}
|
|
||||||
duplicati:
|
|
||||||
image: lscr.io/linuxserver/duplicati:2.0.7
|
|
||||||
container_name: duplicati
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8200:8200"
|
|
||||||
volumes:
|
|
||||||
- ./duplicati/config:/config
|
|
||||||
- /opt/stacks:/source/stacks:ro
|
|
||||||
- /mnt:/source/mnt:ro
|
|
||||||
- /mnt/backups:/backups
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8200/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=utilities"
|
|
||||||
- "homelab.description=Backup software with encryption"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.duplicati.rule=Host(`duplicati.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.duplicati.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.duplicati.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.duplicati.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.duplicati.loadbalancer.server.port=8200"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-duplicati"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Form.io - Form builder
|
|
||||||
# Uncomment and configure if formio/formio image becomes available
|
|
||||||
formio:
|
|
||||||
image: calipseo/formio:latest
|
|
||||||
container_name: formio
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "3002:3001"
|
|
||||||
environment:
|
|
||||||
- MONGO=mongodb://formio-mongo:27017/formio
|
|
||||||
- JWT_SECRET=${FORMIO_JWT_SECRET}
|
|
||||||
- DB_SECRET=${FORMIO_DB_SECRET}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3001/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
depends_on:
|
|
||||||
- formio-mongo
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=utilities"
|
|
||||||
- "homelab.description=Form builder platform"
|
|
||||||
# Traefik labels
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.formio.rule=Host(`forms.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.formio.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.formio.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.formio.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.formio.loadbalancer.server.port=3001"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-formio"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
formio-mongo:
|
|
||||||
image: mongo:4.4
|
|
||||||
container_name: formio-mongo
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
labels:
|
|
||||||
- "homelab.category=utilities"
|
|
||||||
- "homelab.description=Form.io database"
|
|
||||||
|
|
||||||
# Bitwarden (Vaultwarden) - Password manager
|
|
||||||
# Access at: https://vault.${DOMAIN}
|
|
||||||
# Note: SSO disabled for browser extension and mobile app compatibility
|
|
||||||
|
|
||||||
vaultwarden:
|
|
||||||
image: vaultwarden/server:1.30.1
|
|
||||||
container_name: vaultwarden
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8091:80"
|
|
||||||
volumes:
|
|
||||||
- ./vaultwarden/data:/data
|
|
||||||
environment:
|
|
||||||
- DOMAIN=https://vault.${DOMAIN}
|
|
||||||
- SIGNUPS_ALLOWED=${BITWARDEN_SIGNUPS_ALLOWED}
|
|
||||||
- INVITATIONS_ALLOWED=${BITWARDEN_INVITATIONS_ALLOWED}
|
|
||||||
- ADMIN_TOKEN=${BITWARDEN_ADMIN_TOKEN}
|
|
||||||
# SMTP disabled - uncomment and configure to enable email
|
|
||||||
# - SMTP_HOST=${SMTP_HOST}
|
|
||||||
# - SMTP_FROM=${SMTP_FROM}
|
|
||||||
# - SMTP_PORT=${SMTP_PORT}
|
|
||||||
# - SMTP_SECURITY=${SMTP_SECURITY}
|
|
||||||
# - SMTP_USERNAME=${SMTP_USERNAME}
|
|
||||||
# - SMTP_PASSWORD=${SMTP_PASSWORD}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:80/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 30s
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# ==========================================
|
|
||||||
# Service metadata
|
|
||||||
- "homelab.category=utilities"
|
|
||||||
- "homelab.description=Self-hosted password manager (Bitwarden)"
|
|
||||||
# Traefik reverse proxy (comment/uncomment to disable/enable)
|
|
||||||
# If Traefik is on a remote server: these labels are NOT USED;
|
|
||||||
# configure external yml files in /traefik/dynamic folder instead.
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.vaultwarden.rule=Host(`vault.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.vaultwarden.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.vaultwarden.tls=true"
|
|
||||||
- "traefik.http.routers.vaultwarden.tls.certresolver=letsencrypt"
|
|
||||||
# SSO disabled for browser extension and mobile app compatibility
|
|
||||||
# - "traefik.http.routers.vaultwarden.middlewares=authelia@docker"
|
|
||||||
- "traefik.http.services.vaultwarden.loadbalancer.server.port=80"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-vaultwarden"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# Authelia Redis - Session storage for Authelia
|
|
||||||
# No web UI - backend service
|
|
||||||
# authelia-redis:
|
|
||||||
# image: redis:7-alpine
|
|
||||||
# container_name: authelia-redis
|
|
||||||
# restart: unless-stopped
|
|
||||||
# networks:
|
|
||||||
# - homelab-network
|
|
||||||
# volumes:
|
|
||||||
# - authelia-redis-data:/data
|
|
||||||
# command: redis-server --save 60 1 --loglevel warning
|
|
||||||
# labels:
|
|
||||||
# - homelab.category=utilities
|
|
||||||
# - homelab.description=Session storage for Authelia
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
backrest-cache: null
|
|
||||||
formio-mongo-data: null
|
|
||||||
authelia-redis-data: null
|
|
||||||
|
|
||||||
networks:
|
|
||||||
homelab-network:
|
|
||||||
external: true
|
|
||||||
traefik-network:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
x-dockge:
|
|
||||||
urls:
|
|
||||||
- https://backrest.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:9898
|
|
||||||
- https://duplicati.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:8200
|
|
||||||
- https://forms.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:3002
|
|
||||||
- https://vault.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:8091
|
|
||||||
@@ -33,7 +33,7 @@ services:
|
|||||||
- OPENVPN_USER=${SURFSHARK_USERNAME}
|
- OPENVPN_USER=${SURFSHARK_USERNAME}
|
||||||
- OPENVPN_PASSWORD=${SURFSHARK_PASSWORD}
|
- OPENVPN_PASSWORD=${SURFSHARK_PASSWORD}
|
||||||
- SERVER_COUNTRIES=${VPN_SERVER_COUNTRIES}
|
- SERVER_COUNTRIES=${VPN_SERVER_COUNTRIES}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
labels:
|
labels:
|
||||||
# Service metadata
|
# Service metadata
|
||||||
@@ -43,7 +43,7 @@ services:
|
|||||||
- 'traefik.enable=true'
|
- 'traefik.enable=true'
|
||||||
- 'traefik.docker.network=traefik-network'
|
- 'traefik.docker.network=traefik-network'
|
||||||
# Router configuration
|
# Router configuration
|
||||||
- 'traefik.http.routers.qbittorrent.rule=Host(`qbit.${DOMAIN}`)'
|
- 'traefik.http.routers.qbittorrent.rule=Host(`qbittorrent.${DOMAIN}`)'
|
||||||
- 'traefik.http.routers.qbittorrent.entrypoints=websecure'
|
- 'traefik.http.routers.qbittorrent.entrypoints=websecure'
|
||||||
- 'traefik.http.routers.qbittorrent.tls=true'
|
- 'traefik.http.routers.qbittorrent.tls=true'
|
||||||
- 'traefik.http.routers.qbittorrent.middlewares=authelia@docker'
|
- 'traefik.http.routers.qbittorrent.middlewares=authelia@docker'
|
||||||
@@ -71,11 +71,11 @@ services:
|
|||||||
network_mode: 'service:gluetun' # Routes through VPN in same compose file
|
network_mode: 'service:gluetun' # Routes through VPN in same compose file
|
||||||
volumes:
|
volumes:
|
||||||
- ./qbittorrent/config:/config
|
- ./qbittorrent/config:/config
|
||||||
- /mnt/downloads:/downloads
|
- ${DOWNLOADS_DIR}:/downloads
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PGID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
- WEBUI_PORT=8080
|
- WEBUI_PORT=8080
|
||||||
depends_on:
|
depends_on:
|
||||||
- gluetun
|
- gluetun
|
||||||
@@ -88,5 +88,5 @@ networks:
|
|||||||
|
|
||||||
x-dockge:
|
x-dockge:
|
||||||
urls:
|
urls:
|
||||||
- https://qbit.${DOMAIN}
|
- https://qbittorrent.${DOMAIN}
|
||||||
- https://192.168.4.4:8081
|
- https://192.168.4.4:8081
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
# VPN Stack
|
|
||||||
# VPN client and VPN-routed download clients
|
|
||||||
# Place in /opt/stacks/vpn/docker-compose.yml
|
|
||||||
|
|
||||||
# RESTART POLICY GUIDE:
|
|
||||||
# - unless-stopped: Core infrastructure services that should always run
|
|
||||||
# - no: Services with Sablier lazy loading (start on-demand)
|
|
||||||
# - See individual service comments for specific reasoning
|
|
||||||
|
|
||||||
services:
|
|
||||||
# Gluetun - VPN client (Surfshark)
|
|
||||||
# Routes download clients through VPN for security
|
|
||||||
# VPN service should always run to maintain secure connections
|
|
||||||
gluetun:
|
|
||||||
image: qmcgaw/gluetun:latest
|
|
||||||
container_name: gluetun
|
|
||||||
restart: unless-stopped
|
|
||||||
cap_add:
|
|
||||||
- NET_ADMIN
|
|
||||||
devices:
|
|
||||||
- /dev/net/tun:/dev/net/tun
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8888:8888/tcp" # HTTP proxy
|
|
||||||
- "8388:8388/tcp" # Shadowsocks
|
|
||||||
- "8388:8388/udp" # Shadowsocks
|
|
||||||
- "8081:8080" # qBittorrent web UI
|
|
||||||
- "6881:6881" # qBittorrent
|
|
||||||
- "6881:6881/udp" # qBittorrent
|
|
||||||
volumes:
|
|
||||||
- ./gluetun:/gluetun
|
|
||||||
environment:
|
|
||||||
- VPN_SERVICE_PROVIDER=surfshark
|
|
||||||
- VPN_TYPE=openvpn
|
|
||||||
- OPENVPN_USER=${SURFSHARK_USERNAME}
|
|
||||||
- OPENVPN_PASSWORD=${SURFSHARK_PASSWORD}
|
|
||||||
- SERVER_COUNTRIES=${VPN_SERVER_COUNTRIES}
|
|
||||||
- TZ=${TZ}
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
labels:
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=downloaders"
|
|
||||||
- "homelab.description=VPN client for secure downloads"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.qbittorrent.rule=Host(`qbit.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.qbittorrent.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.qbittorrent.tls=true"
|
|
||||||
- "traefik.http.routers.qbittorrent.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.qbittorrent.loadbalancer.server.port=8081"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-qbittorrent"
|
|
||||||
- "sablier.sessionDuration=1h"
|
|
||||||
|
|
||||||
# qBittorrent - Torrent client
|
|
||||||
# Routes through Gluetun VPN
|
|
||||||
qbittorrent:
|
|
||||||
image: lscr.io/linuxserver/qbittorrent:latest
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpus: '1.0'
|
|
||||||
memory: 512M
|
|
||||||
pids: 1024
|
|
||||||
reservations:
|
|
||||||
cpus: '0.50'
|
|
||||||
memory: 256M
|
|
||||||
container_name: qbittorrent
|
|
||||||
restart: unless-stopped
|
|
||||||
network_mode: "service:gluetun" # Routes through VPN in same compose file
|
|
||||||
volumes:
|
|
||||||
- ./qbittorrent/config:/config
|
|
||||||
- /mnt/downloads:/downloads
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
- WEBUI_PORT=8080
|
|
||||||
depends_on:
|
|
||||||
- gluetun
|
|
||||||
|
|
||||||
networks:
|
|
||||||
homelab-network:
|
|
||||||
external: true
|
|
||||||
traefik-network:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
x-dockge:
|
|
||||||
urls:
|
|
||||||
- https://qbit.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:8081
|
|
||||||
@@ -19,9 +19,9 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./dokuwiki/config:/config
|
- ./dokuwiki/config:/config
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PGID}
|
||||||
- TZ=America/New_York
|
- TZ=${TZ}
|
||||||
labels:
|
labels:
|
||||||
# TRAEFIK CONFIGURATION
|
# TRAEFIK CONFIGURATION
|
||||||
# Service metadata
|
# Service metadata
|
||||||
@@ -56,8 +56,8 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./bookstack/config:/config
|
- ./bookstack/config:/config
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=${PUID}
|
||||||
- PGID=1000
|
- PGID=${PGID}
|
||||||
- APP_URL=https://bookstack.${DOMAIN}
|
- APP_URL=https://bookstack.${DOMAIN}
|
||||||
- DB_HOST=bookstack-db
|
- DB_HOST=bookstack-db
|
||||||
- DB_PORT=3306
|
- DB_PORT=3306
|
||||||
@@ -100,7 +100,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- homelab-network
|
- homelab-network
|
||||||
volumes:
|
volumes:
|
||||||
- bookstack-db-data:/var/lib/mysql
|
- ./bookstack/db:/var/lib/mysql
|
||||||
environment:
|
environment:
|
||||||
- MYSQL_ROOT_PASSWORD=${BOOKSTACK_DB_ROOT_PASSWORD}
|
- MYSQL_ROOT_PASSWORD=${BOOKSTACK_DB_ROOT_PASSWORD}
|
||||||
- MYSQL_DATABASE=bookstack
|
- MYSQL_DATABASE=bookstack
|
||||||
@@ -163,7 +163,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- homelab-network
|
- homelab-network
|
||||||
volumes:
|
volumes:
|
||||||
- mediawiki-db-data:/var/lib/mysql
|
- ./mediawiki/db:/var/lib/mysql
|
||||||
environment:
|
environment:
|
||||||
- MYSQL_ROOT_PASSWORD=${MEDIAWIKI_DB_ROOT_PASSWORD}
|
- MYSQL_ROOT_PASSWORD=${MEDIAWIKI_DB_ROOT_PASSWORD}
|
||||||
- MYSQL_DATABASE=mediawiki
|
- MYSQL_DATABASE=mediawiki
|
||||||
@@ -173,10 +173,6 @@ services:
|
|||||||
- 'homelab.category=productivity'
|
- 'homelab.category=productivity'
|
||||||
- 'homelab.description=MediaWiki database'
|
- 'homelab.description=MediaWiki database'
|
||||||
|
|
||||||
volumes:
|
|
||||||
bookstack-db-data:
|
|
||||||
mediawiki-db-data:
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
homelab-network:
|
homelab-network:
|
||||||
external: true
|
external: true
|
||||||
|
|||||||
@@ -1,188 +0,0 @@
|
|||||||
services:
|
|
||||||
# DokuWiki - Wiki without database
|
|
||||||
# Access at: https://wiki.${DOMAIN}
|
|
||||||
# Uses Sablier lazy loading - starts on-demand, stops after 5min inactivity
|
|
||||||
dokuwiki:
|
|
||||||
image: lscr.io/linuxserver/dokuwiki:latest
|
|
||||||
container_name: dokuwiki
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8087:80"
|
|
||||||
volumes:
|
|
||||||
- ./dokuwiki/config:/config
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- TZ=${TZ}
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=productivity"
|
|
||||||
- "homelab.description=File-based wiki"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.dokuwiki.rule=Host(`dokuwiki.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.dokuwiki.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.dokuwiki.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.dokuwiki.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.dokuwiki.loadbalancer.server.port=8087"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-dokuwiki"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
# BookStack - Documentation platform
|
|
||||||
# Access at: https://docs.${DOMAIN}
|
|
||||||
# Uses Sablier lazy loading - starts on-demand, stops after 5min inactivity
|
|
||||||
bookstack:
|
|
||||||
image: lscr.io/linuxserver/bookstack:latest
|
|
||||||
container_name: bookstack
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "6875:80"
|
|
||||||
volumes:
|
|
||||||
- ./bookstack/config:/config
|
|
||||||
environment:
|
|
||||||
- PUID=${PUID}
|
|
||||||
- PGID=${PGID}
|
|
||||||
- APP_URL=https://bookstack.${DOMAIN}
|
|
||||||
- DB_HOST=bookstack-db
|
|
||||||
- DB_PORT=3306
|
|
||||||
- DB_DATABASE=bookstack
|
|
||||||
- DB_USERNAME=bookstack
|
|
||||||
- DB_PASSWORD=${BOOKSTACK_DB_PASSWORD}
|
|
||||||
- APP_KEY=base64:NsYD8+8MAvtBhK8xw9p8pxQDy4x8aOQi/78M3CsseAw=
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
depends_on:
|
|
||||||
- bookstack-db
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=productivity"
|
|
||||||
- "homelab.description=Documentation and wiki platform"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.bookstack.rule=Host(`bookstack.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.bookstack.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.bookstack.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.bookstack.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.bookstack.loadbalancer.server.port=6875"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-bookstack"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
bookstack-db:
|
|
||||||
image: mariadb:10.11
|
|
||||||
container_name: bookstack-db
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
volumes:
|
|
||||||
- bookstack-db-data:/var/lib/mysql
|
|
||||||
environment:
|
|
||||||
- MYSQL_ROOT_PASSWORD=${BOOKSTACK_DB_ROOT_PASSWORD}
|
|
||||||
- MYSQL_DATABASE=bookstack
|
|
||||||
- MYSQL_USER=bookstack
|
|
||||||
- MYSQL_PASSWORD=${BOOKSTACK_DB_PASSWORD}
|
|
||||||
labels:
|
|
||||||
- "homelab.category=productivity"
|
|
||||||
- "homelab.description=BookStack database"
|
|
||||||
|
|
||||||
# MediaWiki - Wiki platform
|
|
||||||
# Access at: https://mediawiki.${DOMAIN}
|
|
||||||
mediawiki:
|
|
||||||
image: mediawiki:latest
|
|
||||||
container_name: mediawiki
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
- traefik-network
|
|
||||||
ports:
|
|
||||||
- "8086:80"
|
|
||||||
volumes:
|
|
||||||
- ./mediawiki/images:/var/www/html/images
|
|
||||||
- ./mediawiki/LocalSettings.php:/var/www/html/LocalSettings.php
|
|
||||||
environment:
|
|
||||||
- MEDIAWIKI_DB_HOST=mediawiki-db
|
|
||||||
- MEDIAWIKI_DB_NAME=mediawiki
|
|
||||||
- MEDIAWIKI_DB_USER=mediawiki
|
|
||||||
- MEDIAWIKI_DB_PASSWORD=${MEDIAWIKI_DB_PASSWORD}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
depends_on:
|
|
||||||
- mediawiki-db
|
|
||||||
labels:
|
|
||||||
# TRAEFIK CONFIGURATION
|
|
||||||
# Service metadata
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
- "homelab.category=productivity"
|
|
||||||
- "homelab.description=MediaWiki platform"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# Router configuration
|
|
||||||
- "traefik.http.routers.mediawiki.rule=Host(`mediawiki.${DOMAIN}`)"
|
|
||||||
- "traefik.http.routers.mediawiki.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.mediawiki.tls.certresolver=letsencrypt"
|
|
||||||
- "traefik.http.routers.mediawiki.middlewares=authelia@docker"
|
|
||||||
# Service configuration
|
|
||||||
- "traefik.http.services.mediawiki.loadbalancer.server.port=8086"
|
|
||||||
# Sablier configuration
|
|
||||||
- "sablier.enable=true"
|
|
||||||
- "sablier.group=${SERVER_HOSTNAME}-mediawiki"
|
|
||||||
- "sablier.start-on-demand=true"
|
|
||||||
|
|
||||||
mediawiki-db:
|
|
||||||
image: mariadb:10.11
|
|
||||||
container_name: mediawiki-db
|
|
||||||
restart: no
|
|
||||||
networks:
|
|
||||||
- homelab-network
|
|
||||||
volumes:
|
|
||||||
- mediawiki-db-data:/var/lib/mysql
|
|
||||||
environment:
|
|
||||||
- MYSQL_ROOT_PASSWORD=${MEDIAWIKI_DB_ROOT_PASSWORD}
|
|
||||||
- MYSQL_DATABASE=mediawiki
|
|
||||||
- MYSQL_USER=mediawiki
|
|
||||||
- MYSQL_PASSWORD=${MEDIAWIKI_DB_PASSWORD}
|
|
||||||
labels:
|
|
||||||
- "homelab.category=productivity"
|
|
||||||
- "homelab.description=MediaWiki database"
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
bookstack-db-data:
|
|
||||||
mediawiki-db-data:
|
|
||||||
|
|
||||||
networks:
|
|
||||||
homelab-network:
|
|
||||||
external: true
|
|
||||||
traefik-network:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
x-dockge:
|
|
||||||
urls:
|
|
||||||
# Proxied URLs (through Traefik)
|
|
||||||
- https://bookstack.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:6875
|
|
||||||
- https://dokuwiki.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:8087
|
|
||||||
- https://mediawiki.${DOMAIN}
|
|
||||||
- https://${SERVER_IP}:8086
|
|
||||||
Reference in New Issue
Block a user