feat: Update Sablier configs for debian hostname and reorganize .env.example

- Change Traefik configs to use ${SERVER_HOSTNAME} placeholder (defaults to debian)
- Update ez-homelab.sh to replace SERVER_HOSTNAME in config templates
- Set Sablier session duration to 5m for testing (increase to 30m for production)
- Add SERVER_HOSTNAME prompt and saving in setup script
- Reorganize .env.example with better structure and SMTP variables
- Add production guidance comments to docker-compose files
- Intentional SMTP variable redundancy for service flexibility
This commit is contained in:
EZ-Homelab
2026-01-23 15:25:25 -05:00
parent 970231fc04
commit 3701b11a73
9 changed files with 1247 additions and 329 deletions

View File

@@ -1,93 +1,88 @@
# Environment Variables Template
# Copy this file to .env and fill in your values: cp .env.example .env
# NEVER commit .env to git!
# Copy this file to .env and fill in your values
# User and Group IDs (get with: id -u and id -g)
# User and Group IDs for file permissions (get with: id -u and id -g)
PUID=1000
PGID=1000
# Timezone (list: timedatectl list-timezones)
TZ=America/New_York
# Server IP address
SERVER_IP=192.168.1.100
SERVER_HOSTNAME=debian # used for Sablier group naming
# Server hostname (used for Sablier group naming)
SERVER_HOSTNAME=debian
# Domain & DuckDNS Configuration
DUCKDNS_SUBDOMAINS=yourdomain # Without .duckdns.org
DOMAIN=${DUCKDNS_SUBDOMAINS}.duckdns.org
DUCKDNS_TOKEN=your-duckdns-token
# Default credentials (used by multiple services for easier setup)
DEFAULT_USER=admin
DEFAULT_PASSWORD=changeme
DEFAULT_EMAIL=admin@example.com
# ====================================
# DOMAIN & DNS CONFIGURATION
# ====================================
# DIRECTORY PATHS
# Your DuckDNS domain (without https://)
DOMAIN=yourdomain.duckdns.org
USERDIR=/opt/stacks # all docker-compose stacks
MEDIADIR=/mnt/media # Large media files on separate drive
DOWNLOADDIR=/mnt/downloads # Downloads on separate drive
PROJECTDIR=~/projects # User's projects folder
# DuckDNS Configuration
DUCKDNS_TOKEN=your-duckdns-token
DUCKDNS_SUBDOMAINS=yourdomain # Without .duckdns.org
###################################################
# ==== Everything above this line is required ====
###################################################
# Surfshark OpenVPN (RECOMMENDED - Default)
# 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
# Optional: Email credentials for services that need SMTP
SMTP_EMAIL_SERVER=smtp.gmail.com
SMTP_EMAIL_PORT=587
SMTP_EMAIL_PASSWORD=your-email-app-password
SMTP_EMAIL_FROM=${DEFAULT_EMAIL}
SMTP_EMAIL_SECURITY=starttls
##################################################
# #### Individual Service Configurations ####
# The default values should work as a starting point
##################################################
# Let's Encrypt / ACME (for SSL certificates)
ACME_EMAIL=${DEFAULT_EMAIL}
ADMIN_EMAIL=${DEFAULT_EMAIL} # Used for admin user account
# Cloudflare API (optional, for DNS challenge instead of DuckDNS)
# CF_DNS_API_TOKEN=your-cloudflare-api-token
# ====================================
# AUTHELIA SSO CONFIGURATION
# ====================================
# Generate these secrets with: openssl rand -hex 64
# The setup script will auto-generate these if not set
AUTHELIA_JWT_SECRET=generate-with-openssl-rand-hex-64
AUTHELIA_SESSION_SECRET=generate-with-openssl-rand-hex-64
AUTHELIA_STORAGE_ENCRYPTION_KEY=generate-with-openssl-rand-hex-64
# Authelia Admin Credentials
# These will be auto-generated by setup-homelab.sh
# DO NOT set these manually - they are generated during setup
# #### Authelia Admin Credentials ####
# These will be auto-generated by EZ-Homelab.sh
# AUTHELIA_ADMIN_USER=${DEFAULT_USER}
# AUTHELIA_ADMIN_EMAIL=${DEFAULT_EMAIL}
# AUTHELIA_ADMIN_PASSWORD=${DEFAULT_PASSWORD}
# SMTP for Authelia Notifications (OPTIONAL)
# If not configured, notifications are saved to file instead
# SMTP_USERNAME=your-email@example.com
# SMTP_PASSWORD=your-smtp-password
# SMTP_USERNAME=${SMTP_EMAIL_FROM}
# SMTP_PASSWORD=${SMTP_EMAIL_PASSWORD}
# ====================================
# VPN CONFIGURATION (GLUETUN)
# ====================================
# Surfshark OpenVPN (RECOMMENDED - Default)
SURFSHARK_USERNAME=your-surfshark-username
SURFSHARK_PASSWORD=your-surfshark-password
VPN_SERVER_COUNTRIES=Netherlands # Preferred VPN server location
# #### VPN OPTIONAL WIREGUARD CONFIGURATION (GLUETUN) ####
# Surfshark WireGuard (OPTIONAL - Advanced users only)
# Only needed if you prefer WireGuard over OpenVPN
# Get WireGuard details from Surfshark dashboard
# SURFSHARK_PRIVATE_KEY=your-wireguard-private-key
# SURFSHARK_ADDRESSES=10.14.0.2/16
# ====================================
# DIRECTORY PATHS
# ====================================
USERDIR=/opt/stacks
MEDIADIR=/mnt/media # Large media files on separate drive
DOWNLOADDIR=/mnt/downloads # Downloads on separate drive
PROJECTDIR=/home/username/projects
# ====================================
# ALTERNATIVE SERVICES (OPTIONAL)
# #### ALTERNATIVE SERVICES (OPTIONAL) ####
# Deploy alternatives.yml stack if you want these
# ====================================
# Authentik SSO (alternative to Authelia with web UI)
# WARNING: Do not run both Authelia and Authentik at the same time
@@ -96,20 +91,10 @@ PROJECTDIR=/home/username/projects
# AUTHENTIK_DB_USER=authentik
# AUTHENTIK_DB_PASSWORD=changeme-authentik-db-password
# AUTHENTIK_DB_NAME=authentik
# PLEX_CLAIM=claim-xxxxxxxxxx # Uncomment to user Plex instead of Jellyfin
# ====================================
# MEDIA SERVICES
# ====================================
PLEX_CLAIM=claim-xxxxxxxxxx
# qBittorrent
QBITTORRENT_USER=admin
QBITTORRENT_PASS=${DEFAULT_PASSWORD}
# ====================================
# INFRASTRUCTURE SERVICES
# ====================================
# #### INFRASTRUCTURE SERVICES ####
# Pi-hole
PIHOLE_PASSWORD=${DEFAULT_PASSWORD}
@@ -117,42 +102,31 @@ PIHOLE_PASSWORD=${DEFAULT_PASSWORD}
# Watchtower Notifications (optional)
# If not set, Watchtower will still update containers but without notifications
# Supports various notification services via Shoutrrr URL format
# Examples:
# Discord: discord://token@webhookid
# Slack: slack://token@channel
# Email: smtp://username:password@host:port/?from=sender@example.com
# WATCHTOWER_NOTIFICATION_URL=
# ====================================
# MONITORING & DASHBOARDS
# ====================================
# #### Other Services ####
# qBittorrent
QBITTORRENT_USER=admin
QBITTORRENT_PASS=${DEFAULT_PASSWORD}
# GRAFANA
GRAFANA_ADMIN_PASSWORD=${DEFAULT_PASSWORD}
# ====================================
# DEVELOPMENT TOOLS
# ====================================
# VS Code Server
CODE_SERVER_PASSWORD=${DEFAULT_PASSWORD}
CODE_SERVER_SUDO_PASSWORD=${DEFAULT_PASSWORD}
# Jupyter Notebook
JUPYTER_TOKEN=${DEFAULT_PASSWORD}
# ====================================
# DATABASES - GENERAL
# ====================================
POSTGRES_USER=${DEFAULT_USER}
POSTGRES_PASSWORD=${DEFAULT_PASSWORD}
POSTGRES_DB=homelab
PGADMIN_EMAIL=${DEFAULT_EMAIL}
PGADMIN_PASSWORD=${DEFAULT_PASSWORD}
# ====================================
# PRODUCTIVITY SERVICES
# ====================================
# Nextcloud
NEXTCLOUD_ADMIN_USER=${DEFAULT_USER}
NEXTCLOUD_ADMIN_PASSWORD=${DEFAULT_PASSWORD}
@@ -174,51 +148,45 @@ BOOKSTACK_DB_ROOT_PASSWORD=${DEFAULT_PASSWORD}
MEDIAWIKI_DB_PASSWORD=${DEFAULT_PASSWORD}
MEDIAWIKI_DB_ROOT_PASSWORD=${DEFAULT_PASSWORD}
# ====================================
# UTILITIES
# ====================================
# Bitwarden (Vaultwarden) Password Manager
# Admin token: openssl rand -base64 48
# Bitwarden (Vaultwarden)
BITWARDEN_ADMIN_TOKEN=${DEFAULT_PASSWORD}
BITWARDEN_SIGNUPS_ALLOWED=true # Set to false after creating accounts
BITWARDEN_INVITATIONS_ALLOWED=true
SMTP_HOST=smtp.gmail.com
SMTP_FROM=${DEFAULT_EMAIL}
SMTP_PORT=587
SMTP_SECURITY=starttls
SMTP_HOST=${SMTP_EMAIL_SERVER}
SMTP_FROM=${SMTP_EMAIL_FROM}
SMTP_PORT=${SMTP_EMAIL_PORT}
SMTP_SECURITY=${SMTP_EMAIL_SECURITY}
# Form.io
FORMIO_JWT_SECRET=${DEFAULT_PASSWORD}
FORMIO_DB_SECRET=${DEFAULT_PASSWORD}
# ====================================
####################################
# HOMEPAGE DASHBOARD - API KEYS
# Generate these from each service's settings page
# ====================================
####################################
HOMEPAGE_VAR_DOMAIN=${DOMAIN}
HOMEPAGE_VAR_SERVER_IP=${SERVER_IP}
HOMEPAGE_VAR_PORTAINER_KEY=your-portainer-api-key
HOMEPAGE_VAR_PIHOLE_KEY=your-pihole-api-key
HOMEPAGE_VAR_PLEX_KEY=your-plex-token
HOMEPAGE_VAR_JELLYFIN_KEY=your-jellyfin-api-key
HOMEPAGE_VAR_SONARR_KEY=your-sonarr-api-key
HOMEPAGE_VAR_RADARR_KEY=your-radarr-api-key
HOMEPAGE_VAR_LIDARR_KEY=your-lidarr-api-key
HOMEPAGE_VAR_READARR_KEY=your-readarr-api-key
HOMEPAGE_VAR_PROWLARR_KEY=your-prowlarr-api-key
HOMEPAGE_VAR_JELLYSEERR_KEY=your-jellyseerr-api-key
HOMEPAGE_VAR_QBITTORRENT_USER=${QBITTORRENT_USER}
HOMEPAGE_VAR_QBITTORRENT_PASS=${QBITTORRENT_PASS}
HOMEPAGE_VAR_HA_KEY=your-home-assistant-long-lived-token
HOMEPAGE_VAR_NEXTCLOUD_USER=${NEXTCLOUD_ADMIN_USER}
HOMEPAGE_VAR_NEXTCLOUD_PASS=${NEXTCLOUD_ADMIN_PASSWORD}
HOMEPAGE_VAR_GRAFANA_USER=admin
HOMEPAGE_VAR_GRAFANA_PASS=${GRAFANA_ADMIN_PASSWORD}
HOMEPAGE_VAR_BOOKSTACK_KEY=your-bookstack-api-token
HOMEPAGE_VAR_UPTIMEKUMA_SLUG=your-uptime-kuma-slug
HOMEPAGE_VAR_OPENWEATHER_KEY=your-openweather-api-key
HOMEPAGE_VAR_WEATHERAPI_KEY=your-weatherapi-key
HOMEPAGE_VAR_UNIFI_USER=your-unifi-username
HOMEPAGE_VAR_UNIFI_PASS=your-unifi-password
# HOMEPAGE_VAR_DOMAIN=${DOMAIN}
# HOMEPAGE_VAR_SERVER_IP=${SERVER_IP}
# HOMEPAGE_VAR_PORTAINER_KEY=your-portainer-api-key
# HOMEPAGE_VAR_PIHOLE_KEY=your-pihole-api-key
# HOMEPAGE_VAR_PLEX_KEY=your-plex-token
# HOMEPAGE_VAR_JELLYFIN_KEY=your-jellyfin-api-key
# HOMEPAGE_VAR_SONARR_KEY=your-sonarr-api-key
# HOMEPAGE_VAR_RADARR_KEY=your-radarr-api-key
# HOMEPAGE_VAR_LIDARR_KEY=your-lidarr-api-key
# HOMEPAGE_VAR_READARR_KEY=your-readarr-api-key
# HOMEPAGE_VAR_PROWLARR_KEY=your-prowlarr-api-key
# HOMEPAGE_VAR_JELLYSEERR_KEY=your-jellyseerr-api-key
# HOMEPAGE_VAR_QBITTORRENT_USER=${QBITTORRENT_USER}
# HOMEPAGE_VAR_QBITTORRENT_PASS=${QBITTORRENT_PASS}
# HOMEPAGE_VAR_HA_KEY=your-home-assistant-long-lived-token
# HOMEPAGE_VAR_NEXTCLOUD_USER=${NEXTCLOUD_ADMIN_USER}
# HOMEPAGE_VAR_NEXTCLOUD_PASS=${NEXTCLOUD_ADMIN_PASSWORD}
# HOMEPAGE_VAR_GRAFANA_USER=admin
# HOMEPAGE_VAR_GRAFANA_PASS=${GRAFANA_ADMIN_PASSWORD}
# HOMEPAGE_VAR_BOOKSTACK_KEY=your-bookstack-api-token
# HOMEPAGE_VAR_UPTIMEKUMA_SLUG=your-uptime-kuma-slug
# HOMEPAGE_VAR_OPENWEATHER_KEY=your-openweather-api-key
# HOMEPAGE_VAR_WEATHERAPI_KEY=your-weatherapi-key
# HOMEPAGE_VAR_UNIFI_USER=your-unifi-username
# HOMEPAGE_VAR_UNIFI_PASS=your-unifi-password

View File

@@ -1,535 +1,535 @@
http:
routers:
backrest-jarvis:
backrest-${SERVER_HOSTNAME}:
rule: "Host(`backrest.${DOMAIN}`)"
entryPoints:
- websecure
service: backrest-jarvis
service: backrest-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-backrest@file
- sablier-${SERVER_HOSTNAME}-backrest@file
- authelia@docker
bookstack-jarvis:
bookstack-${SERVER_HOSTNAME}:
rule: "Host(`bookstack.${DOMAIN}`)"
entryPoints:
- websecure
service: bookstack-jarvis
service: bookstack-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-bookstack@file
- sablier-${SERVER_HOSTNAME}-bookstack@file
- authelia@docker
bitwarden-jarvis:
bitwarden-${SERVER_HOSTNAME}:
rule: "Host(`bitwarden.${DOMAIN}`)"
entryPoints:
- websecure
service: bitwarden-jarvis
service: bitwarden-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-bitwarden@file
- sablier-${SERVER_HOSTNAME}-bitwarden@file
- authelia@docker
calibre-web-jarvis:
calibre-web-${SERVER_HOSTNAME}:
rule: "Host(`calibre.${DOMAIN}`)"
entryPoints:
- websecure
service: calibre-web-jarvis
service: calibre-web-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-calibre-web@file
- sablier-${SERVER_HOSTNAME}-calibre-web@file
- authelia@docker
code-jarvis:
code-${SERVER_HOSTNAME}:
rule: "Host(`code.${DOMAIN}`)"
entryPoints:
- websecure
service: code-jarvis
service: code-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-code-server@file
- sablier-${SERVER_HOSTNAME}-code-server@file
- authelia@docker
dockge-jarvis:
dockge-${SERVER_HOSTNAME}:
rule: "Host(`jarvis.${DOMAIN}`)"
entryPoints:
- websecure
service: dockge-jarvis
service: dockge-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- authelia@docker
dockhand-jarvis:
dockhand-${SERVER_HOSTNAME}:
rule: "Host(`dockhand.${DOMAIN}`)"
entryPoints:
- websecure
service: dockhand-jarvis
service: dockhand-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- authelia@docker
dokuwiki-jarvis:
dokuwiki-${SERVER_HOSTNAME}:
rule: "Host(`dokuwiki.${DOMAIN}`)"
entryPoints:
- websecure
service: dokuwiki-jarvis
service: dokuwiki-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-dokuwiki@file
- sablier-${SERVER_HOSTNAME}-dokuwiki@file
- authelia@docker
dozzle-jarvis:
dozzle-${SERVER_HOSTNAME}:
rule: "Host(`dozzle.${DOMAIN}`)"
entryPoints:
- websecure
service: dozzle-jarvis
service: dozzle-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-dozzle@file
- sablier-${SERVER_HOSTNAME}-dozzle@file
- authelia@docker
duplicati-jarvis:
duplicati-${SERVER_HOSTNAME}:
rule: "Host(`duplicati.${DOMAIN}`)"
entryPoints:
- websecure
service: duplicati-jarvis
service: duplicati-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-duplicati@file
- sablier-${SERVER_HOSTNAME}-duplicati@file
- authelia@docker
formio-jarvis:
formio-${SERVER_HOSTNAME}:
rule: "Host(`formio.${DOMAIN}`)"
entryPoints:
- websecure
service: formio-jarvis
service: formio-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-formio@file
- sablier-${SERVER_HOSTNAME}-formio@file
- authelia@docker
gitea-jarvis:
gitea-${SERVER_HOSTNAME}:
rule: "Host(`gitea.${DOMAIN}`)"
entryPoints:
- websecure
service: gitea-jarvis
service: gitea-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-gitea@file
- sablier-${SERVER_HOSTNAME}-gitea@file
- authelia@docker
glances-jarvis:
glances-${SERVER_HOSTNAME}:
rule: "Host(`glances.jarvis.${DOMAIN}`)"
entryPoints:
- websecure
service: glances-jarvis
service: glances-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-glances@file
- sablier-${SERVER_HOSTNAME}-glances@file
- authelia@docker
homepage-jarvis:
homepage-${SERVER_HOSTNAME}:
rule: "Host(`homepage.jarvis.${DOMAIN}`)"
entryPoints:
- websecure
service: homepage-jarvis
service: homepage-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- authelia@docker
homarr-jarvis:
homarr-${SERVER_HOSTNAME}:
rule: "Host(`homarr.${DOMAIN}`)"
entryPoints:
- websecure
service: homarr-jarvis
service: homarr-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- authelia@docker
- sablier-jarvis-homarr@file
- sablier-${SERVER_HOSTNAME}-homarr@file
jellyfin-jarvis:
jellyfin-${SERVER_HOSTNAME}:
rule: "Host(`jellyfin.${DOMAIN}`)"
entryPoints:
- websecure
service: jellyfin-jarvis
service: jellyfin-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-jellyfin@file
- sablier-${SERVER_HOSTNAME}-jellyfin@file
# No authelia middleware for media apps
kopia-jarvis:
kopia-${SERVER_HOSTNAME}:
rule: "Host(`kopia.${DOMAIN}`)"
entryPoints:
- websecure
service: kopia-jarvis
service: kopia-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-kopia@file
- sablier-${SERVER_HOSTNAME}-kopia@file
- authelia@docker
mealie-jarvis:
mealie-${SERVER_HOSTNAME}:
rule: "Host(`mealie.${DOMAIN}`)"
entryPoints:
- websecure
service: mealie-jarvis
service: mealie-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-mealie@file
- sablier-${SERVER_HOSTNAME}-mealie@file
- authelia@docker
motioneye-jarvis:
motioneye-${SERVER_HOSTNAME}:
rule: "Host(`motioneye.${DOMAIN}`)"
entryPoints:
- websecure
service: motioneye-jarvis
service: motioneye-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- authelia@docker
mediawiki-jarvis:
mediawiki-${SERVER_HOSTNAME}:
rule: "Host(`mediawiki.${DOMAIN}`)"
entryPoints:
- websecure
service: mediawiki-jarvis
service: mediawiki-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-mediawiki@file
- sablier-${SERVER_HOSTNAME}-mediawiki@file
- authelia@docker
nextcloud-jarvis:
nextcloud-${SERVER_HOSTNAME}:
rule: "Host(`nextcloud.${DOMAIN}`)"
entryPoints:
- websecure
service: nextcloud-jarvis
service: nextcloud-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-nextcloud@file
- sablier-${SERVER_HOSTNAME}-nextcloud@file
- authelia@docker
openkm-jarvis:
openkm-${SERVER_HOSTNAME}:
rule: "Host(`openkm.${DOMAIN}`)"
entryPoints:
- websecure
service: openkm-jarvis
service: openkm-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-openkm@file
- sablier-${SERVER_HOSTNAME}-openkm@file
- authelia@docker
openwebui-jarvis:
openwebui-${SERVER_HOSTNAME}:
rule: "Host(`openwebui.${DOMAIN}`)"
entryPoints:
- websecure
service: openwebui-jarvis
service: openwebui-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-openwebui@file
- sablier-${SERVER_HOSTNAME}-openwebui@file
- authelia@docker
qbittorrent-jarvis:
qbittorrent-${SERVER_HOSTNAME}:
rule: "Host(`torrents.${DOMAIN}`)"
entryPoints:
- websecure
service: qbittorrent-jarvis
service: qbittorrent-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- sablier-${SERVER_HOSTNAME}-arr@file
- authelia@docker
tdarr-jarvis:
tdarr-${SERVER_HOSTNAME}:
rule: "Host(`tdarr.${DOMAIN}`)"
entryPoints:
- websecure
service: tdarr-jarvis
service: tdarr-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- sablier-${SERVER_HOSTNAME}-arr@file
- authelia@docker
unmanic-jarvis:
unmanic-${SERVER_HOSTNAME}:
rule: "Host(`unmanic.${DOMAIN}`)"
entryPoints:
- websecure
service: unmanic-jarvis
service: unmanic-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-unmanic@file
- sablier-${SERVER_HOSTNAME}-unmanic@file
- authelia@docker
wordpress-jarvis:
wordpress-${SERVER_HOSTNAME}:
rule: "Host(`knot-u.${DOMAIN}`)"
entryPoints:
- websecure
service: wordpress-jarvis
service: wordpress-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-wordpress@file
- sablier-${SERVER_HOSTNAME}-wordpress@file
- authelia@file
# Arr Services (no SSO for media apps)
jellyseerr-jarvis:
jellyseerr-${SERVER_HOSTNAME}:
rule: "Host(`jellyseerr.${DOMAIN}`)"
entryPoints:
- websecure
service: jellyseerr-jarvis
service: jellyseerr-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- sablier-${SERVER_HOSTNAME}-arr@file
- authelia@docker
prowlarr-jarvis:
prowlarr-${SERVER_HOSTNAME}:
rule: "Host(`prowlarr.${DOMAIN}`)"
entryPoints:
- websecure
service: prowlarr-jarvis
service: prowlarr-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- sablier-${SERVER_HOSTNAME}-arr@file
- authelia@docker
radarr-jarvis:
radarr-${SERVER_HOSTNAME}:
rule: "Host(`radarr.${DOMAIN}`)"
entryPoints:
- websecure
service: radarr-jarvis
service: radarr-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- sablier-${SERVER_HOSTNAME}-arr@file
- authelia@docker
sonarr-jarvis:
sonarr-${SERVER_HOSTNAME}:
rule: "Host(`sonarr.${DOMAIN}`)"
entryPoints:
- websecure
service: sonarr-jarvis
service: sonarr-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- sablier-${SERVER_HOSTNAME}-arr@file
- authelia@docker
lidarr-jarvis:
lidarr-${SERVER_HOSTNAME}:
rule: "Host(`lidarr.${DOMAIN}`)"
entryPoints:
- websecure
service: lidarr-jarvis
service: lidarr-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- sablier-${SERVER_HOSTNAME}-arr@file
- authelia@docker
readarr-jarvis:
readarr-${SERVER_HOSTNAME}:
rule: "Host(`readarr.${DOMAIN}`)"
entryPoints:
- websecure
service: readarr-jarvis
service: readarr-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- sablier-${SERVER_HOSTNAME}-arr@file
- authelia@docker
mylar3-jarvis:
mylar3-${SERVER_HOSTNAME}:
rule: "Host(`mylar3.${DOMAIN}`)"
entryPoints:
- websecure
service: mylar3-jarvis
service: mylar3-${SERVER_HOSTNAME}
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- sablier-${SERVER_HOSTNAME}-arr@file
- authelia@docker
services:
backrest-jarvis:
backrest-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:9898"
passHostHeader: true
bitwarden-jarvis:
bitwarden-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8000"
passHostHeader: true
bookstack-jarvis:
bookstack-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:6875"
passHostHeader: true
calibre-web-jarvis:
calibre-web-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8083"
passHostHeader: true
code-jarvis:
code-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8079"
passHostHeader: true
dockge-jarvis:
dockge-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:5001"
passHostHeader: true
dockhand-jarvis:
dockhand-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:3003"
passHostHeader: true
dokuwiki-jarvis:
dokuwiki-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8087"
passHostHeader: true
dozzle-jarvis:
dozzle-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8085"
passHostHeader: true
duplicati-jarvis:
duplicati-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8200"
passHostHeader: true
formio-jarvis:
formio-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:3002"
passHostHeader: true
gitea-jarvis:
gitea-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:3010"
passHostHeader: true
glances-jarvis:
glances-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:61208"
passHostHeader: true
homarr-jarvis:
homarr-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:7575"
passHostHeader: true
homepage-jarvis:
homepage-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:3000"
passHostHeader: true
jellyfin-jarvis:
jellyfin-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8096"
passHostHeader: true
kopia-jarvis:
kopia-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:51515"
passHostHeader: true
mealie-jarvis:
mealie-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:9000"
passHostHeader: true
mediawiki-jarvis:
mediawiki-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8084"
passHostHeader: true
motioneye-jarvis:
motioneye-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8081"
passHostHeader: true
nextcloud-jarvis:
nextcloud-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8089"
passHostHeader: true
openkm-jarvis:
openkm-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:18080"
passHostHeader: true
openwebui-jarvis:
openwebui-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:3000"
passHostHeader: true
qbittorrent-jarvis:
qbittorrent-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8080"
passHostHeader: true
tdarr-jarvis:
tdarr-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8265"
passHostHeader: true
unmanic-jarvis:
unmanic-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8888"
passHostHeader: true
wordpress-jarvis:
wordpress-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8088"
@@ -537,43 +537,43 @@ http:
# Arr Services
jellyseerr-jarvis:
jellyseerr-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:5055"
passHostHeader: true
prowlarr-jarvis:
prowlarr-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:9696"
passHostHeader: true
radarr-jarvis:
radarr-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:7878"
passHostHeader: true
sonarr-jarvis:
sonarr-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8989"
passHostHeader: true
lidarr-jarvis:
lidarr-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8686"
passHostHeader: true
readarr-jarvis:
readarr-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8787"
passHostHeader: true
mylar3-jarvis:
mylar3-${SERVER_HOSTNAME}:
loadBalancer:
servers:
- url: "http://192.168.4.11:8090"

View File

@@ -1,215 +1,216 @@
# Session duration set to 5m for testing. Increase to 30m for production.
http:
middlewares:
sablier-debian-arr:
sablier-${SERVER_HOSTNAME}-arr:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-arr
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-arr
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Arr Apps
theme: ghost
show-details-by-default: true
sablier-debian-backrest:
sablier-${SERVER_HOSTNAME}-backrest:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-backrest
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-backrest
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Backrest
theme: ghost
show-details-by-default: true
sablier-debian-bookstack:
sablier-${SERVER_HOSTNAME}-bookstack:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-bookstack
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-bookstack
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Bookstack
theme: ghost
show-details-by-default: true
sablier-debian-jellyfin:
sablier-${SERVER_HOSTNAME}-jellyfin:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-jellyfin
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-jellyfin
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Jellyfin
theme: ghost
show-details-by-default: true
sablier-debian-calibre-web:
sablier-${SERVER_HOSTNAME}-calibre-web:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-calibre-web
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-calibre-web
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Calibre Web
theme: ghost
show-details-by-default: true
sablier-debian-code-server:
sablier-${SERVER_HOSTNAME}-code-server:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-code-server
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-code-server
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Code Server
theme: ghost
show-details-by-default: true
sablier-debian-bitwarden:
sablier-${SERVER_HOSTNAME}-bitwarden:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-bitwarden
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-bitwarden
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: bitwarden
theme: ghost
show-details-by-default: true
sablier-debian-wordpress:
sablier-${SERVER_HOSTNAME}-wordpress:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-wordpress
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-wordpress
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: wordpress
theme: ghost
show-details-by-default: true
sablier-debian-nextcloud:
sablier-${SERVER_HOSTNAME}-nextcloud:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-nextcloud
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-nextcloud
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: NextCloud
theme: ghost
show-details-by-default: true
sablier-debian-mediawiki:
sablier-${SERVER_HOSTNAME}-mediawiki:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-mediawiki
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-mediawiki
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: mediawiki
theme: ghost
show-details-by-default: true
sablier-debian-mealie:
sablier-${SERVER_HOSTNAME}-mealie:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-mealie
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-mealie
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Mealie
theme: ghost
show-details-by-default: true
sablier-debian-gitea:
sablier-${SERVER_HOSTNAME}-gitea:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-gitea
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-gitea
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Gitea
theme: ghost
show-details-by-default: true
sablier-debian-formio:
sablier-${SERVER_HOSTNAME}-formio:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-formio
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-formio
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: FormIO
theme: ghost
show-details-by-default: true
sablier-debian-dozzle:
sablier-${SERVER_HOSTNAME}-dozzle:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-dozzle
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-dozzle
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: dozzle
theme: ghost
show-details-by-default: true
sablier-debian-duplicati:
sablier-${SERVER_HOSTNAME}-duplicati:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-duplicati
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-duplicati
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Duplicati
theme: ghost
show-details-by-default: true
sablier-debian-glances:
sablier-${SERVER_HOSTNAME}-glances:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-glances
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-glances
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Glances
theme: ghost
show-details-by-default: true
sablier-debian-homarr:
sablier-${SERVER_HOSTNAME}-homarr:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-homarr
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-homarr
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Homarr
theme: ghost
show-details-by-default: true
sablier-debian-komodo:
sablier-${SERVER_HOSTNAME}-komodo:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-komodo
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-komodo
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Komodo
@@ -217,84 +218,84 @@ http:
show-details-by-default: true
sablier-debian-kopia:
sablier-${SERVER_HOSTNAME}-kopia:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-kopia
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-kopia
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Kopia
theme: ghost
show-details-by-default: true
sablier-debian-openkm:
sablier-${SERVER_HOSTNAME}-openkm:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-openkm
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-openkm
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: OpenKM
theme: ghost
show-details-by-default: true
sablier-debian-openwebui:
sablier-${SERVER_HOSTNAME}-openwebui:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-openwebui
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-openwebui
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: OpenWebUI
theme: ghost
show-details-by-default: true
sablier-debian-pulse:
sablier-${SERVER_HOSTNAME}-pulse:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-pulse
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-pulse
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Pulse
theme: ghost
show-details-by-default: true
sablier-debian-tdarr:
sablier-${SERVER_HOSTNAME}-tdarr:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-tdarr
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-tdarr
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Tdarr
theme: ghost
show-details-by-default: true
sablier-debian-unmanic:
sablier-${SERVER_HOSTNAME}-unmanic:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-unmanic
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-unmanic
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: Unmanic
theme: ghost
show-details-by-default: true
sablier-debian-dokuwiki:
sablier-${SERVER_HOSTNAME}-dokuwiki:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: debian-dokuwiki
sessionDuration: 30m
group: ${SERVER_HOSTNAME}-dokuwiki
sessionDuration: 5m
ignoreUserAgent: curl
dynamic:
displayName: DokuWiki

View File

@@ -2,6 +2,8 @@
# Homepage and Homarr for homelab dashboards
# Place in /opt/stacks/dashboards/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)
@@ -31,6 +33,8 @@ services:
networks:
- homelab-network
- traefik-network
ports:
- "3000:3000"
volumes:
- ./homepage:/app/config
- /var/run/docker.sock:/var/run/docker.sock # For Docker integration do not mount RO
@@ -52,7 +56,7 @@ services:
# Homarr - Modern dashboard
# Access at: https://homarr.${DOMAIN}
# Uses Sablier lazy loading - starts on-demand, stops after 30min inactivity
# Uses Sablier lazy loading - starts on-demand, stops after 5min inactivity
homarr:
image: ghcr.io/ajnart/homarr:latest
deploy:
@@ -69,6 +73,8 @@ services:
networks:
- homelab-network
- traefik-network
ports:
- "7575:7575"
volumes:
- ./homarr/config:/app/config/configs
- ./homarr/data:/data

View File

@@ -4,6 +4,8 @@
# NOTE: Traefik, Authelia, DuckDNS, and Gluetun have their own separate stacks
# See /opt/stacks/traefik/, /opt/stacks/authelia/, etc.
# 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)
@@ -111,7 +113,7 @@ services:
# Dozzle - Real-time Docker log viewer
# Access at: https://dozzle.${DOMAIN}
# Uses Sablier lazy loading - starts on-demand, stops after 30min inactivity
# Uses Sablier lazy loading - starts on-demand, stops after 5min inactivity
dozzle:
image: amir20/dozzle:latest
deploy:
@@ -128,6 +130,8 @@ services:
networks:
- homelab-network
- traefik-network
ports:
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
@@ -166,6 +170,8 @@ services:
networks:
- homelab-network
- traefik-network
ports:
- "61208:61208"
pid: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
@@ -204,6 +210,8 @@ services:
networks:
- homelab-network
- traefik-network
ports:
- "8443:8443"
volumes:
- ./code-server/config:/config
- /opt/stacks:/opt/stacks # Access to all stacks

View File

@@ -2,6 +2,8 @@
# 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)
@@ -16,7 +18,7 @@ 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 30min inactivity
# Uses Sablier lazy loading - starts on-demand, stops after 5min inactivity
jellyfin:
image: jellyfin/jellyfin:10.8.13
deploy:
@@ -34,6 +36,8 @@ services:
- media-network
- homelab-network
- traefik-network
ports:
- "8096:8096"
volumes:
- ./jellyfin/config:/config
- ./jellyfin/cache:/cache
@@ -86,6 +90,8 @@ services:
- media-network
- homelab-network
- traefik-network
ports:
- "8083:8083"
volumes:
- ./calibre-web/config:/config
- /mnt/media/books:/books

View File

@@ -1,6 +1,8 @@
# 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)
@@ -36,6 +38,8 @@ services:
- homelab-network
- traefik-network
- nextcloud-network
ports:
- "80:80"
volumes:
- ./nextcloud/html:/var/www/html
- /mnt/nextcloud-data:/var/www/html/data # Large data on separate drive
@@ -89,6 +93,8 @@ services:
networks:
- homelab-network
- traefik-network
ports:
- "9000:9000"
volumes:
- ./mealie/data:/app/data
environment:
@@ -117,6 +123,8 @@ services:
- homelab-network
- traefik-network
- wordpress-network
ports:
- "80:80"
volumes:
- ./wordpress/html:/var/www/html
environment:
@@ -172,6 +180,8 @@ services:
- homelab-network
- traefik-network
- gitea-network
ports:
- "3000:3000"
volumes:
- ./gitea/data:/data
- /etc/timezone:/etc/timezone:ro
@@ -214,7 +224,7 @@ services:
# DokuWiki - Wiki without database
# Access at: https://wiki.${DOMAIN}
# Uses Sablier lazy loading - starts on-demand, stops after 30min inactivity
# Uses Sablier lazy loading - starts on-demand, stops after 5min inactivity
dokuwiki:
image: lscr.io/linuxserver/dokuwiki:latest
container_name: dokuwiki
@@ -222,6 +232,8 @@ services:
networks:
- homelab-network
- traefik-network
ports:
- "80:80"
volumes:
- ./dokuwiki/config:/config
environment:
@@ -251,6 +263,8 @@ services:
- homelab-network
- traefik-network
- bookstack-network
ports:
- "80:80"
volumes:
- ./bookstack/config:/config
environment:
@@ -304,6 +318,8 @@ services:
- homelab-network
- traefik-network
- mediawiki-network
ports:
- "80:80"
volumes:
- ./mediawiki/images:/var/www/html/images
- ./mediawiki/LocalSettings.php:/var/www/html/LocalSettings.php
@@ -351,6 +367,8 @@ services:
networks:
- homelab-network
- traefik-network
ports:
- "8888:8888"
volumes:
- ./config/jupyter:/home/jovyan/work
environment:

View File

@@ -55,6 +55,7 @@ load_env_file() {
echo "Current configuration:"
echo " Domain: ${DOMAIN:-Not set}"
echo " Server IP: ${SERVER_IP:-Not set}"
echo " Server Hostname: ${SERVER_HOSTNAME:-Not set}"
echo " Admin User: ${AUTHELIA_ADMIN_USER:-Not set}"
echo " Admin Email: ${AUTHELIA_ADMIN_EMAIL:-Not set}"
echo " Timezone: ${TZ:-Not set}"
@@ -79,6 +80,7 @@ save_env_file() {
# Update values
sed -i "s%DOMAIN=.*%DOMAIN=$DOMAIN%" "$REPO_DIR/.env"
sed -i "s%SERVER_IP=.*%SERVER_IP=$SERVER_IP%" "$REPO_DIR/.env"
sed -i "s%SERVER_HOSTNAME=.*%SERVER_HOSTNAME=$SERVER_HOSTNAME%" "$REPO_DIR/.env"
sed -i "s%TZ=.*%TZ=$TZ%" "$REPO_DIR/.env"
# Authelia settings (only if deploying core)
@@ -165,6 +167,13 @@ prompt_for_values() {
[ -n "$input" ] && SERVER_IP="$input"
fi
# Server Hostname
if [ -z "$SERVER_HOSTNAME" ]; then
SERVER_HOSTNAME="debian"
fi
read -p "Server hostname [$SERVER_HOSTNAME] (press Enter to keep current): " input
[ -n "$input" ] && SERVER_HOSTNAME="$input"
# Timezone
if [ -z "$TZ" ]; then
TZ="America/New_York"
@@ -369,6 +378,7 @@ perform_deployment() {
# Replace domain placeholders in traefik dynamic configs
find /opt/stacks/core/traefik/dynamic -name "*.yml" -exec sed -i "s/\${DOMAIN}/${DOMAIN}/g" {} \;
find /opt/stacks/core/traefik/dynamic -name "*.yml" -exec sed -i "s/\${SERVER_HOSTNAME}/${SERVER_HOSTNAME}/g" {} \;
if [ -d "/opt/stacks/core/authelia" ]; then
mv /opt/stacks/core/authelia /opt/stacks/core/authelia.backup.$(date +%Y%m%d_%H%M%S)

View File

@@ -0,0 +1,901 @@
This file contains the current configuration for Traefik & Sablier on the server jarvis (192.168.4.4)
This configuration was working in a previous test round.
external-host-jarvis.yml
```yaml
http:
routers:
backrest-jarvis:
rule: "Host(`backrest.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: backrest-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-backrest@file
- authelia@docker
bookstack-jarvis:
rule: "Host(`bookstack.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: bookstack-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-bookstack@file
- authelia@docker
bitwarden-jarvis:
rule: "Host(`bitwarden.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: bitwarden-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-bitwarden@file
- authelia@docker
calibre-web-jarvis:
rule: "Host(`calibre.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: calibre-web-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-calibre-web@file
- authelia@docker
code-jarvis:
rule: "Host(`code.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: code-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-code-server@file
- authelia@docker
dockge-jarvis:
rule: "Host(`jarvis.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: dockge-jarvis
tls:
certResolver: letsencrypt
middlewares:
- authelia@docker
dockhand-jarvis:
rule: "Host(`dockhand.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: dockhand-jarvis
tls:
certResolver: letsencrypt
middlewares:
- authelia@docker
dokuwiki-jarvis:
rule: "Host(`wiki.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: dokuwiki-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-dokuwiki@file
- authelia@docker
dozzle-jarvis:
rule: "Host(`dozzle.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: dozzle-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-dozzle@file
- authelia@docker
duplicati-jarvis:
rule: "Host(`duplicati.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: duplicati-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-duplicati@file
- authelia@docker
formio-jarvis:
rule: "Host(`formio.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: formio-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-formio@file
- authelia@docker
gitea-jarvis:
rule: "Host(`gitea.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: gitea-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-gitea@file
- authelia@docker
glances-jarvis:
rule: "Host(`glances.jarvis.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: glances-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-glances@file
- authelia@docker
homepage-jarvis:
rule: "Host(`homepage.jarvis.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: homepage-jarvis
tls:
certResolver: letsencrypt
middlewares:
- authelia@docker
homarr-jarvis:
rule: "Host(`homarr.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: homarr-jarvis
tls:
certResolver: letsencrypt
middlewares:
- authelia@docker
- sablier-jarvis-homarr@file
jellyfin-jarvis:
rule: "Host(`jellyfin.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: jellyfin-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-jellyfin@file
# No authelia middleware for media apps
kopia-jarvis:
rule: "Host(`kopia.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: kopia-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-kopia@file
- authelia@docker
mealie-jarvis:
rule: "Host(`mealie.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: mealie-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-mealie@file
- authelia@docker
motioneye-jarvis:
rule: "Host(`motioneye.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: motioneye-jarvis
tls:
certResolver: letsencrypt
middlewares:
- authelia@docker
mediawiki-jarvis:
rule: "Host(`mediawiki.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: mediawiki-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-mediawiki@file
- authelia@docker
nextcloud-jarvis:
rule: "Host(`nextcloud.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: nextcloud-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-nextcloud@file
- authelia@docker
openkm-jarvis:
rule: "Host(`openkm.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: openkm-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-openkm@file
- authelia@docker
openwebui-jarvis:
rule: "Host(`openwebui.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: openwebui-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-openwebui@file
- authelia@docker
qbittorrent-jarvis:
rule: "Host(`torrents.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: qbittorrent-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- authelia@docker
tdarr-jarvis:
rule: "Host(`tdarr.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: tdarr-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- authelia@docker
unmanic-jarvis:
rule: "Host(`unmanic.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: unmanic-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-unmanic@file
- authelia@docker
wordpress-jarvis:
rule: "Host(`knot-u.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: wordpress-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-wordpress@file
- authelia@file
# Arr Services (no SSO for media apps)
jellyseerr-jarvis:
rule: "Host(`jellyseerr.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: jellyseerr-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- authelia@docker
prowlarr-jarvis:
rule: "Host(`prowlarr.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: prowlarr-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- authelia@docker
radarr-jarvis:
rule: "Host(`radarr.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: radarr-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- authelia@docker
sonarr-jarvis:
rule: "Host(`sonarr.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: sonarr-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- authelia@docker
lidarr-jarvis:
rule: "Host(`lidarr.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: lidarr-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- authelia@docker
readarr-jarvis:
rule: "Host(`readarr.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: readarr-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- authelia@docker
mylar3-jarvis:
rule: "Host(`mylar3.kelinreij.duckdns.org`)"
entryPoints:
- websecure
service: mylar3-jarvis
tls:
certResolver: letsencrypt
middlewares:
- sablier-jarvis-arr@file
- authelia@docker
services:
backrest-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:9898"
passHostHeader: true
bitwarden-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8000"
passHostHeader: true
bookstack-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:6875"
passHostHeader: true
calibre-web-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8083"
passHostHeader: true
code-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8079"
passHostHeader: true
dockge-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:5001"
passHostHeader: true
dockhand-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:3003"
passHostHeader: true
dokuwiki-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8087"
passHostHeader: true
dozzle-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8085"
passHostHeader: true
duplicati-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8200"
passHostHeader: true
formio-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:3002"
passHostHeader: true
gitea-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:3010"
passHostHeader: true
glances-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:61208"
passHostHeader: true
homarr-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:7575"
passHostHeader: true
homepage-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:3000"
passHostHeader: true
jellyfin-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8096"
passHostHeader: true
kopia-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:51515"
passHostHeader: true
mealie-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:9000"
passHostHeader: true
mediawiki-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8084"
passHostHeader: true
motioneye-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8081"
passHostHeader: true
nextcloud-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8089"
passHostHeader: true
openkm-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:18080"
passHostHeader: true
openwebui-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:3004"
passHostHeader: true
qbittorrent-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8080"
passHostHeader: true
tdarr-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8265"
passHostHeader: true
unmanic-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8888"
passHostHeader: true
wordpress-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8088"
passHostHeader: true
# Arr Services
jellyseerr-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:5055"
passHostHeader: true
prowlarr-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:9696"
passHostHeader: true
radarr-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:7878"
passHostHeader: true
sonarr-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8989"
passHostHeader: true
lidarr-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8686"
passHostHeader: true
readarr-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8787"
passHostHeader: true
mylar3-jarvis:
loadBalancer:
servers:
- url: "http://192.168.4.11:8090"
passHostHeader: true
```
sablier.yml
```yaml
http:
middlewares:
sablier-jarvis-arr:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-arr
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: Arr Apps
theme: ghost
show-details-by-default: true
sablier-jarvis-backrest:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-backrest
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: Backrest
theme: ghost
show-details-by-default: true
sablier-jarvis-bookstack:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-bookstack
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: Bookstack
theme: ghost
show-details-by-default: true
sablier-jarvis-jellyfin:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-jellyfin
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: Jellyfin
theme: ghost
show-details-by-default: true
sablier-jarvis-calibre-web:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-calibre-web
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: Calibre Web
theme: ghost
show-details-by-default: true
sablier-jarvis-code-server:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-code-server
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: Code Server
theme: ghost
show-details-by-default: true
sablier-jarvis-bitwarden:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-bitwarden
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: bitwarden
theme: ghost
show-details-by-default: true
sablier-jarvis-wordpress:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-wordpress
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: wordpress
theme: ghost
show-details-by-default: true
sablier-jarvis-nextcloud:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-nextcloud
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: NextCloud
theme: ghost
show-details-by-default: true
sablier-jarvis-mediawiki:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-mediawiki
sessionDuration: 2m
ignoreUserAgent: curl
dynamic:
displayName: mediawiki
theme: ghost
show-details-by-default: true
sablier-jarvis-mealie:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-mealie
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: Mealie
theme: ghost
show-details-by-default: true
sablier-jarvis-gitea:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-gitea
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: Gitea
theme: ghost
show-details-by-default: true
sablier-jarvis-formio:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-formio
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: FormIO
theme: ghost
show-details-by-default: true
sablier-jarvis-dozzle:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-dozzle
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: dozzle
theme: ghost
show-details-by-default: true
sablier-jarvis-duplicati:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-duplicati
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: Duplicati
theme: ghost
show-details-by-default: true
sablier-jarvis-glances:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-glances
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: Glances
theme: ghost
show-details-by-default: true
sablier-jarvis-homarr:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-homarr
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: Homarr
theme: ghost
show-details-by-default: true
sablier-jarvis-komodo:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-komodo
sessionDuration: 2m
ignoreUserAgent: curl
dynamic:
displayName: Komodo
theme: ghost
show-details-by-default: true
sablier-jarvis-kopia:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-kopia
sessionDuration: 2m
ignoreUserAgent: curl
dynamic:
displayName: Kopia
theme: ghost
show-details-by-default: true
sablier-jarvis-openkm:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-openkm
sessionDuration: 2m
ignoreUserAgent: curl
dynamic:
displayName: OpenKM
theme: ghost
show-details-by-default: true
sablier-jarvis-openwebui:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: openwebui-jarvis
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: OpenWebUI
theme: ghost
show-details-by-default: true
sablier-jarvis-pulse:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-pulse
sessionDuration: 2m
ignoreUserAgent: curl
dynamic:
displayName: Pulse
theme: ghost
show-details-by-default: true
sablier-jarvis-tdarr:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-tdarr
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: Tdarr
theme: ghost
show-details-by-default: true
sablier-jarvis-unmanic:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-unmanic
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: Unmanic
theme: ghost
show-details-by-default: true
sablier-jarvis-dokuwiki:
plugin:
sablier:
sablierUrl: http://sablier-service:10000
group: jarvis-dokuwiki
sessionDuration: 30m
ignoreUserAgent: curl
dynamic:
displayName: DokuWiki
theme: ghost
show-details-by-default: true
authelia:
forwardauth:
address: http://authelia:9091/api/verify?rd=https://auth.kelinreij.duckdns.org/
authResponseHeaders:
- X-Secret
trustForwardHeader: true
```