diff --git a/.gitignore b/.gitignore index 9fffd3b..ab48ca3 100644 --- a/.gitignore +++ b/.gitignore @@ -190,6 +190,10 @@ backup-scripts/* !backups backups/* +# Include the compose directory +!compose +!compose/* + # Include the .github directory !.github !.github/* diff --git a/appdata/traefik2/rules/middlewares-chains.yml b/appdata/traefik2/rules/middlewares-chains.yml index aca8f46..e5da77a 100644 --- a/appdata/traefik2/rules/middlewares-chains.yml +++ b/appdata/traefik2/rules/middlewares-chains.yml @@ -48,3 +48,11 @@ http: - middlewares-rate-limit - nextcloud-middlewares-secure-headers - nextcloud-redirect + + chain-audiobookshelf: + chain: + middlewares: + - middlewares-rate-limit + - middlewares-secure-headers-audiobookshelf + ## Need to use audiobookshelf authentication + # - middlewares-authelia diff --git a/appdata/traefik2/rules/middlewares.yml b/appdata/traefik2/rules/middlewares.yml index ae04641..43d3ce1 100644 --- a/appdata/traefik2/rules/middlewares.yml +++ b/appdata/traefik2/rules/middlewares.yml @@ -46,6 +46,39 @@ http: X-Robots-Tag: "none,noarchive,nosnippet,notranslate,noimageindex," server: "" + middlewares-secure-headers-audiobookshelf: + headers: + ## Disable per https://github.com/advplyr/audiobookshelf/blob/32da0f12242602ae18b858eaf8a4faa48cffb7a9/readme.md?plain=1#L246-L254 + # accessControlAllowMethods: + # - GET + # - OPTIONS + # - PUT + # accessControlMaxAge: 100 + hostsProxyHeaders: + - "X-Forwarded-Host" + stsSeconds: 63072000 + stsIncludeSubdomains: true + stsPreload: true + forceSTSHeader: true + # frameDeny: true # Overwritten by customFrameOptionsValue + ## CSP takes care of this but may be needed for organizr. + customFrameOptionsValue: 'allow-from https:{{env "DOMAINNAME0"}}' + contentTypeNosniff: true + browserXssFilter: true + # sslForceHost: true # Add sslHost to all of the services + # sslHost: "{{env "DOMAINNAME0"}}" + referrerPolicy: "same-origin" + ## Setting contentSecurityPolicy is more secure but it can break + ## things. Proper auth will reduce the risk. The below line also breaks + ## some apps due to 'none' - sonarr, radarr, etc. + ## yamllint disable-line rule:line-length + # contentSecurityPolicy: "frame-ancestors '*.{{env "DOMAINNAME0"}}:*';object-src 'none';script-src 'none';" + ## yamllint disable-line rule:line-length + permissionsPolicy: "camera 'none'; geolocation 'none'; microphone 'none'; payment 'none'; usb 'none'; vr 'none';" + customResponseHeaders: + X-Robots-Tag: "none,noarchive,nosnippet,notranslate,noimageindex," + server: "" + ## Documentation: https://www.authelia.com/integration/proxies/traefik/ middlewares-authelia: forwardAuth: diff --git a/compose/adminer.yml b/compose/adminer.yml new file mode 100644 index 0000000..ffaaa7e --- /dev/null +++ b/compose/adminer.yml @@ -0,0 +1,26 @@ +--- +services: + ## Adminer - Database management in a single PHP file. + adminer: + container_name: adminer + image: adminer:latest + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + environment: + ## https://github.com/vrana/adminer/tree/master/designs + # ADMINER_DESIGN: 'nette' + ADMINER_DEFAULT_SERVER: postgres + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.adminer-rtr.entrypoints=https" + - "traefik.http.routers.adminer-rtr.rule=Host(`adminer.$DOMAINNAME0`)" + - "traefik.http.routers.adminer-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.adminer-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.adminer-rtr.service=adminer-svc" + - "traefik.http.services.adminer-svc.loadbalancer.server.port=8080" diff --git a/compose/audiobookshelf.yml b/compose/audiobookshelf.yml new file mode 100644 index 0000000..5820385 --- /dev/null +++ b/compose/audiobookshelf.yml @@ -0,0 +1,33 @@ +--- +services: + # audiobookshelf - Self-hosted audiobook and podcast server + audiobookshelf: + image: ghcr.io/advplyr/audiobookshelf:latest + container_name: audiobookshelf + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/audiobookshelf/config:/config + - $DATADIR/media/audiobooks:/audiobooks + - $DATADIR/media/podcasts:/podcasts + ## Could be in $DATADIR to minimize storage usage on host + - $APPDIR/audiobookshelf/metadata:/metadata + environment: + # HOST: 127.0.0.1 + PORT: $AUDIOBOOKSHELF_PORT + SOURCE: docker + ALLOW_CORS: 1 + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.audiobookshelf-rtr.entrypoints=https" + - "traefik.http.routers.audiobookshelf-rtr.rule=Host(`abs.$DOMAINNAME0`)" + - "traefik.http.routers.audiobookshelf-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.audiobookshelf-rtr.middlewares=chain-audiobookshelf@file" + ## HTTP Services + - "traefik.http.routers.audiobookshelf-rtr.service=audiobookshelf-svc" + - "traefik.http.services.audiobookshelf-svc.loadbalancer.server.port=$AUDIOBOOKSHELF_PORT" diff --git a/compose/authelia.yml b/compose/authelia.yml new file mode 100644 index 0000000..1a53bd7 --- /dev/null +++ b/compose/authelia.yml @@ -0,0 +1,68 @@ +--- +secrets: + authelia_duo_api_secret_key: + file: $SECRETSDIR/authelia_duo_api_secret_key + authelia_identity_validation_reset_password_jwt_secret_file: + ## https://www.grc.com/passwords.htm + file: $SECRETSDIR/authelia_identity_validation_reset_password_jwt_secret_file + authelia_notifier_smtp_password: + file: $SECRETSDIR/authelia_notifier_smtp_password + authelia_session_redis_password: + file: $SECRETSDIR/authelia_session_redis_password + authelia_session_secret: + file: $SECRETSDIR/authelia_session_secret + authelia_storage_encryption_key: + file: $SECRETSDIR/authelia_storage_encryption_key + authelia_storage_mysql_password: + file: $SECRETSDIR/authelia_storage_mysql_password +services: + ## Authelia (Lite) - Self-Hosted Single Sign-On and Two-Factor Authentication + ## For configuration file template see + ## https://github.com/authelia/authelia/blob/master/config.template.yml + authelia: + container_name: authelia + ## Check this before upgrading: + ## https://github.com/authelia/authelia#breaking-changes + image: ghcr.io/authelia/authelia:4.38 + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: always + ## Allow for separate configuration and acl configuration files + ## See https://www.authelia.com/configuration/methods/files/#docker-compose + volumes: + - $APPDIR/authelia/config/configuration.yml:/config/configuration.yml + - $APPDIR/authelia/config/configuration.acl.yml:/config/configuration.acl.yml + - $APPDIR/authelia/config/users_database.yml:/config/users_database.yml + environment: + ## Using PUID:PGID causes container to be unable to read secrets + # <<: *default-tz-puid-pgid + TZ: $TZ + AUTHELIA_SESSION_SECRET_FILE: /run/secrets/authelia_session_secret + X_AUTHELIA_CONFIG: /config/configuration.yml,/config/configuration.acl.yml + AUTHELIA_DUO_API_SECRET_KEY_FILE: /run/secrets/authelia_duo_api_secret_key + AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE: /run/secrets/authelia_identity_validation_reset_password_jwt_secret_file + AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE: /run/secrets/authelia_notifier_smtp_password + AUTHELIA_SESSION_REDIS_PASSWORD_FILE: /run/secrets/authelia_session_redis_password + AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE: /run/secrets/authelia_storage_encryption_key + AUTHELIA_STORAGE_MYSQL_PASSWORD_FILE: /run/secrets/authelia_storage_mysql_password + secrets: + - authelia_identity_validation_reset_password_jwt_secret_file + - authelia_session_secret + - authelia_session_redis_password + - authelia_storage_mysql_password + - authelia_notifier_smtp_password + - authelia_duo_api_secret_key + - authelia_storage_encryption_key + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.authelia-rtr.entrypoints=https" + - "traefik.http.routers.authelia-rtr.rule=Host(`auth.$DOMAINNAME0`)" + - "traefik.http.routers.authelia-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.authelia-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.authelia-rtr.service=authelia-svc" + - "traefik.http.services.authelia-svc.loadbalancer.server.port=$AUTHELIA_PORT" diff --git a/compose/authentik.yml b/compose/authentik.yml new file mode 100644 index 0000000..0826f9c --- /dev/null +++ b/compose/authentik.yml @@ -0,0 +1,167 @@ +--- +secrets: + authentik_email__password: + file: $SECRETSDIR/authentik_email__password + authentik_postgresql__name: + file: $SECRETSDIR/authentik_postgresql__name + authentik_postgresql__user: + file: $SECRETSDIR/authentik_postgresql__user + authentik_postgresql__password: + file: $SECRETSDIR/authentik_postgresql__password + authentik_redis__password: + file: $SECRETSDIR/authentik_redis__password + authentik_secret_key: + file: $SECRETSDIR/authentik_secret_key + authentik_token_ldap: + file: $SECRETSDIR/authentik_token_ldap +services: + ## Authentik - an open-source Identity Provider, focused on flexibility and + ## versatility + authentik: + container_name: authentik + image: ghcr.io/goauthentik/server:latest + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: always + command: server + # ports: + # - "$AUTHENTIK_PORT:$AUTHENTIK_PORT" + volumes: + - $APPDIR/authentik/media:/media + - $APPDIR/authentik/templates:/templates + environment: + ## https://goauthentik.io/docs/installation/configuration + ## Test configuration with `dcrun2 run --rm authentik-server dump_config` + ## Use `file://` prefix to load from docker secret + ## https://goauthentik.io/docs/installation/configuration#about-authentik-configurations + COMPOSE_PORT_HTTP: $AUTHENTIK_PORT + # COMPOSE_PORT_HTTPS: + AUTHENTIK_POSTGRESQL__HOST: $POSTGRES_HOST + AUTHENTIK_POSTGRESQL__NAME: file:///run/secrets/authentik_postgresql__name + AUTHENTIK_POSTGRESQL__USER: file:///run/secrets/authentik_postgresql__user + AUTHENTIK_POSTGRESQL__PORT: $POSTGRES_PORT + AUTHENTIK_POSTGRESQL__PASSWORD: file:///run/secrets/authentik_postgresql__password + AUTHENTIK_REDIS__HOST: $REDIS_HOST + AUTHENTIK_REDIS__PORT: $REDIS_PORT + # AUTHENTIK_REDIS__USERNAME: $REDIS_USER + AUTHENTIK_REDIS__PASSWORD: file:///run/secrets/authentik_redis__password + AUTHENTIK_LISTEN__HTTP: "0.0.0.0:${AUTHENTIK_PORT}" + # AUTHENTIK_LISTEN__HTTPS: "0.0.0.0:" + AUTHENTIK_LISTEN__LDAP: "0.0.0.0:${AUTHENTIK_LDAP_PORT}" + AUTHENTIK_LISTEN__LDAPS: "0.0.0.0:${AUTHENTIK_LDAPS_PORT}" + AUTHENTIK_LISTEN__METRICS: "0.0.0.0:${AUTHENTIK_METRICS_PORT}" + AUTHENTIK_LISTEN__DEBUG: "0.0.0.0:${AUTHENTIK_DEBUG_PORT}" + # AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS: + AUTHENTIK_SECRET_KEY: file:///run/secrets/authentik_secret_key + AUTHENTIK_LOG_LEVEL: info # trace, debug, info, warning, error + AUTHENTIK_COOKIE_DOMAIN: $DOMAINNAME0 + # AUTHENTIK_ERROR_REPORTING__ENABLED: 'true' + AUTHENTIK_EMAIL__HOST: $EMAIL_SERVER + AUTHENTIK_EMAIL__PORT: $EMAIL_SERVER_PORT + AUTHENTIK_EMAIL__USERNAME: $EMAIL_SERVER_USER + AUTHENTIK_EMAIL__PASSWORD: file:///run/secrets/authentik_email__password + AUTHENTIK_EMAIL__USE_TLS: "false" + AUTHENTIK_EMAIL__USE_SSL: "true" + AUTHENTIK_EMAIL__TIMEOUT: 10 + AUTHENTIK_EMAIL__FROM: server@authentik.$DOMAINNAME0 + AUTHENTIK_AVATARS: initials + AUTHENTIK_DEFAULT_USER_CHANGE_NAME: "true" + AUTHENTIK_DEFAULT_USER_CHANGE_EMAIL: "true" + AUTHENTIK_DEFAULT_USER_CHANGE_USERNAME: "true" + AUTHENTIK_GDPR_COMPLIANCE: "true" + # AUTHENTIK_DEFAULT_TOKEN_LENGTH: + AUTHENTIK_IMPERSONATION: "true" + # AUTHENTIK_FOOTER_LINKS: + # COMPOSE_PORT_HTTPS: + secrets: + - authentik_postgresql__name + - authentik_postgresql__user + - authentik_postgresql__password + - authentik_redis__password + - authentik_secret_key + - authentik_email__password + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.authentik-rtr.entrypoints=https" + - "traefik.http.routers.authentik-rtr.rule=Host(`authentik.$DOMAINNAME0`)" + - "traefik.http.routers.authentik-rtr.tls.options=tls-opts@file" + ## Middlewares + ## Do not use authentication, but use rate limiting and secure headers + - "traefik.http.routers.authentik-rtr.middlewares=chain-no-auth@file" + ## HTTP Services + - "traefik.http.routers.authentik-rtr.service=authentik-svc" + - "traefik.http.services.authentik-svc.loadbalancer.server.port=$AUTHENTIK_PORT" + + authentik-worker: + container_name: authentik-worker + image: ghcr.io/goauthentik/server:latest + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: always + command: worker + ## `user: root` and the docker socket volume are optional. + ## See more for the docker socket integration here: + ## https://goauthentik.io/docs/outposts/integrations/docker + ## Removing `user: root` also prevents the worker from fixing the + ## permissions on the mounted folders, so when removing this make sure the + ## folders have the correct UID/GID (1000:1000 by default) + user: root + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - $APPDIR/authentik/media:/media + - $APPDIR/authentik/certs:/certs + - $APPDIR/authentik/templates:/templates + environment: + ## https://goauthentik.io/docs/installation/configuration + ## Test configuration with `dcrun2 run --rm authentik-server dump_config` + ## Use `file://` prefix to load from docker secret + ## https://goauthentik.io/docs/installation/configuration#about-authentik-configurations + AUTHENTIK_POSTGRESQL__HOST: $POSTGRES_HOST + AUTHENTIK_POSTGRESQL__NAME: "file:///run/secrets/authentik_postgresql__name" + AUTHENTIK_POSTGRESQL__USER: "file:///run/secrets/authentik_postgresql__user" + AUTHENTIK_POSTGRESQL__PORT: $POSTGRES_PORT + AUTHENTIK_POSTGRESQL__PASSWORD: "file:///run/secrets/authentik_postgresql__password" + AUTHENTIK_REDIS__HOST: $REDIS_HOST + AUTHENTIK_REDIS__PORT: $REDIS_PORT + # AUTHENTIK_REDIS__USERNAME: $REDIS_USER + AUTHENTIK_REDIS__PASSWORD: "file:///run/secrets/authentik_redis__password" + AUTHENTIK_LISTEN__HTTP: "0.0.0.0:${AUTHENTIK_PORT}" + # AUTHENTIK_LISTEN__HTTPS: "0.0.0.0:" + AUTHENTIK_LISTEN__LDAP: "0.0.0.0:${AUTHENTIK_LDAP_PORT}" + AUTHENTIK_LISTEN__LDAPS: "0.0.0.0:${AUTHENTIK_LDAPS_PORT}" + AUTHENTIK_LISTEN__METRICS: "0.0.0.0:${AUTHENTIK_METRICS_PORT}" + AUTHENTIK_LISTEN__DEBUG: "0.0.0.0:${AUTHENTIK_DEBUG_PORT}" + # AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS: + AUTHENTIK_SECRET_KEY: "file:///run/secrets/authentik_secret_key" + AUTHENTIK_LOG_LEVEL: info # trace, debug, info, warning, error + AUTHENTIK_COOKIE_DOMAIN: authentik.$DOMAINNAME0 + # AUTHENTIK_ERROR_REPORTING__ENABLED: 'true' + AUTHENTIK_EMAIL__HOST: $EMAIL_SERVER + AUTHENTIK_EMAIL__PORT: $EMAIL_SERVER_PORT + AUTHENTIK_EMAIL__USERNAME: $EMAIL_SERVER_USER + AUTHENTIK_EMAIL__PASSWORD: "file:///run/secrets/authentik_email__password" + AUTHENTIK_EMAIL__USE_TLS: "false" + AUTHENTIK_EMAIL__USE_SSL: "true" + AUTHENTIK_EMAIL__TIMEOUT: 10 + AUTHENTIK_EMAIL__FROM: server@authentik.$DOMAINNAME0 + AUTHENTIK_AVATARS: initials + AUTHENTIK_DEFAULT_USER_CHANGE_NAME: "true" + AUTHENTIK_DEFAULT_USER_CHANGE_EMAIL: "true" + AUTHENTIK_DEFAULT_USER_CHANGE_USERNAME: "true" + AUTHENTIK_GDPR_COMPLIANCE: "true" + # AUTHENTIK_DEFAULT_TOKEN_LENGTH: + AUTHENTIK_IMPERSONATION: "true" + # AUTHENTIK_FOOTER_LINKS: + # COMPOSE_PORT_HTTPS: + secrets: + - authentik_postgresql__name + - authentik_postgresql__user + - authentik_postgresql__password + - authentik_redis__password + - authentik_secret_key + - authentik_email__password diff --git a/compose/bazarr.yml b/compose/bazarr.yml new file mode 100644 index 0000000..e0ab321 --- /dev/null +++ b/compose/bazarr.yml @@ -0,0 +1,37 @@ +--- +services: + # Bazarr - Subtitle Management + bazarr: + image: lscr.io/linuxserver/bazarr + container_name: bazarr + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/bazarr/config:/config + - $DATADIR/media:/data/media + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + labels: + - "traefik.enable=true" + ## HTTP Routers API Auth Bypass + - "traefik.http.routers.bazarr-rtr-bypass.entrypoints=https" + - "traefik.http.routers.bazarr-rtr-bypass.rule=Host(`bazarr.$DOMAINNAME0`) && (Header(`X-Api-Key`, `$BAZARR_API_KEY`) || Query(`apikey`, `$BAZARR_API_KEY`))" + - "traefik.http.routers.bazarr-rtr-bypass.tls.options=tls-opts@file" + - "traefik.http.routers.bazarr-rtr-bypass.priority=100" + ## HTTP Routers + - "traefik.http.routers.bazarr-rtr.entrypoints=https" + - "traefik.http.routers.bazarr-rtr.rule=Host(`bazarr.$DOMAINNAME0`)" + - "traefik.http.routers.bazarr-rtr.tls.options=tls-opts@file" + - "traefik.http.routers.bazarr-rtr.priority=99" + ## Middlewares + - "traefik.http.routers.bazarr-rtr-bypass.middlewares=chain-no-auth@file" + - "traefik.http.routers.bazarr-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.bazarr-rtr-bypass.service=bazarr-svc" + - "traefik.http.routers.bazarr-rtr.service=bazarr-svc" + - "traefik.http.services.bazarr-svc.loadbalancer.server.port=6767" diff --git a/compose/bluebubbles.yml b/compose/bluebubbles.yml new file mode 100644 index 0000000..8430e4c --- /dev/null +++ b/compose/bluebubbles.yml @@ -0,0 +1,78 @@ +--- +services: + ## BlueBubbles - Bringing iMessage to Windows, Linux, and Android + ## Stopped due to issues with keeping the container alive and usable + bluebubbles-setup: + image: sickcodes/docker-osx:ventura + container_name: bluebubbles-setup + networks: + - t2_proxy + security_opt: + - no-new-privileges:false + restart: unless-stopped + # privileged: true + # network_mode: "host" + # cap_add: + # - ALL + user: "${PUID}:${PGID}" + devices: + - /dev/kvm + ports: + - $BLUEBUBBLES_VNC_PORT:5999 + environment: + IMAGE_PATH: /image + EXTRA: -display none -vnc 0.0.0.0:99,password-secret=secvnc0 -object secret,id=secvnc0,data=$BLUEBUBBLES_VNC_PASSWORD + DISPLAY: ":99" + WIDTH: 1920 + HEIGHT: 1080 + GENERATE_UNIQUE: true + volumes: + - /tmp/.X11-unix:/tmp/.X11-unix + - $DATADIR/docker/bluebubbles/maindisk.qcow2:/image + + # BlueBubbles - Bringing iMessage to Windows, Linux, and Android + # Stopped due to issues with keeping the container alive and usable + bluebubbles: + image: sickcodes/docker-osx:naked + container_name: bluebubbles + networks: + - t2_proxy + security_opt: + - no-new-privileges:false + restart: unless-stopped + # privileged: true + # network_mode: "host" + # cap_add: + # - ALL + user: "${PUID}:${PGID}" + devices: + - /dev/kvm + ports: + ## Must connect to the server via VPN to have access to VNC + - $BLUEBUBBLES_VNC_PORT:$BLUEBUBBLES_VNC_PORT + - $BLUEBUBBLES_SERVER_PORT:$BLUEBUBBLES_SERVER_PORT + - 50922:10022 + environment: + DISPLAY: ${DISPLAY:-:0.0} + IMAGE_PATH: /image + BOOTDISK: /bootdisk + EXTRA: -display none -vnc 0.0.0.0:99,password-secret=secvnc0 -object secret,id=secvnc0,data=$BLUEBUBBLES_VNC_PASSWORD + ADDITIONAL_PORTS: "hostfwd=tcp::$BLUEBUBBLES_SERVER_PORT-:$BLUEBUBBLES_SERVER_PORT," + # DISPLAY: ":99" + WIDTH: 1920 + HEIGHT: 1080 + NOPICKER: true + volumes: + - /tmp/.X11-unix:/tmp/.X11-unix + - $DATADIR/docker/bluebubbles/maindisk.qcow2:/image + - $DATADIR/docker/bluebubbles/bootdisk.qcow2:/bootdisk + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.bluebubbles-rtr.entrypoints=https" + - "traefik.http.routers.bluebubbles-rtr.rule=Host(`bluebubbles.$DOMAINNAME0`)" + ## Middlewares + - "traefik.http.routers.bluebubbles-rtr.middlewares=chain-no-auth@file" + ## HTTP Services + - "traefik.http.routers.bluebubbles-rtr.service=bluebubbles-svc" + - "traefik.http.services.bluebubbles-svc.loadbalancer.server.port=$BLUEBUBBLES_SERVER_PORT" diff --git a/compose/calibre-web.yml b/compose/calibre-web.yml new file mode 100644 index 0000000..3d734b2 --- /dev/null +++ b/compose/calibre-web.yml @@ -0,0 +1,31 @@ +--- +services: + ## Calibre-Web - A web app that offers a clean and intuitive interface for + ## browsing, reading, and downloading eBooks using a valid Calibre database. + calibre-web: + image: lscr.io/linuxserver/calibre-web:latest + container_name: calibre-web + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + DOCKER_MODS: linuxserver/mods:universal-calibre + volumes: + - $APPDIR/calibre-web/config:/config + - "$DATADIR/media/Calibre Library:/books" + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.calibre-web-rtr.entrypoints=https" + - "traefik.http.routers.calibre-web-rtr.rule=Host(`calibre-web.$DOMAINNAME0`)" + - "traefik.http.routers.calibre-web-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.calibre-web-rtr.middlewares=chain-no-auth@file" + ## HTTP Services + - "traefik.http.routers.calibre-web-rtr.service=calibre-web-svc" + - "traefik.http.services.calibre-web-svc.loadbalancer.server.port=8083" diff --git a/compose/calibre.yml b/compose/calibre.yml new file mode 100644 index 0000000..9bb1b3c --- /dev/null +++ b/compose/calibre.yml @@ -0,0 +1,46 @@ +--- +services: + ## Calibre - A powerful and easy to use e-book manager. + calibre: + image: lscr.io/linuxserver/calibre:latest + container_name: calibre + networks: + - t2_proxy + security_opt: + ## Required for some setups + - seccomp:unconfined + - no-new-privileges:true + restart: unless-stopped + devices: + - /dev/dri:/dev/dri + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + # CLI_ARGS: + CUSTOM_PORT: $CALIBRE_PORT + # CUSTOM_HTTPS_PORT: $CALIBRE_HTTPS_PORT + # CUSTOM_USER: + ## Use reverse proxy authentication instead + # PASSWORD: + # SUBFOLDER: + TITLE: Calibre + FM_HOME: /import + ## Set to FALSE to disable DinD Docker setup + # START_DOCKER: + DRI_NODE: /dev/dri/renderD128 + volumes: + - $APPDIR/calibre/config:/config + - "$DATADIR/media/Calibre Library:/books" + - $DATADIR/torrents-private/books:/import:ro + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.calibre-rtr.entrypoints=https" + - "traefik.http.routers.calibre-rtr.rule=Host(`calibre.$DOMAINNAME0`)" + - "traefik.http.routers.calibre-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.calibre-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.calibre-rtr.service=calibre-svc" + - "traefik.http.services.calibre-svc.loadbalancer.server.port=$CALIBRE_PORT" diff --git a/compose/cf-ddns.yml b/compose/cf-ddns.yml new file mode 100644 index 0000000..a0b8316 --- /dev/null +++ b/compose/cf-ddns.yml @@ -0,0 +1,30 @@ +--- +secrets: + cloudflare_ddns_api_token: + ## Not currently working + file: $SECRETSDIR/cloudflare_ddns_api_token +services: + ## Cloudflare DDNS - Dynamic DNS service to update Cloudflare DNS records + cf-ddns: + container_name: cf-ddns + image: favonia/cloudflare-ddns:1 + restart: always + user: "${PUID}:${PGID}" + cap_drop: + - all + read_only: true + security_opt: + - no-new-privileges:true + volumes: + - $APPDIR/cf-ddns/config/cloudflare_ddns_api_token:/cloudflare_ddns_api_token:ro + ## Environmental variables deprecated + environment: + TZ: $TZ + CLOUDFLARE_API_TOKEN_FILE: "/cloudflare_ddns_api_token" + DOMAINS: $DOMAINNAME0 + PROXIED: "true" + UPDATE_CRON: "*/5 * * * *" + RECORD_COMMENT: "Updated with cf-ddns" + # SHOUTRRR: # TODO + # secrets: + # - cloudflare_ddns_api_token diff --git a/compose/docker-gc.yml b/compose/docker-gc.yml new file mode 100644 index 0000000..899bbb0 --- /dev/null +++ b/compose/docker-gc.yml @@ -0,0 +1,30 @@ +--- +services: + ## Docker-GC - Automatic Docker Garbage Collection + ## Create docker-gc-exclude file + docker-gc: + image: clockworksoul/docker-gc-cron:latest + container_name: docker-gc + networks: + - socket_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + depends_on: + - socket-proxy + volumes: + ## Use Docker Socket Proxy instead for improved security + # - /var/run/docker.sock:/var/run/docker.sock + ## Must create this folder + - $APPDIR/docker-gc/config/docker-gc-exclude:/etc/docker-gc-exclude + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + CRON: "0 0 0 * * ?" # Everyday at midnight. Previously "0 0 * * *" + FORCE_IMAGE_REMOVAL: 1 + FORCE_CONTAINER_REMOVAL: 0 + GRACE_PERIOD_SECONDS: 604800 + DRY_RUN: 0 + CLEAN_UP_VOLUMES: 1 + DOCKER_HOST: tcp://socket-proxy:2375 diff --git a/compose/dozzle.yml b/compose/dozzle.yml new file mode 100644 index 0000000..e3c5050 --- /dev/null +++ b/compose/dozzle.yml @@ -0,0 +1,42 @@ +--- +services: + ## Dozzle - Real-time Docker Log Viewer + dozzle: + image: amir20/dozzle:latest + container_name: dozzle + networks: + - t2_proxy + - socket_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + depends_on: + - socket-proxy + healthcheck: + test: ["CMD", "/dozzle", "healthcheck"] + interval: 3s + timeout: 30s + retries: 5 + start_period: 30s + # volumes: + # ## Use Docker Socket Proxy instead for improved security + # - /var/run/docker.sock:/var/run/docker.sock + environment: + DOZZLE_ADDR: ":$DOZZLE_PORT" + DOCKER_HOST: tcp://socket-proxy:2375 + DOZZLE_FILTER: "status=running" + ## limits logs displayed to containers with this label + # DOZZLE_FILTER: "label=log_me" + DOZZLE_LEVEL: info + DOZZLE_NO_ANALYTICS: true + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.dozzle-rtr.entrypoints=https" + - "traefik.http.routers.dozzle-rtr.rule=Host(`dozzle.$DOMAINNAME0`)" + - "traefik.http.routers.dozzle-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.dozzle-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.dozzle-rtr.service=dozzle-svc" + - "traefik.http.services.dozzle-svc.loadbalancer.server.port=$DOZZLE_PORT" diff --git a/compose/duckdns.yml b/compose/duckdns.yml new file mode 100644 index 0000000..da8f747 --- /dev/null +++ b/compose/duckdns.yml @@ -0,0 +1,27 @@ +--- +secrets: + duckdns_token: + file: $SECRETSDIR/duckdns_token +services: + ## DuckDNS - Dynamic DNS service provided by duckdns.org + duckdns: + image: lscr.io/linuxserver/duckdns:latest + container_name: duckdns + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: always + # volumes: + # - $APPDIR/duckdns/config:/config # Optional + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + SUBDOMAINS: "$DOMAINNAME_DUCKDNS0,$DOMAINNAME_DUCKDNS1,$DOMAINNAME_DUCKDNS2,$DOMAINNAME_DUCKDNS3,$DOMAINNAME_DUCKDNS4" + ## Note, MUST truncate EOF carriage return if present + ## `truncate -s -1 $SECRETSDIR/duckdns_token` + FILE__TOKEN: /run/secrets/duckdns_token + # LOG_FILE: "true" # Optional + secrets: + - duckdns_token diff --git a/compose/dupeguru.yml b/compose/dupeguru.yml new file mode 100644 index 0000000..1614465 --- /dev/null +++ b/compose/dupeguru.yml @@ -0,0 +1,40 @@ +--- +services: + ## DupeGuru - Duplicate File/Folder Remover + dupeguru: + image: jlesage/dupeguru:latest + container_name: dupeguru + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + # ports: + # - "$DUPEGURU_PORT:5800" + volumes: + - $DATADIR:/storage:rw + - $USERDIR:/data/home:ro + - $APPDIR/dupeguru/config:/config:rw + environment: + TZ: $TZ + USER_ID: $PUID + GROUP_ID: $PGID + UMASK: 002 + KEEP_APP_RUNNING: 1 + CLEAN_TMP_DIR: 1 + DISPLAY_WIDTH: 1600 + DISPLAY_HEIGHT: 960 + VNC_PASSWORD: $DUPEGURU_VNC_PASSWD + WEB_LISTENING_PORT: $DUPEGURU_PORT + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.dupeguru-rtr.entrypoints=https" + - "traefik.http.routers.dupeguru-rtr.rule=Host(`dupe.$DOMAINNAME0`)" + - "traefik.http.routers.dupeguru-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.dupeguru-rtr.middlewares=chain-authelia@file,dupeguru-remove-bypass-cache" + - "traefik.http.middlewares.dupeguru-remove-bypass-cache.stripprefix.prefixes=/bypass_cache" + ## HTTP Services + - "traefik.http.routers.dupeguru-rtr.service=dupeguru-svc" + - "traefik.http.services.dupeguru-svc.loadbalancer.server.port=$DUPEGURU_PORT" diff --git a/compose/filebrowser.yml b/compose/filebrowser.yml new file mode 100644 index 0000000..ad4d433 --- /dev/null +++ b/compose/filebrowser.yml @@ -0,0 +1,31 @@ +--- +services: + ## File Browser - Explorer + filebrowser: + image: filebrowser/filebrowser:s6 + container_name: filebrowser + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $DOCKERDIR/appdata/filebrowser/config/settings.json:/config/settings.json + - $DOCKERDIR/appdata/filebrowser/db/filebrowser.db:/database/filebrowser.db + - $DATADIR:/srv + - $USERDIR:/data/home + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.filebrowser-rtr.entrypoints=https" + - "traefik.http.routers.filebrowser-rtr.rule=Host(`fb.$DOMAINNAME0`)" + - "traefik.http.routers.filebrowser-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.filebrowser-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.filebrowser-rtr.service=filebrowser-svc" + - "traefik.http.services.filebrowser-svc.loadbalancer.server.port=80" diff --git a/compose/firefly.yml b/compose/firefly.yml new file mode 100644 index 0000000..f7685bd --- /dev/null +++ b/compose/firefly.yml @@ -0,0 +1,252 @@ +--- +secrets: + firefly_iii_access_token: + file: $SECRETSDIR/firefly_iii_access_token + firefly_mail_server_password: + file: $SECRETSDIR/firefly_mail_server_password + firefly_mysql_db_name: + file: $SECRETSDIR/firefly_mysql_db_name + firefly_mysql_user: + file: $SECRETSDIR/firefly_mysql_user + firefly_mysql_password: + file: $SECRETSDIR/firefly_mysql_password + firefly_redis_password: + ## Should be symlinked to `redis_password` + ## ln -s ./redis_password firefly_redis_password + file: $SECRETSDIR/firefly_redis_password +services: + ## Firefly III - Finance Manager + ## Create a unique App Key which is a random 32 character string + ## `date +%s | sha256sum | base64 | head -c 32 ; echo` + firefly: + container_name: firefly + image: fireflyiii/core:latest + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + hostname: money.$DOMAINNAME0 + volumes: + - $APPDIR/firefly/export:/var/www/firefly-iii/storage/export + - $APPDIR/firefly/upload:/var/www/firefly-iii/storage/upload + environment: + ## https://github.com/firefly-iii/firefly-iii/blob/main/.env.example + TZ: $TZ + PUID: $PUID + PGID: $PGID + APP_ENV: local # testing, local, production + APP_DEBUG: "false" + SITE_OWNER: admin@money.$DOMAINNAME0 + APP_KEY: $FIREFLY_APP_KEY + DEFAULT_LANGUAGE: en_US + DEFAULT_LOCALE: equal + ## TRUSTED_PROXIES is a useful variable when using Docker and/or a + ## reverse proxy. Set it to ** and reverse proxies work just fine. + TRUSTED_PROXIES: "**" + ## "single" for one big fat error log (not recommended); "syslog", + ## "errorlog" and "stdout" which will log to the system itself; "daily", + ## creates 5 files that (surprise) rotate; "papertrail" for cloud + ## logging; "stack" will log to "daily" and to "stdout" at the same time + LOG_CHANNEL: stack + # PAPERTRAIL_HOST: + # PAPERTRAIL_PORT: + ## debug, info, notice, warning, error, critical, alert, emergency + APP_LOG_LEVEL: debug + AUDIT_LOG_LEVEL: debug # info, emergency + DB_CONNECTION: mysql # pgsql, mysql, sqlite + DB_HOST: $MARIADB_HOST + DB_PORT: $MARIADB_PORT + DB_DATABASE_FILE: /run/secrets/firefly_mysql_db_name + DB_USERNAME_FILE: /run/secrets/firefly_mysql_user + DB_PASSWORD_FILE: /run/secrets/firefly_mysql_password + # DB_SOCKET: + # MYSQL_USE_SSL: + # MYSQL_SSL_VERIFY_SERVER_CERT: + # MYSQL_SSL_CAPATH: /etc/ssl/certs/ + # MYSQL_SSL_CA: + # MYSQL_SSL_CERT: + # MYSQL_SSL_KEY: + # MYSQL_SSL_CIPHER: + # PGSQL_SSL_MODE: prefer + # PGSQL_SSL_ROOT_CERT: null + # PGSQL_SSL_CERT: null + # PGSQL_SSL_KEY: null + # PGSQL_SSL_CRL_FILE: null + # PGSQL_SCHEMA: + CACHE_DRIVER: redis + SESSION_DRIVER: redis + REDIS_SCHEME: tcp + # REDIS_PATH: # For use with "unix" REDIS_SCHEME only + REDIS_HOST: $REDIS_HOST + REDIS_PORT: $REDIS_PORT + REDIS_PASSWORD_FILE: /run/secrets/firefly_redis_password + REDIS_DB: "0" + REDIS_CACHE_DB: "1" + # COOKIE_PATH: "/" + # COOKIE_DOMAIN: $DOMAINNAME0 + # COOKIE_SECURE: false + # COOKIE_SAMESITE: lax + ## https://docs.firefly-iii.org/firefly-iii/advanced-installation/email/ + MAIL_MAILER: smtp + MAIL_HOST: $EMAIL_SERVER + MAIL_PORT: $EMAIL_SERVER_PORT + MAIL_FROM: server@money.$DOMAINNAME0 + MAIL_USERNAME: $EMAIL_SERVER_USER + MAIL_PASSWORD_FILE: /run/secrets/firefly_mail_server_password + MAIL_ENCRYPTION: ssl + # MAILGUN_DOMAIN: + # MAILGUN_SECRET: + # MAILGUN_ENDPOINT: + # MANDRILL_SECRET: + # SPARKPOST_SECRET: + SEND_REGISTRATION_MAIL: "true" + SEND_ERROR_MESSAGE: "true" + SEND_LOGIN_NEW_IP_WARNING: "true" + SEND_REPORT_JOURNALS: "true" + ENABLE_EXTERNAL_MAP: "true" + MAP_DEFAULT_LAT: $DEFAULT_LATITUDE + MAP_DEFAULT_LONG: $DEFAULT_LONGITUDE + # MAP_DEFAULT_ZOOM: 6 + ## https://docs.firefly-iii.org/advanced-installation/authentication + AUTHENTICATION_GUARD: web + AUTHENTICATION_GUARD_HEADER: HTTP_REMOTE_USER + AUTHENTICATION_GUARD_EMAIL: HTTP_REMOTE_EMAIL + # CUSTOM_LOGOUT_URL: + # DISABLE_FRAME_HEADER: "true" + # DISABLE_CSP_HEADER: "true" + # TRACKER_SITE_ID: + # TRACKER_URL: + ALLOW_WEBHOOKS: "true" # default false + ## https://docs.firefly-iii.org/firefly-iii/advanced-installation/cron/ + # STATIC_CRON_TOKEN_FILE: + ## Use this at your own risk. Disabling certain checks and features may + ## result in lost of inconsistent data. + # DKR_BUILD_LOCALE: + # DKR_CHECK_SQLITE: + # DKR_RUN_MIGRATION: + # DKR_RUN_UPGRADE: + # DKR_RUN_VERIFY: + # DKR_RUN_REPORT: + # DKR_RUN_PASSPORT_INSTALL: + ## Leave the following configuration vars as is. Unless you like to + ## tinker and know what you're doing. + # APP_NAME: FireflyIII + # BROADCAST_DRIVER: log + # QUEUE_DRIVER: sync + # CACHE_PREFIX: firefly + # PUSHER_KEY: + # IPINFO_TOKEN: + # PUSHER_SECRET: + # PUSHER_ID: + # DEMO_USERNAME: + # DEMO_PASSWORD: + # IS_HEROKU: false + # FIREFLY_III_LAYOUT: v1 + APP_URL: "https://money.$DOMAINNAME0" + secrets: + - firefly_mysql_db_name + - firefly_mysql_user + - firefly_mysql_password + - firefly_redis_password + - firefly_mail_server_password + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.firefly-rtr.entrypoints=https" + - "traefik.http.routers.firefly-rtr.rule=Host(`money.$DOMAINNAME0`)" + - "traefik.http.routers.firefly-rtr.tls.options=tls-opts@file" + ## Middlewares + ## Note: possible issue before using Authelia, would need to configure + ## /path for importer to bypass Authelia (/api/v1) - or just use + ## http://firefly:$FIREFLY_PORT + - "traefik.http.routers.firefly-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.firefly-rtr.service=firefly-svc" + - "traefik.http.services.firefly-svc.loadbalancer.server.port=8080" + + ## Firefly III Data Importer + importer: + container_name: importer + image: fireflyiii/data-importer:latest + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + depends_on: + - firefly + hostname: import.$DOMAINNAME0 + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + # FIREFLY_III_URL: https://money.$DOMAINNAME0 + FIREFLY_III_URL: http://firefly:$FIREFLY_PORT + VANITY_URL: https://money.$DOMAINNAME0 + FIREFLY_III_ACCESS_TOKEN_FILE: /run/secrets/firefly_iii_access_token + # FIREFLY_III_ACCESS_TOKEN: $FIREFLY_III_ACCESS_TOKEN + # FIREFLY_III_CLIENT_ID: $FIREFLY_III_CLIENT_ID + # NORDIGEN_ID_FILE: + # NORDIGEN_KEY_FILE: + # NORDIGEN_SANDBOX: "false" + # SPECTRE_APP_ID_FILE: + # SPECTRE_SECRET_FILE: + # USE_CACHE: "false" + # IGNORE_DUPLICATE_ERRORS: "false" + # AUTO_IMPORT_SECRET_FILE: + # CAN_POST_AUTOIMPORT: + # CAN_POST_FILES: + # IMPORT_DIR_WHITELIST_FILE: + VERIFY_TLS_SECURITY: "false" + # JSON_CONFIGURATION_DIR_FILE: + CONNECTION_TIMEOUT: 31.41 # π*10 seconds is usually fine. + # APP_ENV: local # These three are good for debugging + APP_DEBUG: "false" + # LOG_CHANNEL: stack + ## debug, info, notice, warning, error, critical, alert, emergency + LOG_LEVEL: info + ## TRUSTED_PROXIES is a useful variable when using Docker and/or a + ## reverse proxy. Set it to ** and reverse proxies work just fine. + TRUSTED_PROXIES: "**" + # ASSET_URL: + ENABLE_MAIL_REPORT: "true" + EXPECT_SECURE_URL: "true" + MAIL_MAILER: smtp + MAIL_DESTINATION: importer-admin@money.$DOMAINNAME0 + MAIL_FROM_ADDRESS: import@money.$DOMAINNAME0 + MAIL_HOST: $EMAIL_SERVER + MAIL_PORT: $EMAIL_SERVER_PORT + MAIL_USERNAME: $EMAIL_SERVER_USER + MAIL_PASSWORD_FILE: /run/secrets/firefly_mail_server_password + MAIL_ENCRYPTION: ssl + ## You probably won't need to change these settings. + # BROADCAST_DRIVER: log + # CACHE_DRIVER: redis # Not working + # QUEUE_CONNECTION: sync + # SESSION_DRIVER: redis # Not working + # SESSION_LIFETIME: 120 + # IS_EXTERNAL: "false" + REDIS_HOST: $REDIS_HOST + REDIS_PASSWORD: $REDIS_PASSWORD + REDIS_PORT: $REDIS_PORT + REDIS_DB: "0" # always use quotes + REDIS_CACHE_DB: "1" # always use quotes + # TRACKER_SITE_ID: + # TRACKER_URL: + # APP_NAME: + APP_URL: "https://import.$DOMAINNAME0" + secrets: + - firefly_iii_access_token + - firefly_mail_server_password + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.firefly-importer-rtr.entrypoints=https" + - "traefik.http.routers.firefly-importer-rtr.rule=Host(`import.$DOMAINNAME0`)" + - "traefik.http.routers.firefly-importer-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.firefly-importer-rtr.middlewares=chain-authelia@file" # Note: issue when using Authelia, default buffer size of 4096 not large enough, currently set to 8192 + ## HTTP Services + - "traefik.http.routers.firefly-importer-rtr.service=firefly-importer-svc" + - "traefik.http.services.firefly-importer-svc.loadbalancer.server.port=8080" diff --git a/compose/flaresolverr.yml b/compose/flaresolverr.yml new file mode 100644 index 0000000..963016b --- /dev/null +++ b/compose/flaresolverr.yml @@ -0,0 +1,22 @@ +--- +services: + # FlareSolverr - Proxy server to bypass Cloudflare protection + # Not sure if I need this or not. Just testing. + flaresolverr: + image: ghcr.io/flaresolverr/flaresolverr:latest + container_name: flaresolverr + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + LOG_LEVEL: info + LOG_HTML: false + CAPTCHA_SOLVER: none + # TEST_URL: "www.eff.org" + ports: + - "$FLARESOLVERR_PORT:8191" diff --git a/compose/glances.yml b/compose/glances.yml new file mode 100644 index 0000000..d04e1a8 --- /dev/null +++ b/compose/glances.yml @@ -0,0 +1,39 @@ +--- +services: + ## Glances - System Information + glances: + image: nicolargo/glances:latest + container_name: glances + privileged: true + networks: + - t2_proxy + - socket_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + depends_on: + - socket-proxy + pid: host + volumes: + ## Use this if you want to add a glances.conf file + # - $APPDIR/glances/config/glances.conf:/glances/conf/glances.conf + - $USERDIR:/data/home:ro + # - /media/hdd1:/data/hdd1:ro + ## Use Docker Socket Proxy instead for improved security + # - /var/run/docker.sock:/var/run/docker.sock:ro + environment: + # GLANCES_OPT: "-C /glances/conf/glances.conf --quiet --export influxdb" + # GLANCES_OPT: "--export influxdb" + GLANCES_OPT: "-w" # Run in "w" or Web Server mode + DOCKER_HOST: tcp://socket-proxy:2375 + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.glances-rtr.entrypoints=https" + - "traefik.http.routers.glances-rtr.rule=Host(`glances.$DOMAINNAME0`)" + - "traefik.http.routers.glances-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.glances-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.glances-rtr.service=glances-svc" + - "traefik.http.services.glances-svc.loadbalancer.server.port=61208" diff --git a/compose/gluetun-private.yml b/compose/gluetun-private.yml new file mode 100644 index 0000000..c952fc4 --- /dev/null +++ b/compose/gluetun-private.yml @@ -0,0 +1,61 @@ +--- +secrets: + gluetun_openvpn_user: + file: $SECRETSDIR/gluetun_openvpn_user + gluetun_openvpn_password: + file: $SECRETSDIR/gluetun_openvpn_password +services: + ## Gluetun - VPN client in a thin Docker container + ## gluetun-private is used for private trackers + gluetun-private: + image: ghcr.io/qdm12/gluetun:v3 + container_name: gluetun-private + networks: + gluetun_net: + ipv4_address: $GLUETUN_PRIVATE_IPV4 + t2_proxy: + security_opt: + - no-new-privileges:true + restart: unless-stopped + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun:/dev/net/tun + ports: + - $GLUETUN_PRIVATE_HTTP_CONTROL_SERVER_PORT:$GLUETUN_PRIVATE_HTTP_CONTROL_SERVER_PORT + ## qBittorrent web UI + - $QBITTORRENT_PRIVATE_PORT:$QBITTORRENT_PRIVATE_PORT + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + VPN_SERVICE_PROVIDER: $GLUETUN_VPN_SERVICE_PROVIDER + VPN_TYPE: "openvpn" + # OpenVPN: + OPENVPN_USER_SECRETFILE: /run/secrets/gluetun_openvpn_user + OPENVPN_PASSWORD_SECRETFILE: /run/secrets/gluetun_openvpn_password + ## Fix "WARN [openvpn] 'link-mtu' is used inconsistently" + ## See https://github.com/qdm12/gluetun/discussions/666 + OPENVPN_FLAGS: "--comp-lzo" + VPN_PORT_FORWARDING: "on" + PORT_FORWARD_ONLY: "on" + VPN_PORT_FORWARDING_PROVIDER: $GLUETUN_PRIVATE_VPN_SERVICE_PROVIDER + # Wireguard: + # WIREGUARD_PRIVATE_KEY: + # WIREGUARD_ADDRESSES: + SERVER_COUNTRIES: $GLUETUN_PRIVATE_SERVER_COUNTRIES + SERVER_CITIES: $GLUETUN_PRIVATE_SERVER_CITIES + SERVER_HOSTNAMES: $GLUETUN_PRIVATE_SERVER_HOSTNAMES + ## See https://github.com/qdm12/gluetun-wiki/blob/main/setup/servers.md#update-the-vpn-servers-list + UPDATER_PERIOD: "24h" + HTTP_CONTROL_SERVER_ADDRESS: ":$GLUETUN_PRIVATE_HTTP_CONTROL_SERVER_PORT" + HEALTH_VPN_DURATION_INITIAL: "120s" + HEALTH_VPN_DURATION_ADDITION: "120s" + HEALTH_SUCCESS_WAIT_DURATION: "120s" + secrets: + - gluetun_openvpn_user + - gluetun_openvpn_password + labels: + ## Connectivity issue when restarted with Watchtower + ## See https://github.com/qdm12/gluetun/issues/641 + - "com.centurylinklabs.watchtower.enable=false" diff --git a/compose/gluetun-temp.yml b/compose/gluetun-temp.yml new file mode 100644 index 0000000..61d5660 --- /dev/null +++ b/compose/gluetun-temp.yml @@ -0,0 +1,62 @@ +--- +secrets: + gluetun_openvpn_user: + file: $SECRETSDIR/gluetun_openvpn_user + gluetun_openvpn_password: + file: $SECRETSDIR/gluetun_openvpn_password +services: + ## Gluetun - VPN client in a thin Docker container + ## gluetun-temp is used for temporary files, because nothing is more + ## permanent than a temporary solution + gluetun-temp: + image: ghcr.io/qdm12/gluetun:v3 + container_name: gluetun-temp + networks: + gluetun_net: + ipv4_address: $GLUETUN_TEMP_IPV4 + t2_proxy: + security_opt: + - no-new-privileges:true + restart: unless-stopped + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun:/dev/net/tun + ports: + - $GLUETUN_TEMP_HTTP_CONTROL_SERVER_PORT:$GLUETUN_TEMP_HTTP_CONTROL_SERVER_PORT + ## qBittorrent web UI + - $QBITTORRENT_TEMP_PORT:$QBITTORRENT_TEMP_PORT + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + VPN_SERVICE_PROVIDER: $GLUETUN_VPN_SERVICE_PROVIDER + VPN_TYPE: "openvpn" + # OpenVPN: + OPENVPN_USER_SECRETFILE: /run/secrets/gluetun_openvpn_user + OPENVPN_PASSWORD_SECRETFILE: /run/secrets/gluetun_openvpn_password + ## Fix "WARN [openvpn] 'link-mtu' is used inconsistently" + ## See https://github.com/qdm12/gluetun/discussions/666 + OPENVPN_FLAGS: "--comp-lzo" + VPN_PORT_FORWARDING: "on" + PORT_FORWARD_ONLY: "on" + VPN_PORT_FORWARDING_PROVIDER: $GLUETUN_TEMP_VPN_SERVICE_PROVIDER + # Wireguard: + # WIREGUARD_PRIVATE_KEY: + # WIREGUARD_ADDRESSES: + SERVER_COUNTRIES: $GLUETUN_TEMP_SERVER_COUNTRIES + SERVER_CITIES: $GLUETUN_TEMP_SERVER_CITIES + SERVER_HOSTNAMES: $GLUETUN_TEMP_SERVER_HOSTNAMES + ## See https://github.com/qdm12/gluetun-wiki/blob/main/setup/servers.md#update-the-vpn-servers-list + UPDATER_PERIOD: "24h" + HTTP_CONTROL_SERVER_ADDRESS: ":$GLUETUN_TEMP_HTTP_CONTROL_SERVER_PORT" + HEALTH_VPN_DURATION_INITIAL: "120s" + HEALTH_VPN_DURATION_ADDITION: "120s" + HEALTH_SUCCESS_WAIT_DURATION: "120s" + secrets: + - gluetun_openvpn_user + - gluetun_openvpn_password + labels: + ## Connectivity issue when restarted with Watchtower + ## See https://github.com/qdm12/gluetun/issues/641 + - "com.centurylinklabs.watchtower.enable=false" diff --git a/compose/gluetun.yml b/compose/gluetun.yml new file mode 100644 index 0000000..3451058 --- /dev/null +++ b/compose/gluetun.yml @@ -0,0 +1,59 @@ +--- +secrets: + gluetun_openvpn_user: + file: $SECRETSDIR/gluetun_openvpn_user + gluetun_openvpn_password: + file: $SECRETSDIR/gluetun_openvpn_password +services: + ## Gluetun - VPN client in a thin Docker container + gluetun: + image: ghcr.io/qdm12/gluetun:v3 + container_name: gluetun + networks: + gluetun_net: + ipv4_address: $GLUETUN_IPV4 + security_opt: + - no-new-privileges:true + restart: unless-stopped + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun:/dev/net/tun + ports: + - $GLUETUN_HTTP_CONTROL_SERVER_PORT:$GLUETUN_HTTP_CONTROL_SERVER_PORT + ## qBittorrent web UI + - $QBITTORRENT_PORT:$QBITTORRENT_PORT + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + VPN_SERVICE_PROVIDER: $GLUETUN_VPN_SERVICE_PROVIDER + VPN_TYPE: "openvpn" + # OpenVPN: + OPENVPN_USER_SECRETFILE: /run/secrets/gluetun_openvpn_user + OPENVPN_PASSWORD_SECRETFILE: /run/secrets/gluetun_openvpn_password + ## Fix "WARN [openvpn] 'link-mtu' is used inconsistently" + ## See https://github.com/qdm12/gluetun/discussions/666 + OPENVPN_FLAGS: "--comp-lzo" + VPN_PORT_FORWARDING: "on" + PORT_FORWARD_ONLY: "on" + VPN_PORT_FORWARDING_PROVIDER: $GLUETUN_VPN_SERVICE_PROVIDER + # Wireguard: + # WIREGUARD_PRIVATE_KEY: + # WIREGUARD_ADDRESSES: + SERVER_COUNTRIES: $GLUETUN_SERVER_COUNTRIES + SERVER_CITIES: $GLUETUN_SERVER_CITIES + SERVER_HOSTNAMES: $GLUETUN_SERVER_HOSTNAMES + ## See https://github.com/qdm12/gluetun-wiki/blob/main/setup/servers.md#update-the-vpn-servers-list + UPDATER_PERIOD: "24h" + HTTP_CONTROL_SERVER_ADDRESS: ":$GLUETUN_HTTP_CONTROL_SERVER_PORT" + HEALTH_VPN_DURATION_INITIAL: "120s" + HEALTH_VPN_DURATION_ADDITION: "120s" + HEALTH_SUCCESS_WAIT_DURATION: "120s" + secrets: + - gluetun_openvpn_user + - gluetun_openvpn_password + labels: + ## Connectivity issue when restarted with Watchtower + ## See https://github.com/qdm12/gluetun/issues/641 + - "com.centurylinklabs.watchtower.enable=false" diff --git a/compose/gotify.yml b/compose/gotify.yml new file mode 100644 index 0000000..28bb540 --- /dev/null +++ b/compose/gotify.yml @@ -0,0 +1,77 @@ +--- +secrets: + gotify_database_connection: + file: $SECRETSDIR/gotify_database_connection + gotify_defaultuser_name: + file: $SECRETSDIR/gotify_defaultuser_name + gotify_defaultuser_pass: + file: $SECRETSDIR/gotify_defaultuser_pass +services: + ## Gotify - A simple server for sending and receiving messages + gotify: + container_name: gotify + image: gotify/server:latest + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/gotify/app:/app/data + ## Allows passing the hijacked entrypoint.sh + - $APPDIR/gotify/config:/config:ro + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + GOTIFY_SERVER_PORT: $GOTIFY_SERVER_PORT + # GOTIFY_SERVER_KEEPALIVEPERIODSECONDS: 0 + # GOTIFY_SERVER_LISTENADDR: + GOTIFY_SERVER_SSL_ENABLED: "false" + # GOTIFY_SERVER_SSL_REDIRECTTOHTTPS: true + # GOTIFY_SERVER_SSL_LISTENADDR: + # GOTIFY_SERVER_SSL_PORT: 443 + # GOTIFY_SERVER_SSL_CERTFILE: + # GOTIFY_SERVER_SSL_CERTKEY: + # GOTIFY_SERVER_SSL_LETSENCRYPT_ENABLED: false + # GOTIFY_SERVER_SSL_LETSENCRYPT_ACCEPTTOS: false + # GOTIFY_SERVER_SSL_LETSENCRYPT_CACHE: certs + # lists are a little weird but do-able (: + # GOTIFY_SERVER_SSL_LETSENCRYPT_HOSTS: - mydomain.tld\n- myotherdomain.tld + # GOTIFY_SERVER_RESPONSEHEADERS: "X-Custom-Header: \"custom value\"" + # GOTIFY_SERVER_CORS_ALLOWORIGINS: "- \".+.example.com\"\n- \"otherdomain.com\"" + # GOTIFY_SERVER_CORS_ALLOWMETHODS: "- \"GET\"\n- \"POST\"" + # GOTIFY_SERVER_CORS_ALLOWHEADERS: "- \"Authorization\"\n- \"content-type\"" + # GOTIFY_SERVER_STREAM_ALLOWEDORIGINS: "- \".+.example.com\"\n- \"otherdomain.com\"" + # GOTIFY_SERVER_STREAM_PINGPERIODSECONDS: 45 + GOTIFY_DATABASE_DIALECT: mysql + ## Hijack default entrypoint to pass in Docker secrets + GOTIFY_DATABASE_CONNECTION__FILE: /run/secrets/gotify_database_connection + # GOTIFY_DATABASE_CONNECTION: data/gotify.db + ## Hijack default entrypoint to pass in Docker secrets + GOTIFY_DEFAULTUSER_NAME__FILE: /run/secrets/gotify_defaultuser_name + # GOTIFY_DEFAULTUSER_NAME: admin + ## Hijack default entrypoint to pass in Docker secrets + GOTIFY_DEFAULTUSER_PASS__FILE: /run/secrets/gotify_defaultuser_pass + # GOTIFY_DEFAULTUSER_PASS: admin + GOTIFY_PASSSTRENGTH: 10 + GOTIFY_UPLOADEDIMAGESDIR: data/images + GOTIFY_PLUGINSDIR: data/plugins + # GOTIFY_REGISTRATION: false + secrets: + - gotify_database_connection + - gotify_defaultuser_name + - gotify_defaultuser_pass + entrypoint: + - /config/entrypoint.sh + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.gotify-rtr.entrypoints=https" + - "traefik.http.routers.gotify-rtr.rule=Host(`gotify.$DOMAINNAME0`)" + - "traefik.http.routers.gotify-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.gotify-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.gotify-rtr.service=gotify-svc" + - "traefik.http.services.gotify-svc.loadbalancer.server.port=$GOTIFY_SERVER_PORT" diff --git a/compose/guacamole.yml b/compose/guacamole.yml new file mode 100644 index 0000000..b00c146 --- /dev/null +++ b/compose/guacamole.yml @@ -0,0 +1,59 @@ +--- +secrets: + guac_db_name: + file: $SECRETSDIR/guac_db_name + guac_mysql_user: + file: $SECRETSDIR/guac_mysql_user + guac_mysql_password: + file: $SECRETSDIR/guac_mysql_password +services: + ## Guacamole - Remote desktop, SSH, on Telnet on any HTML5 Browser + ## Create all databases and tables first + ## https://guacamole.apache.org/doc/1.4.0/gug/guacamole-docker.html?highlight=mysql#mysql-authentication + guacamole: + image: guacamole/guacamole:latest + container_name: guacamole + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: always + depends_on: + - guacd + # ports: + # - "$GUACAMOLE_PORT:8080" + environment: + GUACD_HOSTNAME: guacd + MYSQL_HOSTNAME: $MARIADB_HOST + MYSQL_PORT: $MARIADB_PORT + ## Secrets do not work with 600 secrets, must chmod 644 + MYSQL_DATABASE_FILE: /run/secrets/guac_db_name + MYSQL_USER_FILE: /run/secrets/guac_mysql_user + MYSQL_PASSWORD_FILE: /run/secrets/guac_mysql_password + secrets: + - guac_db_name + - guac_mysql_user + - guac_mysql_password + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.guacamole-rtr.entrypoints=https" + - "traefik.http.routers.guacamole-rtr.rule=Host(`guac.$DOMAINNAME0`)" + - "traefik.http.routers.guacamole-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.guacamole-rtr.middlewares=chain-authelia@file,guacamole-remove-bypass-cache,add-guacamole" + - "traefik.http.middlewares.guacamole-remove-bypass-cache.stripprefix.prefixes=/bypass_cache" + - "traefik.http.middlewares.add-guacamole.addPrefix.prefix=/guacamole" + ## HTTP Services + - "traefik.http.routers.guacamole-rtr.service=guacamole-svc" + - "traefik.http.services.guacamole-svc.loadbalancer.server.port=8080" + + ## Guacamole Daemon - Needed for Guacamole + guacd: + image: guacamole/guacd:latest + container_name: guacd + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: always diff --git a/compose/handbrake.yml b/compose/handbrake.yml new file mode 100644 index 0000000..d2f2d83 --- /dev/null +++ b/compose/handbrake.yml @@ -0,0 +1,38 @@ +--- +services: + # Handbrake - Video Conversion (transcoding and compression) + handbrake: + image: jlesage/handbrake:latest + container_name: handbrake + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $DATADIR:/data + - $APPDIR/handbrake/config:/config + # - $APPDIR/handbrake/watch:/watch + environment: + TZ: $TZ + USER_ID: $PUID + GROUP_ID: $PGID + UMASK: 002 + KEEP_APP_RUNNING: 1 + CLEAN_TMP_DIR: 1 + DISPLAY_WIDTH: 1600 + DISPLAY_HEIGHT: 960 + AUTOMATED_CONVERSION_KEEP_SOURCE: 1 + # VNC_PASSWORD: $HANDBRAKE_VNC_PASSWD + WEB_LISTENING_PORT: $HANDBRAKE_PORT + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.handbrake-rtr.entrypoints=https" + - "traefik.http.routers.handbrake-rtr.rule=Host(`handbrake.$DOMAINNAME0`)" + - "traefik.http.routers.handbrake-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.handbrake-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.handbrake-rtr.service=handbrake-svc" + - "traefik.http.services.handbrake-svc.loadbalancer.server.port=$HANDBRAKE_PORT" diff --git a/compose/heimdall.yml b/compose/heimdall.yml new file mode 100644 index 0000000..831d134 --- /dev/null +++ b/compose/heimdall.yml @@ -0,0 +1,28 @@ +--- +services: + ## Heimdall - Application Dashboard + heimdall: + image: lscr.io/linuxserver/heimdall + container_name: heimdall + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/heimdall/config:/config + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.heimdall-rtr.entrypoints=https" + - "traefik.http.routers.heimdall-rtr.rule=Host(`dash.$DOMAINNAME0`) || Host(`heimdall.$DOMAINNAME0`)" + - "traefik.http.routers.heimdall-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.heimdall-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.heimdall-rtr.service=heimdall-svc" + - "traefik.http.services.heimdall-svc.loadbalancer.server.port=80" diff --git a/compose/jellyfin.yml b/compose/jellyfin.yml new file mode 100644 index 0000000..d64f2f8 --- /dev/null +++ b/compose/jellyfin.yml @@ -0,0 +1,46 @@ +--- +services: + ## Jellyfin - Free Software Media System + jellyfin: + ## Issues with hardware transcoding with linuxserver.io image + image: jellyfin/jellyfin:latest + container_name: jellyfin + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + devices: + ## AMD hardware transcoding? + # - /dev/dri:/dev/dri + - /dev/dri/renderD128:/dev/dri/renderD128 + - /dev/dri/card1:/dev/dri/card0 + group_add: + ## Add render group permission to allow GPU render access + - $RENDER_GROUP + volumes: + - $APPDIR/jellyfin/config:/config + - $APPDIR/jellyfin/config/web-config.json:/jellyfin/jellyfin-web/config.json + - $DATADIR/temp/appdata/jellyfin/metadata:/config/metadata + - $DATADIR/downloads:/data/downloads + - $DATADIR/media:/data/media + ## Perform transcoding in RAM + # - /dev/shm:/data/transcode + ## Perform transcoding on SSD + - /$APPDIR/jellyfin/transcodes:/data/transcode + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.jellyfin-rtr.entrypoints=https" + - "traefik.http.routers.jellyfin-rtr.rule=Host(`jellyfin.$DOMAINNAME0`)" + - "traefik.http.routers.jellyfin-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.jellyfin-rtr.middlewares=chain-authelia@file,jellyfin-remove-bypass-cache" + - "traefik.http.middlewares.jellyfin-remove-bypass-cache.stripPrefix.prefixes=/bypass_cache" + ## HTTP Services + - "traefik.http.routers.jellyfin-rtr.service=jellyfin-svc" + - "traefik.http.services.jellyfin-svc.loadbalancer.server.port=8096" diff --git a/compose/keycloak.yml b/compose/keycloak.yml new file mode 100644 index 0000000..a1f318b --- /dev/null +++ b/compose/keycloak.yml @@ -0,0 +1,107 @@ +--- +secrets: + keycloak_admin: + file: $SECRETSDIR/keycloak_admin + keycloak_admin_password: + file: $SECRETSDIR/keycloak_admin_password + kc_db_username: + file: $SECRETSDIR/kc_db_username + kc_db_password: + file: $SECRETSDIR/kc_db_password +services: + ## Keycloak - Open Source Identity and Access Management + keycloak: + container_name: keycloak + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: always + build: + context: . + dockerfile: $APPDIR/keycloak/build/keycloak.Dockerfile + args: + ARG_KC_CACHE: "local" + # ARG_KC_CACHE_CONFIG_FILE: + # ARG_KC_CACHE_STACK: + ARG_KC_DB: "mariadb" + ARG_KC_TRANSACTION_XA_ENABLED: "true" + ## yamllint disable-line rule:line-length + ARG_KC_FEATURES: "docker,declarative-user-profile,recovery-codes,update-email" + # ARG_KC_HTTP_RELATIVE_PATH: + ARG_KC_HEALTH_ENABLED: "true" + ARG_KC_METRICS_ENABLED: "true" + # ARG_KC_VAULT: + # ARG_KC_FIPS_MODE: + ARG_QUARKUS_TRANSACTION_MANAGER_ENABLE_RECOVERY: "true" + command: ["start", "--optimized"] + volumes: + - $APPDIR/keycloak/config:/conf + ## https://github.com/keycloak/keycloak/issues/15255#issuecomment-1446166497 + - $APPDIR/keycloak/ObjectStore:/ObjectStore + # Remember to `chmod +x` for all .sh scripts + ## Workaround to enable docker secrets + - $APPDIR/keycloak/build/docker_secrets.sh:/build/docker_secrets.sh:ro + ## Workaround to enable docker secrets + - $APPDIR/keycloak/build/entrypoint.sh:/build/entrypoint.sh:ro + ## Workaround to use healthcheck without `curl` + - $APPDIR/keycloak/build/healthcheck.sh:/build/healthcheck.sh:ro + environment: + # KC_CACHE: local + FILE__KEYCLOAK_ADMIN: /run/secrets/keycloak_admin + FILE__KEYCLOAK_ADMIN_PASSWORD: /run/secrets/keycloak_admin_password + # KC_DB: postgres + KC_DB: mariadb + FILE__KC_DB_PASSWORD: /run/secrets/kc_db_password + # KC_DB_URL: "jdbc:postgresql://${POSTGRES_HOST}:${POSTGRES_PORT}/keycloak" + # KC_DB_URL: "jdbc:mariadb://${MARIADB_HOST}:${MARIADB_PORT}/keycloak" + KC_DB_URL_DATABASE: keycloak + # KC_DB_URL_HOST: $POSTGRES_HOST + # KC_DB_URL_PORT: $POSTGRES_PORT + KC_DB_URL_HOST: $MARIADB_HOST + KC_DB_URL_PORT: $MARIADB_PORT + FILE__KC_DB_USERNAME: /run/secrets/kc_db_username + # KC_FEATURES: "docker,declarative-user-profile,recovery-codes,update-email" + # KC_HOSTNAME: "key.${DOMAINNAME0}" + # KC_HOSTNAME_ADMIN: "key.${DOMAINNAME0}" + KC_HOSTNAME_ADMIN_URL: "https://key.${DOMAINNAME0}" + KC_HOSTNAME_DEBUG: "true" + KC_HOSTNAME_STRICT: "false" + KC_HOSTNAME_URL: "https://key.${DOMAINNAME0}" + KC_HTTP_ENABLED: "true" + KC_HTTP_PORT: $KEYCLOAK_PORT + # KC_HEALTH_ENABLED: "true" + # KC_METRICS_ENABLED: "true" + KC_PROXY: edge + ## https://github.com/keycloak/keycloak/issues/15255#issuecomment-1446166497 + QUARKUS_TRANSACTION_MANAGER_ENABLE_RECOVERY: "true" + secrets: + - keycloak_admin + - keycloak_admin_password + - kc_db_password + - kc_db_username + labels: + - "traefik.enable=true" + #### Authentication routers and middlewares + ## HTTP Routers + - "traefik.http.routers.keycloak-rtr.entrypoints=https" + ## https://www.keycloak.org/server/reverseproxy#_exposed_path_recommendations + - "traefik.http.routers.keycloak-rtr.rule=Host(`key.$DOMAINNAME0`) && (Path(`/`) || PathPrefix(`/realms`) || PathPrefix(`/resources`))" + - "traefik.http.routers.keycloak-rtr.tls.options=tls-opts@file" + - "traefik.http.routers.keycloak-rtr-bypass.priority=99" + ## Middlewares + - "traefik.http.routers.keycloak-rtr.middlewares=chain-keycloak@file" + #### Administration routers and middlewares + ## HTTP Routers + - "traefik.http.routers.keycloak-admin-rtr.entrypoints=https" + # https://www.keycloak.org/server/reverseproxy#_exposed_path_recommendations + - "traefik.http.routers.keycloak-admin-rtr.rule=Host(`key.$DOMAINNAME0`) && ClientIP(`$LAN_NETWORK`)" # Only allow admin paths on local network (or VPN) + - "traefik.http.routers.keycloak-admin-rtr.tls.options=tls-opts@file" + ## Give priority to bypass rule if matched + - "traefik.http.routers.keycloak-admin-rtr-bypass.priority=100" + ## Middlewares + - "traefik.http.routers.keycloak-admin-rtr.middlewares=chain-keycloak@file" + #### Combined services + ## HTTP Services + - "traefik.http.routers.keycloak-admin-rtr.service=keycloak-admin-svc" + - "traefik.http.services.keycloak-admin-svc.loadbalancer.server.port=$KEYCLOAK_PORT" diff --git a/compose/lidarr.yml b/compose/lidarr.yml new file mode 100644 index 0000000..bae0e23 --- /dev/null +++ b/compose/lidarr.yml @@ -0,0 +1,37 @@ +--- +services: + ## Lidarr - Music Management + lidarr: + image: lscr.io/linuxserver/lidarr:latest + container_name: lidarr + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/lidarr/config:/config + - $DATADIR:/data + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + labels: + - "traefik.enable=true" + ## HTTP Routers Auth Bypass + - "traefik.http.routers.lidarr-rtr-bypass.entrypoints=https" + - "traefik.http.routers.lidarr-rtr-bypass.rule=Host(`lidarr.$DOMAINNAME0`) && (Header(`X-Api-Key`, `$LIDARR_API_KEY`) || Query(`apikey`, `$LIDARR_API_KEY`))" + - "traefik.http.routers.lidarr-rtr-bypass.tls.options=tls-opts@file" + - "traefik.http.routers.lidarr-rtr-bypass.priority=100" + ## HTTP Routers Auth + - "traefik.http.routers.lidarr-rtr.entrypoints=https" + - "traefik.http.routers.lidarr-rtr.rule=Host(`lidarr.$DOMAINNAME0`)" + - "traefik.http.routers.lidarr-rtr.tls.options=tls-opts@file" + - "traefik.http.routers.lidarr-rtr.priority=99" + ## Middlewares + - "traefik.http.routers.lidarr-rtr-bypass.middlewares=chain-no-auth@file" + - "traefik.http.routers.lidarr-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.lidarr-rtr.service=lidarr-svc" + - "traefik.http.routers.lidarr-rtr-bypass.service=lidarr-svc" + - "traefik.http.services.lidarr-svc.loadbalancer.server.port=8686" diff --git a/compose/maintainerr.yml b/compose/maintainerr.yml new file mode 100644 index 0000000..249b6a9 --- /dev/null +++ b/compose/maintainerr.yml @@ -0,0 +1,27 @@ +--- +services: + ## Maintainerr + maintainerr: + image: ghcr.io/jorenn92/maintainerr:latest + container_name: maintainerr + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/maintainerr/config:/opt/data + environment: + API_PORT: 3001 + UI_PORT: 6246 + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.maintainerr-rtr.entrypoints=https" + - "traefik.http.routers.maintainerr-rtr.rule=Host(`maintainerr.$DOMAINNAME0`)" + - "traefik.http.routers.maintainerr-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.maintainerr-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.maintainerr-rtr.service=maintainerr-svc" + - "traefik.http.services.maintainerr-svc.loadbalancer.server.port=6246" diff --git a/compose/mariadb.yml b/compose/mariadb.yml new file mode 100644 index 0000000..4fa8390 --- /dev/null +++ b/compose/mariadb.yml @@ -0,0 +1,26 @@ +--- +secrets: + mysql_root_password: + file: $SECRETSDIR/mysql_root_password +services: + ## MariaDB - MySQL Database + ## After starting container for first time dexec and + ## `mysqladmin -u root password ` + mariadb: + container_name: mariadb + image: lscr.io/linuxserver/mariadb:latest + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: always + volumes: + - $APPDIR/mariadb/data:/config + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + ## https://github.com/linuxserver/docker-mariadb/issues/138 + FILE__MYSQL_ROOT_PASSWORD: /run/secrets/mysql_root_password + secrets: + - mysql_root_password diff --git a/compose/mc-backup.yml b/compose/mc-backup.yml new file mode 100644 index 0000000..d6a2e48 --- /dev/null +++ b/compose/mc-backup.yml @@ -0,0 +1,27 @@ +--- +services: + ## Minecraft Backup - Backup Minecraft worlds + mc-backup: + image: itzg/mc-backup:latest + container_name: mc-backup + security_opt: + - no-new-privileges:true + restart: unless-stopped + # depends_on: + # - minecraft + environment: + RCON_HOST: minecraft + RCON_PORT: $MINECRAFT_RCON_PORT + RCON_PASSWORD: $MINECRAFT_RCON_PASSWORD + EXCLUDES: "*.jar,cache,logs" + BACKUP_METHOD: tar + SRC_DIR: /data + BACKUP_NAME: world + INITIAL_DELAY: 15m + BACKUP_INTERVAL: 2h + PRUNE_BACKUPS_DAYS: 7 + PRUNE_RESTIC_RETENTION: "--keep-daily 7 --keep-weekly 5 --keep-monthly 3" + LINK_LATEST: true + volumes: + - $APPDIR/minecraft/technic/data:/data:ro + - $APPDIR/minecraft/mc-backups:/backups diff --git a/compose/minecraft-rcon.yml b/compose/minecraft-rcon.yml new file mode 100644 index 0000000..32ebb42 --- /dev/null +++ b/compose/minecraft-rcon.yml @@ -0,0 +1,39 @@ +--- +services: + ## Minecraft RCON + ## Issue commands issued to the server via a "remote console", or RCON + minecraft-rcon: + image: itzg/rcon:latest + container_name: minecraft-rcon + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + depends_on: + - minecraft + environment: + RWA_USERNAME: $MINECRAFT_RWA_USERNAME + RWA_PASSWORD: $MINECRAFT_RWA_PASSWORD + RWA_ADMIN: "TRUE" + # is referring to the hostname of 'mc' compose service above + RWA_RCON_HOST: minecraft + # needs to match the password configured for the container, which is 'minecraft' by default + RWA_RCON_PASSWORD: $MINECRAFT_RCON_PASSWORD + # ports: + # - $MINECRAFT_RCON_PORT:4326 + # - $MINECRAFT_RCON_WEBSOCKET_PORT:4327 + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.minecraft-rcon-rtr.entrypoints=https" + - "traefik.http.routers.minecraft-rcon-websocket-rtr.entrypoints=minecraft-rcon-websocket" + - "traefik.http.routers.minecraft-rcon-rtr.rule=Host(`vanilla-rcon.mc.$DOMAINNAME0`)" + ## Middlewares + - "traefik.http.routers.minecraft-rcon-rtr.middlewares=chain-no-auth@file" + - "traefik.http.routers.minecraft-rcon-websocket-rtr.middlewares=chain-no-auth@file" + ## HTTP Services + - "traefik.http.routers.minecraft-rcon-rtr.service=minecraft-rcon-svc" + - "traefik.http.services.minecraft-rcon-svc.loadbalancer.server.port=4326" + - "traefik.http.routers.minecraft-rcon-websocket-rtr.service=minecraft-rcon-websocket-svc" + - "traefik.http.services.minecraft-rcon-websocket-svc.loadbalancer.server.port=4327" diff --git a/compose/minecraft.yml b/compose/minecraft.yml new file mode 100644 index 0000000..b83100b --- /dev/null +++ b/compose/minecraft.yml @@ -0,0 +1,149 @@ +--- +services: + ## Minecraft - Minecraft server + minecraft: + image: itzg/minecraft-server:java8 + container_name: minecraft + security_opt: + - no-new-privileges:true + restart: unless-stopped + tty: true + ports: + - $MINECRAFT_PORT:25565 + deploy: + resources: + limits: + memory: 8G + networks: + - default + volumes: + - $APPDIR/minecraft/technic/data:/data + ## Mount as read-only to ensure integrity + - $APPDIR/minecraft/technic/worlds:/worlds:ro + ## Ensure you specify different volumes for different worlds: + ## https://github.com/itzg/docker-minecraft-server/blob/master/README.md#data-directory + environment: + # UID: $PUID + # GID: $PGID + TZ: $TZ + EULA: TRUE + # MEMORY: 6G + INIT_MEMORY: 1G # Independently sets the initial heap size + MAX_MEMORY: 6G # Independently sets the max heap size + VERSION: 1.12.2 # LATEST, SNAPSHOT, + TYPE: FORGE + FORGEVERSION: 14.23.5.2855 + # OVERRIDE_SERVER_PROPERTIES: true + ## Will overwrite the world on server start + # FORCE_WORLD_COPY: TRUE + ## Read the world from the folder my_world + # WORLD: /worlds/backups/world_backup + ## Read the world from a URL + # WORLD: http://www.example.com/worlds/MySave.zip + SERVER_NAME: NUC_Server + ## Dangerous to change if you don't know what you're doing + # SERVER_PORT: $MINECRAFT_PORT + DIFFICULTY: 1 # peaceful, easy, normal, hard + WHITELIST: $MINECRAFT_USER_LIST # Allow-listed players + OPS: $MINECRAFT_USER_LIST # Op/Administrator players + # ICON: https://oldschool.runescape.wiki/images/c/ce/Gnome_child_chathead.png # Set the server icon + # OVERRIDE_ICON: TRUE # Override the icon on server startup + MAX_PLAYERS: 10 # Default : 20 + # MAX_WORLD_SIZE: 10000 # Max world radius in chunks + # ALLOW_NETHER: true + ANNOUNCE_PLAYER_ACHIEVEMENTS: true + ENABLE_COMMAND_BLOCK: false + # FORCE_GAMEMODE: false + GENERATE_STRUCTURES: true + ## If set to true, players will be set to spectator mode if they die + HARDCORE: false + ## If set to false, the server will not send data to snoop.minecraft.net + ## server. + SNOOPER_ENABLED: false + ## Terrain may still naturally generate above a low height limit + MAX_BUILD_HEIGHT: 256 + ## In milliseconds, -1 to disable. Should be max 50 (0.05s). Considering + ## it to be crashed, server will forcibly shutdown. + MAX_TICK_TIME: -1 + SPAWN_ANIMALS: true + SPAWN_MONSTERS: true + SPAWN_NPCS: true + SPAWN_PROTECTION: 50 + ## Sets the amount of world data the server sends the client, measured in + ## chunks in each direction of the player (radius, not diameter). It + ## determines the server-side viewing distance. + VIEW_DISTANCE: 10 + SEED: "-9075357542416790126" # Ensure quotes are used if negative + # MODE: survival # creative, survival, adventure. Default: survival + MOTD: "The §c§lspiceest§r Minecraft server" + PVP: true + ## DEFAULT, FLAT, LARGEBIOMES, AMPLIFIED, CUSTOMIZED, BUFFET + LEVEL_TYPE: BIOMESOP + ## Can be paired with GENERATOR_SETTINGS for further customization + # GENERATOR_SETTINGS: '3;minecraft:bedrock,3*minecraft:stone,52*minecraft:sandstone;2;' + ## NOTE: : and : must be escaped using \. The checksum is plain-text + ## hexadecimal + # RESOURCE_PACK: 'http\://link.com/to/pack.zip?\: 1' + # RESOURCE_PACK_SHA1: 'd5db29cd03a2ed055086cef9c31c252b4587d6d0' + ## Use the LEVEL option to specify multiple worlds. NOTE: if running + ## multiple containers be sure to specify a different -v host directory + ## for each LEVEL + ## Default: world. You can either switch between world saves or run + ## multiple containers with different saves by using the LEVEL option, + ## where the default is "world" + LEVEL: world + ONLINE_MODE: TRUE + ALLOW_FLIGHT: TRUE + ## Set RCON settings + ENABLE_RCON: true + RCON_PASSWORD: $MINECRAFT_RCON_PASSWORD + RCON_PORT: $MINECRAFT_RCON_PORT + ## Other server settings + PLAYER_IDLE_TIMEOUT: 0 + # BROADCAST_CONSOLE_TO_OPS: + # BROADCAST_RCON_TO_OPS: + # ENABLE_JMX: + USE_AIKAR_FLAGS: true + # SYNC_CHUNK_WRITES: + # ENABLE_STATUS: + # ENTITY_BROADCAST_RANGE_PERCENTAGE: + # FUNCTION_PERMISSION_LEVEL: + NETWORK_COMPRESSION_THRESHOLD: 256 + OP_PERMISSION_LEVEL: 4 + # PREVENT_PROXY_CONNECTIONS: + # USE_NATIVE_TRANSPORT: + # ENFORCE_WHITELIST: + # ENABLE_WHITELIST: + # STOP_SERVER_ANNOUNCE_DELAY: 30 + ENABLE_ROLLING_LOGS: true + ## Set up autopause for server usage optimization + ## See https://github.com/itzg/docker-minecraft-server/blob/master/README.md#autopause + ## MAX_TICK_TIME must be set to an arbitrarily large number or disabled + ## (-1) to allow for autopause + ENABLE_AUTOPAUSE: TRUE + ## Default: 3600. Time between the last client disconnect and the pausing + ## of the process + # AUTOPAUSE_TIMEOUT_EST: 3600 + ## Default: 600. Time between server start and the pausing of the + ## process, when no client connects inbetween + # AUTOPAUSE_TIMEOUT_INIT: 600 + ## Default: 120. Time between knocking of the port (e.g. by the main menu + # ping) and the pausing of the process, when no client connects inbetween + # AUTOPAUSE_TIMEOUT_KN: 120 + ## Default: 10. Period of the daemonized state machine, that handles the + ## pausing of the process (resuming is done independently) + # AUTOPAUSE_PERIOD: 10 + ## See https://github.com/itzg/docker-minecraft-server/blob/master/README.md#enabling-autopause + # AUTOPAUSE_KNOCK_INTERFACE: eth0 + ## enp4s0, eth0, lo, eno1, docker0, br-ab276aa20945, br-4d480c1adff5, t2_proxy + # labels: + # - "traefik.enable=true" + # ## HTTP Routers + # - "traefik.http.routers.minecraft-rtr.entrypoints=minecraft" + # - "traefik.http.routers.minecraft-rtr.rule=Host(`vanilla.mc.$DOMAINNAME0`)" + # ## Middlewares + # - "traefik.http.routers.minecraft-rtr.middlewares=chain-no-auth@file,minecraft-remove-bypass-cache" + # - "traefik.http.middlewares.minecraft-remove-bypass-cache.stripprefix.prefixes=/bypass_cache" + # ## HTTP Services + # - "traefik.http.routers.minecraft-rtr.service=minecraft-svc" + # - "traefik.http.services.minecraft-svc.loadbalancer.server.port=$MINECRAFT_PORT" diff --git a/compose/newrelic-infra.yml b/compose/newrelic-infra.yml new file mode 100644 index 0000000..70f533d --- /dev/null +++ b/compose/newrelic-infra.yml @@ -0,0 +1,26 @@ +--- +services: + # New Relic - Infrastructure and container monitoring + # https://docs.newrelic.com/docs/infrastructure/install-infrastructure-agent/linux-installation/container-infrastructure-monitoring/ + newrelic-infra: + image: newrelic/infrastructure:latest + container_name: newrelic-infra + cap_add: + ## Allows the agent to gather data about processes running on the host + - SYS_PTRACE + ## Allows the agent to collect the network metrics about the host. + network_mode: host + ## Required to monitor host processes / performance + pid: host + ## Required to monitor host processes / performance + privileged: true + restart: unless-stopped + volumes: + ## Allows the agent to collect process and storage metrics as well as + ## Inventory data from the host + - "/:/host:ro" + ## Allows the agent to connect to the Engine API via the Docker daemon + ## socket to collect the host's container data + - "/var/run/docker.sock:/var/run/docker.sock" + environment: + NRIA_LICENSE_KEY: $NRIA_LICENSE_KEY diff --git a/compose/nextcloud.yml b/compose/nextcloud.yml new file mode 100644 index 0000000..1797ff7 --- /dev/null +++ b/compose/nextcloud.yml @@ -0,0 +1,84 @@ +--- +secrets: + nextcloud_admin_user: + file: $SECRETSDIR/nextcloud_admin_user + nextcloud_admin_password: + file: $SECRETSDIR/nextcloud_admin_password + nextcloud_mysql_user: + file: $SECRETSDIR/nextcloud_mysql_user + nextcloud_mysql_password: + file: $SECRETSDIR/nextcloud_mysql_password + nextcloud_redis_password: + ## Should be symlinked to `redis_password` + ## ln -s ./redis_password nextcloud_redis_password + file: $SECRETSDIR/nextcloud_redis_password + nextcloud_smtp_name: + ## Currently unsupported + file: $SECRETSDIR/nextcloud_smtp_name + nextcloud_smtp_password: + ## Currently unsupported + file: $SECRETSDIR/nextcloud_smtp_password +services: + ## Nextcloud - A safe home for all your data + nextcloud: + container_name: nextcloud + image: nextcloud:29 + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/nextcloud:/var/www/html + - $APPDIR/nextcloud/custom_apps:/var/www/html/custom_apps + - $APPDIR/nextcloud/config:/var/www/html/config + - $DATADIR/nextcloud:/var/www/html/data + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + NEXTCLOUD_UPDATE: 1 + NEXTCLOUD_ADMIN_USER_FILE: /run/secrets/nextcloud_admin_user + NEXTCLOUD_ADMIN_PASSWORD_FILE: /run/secrets/nextcloud_admin_password + SERVERNAME: drive.$DOMAINNAME0 + MYSQL_USER_FILE: /run/secrets/nextcloud_mysql_user + MYSQL_PASSWORD_FILE: /run/secrets/nextcloud_mysql_password + MYSQL_DATABASE: nextcloud + MYSQL_HOST: $MARIADB_HOST + ## Have to set manually in the config.php for whatever reason, setting + ## this with environmental variables messes things up + # REDIS_HOST: redis + REDIS_HOST_PORT: $REDIS_PORT + REDIS_HOST_PASSWORD_FILE: /run/secrets/nextcloud_redis_password + SMTP_HOST: $EMAIL_SERVER + SMTP_SECURE: ssl + SMTP_PORT: $EMAIL_SERVER_PORT + SMTP_AUTHTYPE: PLAIN + ## Currently unsupported + # SMTP_NAME_FILE: /run/secrets/nextcloud_smtp_name + SMTP_NAME: $EMAIL_SERVER_USER + SMTP_PASSWORD_FILE: /run/secrets/nextcloud_smtp_password + MAIL_FROM_ADDRESS: admin@drive.$DOMAINNAME0 + # MAIL_DOMAIN: + NEXTCLOUD_TRUSTED_DOMAINS: drive.$DOMAINNAME0 + TRUSTED_PROXIES: $T2_PROXY_SUBNET + secrets: + - nextcloud_admin_user + - nextcloud_admin_password + - nextcloud_mysql_user + - nextcloud_mysql_password + - nextcloud_smtp_name + - nextcloud_smtp_password + - nextcloud_redis_password + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.nextcloud-rtr.entrypoints=https" + - "traefik.http.routers.nextcloud-rtr.rule=Host(`drive.$DOMAINNAME0`)" + - "traefik.http.routers.nextcloud-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.nextcloud-rtr.middlewares=chain-nextcloud@file,nextcloud-remove-bypass-cache" + - "traefik.http.middlewares.nextcloud-remove-bypass-cache.stripprefix.prefixes=/bypass_cache" + ## HTTP Services + - "traefik.http.routers.nextcloud-rtr.service=nextcloud-svc" + - "traefik.http.services.nextcloud-svc.loadbalancer.server.port=80" diff --git a/compose/ntp.yml b/compose/ntp.yml new file mode 100644 index 0000000..41261ef --- /dev/null +++ b/compose/ntp.yml @@ -0,0 +1,25 @@ +--- +services: + ## NTP - NTP server running in a Docker container (without the priviledged flag) + ## NTP server + ## Query the NTP server: ntpdate -q mint.home.arpa + ## Check sources: docker exec ntp chronyc sources + ## View source stats: docker exec ntp chronyc sourcestats + ## View NPT status: docker exec ntp chronyc tracking + ## Automatically update system time (Linux): + ## https://winaero.com/how-to-set-time-from-the-internet-ntp-in-linux-mint-17/ + ## Automatically update system time (Windows): + ## https://winaero.com/configure-internet-time-ntp-options-in-windows-10/ + ntp: + image: cturra/ntp:latest + container_name: ntp + security_opt: + - no-new-privileges:true + restart: unless-stopped + ports: + # - $NTP_PORT:123 + - $NTP_PORT:123/udp + environment: + NTP_SERVERS: $NTP_SERVERS + ## 0 (info), 1 (warning), 2 (non-fatal error), and 3 (fatal error) + LOG_LEVEL: 1 diff --git a/compose/ombi.yml b/compose/ombi.yml new file mode 100644 index 0000000..7a9f480 --- /dev/null +++ b/compose/ombi.yml @@ -0,0 +1,28 @@ +--- +services: + ## Ombi - Request Management System + ombi: + image: lscr.io/linuxserver/ombi:latest + container_name: ombi + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + volumes: + - $APPDIR/ombi/config:/config + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.ombi-rtr.entrypoints=https" + - "traefik.http.routers.ombi-rtr.rule=Host(`ombi.$DOMAINNAME0`)" + - "traefik.http.routers.ombi-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.ombi-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.ombi-rtr.service=ombi-svc" + - "traefik.http.services.ombi-svc.loadbalancer.server.port=3579" diff --git a/compose/organizr.yml b/compose/organizr.yml new file mode 100644 index 0000000..5825f64 --- /dev/null +++ b/compose/organizr.yml @@ -0,0 +1,29 @@ +--- +services: + ## Organizr - Application Dashboard + organizr: + image: organizr/organizr + container_name: organizr + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/organizr/config:/config + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + fpm: "true" + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.organizr-rtr.entrypoints=https" + - "traefik.http.routers.organizr-rtr.rule=Host(`$DOMAINNAME0`,`www.$DOMAINNAME0`)" + - "traefik.http.routers.organizr-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.organizr-rtr.middlewares=chain-authelia0@file" + ## HTTP Services + - "traefik.http.routers.organizr-rtr.service=organizr-svc" + - "traefik.http.services.organizr-svc.loadbalancer.server.port=80" diff --git a/compose/overseerr.yml b/compose/overseerr.yml new file mode 100644 index 0000000..2417162 --- /dev/null +++ b/compose/overseerr.yml @@ -0,0 +1,35 @@ +--- +services: + ## Overseerr - Request Management System (Plex Only) + overseerr: + image: lscr.io/linuxserver/overseerr:latest + container_name: overseerr + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + volumes: + - $APPDIR/overseerr/config:/config + healthcheck: + # https://github.com/sct/overseerr/issues/411#issuecomment-755083037 + start_period: 10s + test: wget --spider "http://localhost:$OVERSEERR_PORT/api/v1/status" -qO /dev/null || exit 1 + interval: 30s + timeout: 20s + retries: 3 + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.overseerr-rtr.entrypoints=https" + - "traefik.http.routers.overseerr-rtr.rule=Host(`overseerr.$DOMAINNAME0`) || Host(`request.$DOMAINNAME0`)" + - "traefik.http.routers.overseerr-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.overseerr-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.overseerr-rtr.service=overseerr-svc" + - "traefik.http.services.overseerr-svc.loadbalancer.server.port=5055" diff --git a/compose/phpmyadmin.yml b/compose/phpmyadmin.yml new file mode 100644 index 0000000..a50198d --- /dev/null +++ b/compose/phpmyadmin.yml @@ -0,0 +1,46 @@ +--- +secrets: + phpmyadmin_mysql_root_password: + ## Should be symlinked to `mysql_root_password` + ## ln -s ./mysql_root_password phpmyadmin_mysql_root_password + file: $SECRETSDIR/phpmyadmin_mysql_root_password +services: + ## phpMyAdmin - Database management + ## Create a new user with admin privileges. Cannot login as MySQL root for + ## some reason. + phpmyadmin: + image: phpmyadmin:latest + container_name: phpmyadmin + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + depends_on: + - mariadb + # volumes: + # - $APPDIR/phpmyadmin/config:/etc/phpmyadmin/conf.d:ro + # - $APPDIR/phpmyadmin/sessions:/sessions:rw + environment: + PMA_HOST: $MARIADB_HOST + PMA_PORT: $MARIADB_PORT + # PMA_ARBITRARY: 1 + MYSQL_ROOT_PASSWORD_FILE: /run/secrets/phpmyadmin_mysql_root_password + PMA_ABSOLUTE_URI: pma.$DOMAINNAME0 + # PMA_USER: pma + # PMA_PASSWORD_FILE: /run/secrets/pma_password + secrets: + - phpmyadmin_mysql_root_password + # - pma_password + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.phpmyadmin-rtr.entrypoints=https" + - "traefik.http.routers.phpmyadmin-rtr.rule=Host(`pma.$DOMAINNAME0`)" + - "traefik.http.routers.phpmyadmin-rtr.tls.options=tls-opts@file" + ## Middlewares + # - "traefik.http.routers.phpmyadmin-rtr.middlewares=chain-no-auth@file" + - "traefik.http.routers.phpmyadmin-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.phpmyadmin-rtr.service=phpmyadmin-svc" + - "traefik.http.services.phpmyadmin-svc.loadbalancer.server.port=80" diff --git a/compose/pi-hole.yml b/compose/pi-hole.yml new file mode 100644 index 0000000..aa23f83 --- /dev/null +++ b/compose/pi-hole.yml @@ -0,0 +1,46 @@ +--- +services: + ## Pi-Hole - Network-wide ad blocking + pihole: + ## Note: several steps must be taken to ensure compatability + ## https://www.smarthomebeginner.com/run-pihole-in-docker-on-ubuntu-with-reverse-proxy/ + image: pihole/pihole:latest + container_name: pihole + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + ports: + - $PIHOLE_PORT:53 + - $PIHOLE_PORT:53/udp + # - $PIHOLE_WEB_PORT:80 + volumes: + - $APPDIR/pihole/etc/pihole:/etc/pihole + - $APPDIR/pihole/etc/dnsmasq.d:/etc/dnsmasq.d + ## touch pihole.log first + - $APPDIR/pihole/var/log/pihole.log:/var/log/pihole.log + # cap_add: + # - NET_ADMIN + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + ServerIP: $IP + PROXY_LOCATION: pihole + VIRTUAL_HOST: pihole.$DOMAINNAME0 + VIRTUAL_PORT: 80 + WEBPASSWORD: $PIHOLE_WEBPASSWORD + PIHOLE_DNS_: 127.0.0.1#8053;192.168.1.2 + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.pihole-rtr.entrypoints=https" + - "traefik.http.routers.pihole-rtr.rule=Host(`pihole.$DOMAINNAME0`)" + - "traefik.http.routers.pihole-rtr.tls.options=tls-opts@file" + ## Middlewares + #- "traefik.http.routers.pihole-rtr.middlewares=chain-basic-auth@file" + - "traefik.http.routers.pihole-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.pihole-rtr.service=pihole-svc" + - "traefik.http.services.pihole-svc.loadbalancer.server.port=80" diff --git a/compose/plex.yml b/compose/plex.yml new file mode 100644 index 0000000..fd587a5 --- /dev/null +++ b/compose/plex.yml @@ -0,0 +1,45 @@ +--- +secrets: + plex_claim: + file: $SECRETSDIR/plex_claim +services: + ## Plex - Media Server + plex: + image: lscr.io/linuxserver/plex:latest + container_name: plex + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + devices: + ## AMD hardware transcoding? + - /dev/dri:/dev/dri + - /dev/dri/renderD128:/dev/dri/renderD128 + - /dev/dri/card0:/dev/dri/card0 + volumes: + - $DOCKERDIR/appdata/plex:/config + - $DATADIR/media:/media + ## Perform transcoding in RAM + - /dev/shm:/transcode + ## Perform transcoding on SSD + - /$APPDIR/plex/transcodes:/data/transcode + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + PLEX_CLAIM: /run/secrets/plex_claim + VERSION: docker + secrets: + - plex_claim + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.plex-rtr.entrypoints=https" + - "traefik.http.routers.plex-rtr.rule=Host(`plex.$DOMAINNAME0`)" + ## Middlewares + - "traefik.http.routers.plex-rtr.middlewares=chain-authelia@file,plex-remove-bypass-cache" + - "traefik.http.middlewares.plex-remove-bypass-cache.stripPrefix.prefixes=/bypass_cache" + ## HTTP Services + - "traefik.http.routers.plex-rtr.service=plex-svc" + - "traefik.http.services.plex-svc.loadbalancer.server.port=32400" diff --git a/compose/portfolio.yml b/compose/portfolio.yml new file mode 100644 index 0000000..1637fac --- /dev/null +++ b/compose/portfolio.yml @@ -0,0 +1,34 @@ +--- +services: + ## Portfolio Performance + ## Issue with installation - /startapp.sh: cd: line 2: can't cd to + ## /opt/portfolio/workspace: No such file or directory + ## Need to change the startapp.sh to reference something other than + ## /workspace because /opt/portfolio exists + portfolio: + image: ghcr.io/devben-io/docker-portfolio/docker-portfolio:latest + container_name: portfolio + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + hostname: portfolio.$DOMAINNAME0 + environment: + TZ: $TZ + APP_NAME: "Portfolio Performance" + LOCALE: en_us + # APP_ICON_URL: https://www.portfolio-performance.info/images/logo.png + KEEP_APP_RUNNING: 1 + # USER_ID: $PUID + # GROUP_ID: $PGID + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.portfolio-rtr.entrypoints=https" + - "traefik.http.routers.portfolio-rtr.rule=Host(`portfolio.$DOMAINNAME0`)" + ## Middlewares + - "traefik.http.routers.portfolio-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.portfolio-rtr.service=portfolio-svc" + - "traefik.http.services.portfolio-svc.loadbalancer.server.port=$PORTFOLIO_PORT" diff --git a/compose/postgres.yml b/compose/postgres.yml new file mode 100644 index 0000000..586d1ff --- /dev/null +++ b/compose/postgres.yml @@ -0,0 +1,54 @@ +--- +secrets: + postgres_user: + file: $SECRETSDIR/postgres_user + postgres_password: + file: $SECRETSDIR/postgres_password +services: + ## PostgreSQL - PostgreSQL Database + ## Steps for adding a new user/database: + ## 1. Log in to adminer.$DOMAINNAME0 with postgres root + ## 2. Open `SQL command` and execute the following lines: + ## CREATE USER WITH PASSWORD ''; + ## CREATE DATABASE OWNER ; + ## GRANT ALL PRIVILEGES ON DATABASE TO ; + ## + ## Steps for restoring from a backup: + ## 1. Place the output of pg_dump in a convenient location, e.g., "${DOCKERDIR}/backup/postgres_dump.sql" + ## 2. Start `postgres` with a clean data directory + ## 3. Run the following command to recreate the database as specified in the postgres_dump.sql file + ## sudo docker exec -i --user=postgres postgres psql --dbname=postgres < ./backup/postgres_dump.sql + postgres: + container_name: postgres + image: postgres:16 + user: "${PUID}:${PGID}" + networks: + t2_proxy: + ipv4_address: $POSTGRES_IPV4 + security_opt: + - no-new-privileges:true + restart: always + healthcheck: + test: + [ + "CMD-SHELL", + 'pg_isready -d "$${POSTGRES_DB:-$${POSTGRES_USER:-$$(cat "$${POSTGRES_USER_FILE}")}}" -U "$${POSTGRES_USER:-$$(cat "$$POSTGRES_USER_FILE")}"', + ] + start_period: 20s + interval: 30s + retries: 5 + timeout: 5s + volumes: + - $APPDIR/postgres/config:/config + - $APPDIR/postgres/data:/var/lib/postgresql/data + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + POSTGRES_USER_FILE: /run/secrets/postgres_user + POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password + PGPORT: $POSTGRES_PORT + PGDATA: /var/lib/postgresql/data/pgdata + secrets: + - postgres_user + - postgres_password diff --git a/compose/prowlarr.yml b/compose/prowlarr.yml new file mode 100644 index 0000000..7f6cdec --- /dev/null +++ b/compose/prowlarr.yml @@ -0,0 +1,36 @@ +--- +services: + # Prowlarr - Torrent proxy + prowlarr: + image: lscr.io/linuxserver/prowlarr:develop + container_name: prowlarr + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/prowlarr/config:/config + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + labels: + - "traefik.enable=true" + ## HTTP Routers API Auth Bypass + - "traefik.http.routers.prowlarr-rtr-bypass.entrypoints=https" + - "traefik.http.routers.prowlarr-rtr-bypass.rule=Host(`prowlarr.$DOMAINNAME0`) && ( Header(`X-Api-Key`, `$PROWLARR_API_KEY`) || Query(`apikey`, `$PROWLARR_API_KEY`) )" + - "traefik.http.routers.prowlarr-rtr-bypass.tls.options=tls-opts@file" + - "traefik.http.routers.prowlarr-rtr-bypass.priority=100" + ## HTTP Routers Auth + - "traefik.http.routers.prowlarr-rtr.entrypoints=https" + - "traefik.http.routers.prowlarr-rtr.rule=Host(`prowlarr.$DOMAINNAME0`)" + - "traefik.http.routers.prowlarr-rtr.tls.options=tls-opts@file" + - "traefik.http.routers.prowlarr-rtr.priority=99" + ## Middlewares + - "traefik.http.routers.prowlarr-rtr-bypass.middlewares=chain-no-auth@file" + - "traefik.http.routers.prowlarr-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.prowlarr-rtr-bypass.service=prowlarr-svc" + - "traefik.http.routers.prowlarr-rtr.service=prowlarr-svc" + - "traefik.http.services.prowlarr-svc.loadbalancer.server.port=9696" diff --git a/compose/qbit-private.yml b/compose/qbit-private.yml new file mode 100644 index 0000000..ce64121 --- /dev/null +++ b/compose/qbit-private.yml @@ -0,0 +1,49 @@ +--- +secrets: + qbittorrent_user: + file: $SECRETSDIR/qbittorrent_user + qbittorrent_pass: + file: $SECRETSDIR/qbittorrent_pass +services: + ## qBittorrent - an open-source software alternative to µTorrent + ## qbit-private is used for private trackers + qbit-private: + image: lscr.io/linuxserver/qbittorrent:5.0.4 + container_name: qbit-private + security_opt: + - no-new-privileges:true + restart: unless-stopped + ## We do not want this to be able to communicate locally (except as + ## specified) + network_mode: "service:gluetun-private" + environment: + # Built-in env variables + TZ: $TZ + PUID: $PUID + PGID: $PGID + WEBUI_PORT: $QBITTORRENT_PRIVATE_PORT + # Custom env variables + LOG_LEVEL: "WARN" # "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" + FILE__QBITTORRENT_USERNAME: /run/secrets/qbittorrent_user + FILE__QBITTORRENT_PASSWORD: /run/secrets/qbittorrent_pass + GLUETUN_IPV4: $GLUETUN_PRIVATE_IPV4 + GLUETUN_HTTP_CONTROL_SERVER_PORT: $GLUETUN_PRIVATE_HTTP_CONTROL_SERVER_PORT + volumes: + - $APPDIR/qbittorrent-private/config:/config + ## Add scripts + - $APPDIR/qbittorrent-private/scripts:/scripts:ro + ## Space for persistent storage + - $APPDIR/qbittorrent-private/persistent:/persistent + ## Add init scripts + - $APPDIR/qbittorrent-private/custom-cont-init.d:/custom-cont-init.d:ro + - $APPDIR/qbittorrent-private/custom-services.d:/custom-services.d:ro + ## Final home for data + - $DATADIR/torrents-private:/data/torrents-private + ## Allows for local download before transfer + - $DOCKERDIR/temp-data/torrents:/temp-data/torrents + secrets: + - qbittorrent_user + - qbittorrent_pass + labels: + ## Ensure constant connectivity is prioritized for trackers + - "com.centurylinklabs.watchtower.enable=false" diff --git a/compose/qbit-temp.yml b/compose/qbit-temp.yml new file mode 100644 index 0000000..06e6dd7 --- /dev/null +++ b/compose/qbit-temp.yml @@ -0,0 +1,49 @@ +--- +secrets: + qbittorrent_user: + file: $SECRETSDIR/qbittorrent_user + qbittorrent_pass: + file: $SECRETSDIR/qbittorrent_pass +services: + ## qBittorrent - an open-source software alternative to µTorrent + ## qbit-private is used for private trackers + qbit-temp: + image: lscr.io/linuxserver/qbittorrent:5.0.4 + container_name: qbit-temp + security_opt: + - no-new-privileges:true + restart: unless-stopped + ## We do not want this to be able to communicate locally (except as + ## specified) + network_mode: "service:gluetun-temp" + environment: + # Built-in env variables + TZ: $TZ + PUID: $PUID + PGID: $PGID + WEBUI_PORT: $QBITTORRENT_TEMP_PORT + # Custom env variables + LOG_LEVEL: "WARN" # "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" + FILE__QBITTORRENT_USERNAME: /run/secrets/qbittorrent_user + FILE__QBITTORRENT_PASSWORD: /run/secrets/qbittorrent_pass + GLUETUN_IPV4: $GLUETUN_TEMP_IPV4 + GLUETUN_HTTP_CONTROL_SERVER_PORT: $GLUETUN_TEMP_HTTP_CONTROL_SERVER_PORT + volumes: + - $APPDIR/qbittorrent-temp/config:/config + ## Add scripts + - $APPDIR/qbittorrent-temp/scripts:/scripts:ro + ## Space for persistent storage + - $APPDIR/qbittorrent-temp/persistent:/persistent + ## Add init scripts + - $APPDIR/qbittorrent-temp/custom-cont-init.d:/custom-cont-init.d:ro + - $APPDIR/qbittorrent-temp/custom-services.d:/custom-services.d:ro + ## Final home for data + - $DATADIR/torrents-private:/data/torrents-private + ## Allows for local download before transfer + - $DOCKERDIR/temp-data/torrents:/temp-data/torrents + secrets: + - qbittorrent_user + - qbittorrent_pass + labels: + ## Ensure constant connectivity is prioritized for trackers + - "com.centurylinklabs.watchtower.enable=false" diff --git a/compose/qbit.yml b/compose/qbit.yml new file mode 100644 index 0000000..8b0c10d --- /dev/null +++ b/compose/qbit.yml @@ -0,0 +1,48 @@ +--- +secrets: + qbittorrent_user: + file: $SECRETSDIR/qbittorrent_user + qbittorrent_pass: + file: $SECRETSDIR/qbittorrent_pass +services: + ## qBittorrent - an open-source software alternative to µTorrent + qbit: + image: lscr.io/linuxserver/qbittorrent:latest + container_name: qbit + security_opt: + - no-new-privileges:true + restart: unless-stopped + ## We do not want this to be able to communicate locally (except as + ## specified) + network_mode: "service:gluetun" + environment: + # Built-in env variables + TZ: $TZ + PUID: $PUID + PGID: $PGID + WEBUI_PORT: $QBITTORRENT_PORT + # Custom env variables + LOG_LEVEL: "WARN" # "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" + FILE__QBITTORRENT_USERNAME: /run/secrets/qbittorrent_user + FILE__QBITTORRENT_PASSWORD: /run/secrets/qbittorrent_pass + GLUETUN_IPV4: $GLUETUN_IPV4 + GLUETUN_HTTP_CONTROL_SERVER_PORT: $GLUETUN_HTTP_CONTROL_SERVER_PORT + volumes: + - $APPDIR/qbittorrent/config:/config + ## Add scripts + - $APPDIR/qbittorrent/scripts:/scripts:ro + ## Space for persistent storage + - $APPDIR/qbittorrent/persistent:/persistent + ## Add init scripts + - $APPDIR/qbittorrent/custom-cont-init.d:/custom-cont-init.d:ro + - $APPDIR/qbittorrent/custom-services.d:/custom-services.d:ro + ## Final home for data + - $DATADIR/torrents:/data/torrents + ## Allows for local download before transfer + - $DOCKERDIR/temp-data/torrents:/temp-data/torrents + secrets: + - qbittorrent_user + - qbittorrent_pass + labels: + ## Ensure constant connectivity is prioritized for trackers + - "com.centurylinklabs.watchtower.enable=false" diff --git a/compose/radarr-4k.yml b/compose/radarr-4k.yml new file mode 100644 index 0000000..2d466ae --- /dev/null +++ b/compose/radarr-4k.yml @@ -0,0 +1,39 @@ +--- +services: + # Radarr - Movie management + radarr-4k: + image: lscr.io/linuxserver/radarr:latest + container_name: radarr-4k + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/radarr-4k/config:/config + # - $DATADIR/temp/appdata/radarr/MediaCover:/config/MediaCover + - $DATADIR:/data + - "/etc/localtime:/etc/localtime:ro" + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + labels: + - "traefik.enable=true" + ## HTTP Routers API Auth Bypass + - "traefik.http.routers.radarr-4k-rtr-bypass.entrypoints=https" + - "traefik.http.routers.radarr-4k-rtr-bypass.rule=Host(`radarr-4k.$DOMAINNAME0`) && (Header(`X-Api-Key`, `$RADARR_API_KEY`) || Query(`apikey`, `$RADARR_API_KEY`))" + - "traefik.http.routers.radarr-4k-rtr-bypass.tls.options=tls-opts@file" + - "traefik.http.routers.radarr-4k-rtr-bypass.priority=100" + ## HTTP Routers Auth + - "traefik.http.routers.radarr-4k-rtr.entrypoints=https" + - "traefik.http.routers.radarr-4k-rtr.rule=Host(`radarr-4k.$DOMAINNAME0`)" + - "traefik.http.routers.radarr-4k-rtr.tls.options=tls-opts@file" + - "traefik.http.routers.radarr-4k-rtr.priority=99" + ## Middlewares + - "traefik.http.routers.radarr-4k-rtr-bypass.middlewares=chain-no-auth@file" + - "traefik.http.routers.radarr-4k-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.radarr-4k-rtr-bypass.service=radarr-4k-svc" + - "traefik.http.routers.radarr-4k-rtr.service=radarr-4k-svc" + - "traefik.http.services.radarr-4k-svc.loadbalancer.server.port=7878" diff --git a/compose/radarr.yml b/compose/radarr.yml new file mode 100644 index 0000000..634fa44 --- /dev/null +++ b/compose/radarr.yml @@ -0,0 +1,39 @@ +--- +services: + # Radarr - Movie management + radarr: + image: lscr.io/linuxserver/radarr:latest + container_name: radarr + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/radarr/config:/config + # - $DATADIR/temp/appdata/radarr/MediaCover:/config/MediaCover + - $DATADIR:/data + - "/etc/localtime:/etc/localtime:ro" + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + labels: + - "traefik.enable=true" + ## HTTP Routers API Auth Bypass + - "traefik.http.routers.radarr-rtr-bypass.entrypoints=https" + - "traefik.http.routers.radarr-rtr-bypass.rule=Host(`radarr.$DOMAINNAME0`) && (Header(`X-Api-Key`, `$RADARR_API_KEY`) || Query(`apikey`, `$RADARR_API_KEY`))" + - "traefik.http.routers.radarr-rtr-bypass.tls.options=tls-opts@file" + - "traefik.http.routers.radarr-rtr-bypass.priority=100" + ## HTTP Routers Auth + - "traefik.http.routers.radarr-rtr.entrypoints=https" + - "traefik.http.routers.radarr-rtr.rule=Host(`radarr.$DOMAINNAME0`)" + - "traefik.http.routers.radarr-rtr.tls.options=tls-opts@file" + - "traefik.http.routers.radarr-rtr.priority=99" + ## Middlewares + - "traefik.http.routers.radarr-rtr-bypass.middlewares=chain-no-auth@file" + - "traefik.http.routers.radarr-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.radarr-rtr-bypass.service=radarr-svc" + - "traefik.http.routers.radarr-rtr.service=radarr-svc" + - "traefik.http.services.radarr-svc.loadbalancer.server.port=7878" diff --git a/compose/recyclarr.yml b/compose/recyclarr.yml new file mode 100644 index 0000000..03d938a --- /dev/null +++ b/compose/recyclarr.yml @@ -0,0 +1,19 @@ +--- +services: + ## Recyclarr - A (dockerized) command-line application that will + ## automatically synchronize recommended settings from TRaSH guides to your + ## Sonarr / Radarr instances. + ## https://trash-guides.info/Misc/trash-sync/ + recyclarr: + image: recyclarr/recyclarr:latest + container_name: recyclarr + security_opt: + - no-new-privileges:true + restart: unless-stopped + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + CRON_SCHEDULE: "0 12 * * 1" # Optional - Default "@daily" - https://cron.help/ + volumes: + - $APPDIR/recyclarr/config:/config diff --git a/compose/redis.yml b/compose/redis.yml new file mode 100644 index 0000000..195ea87 --- /dev/null +++ b/compose/redis.yml @@ -0,0 +1,30 @@ +--- +secrets: + ## Not currently working + redis_password: + file: $SECRETSDIR/redis_password +services: + ## Redis - Key-value Store + redis: + container_name: redis + image: redis:latest + networks: + t2_proxy: + ipv4_address: $REDIS_IPV4 + security_opt: + - no-new-privileges:true + restart: always + entrypoint: redis-server --requirepass $REDIS_PASSWORD --maxmemory 512mb --maxmemory-policy allkeys-lru --port $REDIS_PORT + healthcheck: + test: ["CMD-SHELL", "/healthcheck.sh"] + start_period: 5s + interval: 5s + retries: 5 + timeout: 3s + ports: + - "$REDIS_PORT:$REDIS_PORT" + volumes: + - $APPDIR/redis/data:/data + - $APPDIR/redis/config/healthcheck.sh:/healthcheck.sh:ro + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro diff --git a/compose/rediscommander.yml b/compose/rediscommander.yml new file mode 100644 index 0000000..f7a4237 --- /dev/null +++ b/compose/rediscommander.yml @@ -0,0 +1,38 @@ +--- +secrets: + rediscommander_redis_password: + ## Should be symlinked to `redis_password` + ## ln -s ./redis_password rediscommander_redis_password + file: $SECRETSDIR/rediscommander_redis_password +services: + ## Redis Commander - Redis Management Tool + rediscommander: + container_name: rediscommander + image: ghcr.io/joeferner/redis-commander:latest + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + depends_on: + - redis + environment: + REDIS_HOST: $REDIS_HOST + REDIS_PORT: $REDIS_PORT + ## Not currently working + # REDIS_PASSWORD_FILE: /run/secrets/rediscommander_redis_password + REDIS_PASSWORD: $REDIS_PASSWORD + PORT: $REDISCOMMANDER_PORT + secrets: + - rediscommander_redis_password + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.rediscommander-rtr.entrypoints=https" + - "traefik.http.routers.rediscommander-rtr.rule=Host(`rediscom.$DOMAINNAME0`)" + - "traefik.http.routers.rediscommander-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.rediscommander-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.rediscommander-rtr.service=rediscommander-svc" + - "traefik.http.services.rediscommander-svc.loadbalancer.server.port=$REDISCOMMANDER_PORT" diff --git a/compose/socket-proxy.yml b/compose/socket-proxy.yml new file mode 100644 index 0000000..c266e5c --- /dev/null +++ b/compose/socket-proxy.yml @@ -0,0 +1,54 @@ +--- +services: + ## Docker Socket Proxy - Security Enchanced Proxy for Docker Socket + socket-proxy: + container_name: socket-proxy + image: tecnativa/docker-socket-proxy + security_opt: + - no-new-privileges:true + restart: always + networks: + socket_proxy: + ipv4_address: $SOCKET_PROXY_IPV4 # You can specify a static IP + privileged: true + ports: + ## Port 2375 should only ever get exposed to the internal network. When + ## possible use this line. + - 127.0.0.1:2375:2375 + # - 2375:2375 + volumes: + - "/var/run/docker.sock:/var/run/docker.sock" + environment: + ## tecnativa + - LOG_LEVEL=warning # debug,info,notice,warning,err,crit,alert,emerg + ## Variables match the URL prefix (i.e. AUTH blocks access to /auth/* + ## parts of the API, etc.). + ## 0 to revoke access. + ## 1 to grant access. + ## Granted by Default + - EVENTS=1 + - PING=1 + - VERSION=1 + ## Revoked by Default + ## Security critical + - AUTH=0 # 0 + - SECRETS=0 # 0 + - POST=1 # Watchtower + ## Not always needed + - BUILD=0 # 0 + - COMMIT=0 # 0 + - CONFIGS=0 # 0 + - CONTAINERS=1 # Traefik, portainer, etc. + - DISTRIBUTION=0 # 0 + - EXEC=0 # 0 + - IMAGES=1 # Portainer + - INFO=1 # Portainer + - NETWORKS=1 # Portainer + - NODES=0 # 0 + - PLUGINS=0 # 0 + - SERVICES=1 # Portainer + - SESSION=0 # 0 + - SWARM=0 # 0 + - SYSTEM=0 # 0 + - TASKS=1 # Portaienr + - VOLUMES=1 # Portainer diff --git a/compose/sonarr-4k.yml b/compose/sonarr-4k.yml new file mode 100644 index 0000000..e53c87d --- /dev/null +++ b/compose/sonarr-4k.yml @@ -0,0 +1,39 @@ +--- +services: + # Sonarr - TV Shows management + sonarr-4k: + image: lscr.io/linuxserver/sonarr + container_name: sonarr-4k + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/sonarr-4k/config:/config + # - $DATADIR/temp/appdata/sonarr/MediaCover:/config/MediaCover + - $DATADIR:/data + - "/etc/localtime:/etc/localtime:ro" + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + labels: + - "traefik.enable=true" + ## HTTP Routers Auth Bypass + - "traefik.http.routers.sonarr-4k-rtr-bypass.entrypoints=https" + - "traefik.http.routers.sonarr-4k-rtr-bypass.rule=Host(`sonarr-4k.$DOMAINNAME0`) && (Header(`X-Api-Key`, `$SONARR_API_KEY`) || Query(`apikey`, `$SONARR_API_KEY`))" + - "traefik.http.routers.sonarr-4k-rtr-bypass.tls.options=tls-opts@file" + - "traefik.http.routers.sonarr-4k-rtr-bypass.priority=100" + ## HTTP Routers Auth + - "traefik.http.routers.sonarr-4k-rtr.entrypoints=https" + - "traefik.http.routers.sonarr-4k-rtr.rule=Host(`sonarr-4k.$DOMAINNAME0`)" + - "traefik.http.routers.sonarr-4k-rtr.tls.options=tls-opts@file" + - "traefik.http.routers.sonarr-4k-rtr.priority=99" + ## Middlewares + - "traefik.http.routers.sonarr-4k-rtr-bypass.middlewares=chain-no-auth@file" + - "traefik.http.routers.sonarr-4k-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.sonarr-4k-rtr.service=sonarr-4k-svc" + - "traefik.http.routers.sonarr-4k-rtr-bypass.service=sonarr-4k-svc" + - "traefik.http.services.sonarr-4k-svc.loadbalancer.server.port=8989" diff --git a/compose/sonarr.yml b/compose/sonarr.yml new file mode 100644 index 0000000..a834126 --- /dev/null +++ b/compose/sonarr.yml @@ -0,0 +1,39 @@ +--- +services: + # Sonarr - TV Shows management + sonarr: + image: lscr.io/linuxserver/sonarr + container_name: sonarr + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/sonarr/config:/config + # - $DATADIR/temp/appdata/sonarr/MediaCover:/config/MediaCover + - $DATADIR:/data + - "/etc/localtime:/etc/localtime:ro" + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + labels: + - "traefik.enable=true" + ## HTTP Routers Auth Bypass + - "traefik.http.routers.sonarr-rtr-bypass.entrypoints=https" + - "traefik.http.routers.sonarr-rtr-bypass.rule=Host(`sonarr.$DOMAINNAME0`) && (Header(`X-Api-Key`, `$SONARR_API_KEY`) || Query(`apikey`, `$SONARR_API_KEY`))" + - "traefik.http.routers.sonarr-rtr-bypass.tls.options=tls-opts@file" + - "traefik.http.routers.sonarr-rtr-bypass.priority=100" + ## HTTP Routers Auth + - "traefik.http.routers.sonarr-rtr.entrypoints=https" + - "traefik.http.routers.sonarr-rtr.rule=Host(`sonarr.$DOMAINNAME0`)" + - "traefik.http.routers.sonarr-rtr.tls.options=tls-opts@file" + - "traefik.http.routers.sonarr-rtr.priority=99" + ## Middlewares + - "traefik.http.routers.sonarr-rtr-bypass.middlewares=chain-no-auth@file" + - "traefik.http.routers.sonarr-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.sonarr-rtr.service=sonarr-svc" + - "traefik.http.routers.sonarr-rtr-bypass.service=sonarr-svc" + - "traefik.http.services.sonarr-svc.loadbalancer.server.port=8989" diff --git a/compose/tautulli.yml b/compose/tautulli.yml new file mode 100644 index 0000000..b82c4c2 --- /dev/null +++ b/compose/tautulli.yml @@ -0,0 +1,38 @@ +--- +services: + ## Tautulli - Plex Media Server monitoring, analytics, and notifications + tautulli: + image: lscr.io/linuxserver/tautulli:latest + container_name: tautulli + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $APPDIR/tautulli/config:/config + ## Give read-only access to Plex logs for monitoring via Tautulli + - "$DATADIR/docker/plex/Library/Application Support/Plex Media Server/Logs:/plexlogs:ro" + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + labels: + - "traefik.enable=true" + ## HTTP Bypass Routers + - "traefik.http.routers.tautulli-rtr-bypass.entrypoints=https" + - "traefik.http.routers.tautulli-rtr-bypass.rule=Host(`tautulli.$DOMAINNAME0`) && Query(`apikey`, `$TAUTULLI_API_KEY`)" + - "traefik.http.routers.tautulli-rtr-bypass.tls.options=tls-opts@file" + - "traefik.http.routers.tautulli-rtr-bypass.priority=100" + ## HTTP Routers + - "traefik.http.routers.tautulli-rtr.entrypoints=https" + - "traefik.http.routers.tautulli-rtr.rule=Host(`tautulli.$DOMAINNAME0`)" + - "traefik.http.routers.tautulli-rtr.tls.options=tls-opts@file" + - "traefik.http.routers.tautulli-rtr-bypass.priority=99" + ## Middlewares + - "traefik.http.routers.tautulli-rtr-bypass.middlewares=chain-no-auth@file" + - "traefik.http.routers.tautulli-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.tautulli-rtr-bypass.service=tautulli-svc" + - "traefik.http.routers.tautulli-rtr.service=tautulli-svc" + - "traefik.http.services.tautulli-svc.loadbalancer.server.port=8181" diff --git a/compose/tdarr-node.yml b/compose/tdarr-node.yml new file mode 100644 index 0000000..9e6e4f0 --- /dev/null +++ b/compose/tdarr-node.yml @@ -0,0 +1,37 @@ +--- +services: + ## Tdarr - Distributed transcode automation + tdarr-node: + container_name: tdarr-node + image: ghcr.io/haveagitgat/tdarr_node:latest + privileged: true + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + devices: + ## AMD hardware transcoding + - /dev/dri:/dev/dri + # - /dev/dri/renderD128:/dev/dri/renderD128 + # - /dev/dri/card0:/dev/dri/card0 + environment: + UMASK_SET: 02 + serverIP: tdarr + serverPort: $TDARR_SERVER_PORT + nodeID: NucNode + nodeIP: tdarr-node # Container name of the node + nodePort: $TDARR_NODE_PORT + volumes: + - $APPDIR/tdarr/configs:/app/configs + - $APPDIR/tdarr/logs:/app/logs + ## Map single folder for `/data` and use `/data/media` and + ## `/data/temp/transcode` to allow for move operation instead of copy + - $DATADIR:/data + # - $DATADIR/temp/transcode:/data/temp/transcode + # - /dev/shm:/temp # Perform transcoding in RAM + logging: + options: + max-size: "2m" + max-file: "3" + # labels: # Not needed for the node diff --git a/compose/tdarr.yml b/compose/tdarr.yml new file mode 100644 index 0000000..2b9efc3 --- /dev/null +++ b/compose/tdarr.yml @@ -0,0 +1,49 @@ +--- +services: + ## Tdarr - Distributed transcode automation + tdarr: + container_name: tdarr + image: ghcr.io/haveagitgat/tdarr:latest + privileged: true + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + # devices: + # ## AMD hardware transcoding? + # - /dev/dri:/dev/dri + # - /dev/dri/renderD128:/dev/dri/renderD128 + # - /dev/dri/card0:/dev/dri/card0 + environment: + UMASK_SET: 002 + serverIP: tdarr + serverPort: $TDARR_SERVER_PORT + webUIPort: $TDARR_WEBUI_PORT + internalNode: "false" + # nodeID: MyInternalNode + volumes: + - $APPDIR/tdarr/server:/app/server + - $APPDIR/tdarr/configs:/app/configs + - $APPDIR/tdarr/logs:/app/logs + - $APPDIR/tdarr/scripts:/home/Tdarr/scripts + ## Map single folder for `/data` and use `/data/media` and + ## `/data/temp/transcode` to allow for move operation instead of copy + - $DATADIR:/data + # - $DATADIR/temp/transcode:/data/temp/transcode + # - /dev/shm:/temp # Perform transcoding in RAM + logging: + options: + max-size: "2m" + max-file: "3" + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.tdarr-rtr.entrypoints=https" + - "traefik.http.routers.tdarr-rtr.rule=Host(`tdarr.$DOMAINNAME0`)" + - "traefik.http.routers.tdarr-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.tdarr-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.tdarr-rtr.service=tdarr-svc" + - "traefik.http.services.tdarr-svc.loadbalancer.server.port=$TDARR_WEBUI_PORT" diff --git a/compose/traefik.yml b/compose/traefik.yml new file mode 100644 index 0000000..152f7a3 --- /dev/null +++ b/compose/traefik.yml @@ -0,0 +1,184 @@ +--- +secrets: + traefik_cf_api_key: + file: $SECRETSDIR/traefik_cf_api_key + traefik_cf_email: + file: $SECRETSDIR/traefik_cf_email + traefik_htpasswd: + file: $SECRETSDIR/traefik_htpasswd +services: + ## Traefik 2 - Reverse Proxy + ## Touch (create empty files) traefik.log and acme/acme.json. + ## Set acme.json permissions to 600. + ## touch $APPDIR/traefik2/acme/acme.json + ## chmod 600 $APPDIR/traefik2/acme/acme.json + ## touch $APPDIR/traefik2/traefik.log + traefik: + container_name: traefik + image: traefik:comte # comte=3.1.x + security_opt: + - no-new-privileges:true + restart: always + command: # CLI arguments + - --global.checkNewVersion=true + - --global.sendAnonymousUsage=true + - --entryPoints.http.address=:80 + - --entryPoints.https.address=:443 + ## Allow these IPs to set the X-Forwarded-* headers + ## Cloudflare IPs: https://www.cloudflare.com/ips/ + - --entrypoints.https.forwardedHeaders.trustedIPs=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22 + - --entryPoints.traefik.address=:8080 + ## Allows for ping/healthcheck at https://traefik.$DOMAINNAMEX/ping + - --entryPoints.ping.address=:8081 + - --api=true + - --api.insecure=true + - --api.dashboard=true + - --ping=true # Allow for ping/healthcheck + # - --pilot.token=$TRAEFIK_PILOT_TOKEN + # - --serversTransport.insecureSkipVerify=true + - --log=true + ## Default: ERROR; DEBUG, INFO, WARN, ERROR, FATAL, PANIC + - --log.level=INFO + - --accessLog=true + - --accessLog.filePath=/traefik.log + ## Configuring a buffer of 100 lines + - --accessLog.bufferingSize=100 + - --accessLog.filters.statusCodes=400-499 + - --providers.docker=true + ## Use Docker Socket Proxy instead for improved security + # - --providers.docker.endpoint=unix:///var/run/docker.sock + - --providers.docker.endpoint=tcp://socket-proxy:2375 + ## Automatically set Host rule for services + # - --providers.docker.defaultrule=Host(`{{ index .Labels "com.docker.compose.service" }}.$DOMAINNAME0`) + - --providers.docker.exposedByDefault=false + # - --entrypoints.https.http.middlewares=chain-oauth@file + - --entrypoints.https.http.tls.options=tls-opts@file + - --entrypoints.ping.http.tls.options=tls-opts@file + ## Add dns-cloudflare as default certresolver for all services. Also + ## enables TLS and no need to specify on individual services + - --entrypoints.https.http.tls.certresolver=dns-cloudflare + ## Pulls main and wildcard cert for first domain + - --entrypoints.https.http.tls.domains[0].main=$DOMAINNAME0 + - --entrypoints.https.http.tls.domains[0].sans=*.$DOMAINNAME0 + ## Pulls main and wildcard cert for second domain + # - --entrypoints.https.http.tls.domains[1].main=$DOMAINNAME1 + # - --entrypoints.https.http.tls.domains[1].sans=*.$DOMAINNAME1 + - --providers.docker.network=t2_proxy + ## Load dynamic configuration from one or more .toml or .yml files in a + ## directory + - --providers.file.directory=/rules + ## Load dynamic configuration from a file + #- --providers.file.filename=/path/to/file + ## Only works on top level files in the rules folder + - --providers.file.watch=true + ## LetsEncrypt Staging Server - uncomment when testing + # - --certificatesResolvers.dns-cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory + ## Optional. Used to specify the Key Type received from LetsEncrypt + - --certificatesResolvers.dns-cloudflare.acme.keyType=EC384 + - --certificatesResolvers.dns-cloudflare.acme.email=$CLOUDFLARE_EMAIL + - --certificatesResolvers.dns-cloudflare.acme.storage=/acme.json + - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.provider=cloudflare + - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53 + ## To delay DNS check and reduce LE hitrate + - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.delayBeforeCheck=90 + ## Set Wireguard entrypoint + - --entryPoints.wireguard.address=:$WIREGUARD_PORT/udp + ## Set Minecraft entrypoint + # - --entryPoints.minecraft.address=:25565 + ## Set minecraft-rcon entrypoint + # - --entryPoints.minecraft-rcon.address=:4326 + ## Set minecraft-rcon-websocket entrypoint + # - --entryPoints.minecraft-rcon-websocket.address=:4327 + ## Set Authentik LDAPS entrypoint + - --entryPoints.authentik-ldaps.address=:$AUTHENTIK_LDAPS_PORT + networks: + t2_proxy: + ipv4_address: $TRAEFIK_IPV4 # You can specify a static IP + socket_proxy: + # depends_on: + # - socket-proxy + healthcheck: + test: ["CMD", "traefik", "healthcheck", "--ping"] + interval: 5s + retries: 3 + ports: + - target: 80 + published: 80 + protocol: tcp + mode: host + - target: 443 + published: 443 + protocol: tcp + mode: host + - target: 8080 + published: 8080 + protocol: tcp + mode: host + - target: 8081 # Conflicting internal ping/healthcheck port + published: 8082 # To allow for redis at 8081 + protocol: tcp + mode: host + - target: $WIREGUARD_PORT # Port 80 UDP port for Wireguard + published: $WIREGUARD_PORT + protocol: udp + mode: host + - target: $AUTHENTIK_LDAPS_PORT # LDAPS port + published: $AUTHENTIK_LDAPS_PORT + protocol: tcp + mode: host + volumes: + - $APPDIR/traefik2/rules:/rules # File provider directory + ## Use Docker Socket Proxy instead for improved security + # - /var/run/docker.sock:/var/run/docker.sock:ro + ## Cert location - you must touch this file and change permissions to 600 + - $APPDIR/traefik2/acme/acme.json:/acme.json + ## For fail2ban - make sure to touch file before starting container + - $APPDIR/traefik2/traefik.log:/traefik.log + - $DOCKERDIR/shared:/shared + environment: + CF_API_EMAIL_FILE: /run/secrets/traefik_cf_email + CF_API_KEY_FILE: /run/secrets/traefik_cf_api_key + ## HTPASSWD_FILE can be whatever as it is not used/called anywhere. + HTPASSWD_FILE: /run/secrets/traefik_htpassword + ## Include vars so they can be used in Traefik rules + DOMAINNAME0: $DOMAINNAME0 + # DOMAINNAME1: $DOMAINNAME1 + HOMEBRIDGE_PORT: $HOMEBRIDGE_PORT + HOME_ASSISTANT_PORT: $HOME_ASSISTANT_PORT + SYNOLOGY_PORT: $SYNOLOGY_PORT + SYNOLOGY_PHOTO_PORT: $SYNOLOGY_PHOTO_PORT + PLEX_PORT: $PLEX_PORT + QBITTORRENT_PORT: $QBITTORRENT_PORT + QBITTORRENT_PRIVATE_PORT: $QBITTORRENT_PRIVATE_PORT + secrets: + - traefik_cf_email + - traefik_cf_api_key + - traefik_htpasswd + labels: + # - "autoheal=true" + - "traefik.enable=true" + ## HTTP-to-HTTPS Redirect + - "traefik.http.routers.http-catchall.entrypoints=http" + - "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)" + - "traefik.http.routers.http-catchall.middlewares=redirect-to-https" + - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" + # HTTP Routers + ## An example of a service available on both `abcxyz.$DOMAINNAME0` + ## and `abcxyz.$DOMAINNAME1` + - "traefik.http.routers.traefik0-rtr.entrypoints=https" + # - "traefik.http.routers.traefik0-rtr.tls=true" + - "traefik.http.routers.traefik0-rtr.rule=Host(`traefik.$DOMAINNAME0`)" + # - "traefik.http.routers.traefik1-rtr.entrypoints=https" + # - "traefik.http.routers.traefik1-rtr.tls=true" + # - "traefik.http.routers.traefik1-rtr.rule=Host(`traefik.$DOMAINNAME1`)" + ## Services - API + - "traefik.http.routers.traefik0-rtr.service=api@internal" + # - "traefik.http.routers.traefik1-rtr.service=api@internal" + ## Healthcheck/ping + - "traefik.http.routers.ping.rule=Host(`traefik.$DOMAINNAME0`) && Path(`/ping`)" + # - "traefik.http.routers.ping.tls=true" + - "traefik.http.routers.ping.service=ping@internal" + ## Middlewares + # - "traefik.http.routers.traefik0-rtr.middlewares=chain-basic-auth@file" + - "traefik.http.routers.traefik0-rtr.middlewares=chain-authelia@file" + # - "traefik.http.routers.traefik1-rtr.middlewares=chain-authelia1@file" diff --git a/compose/unbound.yml b/compose/unbound.yml new file mode 100644 index 0000000..e753d00 --- /dev/null +++ b/compose/unbound.yml @@ -0,0 +1,22 @@ +--- +services: + ## Unbound - A validating, recursive, and caching DNS resolver + unbound: + image: klutchell/unbound:latest + container_name: unbound + security_opt: + - no-new-privileges:true + restart: unless-stopped + ports: + - $UNBOUND_PORT:53 + - $UNBOUND_PORT:53/udp + volumes: + ## Update $APPDIR/unbound/config/root.hints (from $DOCKERDIR) using + ## `wget https://www.internic.net/domain/named.cache -O ./appdata/unbound/config/root.hints` + - $APPDIR/unbound/config:/opt/unbound/etc/unbound/ + healthcheck: + test: ["CMD", "dig", "ietf.org", "@127.0.0.1", "-p", "53"] + interval: 30s + timeout: 30s + retries: 3 + start_period: 10s diff --git a/compose/vaultwarden.yml b/compose/vaultwarden.yml new file mode 100644 index 0000000..536fb88 --- /dev/null +++ b/compose/vaultwarden.yml @@ -0,0 +1,168 @@ +--- +secrets: + vaultwarden_admin_token: + file: $SECRETSDIR/vaultwarden_admin_token + vaultwarden_duo_host: + file: $SECRETSDIR/vaultwarden_duo_host + vaultwarden_duo_ikey: + file: $SECRETSDIR/vaultwarden_duo_ikey + vaultwarden_duo_skey: + file: $SECRETSDIR/vaultwarden_duo_skey + vaultwarden_mysql_url: + file: $SECRETSDIR/vaultwarden_mysql_url + vaultwarden_smtp_password: + file: $SECRETSDIR/vaultwarden_smtp_password + vaultwarden_yubico_client_id: + file: $SECRETSDIR/vaultwarden_yubico_client_id + vaultwarden_yubico_secret_key: + file: $SECRETSDIR/vaultwarden_yubico_secret_key +services: + ## Vaultwarden - Unofficial Bitwarden compatible server written in Rust + vaultwarden: + container_name: vaultwarden + image: vaultwarden/server:latest + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + ## Run Vaultwarden as non-root user; Currently doesn't work with docker + ## secrets + # user: $PUID:$PGID + depends_on: + - mariadb + environment: + ## Note: can append '_FILE' to any env variable to read from a file + ## (including /run/secrets/my_secret) + # DATA_FOLDER: data + DATABASE_URL_FILE: /run/secrets/vaultwarden_mysql_url + # DATABASE_MAX_CONNS: 10 + # DATABASE_CONN_INIT: "" + # RSA_KEY_FILENAME: data/rsa_key + # ICON_CACHE_FOLDER: data/icon_cache + # ATTACHMENTS_FOLDER: data/attachments + # SENDS_FOLDER: data/sends + # TMP_FOLDER: data/tmp + # TEMPLATES_FOLDER: /path/to/templates + # RELOAD_TEMPLATES: "false" + # IP_HEADER: X-Real-IP + # ICON_CACHE_TTL: 2592000 + # ICON_CACHE_NEGTTL: 259200 + # WEB_VAULT_FOLDER: web-vault/ + WEB_VAULT_ENABLED: "true" + WEBSOCKET_ENABLED: "true" + # WEBSOCKET_ADDRESS: 0.0.0.0 + WEBSOCKET_PORT: $VAULTWARDEN_WEBSOCKET_PORT + SENDS_ALLOWED: "true" + EMERGENCY_ACCESS_ALLOWED: "true" + # JOB_POLL_INTERVAL_MS: 30000 + # SEND_PURGE_SCHEDULE: "0 5 * * * *" + # TRASH_PURGE_SCHEDULE: "0 5 0 * * *" + # INCOMPLETE_2FA_SCHEDULE: "30 * * * * *" + # EMERGENCY_NOTIFICATION_REMINDER_SCHEDULE: "0 5 * * * *" + # EMERGENCY_REQUEST_TIMEOUT_SCHEDULE: "0 5 * * * *" + ## Enable extended logging, which shows timestamps and targets in the logs + EXTENDED_LOGGING: "true" + # LOG_TIMESTAMP_FORMAT: %Y-%m-%d %H:%M:%S.%3f + # LOG_FILE: /data/vaultwarden.log + # USE_SYSLOG: "false" + ## LOG_LEVEL options are: trace, debug, info, warn, error, or off + LOG_LEVEL: info + # ENABLE_DB_WAL: "true" + # DB_CONNECTION_RETRIES: 15 + ICON_SERVICE: bitwarden # internal, bitwarden, duckduckgo, google + ## 301 (legacy permanent), 302 (legacy temporary), 307 (temporary), + ## 308 (permanent); Currently legacy redirects work best with + ## Vaultwarden. Consider permanent redirect for caching + ICON_REDIRECT_CODE: 308 + # DISABLE_ICON_DOWNLOAD: "false" + # ICON_DOWNLOAD_TIMEOUT: 10 + # ICON_BLACKLIST_REGEX: '^(192\.168\.0\.[0-9]+|192\.168\.1\.[0-9]+)$' + ICON_BLACKLIST_NON_GLOBAL_IPS: "true" + DISABLE_2FA_REMEMBER: "false" + # EMAIL_ATTEMPTS_LIMIT: 3 + # EMAIL_EXPIRATION_TIME: 600 + EMAIL_TOKEN_SIZE: 12 + SIGNUPS_ALLOWED: "false" + SIGNUPS_VERIFY: "true" + # SIGNUPS_VERIFY_RESEND_TIME: 3600 + # SIGNUPS_VERIFY_RESEND_LIMIT: 6 + # ORG_CREATION_USERS: + ADMIN_TOKEN_FILE: /run/secrets/vaultwarden_admin_token + DISABLE_ADMIN_TOKEN: "false" + INVITATIONS_ALLOWED: "true" + INVITATION_ORG_NAME: Vaultwarden + # ORG_ATTACHMENT_LIMIT: + # USER_ATTACHMENT_LIMIT: + TRASH_AUTO_DELETE_DAYS: 60 + # INCOMPLETE_2FA_TIME_LIMIT: 3 # Minutes + PASSWORD_ITERATIONS: 250000 + # SHOW_PASSWORD_HINT: "false" + DOMAIN: https://vault.$DOMAINNAME0 + # ALLOWED_IFRAME_ANCESTORS: + # LOGIN_RATELIMIT_SECONDS: 60 + # LOGIN_RATELIMIT_MAX_BURST: 10 + # ADMIN_RATELIMIT_SECONDS: 300 + # ADMIN_RATELIMIT_MAX_BURST: 3 + YUBICO_CLIENT_ID_FILE: /run/secrets/vaultwarden_yubico_client_id + YUBICO_SECRET_KEY_FILE: /run/secrets/vaultwarden_yubico_secret_key + YUBICO_SERVER: https://api.yubico.com/wsapi/2.0/verify + DUO_IKEY_FILE: /run/secrets/vaultwarden_duo_ikey + DUO_SKEY_FILE: /run/secrets/vaultwarden_duo_skey + DUO_HOST_FILE: /run/secrets/vaultwarden_duo_host + # AUTHENTICATOR_DISABLE_TIME_DRIFT: "false" + # ROCKET_ADDRESS: 0.0.0.0 + ROCKET_PORT: $VAULTWARDEN_PORT + # ROCKET_WORKERS: 10 + # ROCKET_TLS: {certs: "/path/to/certs.pem",key: "/path/to/key.pem"} + ## Mail specific settings, set SMTP_HOST and SMTP_FROM to enable the mail + ## service. + SMTP_HOST: $EMAIL_SERVER + SMTP_FROM: admin@vault.$DOMAINNAME0 + SMTP_FROM_NAME: Vaultwarden + SMTP_SECURITY: force_tls # starttls, force_tls, off; Default is starttls + SMTP_PORT: $EMAIL_SERVER_PORT + SMTP_USERNAME: $EMAIL_ADDRESS + SMTP_PASSWORD_FILE: /run/secrets/vaultwarden_smtp_password + # SMTP_TIMEOUT: 15 + SMTP_AUTH_MECHANISM: Plain # Plain, Login, Xoauth2 + # HELO_NAME: + # SMTP_DEBUG: "false" + SMTP_ACCEPT_INVALID_HOSTNAMES: "false" + SMTP_ACCEPT_INVALID_CERTS: "false" + REQUIRE_DEVICE_EMAIL: "true" + # HIBP_API_KEY: + # RUST_BACKTRACE: full + volumes: + - $APPDIR/vaultwarden/data:/data + secrets: + - vaultwarden_mysql_url + - vaultwarden_admin_token + - vaultwarden_yubico_client_id + - vaultwarden_yubico_secret_key + - vaultwarden_duo_ikey + - vaultwarden_duo_skey + - vaultwarden_duo_host + - vaultwarden_smtp_password + labels: + - "traefik.enable=true" + ## UI Labels + ## HTTP Routers + - "traefik.http.routers.vaultwarden-rtr.entrypoints=https" + - "traefik.http.routers.vaultwarden-rtr.rule=Host(`vault.$DOMAINNAME0`)" + - "traefik.http.routers.vaultwarden-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.vaultwarden-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.vaultwarden-rtr.service=vaultwarden-svc" + - "traefik.http.services.vaultwarden-svc.loadbalancer.server.port=$VAULTWARDEN_PORT" + ## Websocket Labels + ## HTTP Routers + - "traefik.http.routers.vaultwarden-websocket-rtr.entrypoints=https" + - "traefik.http.routers.vaultwarden-websocket-rtr.rule=Host(`vault.$DOMAINNAME0`) && Path(`/notifications/hub`)" + - "traefik.http.routers.vaultwarden-websocket-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.vaultwarden-websocket-rtr.middlewares=chain-no-auth@file" + ## HTTP Services + - "traefik.http.routers.vaultwarden-websocket-rtr.service=vaultwarden-websocket-svc" + - "traefik.http.services.vaultwarden-websocket-svc.loadbalancer.server.port=$VAULTWARDEN_WEBSOCKET_PORT" diff --git a/compose/vscode.yml b/compose/vscode.yml new file mode 100644 index 0000000..f2c0458 --- /dev/null +++ b/compose/vscode.yml @@ -0,0 +1,49 @@ +--- +secrets: + vscode_password: + file: $SECRETSDIR/vscode_password + vscode_sudo_password: + file: $SECRETSDIR/vscode_sudo_password +services: + ## VS Code - VS Code in the browser + vscode: + image: lscr.io/linuxserver/code-server:latest + container_name: vscode + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + volumes: + - $DOCKERDIR:/data/docker + - $DATADIR:/data/data + - $APPDIR/vscode/config:/config + ## Ensure the user's GitHub ssh keys are added to be able to use VS Code + ## git features + - $APPDIR/vscode/config/.ssh:/config/ssh + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + ## Note: passwords can be set via hash if desired + ## https://github.com/coder/code-server/blob/main/docs/FAQ.md#can-i-store-my-password-hashed + ## Note: must remove trailing \n using `truncate -s -1 file_name` + FILE__PASSWORD: /run/secrets/vscode_password + ## Note: must remove trailing \n using `truncate -s -1 file_name` + FILE__SUDO_PASSWORD: /run/secrets/vscode_sudo_password + PROXY_DOMAIN: code.$DOMAINNAME0 + DEFAULT_WORKSPACE: /data/docker + secrets: + - vscode_password + - vscode_sudo_password + labels: + - "traefik.enable=true" + ## HTTP Routers + - "traefik.http.routers.vscode-rtr.entrypoints=https" + - "traefik.http.routers.vscode-rtr.rule=Host(`code.$DOMAINNAME0`)" + - "traefik.http.routers.vscode-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.vscode-rtr.middlewares=chain-authelia@file" + ## HTTP Services + - "traefik.http.routers.vscode-rtr.service=vscode-svc" + - "traefik.http.services.vscode-svc.loadbalancer.server.port=8443" diff --git a/compose/watchtower.yml b/compose/watchtower.yml new file mode 100644 index 0000000..76950fc --- /dev/null +++ b/compose/watchtower.yml @@ -0,0 +1,74 @@ +--- +secrets: + watchtower_notification_email_server_password: + file: $SECRETSDIR/watchtower_notification_email_server_password +services: + ## Watchtower - A process for automating Docker container base image updates + watchtower: + image: containrrr/watchtower:latest + container_name: watchtower + privileged: true + # command: -H tcp://127.0.0.1:2375 + command: -H tcp://socket-proxy:2375 # Set host to socket-proxy + networks: + - socket_proxy + - t2_proxy + security_opt: + - no-new-privileges:true + restart: always + # depends_on: + # - socket-proxy + # volumes: + # ## Use Docker Socket Proxy instead for improved security + # - /var/run/docker.sock:/var/run/docker.sock + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + ## Watchtower Settings + WATCHTOWER_CLEANUP: "true" + WATCHTOWER_REMOVE_VOLUMES: "true" + WATCHTOWER_DEBUG: "false" + WATCHTOWER_TRACE: "false" + NO_COLOR: "false" + DOCKER_HOST: tcp://socket-proxy:2375 + ## Replace with Socket Proxy if possible + # DOCKER_HOST: unix:///var/run/docker.sock + DOCKER_API_VERSION: "1.40" + WATCHTOWER_INCLUDE_RESTARTING: "false" + WATCHTOWER_INCLUDE_STOPPED: "true" + WATCHTOWER_REVIVE_STOPPED: "false" + ## In seconds; can use either INTERVAL or SCHEDULE + # WATCHTOWER_POLL_INTERVAL: 86400 + # WATCHTOWER_LABEL_ENABLE: "false" + WATCHTOWER_MONITOR_ONLY: "false" + WATCHTOWER_NO_RESTART: "false" + WATCHTOWER_NO_PULL: "false" + WATCHTOWER_NO_STARTUP_MESSAGE: "false" + WATCHTOWER_RUN_ONCE: "false" + # WATCHTOWER_HTTP_API_UPDATE: "false" + # WATCHTOWER_HTTP_API_TOKEN: "" + # WATCHTOWER_HTTP_API_PERIODIC_POLLS: "false" + # WATCHTOWER_SCOPE: "" + # WATCHTOWER_HTTP_API_METRICS: "false" + ## 12:30 AM daily; "sec min hr day mon yr"; can use either INTERVAL or + ## SCHEDULE + WATCHTOWER_SCHEDULE: "0 30 0 * * 6" + WATCHTOWER_ROLLING_RESTART: "false" + WATCHTOWER_TIMEOUT: 30s # Default 10s + # DOCKER_TLS_VERIFY: "false" + # WATCHTOWER_WARN_ON_HEAD_FAILURE: auto + ## Email Settings + WATCHTOWER_NOTIFICATIONS: email + WATCHTOWER_NOTIFICATIONS_LEVEL: info + WATCHTOWER_NOTIFICATION_EMAIL_FROM: server@watchtower.$DOMAINNAME0 + WATCHTOWER_NOTIFICATION_EMAIL_TO: admin@$DOMAINNAME0 + WATCHTOWER_NOTIFICATION_EMAIL_SERVER: $EMAIL_SERVER + # WATCHTOWER_NOTIFICATION_EMAIL_SERVER_TLS_SKIP_VERIFY: "false" + WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT: $EMAIL_SERVER_PORT + WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER: $EMAIL_SERVER_USER + WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD: /run/secrets/watchtower_notification_email_server_password + WATCHTOWER_NOTIFICATION_EMAIL_DELAY: 90 + # WATCHTOWER_NOTIFICATION_EMAIL_SUBJECTTAG: + secrets: + - watchtower_notification_email_server_password diff --git a/compose/whoami.yml b/compose/whoami.yml new file mode 100644 index 0000000..6436e36 --- /dev/null +++ b/compose/whoami.yml @@ -0,0 +1,32 @@ +--- +services: + ## Whoami - tiny Go webserver that prints os information and HTTP request to + ## output + whoami: + container_name: whoami + image: containous/whoami + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + environment: + ## Not currently working on port other than 80 + WHOAMI_PORT_NUMBER: $WHOAMI_PORT + WHOAMI_NAME: WhoAmI + labels: + - "traefik.enable=true" + ## HTTP Routers # Set to respond on multiple `whoami` domains + - "traefik.http.routers.whoami-authelia-rtr.entrypoints=https" + - "traefik.http.routers.whoami-authelia-rtr.rule=Host(`whoami-authelia.$DOMAINNAME0`)" + - "traefik.http.routers.whoami-authelia-rtr.tls.options=tls-opts@file" + - "traefik.http.routers.whoami-authentik-rtr.entrypoints=https" + - "traefik.http.routers.whoami-authentik-rtr.rule=Host(`whoami-authentik.$DOMAINNAME0`)" + - "traefik.http.routers.whoami-authentik-rtr.tls.options=tls-opts@file" + ## Middlewares + - "traefik.http.routers.whoami-authelia-rtr.middlewares=chain-authelia@file" + - "traefik.http.routers.whoami-authentik-rtr.middlewares=chain-authentik@file" + ## HTTP Services + - "traefik.http.routers.whoami-authelia-rtr.service=whoami-svc" + - "traefik.http.routers.whoami-authentik-rtr.service=whoami-svc" + - "traefik.http.services.whoami-svc.loadbalancer.server.port=$WHOAMI_PORT" diff --git a/compose/wireguard.yml b/compose/wireguard.yml new file mode 100644 index 0000000..c4e8278 --- /dev/null +++ b/compose/wireguard.yml @@ -0,0 +1,46 @@ +--- +services: + ## Wireguard - Fast, modern, secure VPN tunnel + wireguard: + container_name: wireguard + image: lscr.io/linuxserver/wireguard:latest + networks: + - t2_proxy + security_opt: + - no-new-privileges:true + restart: unless-stopped + cap_add: + - NET_ADMIN + - SYS_MODULE + volumes: + - $APPDIR/wireguard/config:/config + - /lib/modules:/lib/modules + environment: + TZ: $TZ + PUID: $PUID + PGID: $PGID + SERVERURL: vpn.$DOMAINNAME0 + SERVERPORT: $WIREGUARD_PORT + PEERS: $WIREGUARD_PEERS + PEERDNS: auto + INTERNAL_SUBNET: 10.13.13.0 + sysctls: + - net.ipv4.conf.all.src_valid_mark=1 + - net.ipv6.conf.all.disable_ipv6=0 + # - net.ipv4.ip_forward=1 + # - net.ipv6.conf.default.forwarding=1 + # - net.ipv6.conf.all.forwarding=1 + # - net.ipv6.conf.all.proxy_ndp = 1 + # - net.ipv6.conf.all.accept_ra = 1 + labels: + - "traefik.enable=true" + ## UDP Routers + - "traefik.udp.routers.wireguard-udp.entrypoints=wireguard" + ## Rules cannot be used with UDP routers at this time + ## https://doc.traefik.io/traefik/routing/routers/#configuring-udp-routers + # - "traefik.udp.routers.wireguard-udp.rule=Host(`vpn.$DOMAINNAME0`)" + ## Middlewares + # - "traefik.udp.routers.wireguard-udp.middlewares=chain-no-auth@file" + ## UDP Services + - "traefik.udp.routers.wireguard-udp.service=wireguard-udp-svc" + - "traefik.udp.services.wireguard-udp-svc.loadbalancer.server.port=51820" diff --git a/docker-compose-t2.yml b/docker-compose-t2.yml index 8a38939..1750af9 100644 --- a/docker-compose-t2.yml +++ b/docker-compose-t2.yml @@ -43,3263 +43,87 @@ networks: default: driver: bridge -############################## SECRETS -secrets: - authelia_duo_api_secret_key: - file: $SECRETSDIR/authelia_duo_api_secret_key - authelia_identity_validation_reset_password_jwt_secret_file: # https://www.grc.com/passwords.htm - file: $SECRETSDIR/authelia_identity_validation_reset_password_jwt_secret_file - authelia_notifier_smtp_password: - file: $SECRETSDIR/authelia_notifier_smtp_password - authelia_session_redis_password: - file: $SECRETSDIR/authelia_session_redis_password - authelia_session_secret: - file: $SECRETSDIR/authelia_session_secret - authelia_storage_encryption_key: - file: $SECRETSDIR/authelia_storage_encryption_key - authelia_storage_mysql_password: - file: $SECRETSDIR/authelia_storage_mysql_password - authentik_email__password: - file: $SECRETSDIR/authentik_email__password - authentik_postgresql__name: - file: $SECRETSDIR/authentik_postgresql__name - authentik_postgresql__user: - file: $SECRETSDIR/authentik_postgresql__user - authentik_postgresql__password: - file: $SECRETSDIR/authentik_postgresql__password - authentik_redis__password: - file: $SECRETSDIR/authentik_redis__password - authentik_secret_key: - file: $SECRETSDIR/authentik_secret_key - authentik_token_ldap: - file: $SECRETSDIR/authentik_token_ldap - cloudflare_api_key: - file: $SECRETSDIR/cloudflare_api_key - cloudflare_ddns_api_token: # Currently unsupported - file: $SECRETSDIR/cloudflare_ddns_api_token - cloudflare_email: - file: $SECRETSDIR/cloudflare_email - duckdns_token: - file: $SECRETSDIR/duckdns_token - firefly_iii_access_token: - file: $SECRETSDIR/firefly_iii_access_token - firefly_mail_server_password: - file: $SECRETSDIR/firefly_mail_server_password - firefly_mysql_db_name: - file: $SECRETSDIR/firefly_mysql_db_name - firefly_mysql_user: - file: $SECRETSDIR/firefly_mysql_user - firefly_mysql_password: - file: $SECRETSDIR/firefly_mysql_password - gluetun_openvpn_user: - file: $SECRETSDIR/gluetun_openvpn_user - gluetun_openvpn_password: - file: $SECRETSDIR/gluetun_openvpn_password - gotify_database_connection: - file: $SECRETSDIR/gotify_database_connection - gotify_defaultuser_name: - file: $SECRETSDIR/gotify_defaultuser_name - gotify_defaultuser_pass: - file: $SECRETSDIR/gotify_defaultuser_pass - guac_db_name: - file: $SECRETSDIR/guac_db_name - guac_mysql_user: - file: $SECRETSDIR/guac_mysql_user - guac_mysql_password: - file: $SECRETSDIR/guac_mysql_password - htpasswd: - file: $SECRETSDIR/htpasswd - keycloak_admin: - file: $SECRETSDIR/keycloak_admin - keycloak_admin_password: - file: $SECRETSDIR/keycloak_admin_password - kc_db_username: - file: $SECRETSDIR/kc_db_username - kc_db_password: - file: $SECRETSDIR/kc_db_password - mysql_root_password: - file: $SECRETSDIR/mysql_root_password - nextcloud_admin_user: - file: $SECRETSDIR/nextcloud_admin_user - nextcloud_admin_password: - file: $SECRETSDIR/nextcloud_admin_password - nextcloud_mysql_user: - file: $SECRETSDIR/nextcloud_mysql_user - nextcloud_mysql_password: - file: $SECRETSDIR/nextcloud_mysql_password - nextcloud_smtp_name: # Currently unsupported - file: $SECRETSDIR/nextcloud_smtp_name - nextcloud_smtp_password: # Currently unsupported - file: $SECRETSDIR/nextcloud_smtp_password - plex_claim: - file: $SECRETSDIR/plex_claim - postgres_user: - file: $SECRETSDIR/postgres_user - postgres_password: - file: $SECRETSDIR/postgres_password - qbittorrent_user: - file: $SECRETSDIR/qbittorrent_user - qbittorrent_pass: - file: $SECRETSDIR/qbittorrent_pass - redis_password: - file: $SECRETSDIR/redis_password - vaultwarden_admin_token: - file: $SECRETSDIR/vaultwarden_admin_token - vaultwarden_duo_host: - file: $SECRETSDIR/vaultwarden_duo_host - vaultwarden_duo_ikey: - file: $SECRETSDIR/vaultwarden_duo_ikey - vaultwarden_duo_skey: - file: $SECRETSDIR/vaultwarden_duo_skey - vaultwarden_mysql_url: - file: $SECRETSDIR/vaultwarden_mysql_url - vaultwarden_smtp_password: - file: $SECRETSDIR/vaultwarden_smtp_password - vaultwarden_yubico_client_id: - file: $SECRETSDIR/vaultwarden_yubico_client_id - vaultwarden_yubico_secret_key: - file: $SECRETSDIR/vaultwarden_yubico_secret_key - vscode_password: - file: $SECRETSDIR/vscode_password - vscode_sudo_password: - file: $SECRETSDIR/vscode_sudo_password - watchtower_notification_email_server_password: - file: $SECRETSDIR/watchtower_notification_email_server_password - -########################### EXTENSION FIELDS -## Helps eliminate repetition of sections -## More Info on how to use this: -## https://github.com/htpcBeginner/docker-traefik/pull/228 - -## Common environment values -x-environment: &default-tz-puid-pgid - TZ: $TZ - PUID: $PUID - PGID: $PGID - -## Proxy Network and Security -x-network-and-security: &network-and-security - networks: - - t2_proxy - security_opt: - - no-new-privileges:true - -## Keys common to some of the services in basic-services.txt -x-common-keys-core: &common-keys-core - <<: *network-and-security - restart: always - # profiles: - # - basic - -## Keys common to some of the dependent services/apps -x-common-keys-apps: &common-keys-apps - <<: *network-and-security - restart: unless-stopped - # profiles: - # - apps - -## Keys common to some of the services in media-services.txt -x-common-keys-media: &common-keys-media - <<: *network-and-security - restart: "no" - # profiles: - # - media - -############################## SERVICES -services: - ############################## FRONTENDS - - ## Traefik 2 - Reverse Proxy - ## Touch (create empty files) traefik.log and acme/acme.json. - ## Set acme.json permissions to 600. - ## touch $APPDIR/traefik2/acme/acme.json - ## chmod 600 $APPDIR/traefik2/acme/acme.json - ## touch $APPDIR/traefik2/traefik.log - traefik: - <<: *common-keys-core - container_name: traefik - image: traefik:comte # comte=3.1.x - command: # CLI arguments - - --global.checkNewVersion=true - - --global.sendAnonymousUsage=true - - --entryPoints.http.address=:80 - - --entryPoints.https.address=:443 - ## Allow these IPs to set the X-Forwarded-* headers - ## Cloudflare IPs: https://www.cloudflare.com/ips/ - - --entrypoints.https.forwardedHeaders.trustedIPs=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22 - - --entryPoints.traefik.address=:8080 - ## Allows for ping/healthcheck at https://traefik.$DOMAINNAMEX/ping - - --entryPoints.ping.address=:8081 - - --api=true - - --api.insecure=true - - --api.dashboard=true - - --ping=true # Allow for ping/healthcheck - # - --pilot.token=$TRAEFIK_PILOT_TOKEN - # - --serversTransport.insecureSkipVerify=true - - --log=true - ## Default: ERROR; DEBUG, INFO, WARN, ERROR, FATAL, PANIC - - --log.level=INFO - - --accessLog=true - - --accessLog.filePath=/traefik.log - ## Configuring a buffer of 100 lines - - --accessLog.bufferingSize=100 - - --accessLog.filters.statusCodes=400-499 - - --providers.docker=true - ## Use Docker Socket Proxy instead for improved security - # - --providers.docker.endpoint=unix:///var/run/docker.sock - - --providers.docker.endpoint=tcp://socket-proxy:2375 - ## Automatically set Host rule for services - # - --providers.docker.defaultrule=Host(`{{ index .Labels "com.docker.compose.service" }}.$DOMAINNAME0`) - - --providers.docker.exposedByDefault=false - # - --entrypoints.https.http.middlewares=chain-oauth@file - - --entrypoints.https.http.tls.options=tls-opts@file - - --entrypoints.ping.http.tls.options=tls-opts@file - ## Add dns-cloudflare as default certresolver for all services. Also - ## enables TLS and no need to specify on individual services - - --entrypoints.https.http.tls.certresolver=dns-cloudflare - ## Pulls main and wildcard cert for first domain - - --entrypoints.https.http.tls.domains[0].main=$DOMAINNAME0 - - --entrypoints.https.http.tls.domains[0].sans=*.$DOMAINNAME0 - ## Pulls main and wildcard cert for second domain - # - --entrypoints.https.http.tls.domains[1].main=$DOMAINNAME1 - # - --entrypoints.https.http.tls.domains[1].sans=*.$DOMAINNAME1 - - --providers.docker.network=t2_proxy - ## Load dynamic configuration from one or more .toml or .yml files in a - ## directory - - --providers.file.directory=/rules - ## Load dynamic configuration from a file - #- --providers.file.filename=/path/to/file - ## Only works on top level files in the rules folder - - --providers.file.watch=true - ## LetsEncrypt Staging Server - uncomment when testing - # - --certificatesResolvers.dns-cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory - ## Optional. Used to specify the Key Type received from LetsEncrypt - - --certificatesResolvers.dns-cloudflare.acme.keyType=EC384 - - --certificatesResolvers.dns-cloudflare.acme.email=$CLOUDFLARE_EMAIL - - --certificatesResolvers.dns-cloudflare.acme.storage=/acme.json - - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.provider=cloudflare - - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53 - ## To delay DNS check and reduce LE hitrate - - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.delayBeforeCheck=90 - ## Set Wireguard entrypoint - - --entryPoints.wireguard.address=:$WIREGUARD_PORT/udp - ## Set Minecraft entrypoint - # - --entryPoints.minecraft.address=:25565 - ## Set minecraft-rcon entrypoint - # - --entryPoints.minecraft-rcon.address=:4326 - ## Set minecraft-rcon-websocket entrypoint - # - --entryPoints.minecraft-rcon-websocket.address=:4327 - ## Set Authentik LDAPS entrypoint - - --entryPoints.authentik-ldaps.address=:$AUTHENTIK_LDAPS_PORT - networks: - t2_proxy: - ipv4_address: $TRAEFIK_IPV4 # You can specify a static IP - socket_proxy: - # depends_on: - # - socket-proxy - healthcheck: - test: ["CMD", "traefik", "healthcheck", "--ping"] - interval: 5s - retries: 3 - ports: - - target: 80 - published: 80 - protocol: tcp - mode: host - - target: 443 - published: 443 - protocol: tcp - mode: host - - target: 8080 - published: 8080 - protocol: tcp - mode: host - - target: 8081 # Conflicting internal ping/healthcheck port - published: 8082 # To allow for redis at 8081 - protocol: tcp - mode: host - - target: $WIREGUARD_PORT # Port 80 UDP port for Wireguard - published: $WIREGUARD_PORT - protocol: udp - mode: host - - target: $AUTHENTIK_LDAPS_PORT # LDAPS port - published: $AUTHENTIK_LDAPS_PORT - protocol: tcp - mode: host - volumes: - - $APPDIR/traefik2/rules:/rules # File provider directory - ## Use Docker Socket Proxy instead for improved security - # - /var/run/docker.sock:/var/run/docker.sock:ro - ## Cert location - you must touch this file and change permissions to 600 - - $APPDIR/traefik2/acme/acme.json:/acme.json - ## For fail2ban - make sure to touch file before starting container - - $APPDIR/traefik2/traefik.log:/traefik.log - - $DOCKERDIR/shared:/shared - environment: - CF_API_EMAIL_FILE: /run/secrets/cloudflare_email - CF_API_KEY_FILE: /run/secrets/cloudflare_api_key - ## HTPASSWD_FILE can be whatever as it is not used/called anywhere. - HTPASSWD_FILE: /run/secrets/htpassword - ## Include vars so they can be used in Traefik rules - DOMAINNAME0: $DOMAINNAME0 - # DOMAINNAME1: $DOMAINNAME1 - HOMEBRIDGE_PORT: $HOMEBRIDGE_PORT - HOME_ASSISTANT_PORT: $HOME_ASSISTANT_PORT - SYNOLOGY_PORT: $SYNOLOGY_PORT - SYNOLOGY_PHOTO_PORT: $SYNOLOGY_PHOTO_PORT - PLEX_PORT: $PLEX_PORT - QBITTORRENT_PORT: $QBITTORRENT_PORT - QBITTORRENT_PRIVATE_PORT: $QBITTORRENT_PRIVATE_PORT - secrets: - - cloudflare_email - - cloudflare_api_key - - htpasswd - labels: - # - "autoheal=true" - - "traefik.enable=true" - ## HTTP-to-HTTPS Redirect - - "traefik.http.routers.http-catchall.entrypoints=http" - - "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)" - - "traefik.http.routers.http-catchall.middlewares=redirect-to-https" - - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" - # HTTP Routers - ## An example of a service available on both `abcxyz.$DOMAINNAME0` - ## and `abcxyz.$DOMAINNAME1` - - "traefik.http.routers.traefik0-rtr.entrypoints=https" - # - "traefik.http.routers.traefik0-rtr.tls=true" - - "traefik.http.routers.traefik0-rtr.rule=Host(`traefik.$DOMAINNAME0`)" - # - "traefik.http.routers.traefik1-rtr.entrypoints=https" - # - "traefik.http.routers.traefik1-rtr.tls=true" - # - "traefik.http.routers.traefik1-rtr.rule=Host(`traefik.$DOMAINNAME1`)" - ## Services - API - - "traefik.http.routers.traefik0-rtr.service=api@internal" - # - "traefik.http.routers.traefik1-rtr.service=api@internal" - ## Healthcheck/ping - - "traefik.http.routers.ping.rule=Host(`traefik.$DOMAINNAME0`) && Path(`/ping`)" - # - "traefik.http.routers.ping.tls=true" - - "traefik.http.routers.ping.service=ping@internal" - ## Middlewares - # - "traefik.http.routers.traefik0-rtr.middlewares=chain-basic-auth@file" - - "traefik.http.routers.traefik0-rtr.middlewares=chain-authelia@file" - # - "traefik.http.routers.traefik1-rtr.middlewares=chain-authelia1@file" - - ## Docker Socket Proxy - Security Enchanced Proxy for Docker Socket - socket-proxy: - <<: *common-keys-core # See EXTENSION FIELDS at the top - container_name: socket-proxy - image: tecnativa/docker-socket-proxy - networks: - socket_proxy: - ipv4_address: $SOCKET_PROXY_IPV4 # You can specify a static IP - privileged: true - ports: - ## Port 2375 should only ever get exposed to the internal network. When - ## possible use this line. - - 127.0.0.1:2375:2375 - # - 2375:2375 - volumes: - - "/var/run/docker.sock:/var/run/docker.sock" - environment: - ## tecnativa - - LOG_LEVEL=warning # debug,info,notice,warning,err,crit,alert,emerg - ## Variables match the URL prefix (i.e. AUTH blocks access to /auth/* - ## parts of the API, etc.). - ## 0 to revoke access. - ## 1 to grant access. - ## Granted by Default - - EVENTS=1 - - PING=1 - - VERSION=1 - ## Revoked by Default - ## Security critical - - AUTH=0 # 0 - - SECRETS=0 # 0 - - POST=1 # Watchtower - ## Not always needed - - BUILD=0 # 0 - - COMMIT=0 # 0 - - CONFIGS=0 # 0 - - CONTAINERS=1 # Traefik, portainer, etc. - - DISTRIBUTION=0 # 0 - - EXEC=0 # 0 - - IMAGES=1 # Portainer - - INFO=1 # Portainer - - NETWORKS=1 # Portainer - - NODES=0 # 0 - - PLUGINS=0 # 0 - - SERVICES=1 # Portainer - - SESSION=0 # 0 - - SWARM=0 # 0 - - SYSTEM=0 # 0 - - TASKS=1 # Portaienr - - VOLUMES=1 # Portainer - - ## Heimdall - Application Dashboard - heimdall: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: lscr.io/linuxserver/heimdall - container_name: heimdall - # ports: - # - "$HEIMDALL_PORT:80" - volumes: - - $APPDIR/heimdall/config:/config - environment: - <<: *default-tz-puid-pgid - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.heimdall-rtr.entrypoints=https" - - "traefik.http.routers.heimdall-rtr.rule=Host(`dash.$DOMAINNAME0`) || Host(`heimdall.$DOMAINNAME0`)" - - "traefik.http.routers.heimdall-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.heimdall-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.heimdall-rtr.service=heimdall-svc" - - "traefik.http.services.heimdall-svc.loadbalancer.server.port=80" - - # ## Organizr - Application Dashboard - # organizr: - # <<: *common-keys-apps # See EXTENSION FIELDS at the top - # image: organizr/organizr - # container_name: organizr - # # ports: - # # - "$ORGANIZR_PORT:80" - # volumes: - # - $APPDIR/organizr/config:/config - # environment: - # <<: *default-tz-puid-pgid - # fpm: "true" - # labels: - # - "traefik.enable=true" - # ## HTTP Routers - # - "traefik.http.routers.organizr-rtr.entrypoints=https" - # - "traefik.http.routers.organizr-rtr.rule=Host(`$DOMAINNAME0`,`www.$DOMAINNAME0`)" - # - "traefik.http.routers.organizr-rtr.tls.options=tls-opts@file" - # ## Middlewares - # - "traefik.http.routers.organizr-rtr.middlewares=chain-authelia1@file" - # ## HTTP Services - # - "traefik.http.routers.organizr-rtr.service=organizr-svc" - # - "traefik.http.services.organizr-svc.loadbalancer.server.port=80" - - ############################## SECURITY - - ## Authelia (Lite) - Self-Hosted Single Sign-On and Two-Factor Authentication - ## For configuration file template see - ## https://github.com/authelia/authelia/blob/master/config.template.yml - authelia: - <<: *common-keys-core - container_name: authelia - ## Check this before upgrading: - ## https://github.com/authelia/authelia#breaking-changes - image: ghcr.io/authelia/authelia:4.38 - # ports: - # - "$AUTHELIA_PORT:$AUTHELIA_PORT" - # - "$AUTHELIA_TELEMETRY_PORT:$AUTHELIA_TELEMETRY_PORT" # Telemetry data - ## Allow for separate configuration and acl configuration files - ## See https://www.authelia.com/configuration/methods/files/#docker-compose - volumes: - - $APPDIR/authelia/config/configuration.yml:/config/configuration.yml - - $APPDIR/authelia/config/configuration.acl.yml:/config/configuration.acl.yml - - $APPDIR/authelia/config/users_database.yml:/config/users_database.yml - environment: - ## Using PUID:PGID causes container to be unable to read secrets - # <<: *default-tz-puid-pgid - TZ: $TZ - AUTHELIA_SESSION_SECRET_FILE: /run/secrets/authelia_session_secret - ## yamllint disable rule:line-length - X_AUTHELIA_CONFIG: /config/configuration.yml,/config/configuration.acl.yml - AUTHELIA_DUO_API_SECRET_KEY_FILE: /run/secrets/authelia_duo_api_secret_key - AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE: /run/secrets/authelia_identity_validation_reset_password_jwt_secret_file - AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE: /run/secrets/authelia_notifier_smtp_password - AUTHELIA_SESSION_REDIS_PASSWORD_FILE: /run/secrets/authelia_session_redis_password - AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE: /run/secrets/authelia_storage_encryption_key - AUTHELIA_STORAGE_MYSQL_PASSWORD_FILE: /run/secrets/authelia_storage_mysql_password - ## yamllint enable rule:line-length - secrets: - - authelia_identity_validation_reset_password_jwt_secret_file - - authelia_session_secret - - authelia_session_redis_password - - authelia_storage_mysql_password - - authelia_notifier_smtp_password - - authelia_duo_api_secret_key - - authelia_storage_encryption_key - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.authelia-rtr.entrypoints=https" - - "traefik.http.routers.authelia-rtr.rule=Host(`auth.$DOMAINNAME0`)" - - "traefik.http.routers.authelia-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.authelia-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.authelia-rtr.service=authelia-svc" - - "traefik.http.services.authelia-svc.loadbalancer.server.port=$AUTHELIA_PORT" - - ## Keycloak - Open Source Identity and Access Management - keycloak: - <<: *common-keys-core - container_name: keycloak - build: - context: . - dockerfile: $APPDIR/keycloak/build/keycloak.Dockerfile - args: - ARG_KC_CACHE: "local" - # ARG_KC_CACHE_CONFIG_FILE: - # ARG_KC_CACHE_STACK: - ARG_KC_DB: "mariadb" - ARG_KC_TRANSACTION_XA_ENABLED: "true" - ## yamllint disable-line rule:line-length - ARG_KC_FEATURES: "docker,declarative-user-profile,recovery-codes,update-email" - # ARG_KC_HTTP_RELATIVE_PATH: - ARG_KC_HEALTH_ENABLED: "true" - ARG_KC_METRICS_ENABLED: "true" - # ARG_KC_VAULT: - # ARG_KC_FIPS_MODE: - ARG_QUARKUS_TRANSACTION_MANAGER_ENABLE_RECOVERY: "true" - command: ["start", "--optimized"] - # ports: - # - "$KEYCLOAK_PORT:$KEYCLOAK_PORT" - volumes: - - $APPDIR/keycloak/config:/conf - ## https://github.com/keycloak/keycloak/issues/15255#issuecomment-1446166497 - - $APPDIR/keycloak/ObjectStore:/ObjectStore - # Remember to `chmod +x` for all .sh scripts - ## Workaround to enable docker secrets - - $APPDIR/keycloak/build/docker_secrets.sh:/build/docker_secrets.sh:ro - ## Workaround to enable docker secrets - - $APPDIR/keycloak/build/entrypoint.sh:/build/entrypoint.sh:ro - ## Workaround to use healthcheck without `curl` - - $APPDIR/keycloak/build/healthcheck.sh:/build/healthcheck.sh:ro - environment: - # KC_CACHE: local - FILE__KEYCLOAK_ADMIN: /run/secrets/keycloak_admin - FILE__KEYCLOAK_ADMIN_PASSWORD: /run/secrets/keycloak_admin_password - # KC_DB: postgres - KC_DB: mariadb - FILE__KC_DB_PASSWORD: /run/secrets/kc_db_password - # KC_DB_URL: "jdbc:postgresql://${POSTGRES_HOST}:${POSTGRES_PORT}/keycloak" - # KC_DB_URL: "jdbc:mariadb://${MARIADB_HOST}:${MARIADB_PORT}/keycloak" - KC_DB_URL_DATABASE: keycloak - # KC_DB_URL_HOST: $POSTGRES_HOST - # KC_DB_URL_PORT: $POSTGRES_PORT - KC_DB_URL_HOST: $MARIADB_HOST - KC_DB_URL_PORT: $MARIADB_PORT - FILE__KC_DB_USERNAME: /run/secrets/kc_db_username - # KC_FEATURES: "docker,declarative-user-profile,recovery-codes,update-email" - # KC_HOSTNAME: "key.${DOMAINNAME0}" - # KC_HOSTNAME_ADMIN: "key.${DOMAINNAME0}" - KC_HOSTNAME_ADMIN_URL: "https://key.${DOMAINNAME0}" - KC_HOSTNAME_DEBUG: "true" - KC_HOSTNAME_STRICT: "false" - KC_HOSTNAME_URL: "https://key.${DOMAINNAME0}" - KC_HTTP_ENABLED: "true" - KC_HTTP_PORT: $KEYCLOAK_PORT - # KC_HEALTH_ENABLED: "true" - # KC_METRICS_ENABLED: "true" - KC_PROXY: edge - ## https://github.com/keycloak/keycloak/issues/15255#issuecomment-1446166497 - QUARKUS_TRANSACTION_MANAGER_ENABLE_RECOVERY: "true" - secrets: - - keycloak_admin - - keycloak_admin_password - - kc_db_password - - kc_db_username - labels: - - "traefik.enable=true" - #### Authentication routers and middlewares - ## HTTP Routers - - "traefik.http.routers.keycloak-rtr.entrypoints=https" - ## https://www.keycloak.org/server/reverseproxy#_exposed_path_recommendations - - "traefik.http.routers.keycloak-rtr.rule=Host(`key.$DOMAINNAME0`) && (Path(`/`) || PathPrefix(`/realms`) || PathPrefix(`/resources`))" - - "traefik.http.routers.keycloak-rtr.tls.options=tls-opts@file" - - "traefik.http.routers.keycloak-rtr-bypass.priority=99" - ## Middlewares - - "traefik.http.routers.keycloak-rtr.middlewares=chain-keycloak@file" - #### Administration routers and middlewares - ## HTTP Routers - - "traefik.http.routers.keycloak-admin-rtr.entrypoints=https" - # https://www.keycloak.org/server/reverseproxy#_exposed_path_recommendations - - "traefik.http.routers.keycloak-admin-rtr.rule=Host(`key.$DOMAINNAME0`) && ClientIP(`$LAN_NETWORK`)" # Only allow admin paths on local network (or VPN) - - "traefik.http.routers.keycloak-admin-rtr.tls.options=tls-opts@file" - ## Give priority to bypass rule if matched - - "traefik.http.routers.keycloak-admin-rtr-bypass.priority=100" - ## Middlewares - - "traefik.http.routers.keycloak-admin-rtr.middlewares=chain-keycloak@file" - #### Combined services - ## HTTP Services - - "traefik.http.routers.keycloak-admin-rtr.service=keycloak-admin-svc" - - "traefik.http.services.keycloak-admin-svc.loadbalancer.server.port=$KEYCLOAK_PORT" - - ## Authentik - an open-source Identity Provider, focused on flexibility and - ## versatility - authentik: - <<: *common-keys-core - container_name: authentik - image: ghcr.io/goauthentik/server:latest - command: server - # ports: - # - "$AUTHENTIK_PORT:$AUTHENTIK_PORT" - volumes: - - $APPDIR/authentik/media:/media - - $APPDIR/authentik/templates:/templates - environment: - ## https://goauthentik.io/docs/installation/configuration - ## Test configuration with `dcrun2 run --rm authentik-server dump_config` - ## Use `file://` prefix to load from docker secret - ## https://goauthentik.io/docs/installation/configuration#about-authentik-configurations - COMPOSE_PORT_HTTP: $AUTHENTIK_PORT - # COMPOSE_PORT_HTTPS: - AUTHENTIK_POSTGRESQL__HOST: $POSTGRES_HOST - AUTHENTIK_POSTGRESQL__NAME: file:///run/secrets/authentik_postgresql__name - AUTHENTIK_POSTGRESQL__USER: file:///run/secrets/authentik_postgresql__user - AUTHENTIK_POSTGRESQL__PORT: $POSTGRES_PORT - AUTHENTIK_POSTGRESQL__PASSWORD: file:///run/secrets/authentik_postgresql__password - AUTHENTIK_REDIS__HOST: $REDIS_HOST - AUTHENTIK_REDIS__PORT: $REDIS_PORT - # AUTHENTIK_REDIS__USERNAME: $REDIS_USER - AUTHENTIK_REDIS__PASSWORD: file:///run/secrets/authentik_redis__password - AUTHENTIK_LISTEN__HTTP: "0.0.0.0:${AUTHENTIK_PORT}" - # AUTHENTIK_LISTEN__HTTPS: "0.0.0.0:" - AUTHENTIK_LISTEN__LDAP: "0.0.0.0:${AUTHENTIK_LDAP_PORT}" - AUTHENTIK_LISTEN__LDAPS: "0.0.0.0:${AUTHENTIK_LDAPS_PORT}" - AUTHENTIK_LISTEN__METRICS: "0.0.0.0:${AUTHENTIK_METRICS_PORT}" - AUTHENTIK_LISTEN__DEBUG: "0.0.0.0:${AUTHENTIK_DEBUG_PORT}" - # AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS: - AUTHENTIK_SECRET_KEY: file:///run/secrets/authentik_secret_key - AUTHENTIK_LOG_LEVEL: info # trace, debug, info, warning, error - AUTHENTIK_COOKIE_DOMAIN: $DOMAINNAME0 - # AUTHENTIK_ERROR_REPORTING__ENABLED: 'true' - AUTHENTIK_EMAIL__HOST: $EMAIL_SERVER - AUTHENTIK_EMAIL__PORT: $EMAIL_SERVER_PORT - AUTHENTIK_EMAIL__USERNAME: $EMAIL_SERVER_USER - AUTHENTIK_EMAIL__PASSWORD: file:///run/secrets/authentik_email__password - AUTHENTIK_EMAIL__USE_TLS: "false" - AUTHENTIK_EMAIL__USE_SSL: "true" - AUTHENTIK_EMAIL__TIMEOUT: 10 - AUTHENTIK_EMAIL__FROM: server@authentik.$DOMAINNAME0 - AUTHENTIK_AVATARS: initials - AUTHENTIK_DEFAULT_USER_CHANGE_NAME: "true" - AUTHENTIK_DEFAULT_USER_CHANGE_EMAIL: "true" - AUTHENTIK_DEFAULT_USER_CHANGE_USERNAME: "true" - AUTHENTIK_GDPR_COMPLIANCE: "true" - # AUTHENTIK_DEFAULT_TOKEN_LENGTH: - AUTHENTIK_IMPERSONATION: "true" - # AUTHENTIK_FOOTER_LINKS: - # COMPOSE_PORT_HTTPS: - secrets: - - authentik_postgresql__name - - authentik_postgresql__user - - authentik_postgresql__password - - authentik_redis__password - - authentik_secret_key - - authentik_email__password - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.authentik-rtr.entrypoints=https" - - "traefik.http.routers.authentik-rtr.rule=Host(`authentik.$DOMAINNAME0`)" - - "traefik.http.routers.authentik-rtr.tls.options=tls-opts@file" - ## Middlewares - ## Do not use authentication, but use rate limiting and secure headers - - "traefik.http.routers.authentik-rtr.middlewares=chain-no-auth@file" - ## HTTP Services - - "traefik.http.routers.authentik-rtr.service=authentik-svc" - - "traefik.http.services.authentik-svc.loadbalancer.server.port=$AUTHENTIK_PORT" - - authentik-worker: - <<: *common-keys-core - container_name: authentik-worker - image: ghcr.io/goauthentik/server:latest - command: worker - ## `user: root` and the docker socket volume are optional. - ## See more for the docker socket integration here: - ## https://goauthentik.io/docs/outposts/integrations/docker - ## Removing `user: root` also prevents the worker from fixing the - ## permissions on the mounted folders, so when removing this make sure the - ## folders have the correct UID/GID (1000:1000 by default) - user: root - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - $APPDIR/authentik/media:/media - - $APPDIR/authentik/certs:/certs - - $APPDIR/authentik/templates:/templates - environment: - ## https://goauthentik.io/docs/installation/configuration - ## Test configuration with `dcrun2 run --rm authentik-server dump_config` - ## Use `file://` prefix to load from docker secret - ## https://goauthentik.io/docs/installation/configuration#about-authentik-configurations - AUTHENTIK_POSTGRESQL__HOST: $POSTGRES_HOST - AUTHENTIK_POSTGRESQL__NAME: "file:///run/secrets/authentik_postgresql__name" - AUTHENTIK_POSTGRESQL__USER: "file:///run/secrets/authentik_postgresql__user" - AUTHENTIK_POSTGRESQL__PORT: $POSTGRES_PORT - AUTHENTIK_POSTGRESQL__PASSWORD: "file:///run/secrets/authentik_postgresql__password" - AUTHENTIK_REDIS__HOST: $REDIS_HOST - AUTHENTIK_REDIS__PORT: $REDIS_PORT - # AUTHENTIK_REDIS__USERNAME: $REDIS_USER - AUTHENTIK_REDIS__PASSWORD: "file:///run/secrets/authentik_redis__password" - AUTHENTIK_LISTEN__HTTP: "0.0.0.0:${AUTHENTIK_PORT}" - # AUTHENTIK_LISTEN__HTTPS: "0.0.0.0:" - AUTHENTIK_LISTEN__LDAP: "0.0.0.0:${AUTHENTIK_LDAP_PORT}" - AUTHENTIK_LISTEN__LDAPS: "0.0.0.0:${AUTHENTIK_LDAPS_PORT}" - AUTHENTIK_LISTEN__METRICS: "0.0.0.0:${AUTHENTIK_METRICS_PORT}" - AUTHENTIK_LISTEN__DEBUG: "0.0.0.0:${AUTHENTIK_DEBUG_PORT}" - # AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS: - AUTHENTIK_SECRET_KEY: "file:///run/secrets/authentik_secret_key" - AUTHENTIK_LOG_LEVEL: info # trace, debug, info, warning, error - AUTHENTIK_COOKIE_DOMAIN: authentik.$DOMAINNAME0 - # AUTHENTIK_ERROR_REPORTING__ENABLED: 'true' - AUTHENTIK_EMAIL__HOST: $EMAIL_SERVER - AUTHENTIK_EMAIL__PORT: $EMAIL_SERVER_PORT - AUTHENTIK_EMAIL__USERNAME: $EMAIL_SERVER_USER - AUTHENTIK_EMAIL__PASSWORD: "file:///run/secrets/authentik_email__password" - AUTHENTIK_EMAIL__USE_TLS: "false" - AUTHENTIK_EMAIL__USE_SSL: "true" - AUTHENTIK_EMAIL__TIMEOUT: 10 - AUTHENTIK_EMAIL__FROM: server@authentik.$DOMAINNAME0 - AUTHENTIK_AVATARS: initials - AUTHENTIK_DEFAULT_USER_CHANGE_NAME: "true" - AUTHENTIK_DEFAULT_USER_CHANGE_EMAIL: "true" - AUTHENTIK_DEFAULT_USER_CHANGE_USERNAME: "true" - AUTHENTIK_GDPR_COMPLIANCE: "true" - # AUTHENTIK_DEFAULT_TOKEN_LENGTH: - AUTHENTIK_IMPERSONATION: "true" - # AUTHENTIK_FOOTER_LINKS: - # COMPOSE_PORT_HTTPS: - secrets: - - authentik_postgresql__name - - authentik_postgresql__user - - authentik_postgresql__password - - authentik_redis__password - - authentik_secret_key - - authentik_email__password - - ############################## DATABASE - - ## MariaDB - MySQL Database - ## After starting container for first time dexec and - ## `mysqladmin -u root password ` - mariadb: - <<: *common-keys-core - container_name: mariadb - image: lscr.io/linuxserver/mariadb:latest - ports: - - "$MARIADB_PORT:3306" - volumes: - - $APPDIR/mariadb/data:/config - environment: - <<: *default-tz-puid-pgid - ## Not taking this pw during initialization - FILE__MYSQL_ROOT_PASSWORD: /run/secrets/mysql_root_password - secrets: - - mysql_root_password - - ## PostgreSQL - PostgreSQL Database - ## Steps for adding a new user/database: - ## 1. Log in to adminer.$DOMAINNAME0 with postgres root - ## 2. Open `SQL command` and execute the following lines: - ## CREATE USER WITH PASSWORD ''; - ## CREATE DATABASE OWNER ; - ## GRANT ALL PRIVILEGES ON DATABASE TO ; - ## - ## Steps for restoring from a backup: - ## 1. Place the output of pg_dump in a convenient location, e.g., "${DOCKERDIR}/backup/postgres_dump.sql" - ## 2. Start `postgres` with a clean data directory - ## 3. Run the following command to recreate the database as specified in the postgres_dump.sql file - ## sudo docker exec -i --user=postgres postgres psql --dbname=postgres < ./backup/postgres_dump.sql - postgres: - <<: *common-keys-core - container_name: postgres - image: postgres:16 - user: "${PUID}:${PGID}" - networks: - t2_proxy: - ipv4_address: $POSTGRES_IPV4 - ports: - - "$POSTGRES_PORT:$POSTGRES_PORT" - healthcheck: - test: - [ - "CMD-SHELL", - 'pg_isready -d "$${POSTGRES_DB:-$${POSTGRES_USER:-$$(cat "$${POSTGRES_USER_FILE}")}}" -U "$${POSTGRES_USER:-$$(cat "$$POSTGRES_USER_FILE")}"', - ] - start_period: 20s - interval: 30s - retries: 5 - timeout: 5s - volumes: - - $APPDIR/postgres/config:/config - - $APPDIR/postgres/data:/var/lib/postgresql/data - environment: - <<: *default-tz-puid-pgid - POSTGRES_USER_FILE: /run/secrets/postgres_user - POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password - PGPORT: $POSTGRES_PORT - PGDATA: /var/lib/postgresql/data/pgdata - secrets: - - postgres_user - - postgres_password - - ## phpMyAdmin - Database management - ## Create a new user with admin privileges. Cannot login as MySQL root for - ## some reason. - phpmyadmin: - <<: *common-keys-apps - image: phpmyadmin:latest - container_name: phpmyadmin - depends_on: - - mariadb - # ports: - # - "$PHPMYADMIN_PORT:80" - # volumes: - # - $APPDIR/phpmyadmin:/etc/phpmyadmin - environment: - PMA_HOST: $MARIADB_HOST - PMA_PORT: $MARIADB_PORT - # PMA_ARBITRARY: 1 - MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password - # PMA_USER: pma - # PMA_PASSWORD_FILE: /run/secrets/pma_password - secrets: - - mysql_root_password - # - pma_password - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.phpmyadmin-rtr.entrypoints=https" - - "traefik.http.routers.phpmyadmin-rtr.rule=Host(`pma.$DOMAINNAME0`)" - - "traefik.http.routers.phpmyadmin-rtr.tls.options=tls-opts@file" - ## Middlewares - # - "traefik.http.routers.phpmyadmin-rtr.middlewares=chain-no-auth@file" - - "traefik.http.routers.phpmyadmin-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.phpmyadmin-rtr.service=phpmyadmin-svc" - - "traefik.http.services.phpmyadmin-svc.loadbalancer.server.port=80" - - ## Adminer - Database management in a single PHP file. - adminer: - <<: *common-keys-core - container_name: adminer - image: adminer:latest - # ports: - # - 8080:8080 - environment: - ## https://github.com/vrana/adminer/tree/master/designs - # ADMINER_DESIGN: 'nette' - ADMINER_DEFAULT_SERVER: postgres - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.adminer-rtr.entrypoints=https" - - "traefik.http.routers.adminer-rtr.rule=Host(`adminer.$DOMAINNAME0`)" - - "traefik.http.routers.adminer-rtr.tls.options=tls-opts@file" - ## Middlewares - # - "traefik.http.routers.adminer-rtr.middlewares=chain-no-auth@file" - - "traefik.http.routers.adminer-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.adminer-rtr.service=adminer-svc" - - "traefik.http.services.adminer-svc.loadbalancer.server.port=8080" - - ## Redis - Key-value Store - redis: - <<: *common-keys-core - container_name: redis - image: redis:latest - networks: - t2_proxy: - ipv4_address: $REDIS_IPV4 - entrypoint: redis-server --requirepass $REDIS_PASSWORD --maxmemory 512mb --maxmemory-policy allkeys-lru --port $REDIS_PORT - healthcheck: - test: ["CMD-SHELL", "/healthcheck.sh"] - start_period: 5s - interval: 5s - retries: 5 - timeout: 3s - ports: - - "$REDIS_PORT:$REDIS_PORT" - volumes: - - $APPDIR/redis/data:/data - - $APPDIR/redis/config/healthcheck.sh:/healthcheck.sh:ro - - /etc/timezone:/etc/timezone:ro - - /etc/localtime:/etc/localtime:ro - - ## Redis Commander - Redis Management Tool - rediscommander: - <<: *common-keys-apps - container_name: rediscommander - image: ghcr.io/joeferner/redis-commander:latest - depends_on: - - redis - # ports: - # - "$REDISCOMMANDER_PORT:$REDISCOMMANDER_PORT" - environment: - REDIS_HOST: $REDIS_HOST - REDIS_PORT: $REDIS_PORT - ## Not currently working - # REDIS_PASSWORD_FILE: /run/secrets/redis_password - REDIS_PASSWORD: $REDIS_PASSWORD - PORT: $REDISCOMMANDER_PORT - secrets: - - redis_password - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.rediscommander-rtr.entrypoints=https" - - "traefik.http.routers.rediscommander-rtr.rule=Host(`rediscom.$DOMAINNAME0`)" - - "traefik.http.routers.rediscommander-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.rediscommander-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.rediscommander-rtr.service=rediscommander-svc" - - "traefik.http.services.rediscommander-svc.loadbalancer.server.port=$REDISCOMMANDER_PORT" - - ############################## MAINTENANCE - - ## Cloudflare DDNS - Dynamic DNS service to update Cloudflare DNS records - cf-ddns: - # <<: *common-keys-core # Must set network mode manually - container_name: cf-ddns - image: favonia/cloudflare-ddns:1 - network_mode: host # To make IPv6 easier - restart: always - user: "${PUID}:${PGID}" - cap_drop: - - all - read_only: true - security_opt: - - no-new-privileges:true - volumes: - - $APPDIR/cf-ddns/config/cloudflare_ddns_api_token:/cloudflare_ddns_api_token:ro - environment: # Environmental variables deprecated - <<: *default-tz-puid-pgid - CF_API_TOKEN_FILE: /cloudflare_ddns_api_token - DOMAINS: $DOMAINNAME0 - PROXIED: "true" - UPDATE_CRON: "*/5 * * * *" - RECORD_COMMENT: "Updated with cloudflare-ddns" - # SHOUTRRR: # TODO - - ## DuckDNS - Dynamic DNS service provided by duckdns.org - duckdns: - <<: *common-keys-core - image: lscr.io/linuxserver/duckdns:latest - container_name: duckdns - # volumes: - # - $APPDIR/duckdns/config:/config # Optional - environment: - <<: *default-tz-puid-pgid - SUBDOMAINS: "$DOMAINNAME_DUCKDNS0,$DOMAINNAME_DUCKDNS1,$DOMAINNAME_DUCKDNS2,$DOMAINNAME_DUCKDNS3,$DOMAINNAME_DUCKDNS4" - ## Note, MUST truncate EOF carriage return if present - ## `truncate -s -1 $SECRETSDIR/duckdns_token` - FILE__TOKEN: /run/secrets/duckdns_token - # LOG_FILE: "true" # Optional - secrets: - - duckdns_token - - ## Docker-GC - Automatic Docker Garbage Collection - ## Create docker-gc-exclude file - docker-gc: - <<: *common-keys-apps - image: clockworksoul/docker-gc-cron:latest - container_name: docker-gc - networks: - - socket_proxy - depends_on: - - socket-proxy - volumes: - ## Use Docker Socket Proxy instead for improved security - # - /var/run/docker.sock:/var/run/docker.sock - ## Must create this folder - - $APPDIR/docker-gc/config/docker-gc-exclude:/etc/docker-gc-exclude - environment: - <<: *default-tz-puid-pgid - CRON: "0 0 0 * * ?" # Everyday at midnight. Previously "0 0 * * *" - FORCE_IMAGE_REMOVAL: 1 - FORCE_CONTAINER_REMOVAL: 0 - GRACE_PERIOD_SECONDS: 604800 - DRY_RUN: 0 - CLEAN_UP_VOLUMES: 1 - TZ: $TZ - DOCKER_HOST: tcp://socket-proxy:2375 - - ## Watchtower - A process for automating Docker container base image updates - watchtower: - <<: *common-keys-core # See EXTENSION FIELDS at the top - image: containrrr/watchtower:latest - container_name: watchtower - privileged: true - # command: -H tcp://127.0.0.1:2375 - command: -H tcp://socket-proxy:2375 # Set host to socket-proxy - networks: - - socket_proxy - - t2_proxy - # depends_on: - # - socket-proxy - # volumes: - # ## Use Docker Socket Proxy instead for improved security - # - /var/run/docker.sock:/var/run/docker.sock - environment: - ## Watchtower Settings - <<: *default-tz-puid-pgid - WATCHTOWER_CLEANUP: "true" - WATCHTOWER_REMOVE_VOLUMES: "true" - WATCHTOWER_DEBUG: "false" - WATCHTOWER_TRACE: "false" - NO_COLOR: "false" - DOCKER_HOST: tcp://socket-proxy:2375 - ## Replace with Socket Proxy if possible - # DOCKER_HOST: unix:///var/run/docker.sock - DOCKER_API_VERSION: "1.40" - WATCHTOWER_INCLUDE_RESTARTING: "false" - WATCHTOWER_INCLUDE_STOPPED: "true" - WATCHTOWER_REVIVE_STOPPED: "false" - ## In seconds; can use either INTERVAL or SCHEDULE - # WATCHTOWER_POLL_INTERVAL: 86400 - # WATCHTOWER_LABEL_ENABLE: "false" - WATCHTOWER_MONITOR_ONLY: "false" - WATCHTOWER_NO_RESTART: "false" - WATCHTOWER_NO_PULL: "false" - WATCHTOWER_NO_STARTUP_MESSAGE: "false" - WATCHTOWER_RUN_ONCE: "false" - # WATCHTOWER_HTTP_API_UPDATE: "false" - # WATCHTOWER_HTTP_API_TOKEN: "" - # WATCHTOWER_HTTP_API_PERIODIC_POLLS: "false" - # WATCHTOWER_SCOPE: "" - # WATCHTOWER_HTTP_API_METRICS: "false" - ## 12:30 AM daily; "sec min hr day mon yr"; can use either INTERVAL or - ## SCHEDULE - WATCHTOWER_SCHEDULE: "0 30 0 * * 6" - WATCHTOWER_ROLLING_RESTART: "false" - WATCHTOWER_TIMEOUT: 30s # Default 10s - # DOCKER_TLS_VERIFY: "false" - # WATCHTOWER_WARN_ON_HEAD_FAILURE: auto - ## Email Settings - WATCHTOWER_NOTIFICATIONS: email - WATCHTOWER_NOTIFICATIONS_LEVEL: info - WATCHTOWER_NOTIFICATION_EMAIL_FROM: server@watchtower.$DOMAINNAME0 - WATCHTOWER_NOTIFICATION_EMAIL_TO: admin@$DOMAINNAME0 - WATCHTOWER_NOTIFICATION_EMAIL_SERVER: $EMAIL_SERVER - # WATCHTOWER_NOTIFICATION_EMAIL_SERVER_TLS_SKIP_VERIFY: "false" - WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT: $EMAIL_SERVER_PORT - WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER: $EMAIL_SERVER_USER - WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD: /run/secrets/watchtower_notification_email_server_password - WATCHTOWER_NOTIFICATION_EMAIL_DELAY: 90 - # WATCHTOWER_NOTIFICATION_EMAIL_SUBJECTTAG: - secrets: - - watchtower_notification_email_server_password - - ############################## UTILITIES - - ## VS Code - VS Code in the browser - vscode: - <<: *common-keys-core # See EXTENSION FIELDS at the top - image: lscr.io/linuxserver/code-server:latest - container_name: vscode - volumes: - - $DOCKERDIR:/data/docker - - $DATADIR:/data/data - - $APPDIR/vscode/config:/config - ## Ensure the user's GitHub ssh keys are added to be able to use VS Code - ## git features - - $APPDIR/vscode/config/.ssh:/config/ssh - environment: - <<: *default-tz-puid-pgid - ## Note: passwords can be set via hash if desired - ## https://github.com/coder/code-server/blob/main/docs/FAQ.md#can-i-store-my-password-hashed - ## Note: must remove trailing \n using `truncate -s -1 file_name` - FILE__PASSWORD: /run/secrets/vscode_password - ## Note: must remove trailing \n using `truncate -s -1 file_name` - FILE__SUDO_PASSWORD: /run/secrets/vscode_sudo_password - PROXY_DOMAIN: code.$DOMAINNAME0 - DEFAULT_WORKSPACE: /data/docker - secrets: - - vscode_password - - vscode_sudo_password - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.vscode-rtr.entrypoints=https" - - "traefik.http.routers.vscode-rtr.rule=Host(`code.$DOMAINNAME0`)" - - "traefik.http.routers.vscode-rtr.tls.options=tls-opts@file" - ## Middlewares - # - "traefik.http.routers.vscode-rtr.middlewares=chain-basic-auth@file" - - "traefik.http.routers.vscode-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.vscode-rtr.service=vscode-svc" - - "traefik.http.services.vscode-svc.loadbalancer.server.port=8443" - - ## File Browser - Explorer - filebrowser: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: filebrowser/filebrowser:s6 - container_name: filebrowser - # ports: - # - "$FILEBROWSER_PORT:80" - volumes: - - $DOCKERDIR/appdata/filebrowser/config/settings.json:/config/settings.json - - $DOCKERDIR/appdata/filebrowser/db/filebrowser.db:/database/filebrowser.db - - $DATADIR:/srv - - $USERDIR:/data/home - environment: - <<: *default-tz-puid-pgid - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.filebrowser-rtr.entrypoints=https" - - "traefik.http.routers.filebrowser-rtr.rule=Host(`fb.$DOMAINNAME0`)" - - "traefik.http.routers.filebrowser-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.filebrowser-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.filebrowser-rtr.service=filebrowser-svc" - - "traefik.http.services.filebrowser-svc.loadbalancer.server.port=80" - - ## Guacamole - Remote desktop, SSH, on Telnet on any HTML5 Browser - ## Create all databases and tables first - ## https://guacamole.apache.org/doc/1.4.0/gug/guacamole-docker.html?highlight=mysql#mysql-authentication - guacamole: - <<: *common-keys-core - image: guacamole/guacamole:latest - container_name: guacamole - depends_on: - - guacd - # ports: - # - "$GUACAMOLE_PORT:8080" - environment: - GUACD_HOSTNAME: guacd - MYSQL_HOSTNAME: $MARIADB_HOST - MYSQL_PORT: $MARIADB_PORT - ## Secrets do not work with 600 secrets, must chmod 644 - MYSQL_DATABASE_FILE: /run/secrets/guac_db_name - MYSQL_USER_FILE: /run/secrets/guac_mysql_user - MYSQL_PASSWORD_FILE: /run/secrets/guac_mysql_password - secrets: - - guac_db_name - - guac_mysql_user - - guac_mysql_password - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.guacamole-rtr.entrypoints=https" - - "traefik.http.routers.guacamole-rtr.rule=Host(`guac.$DOMAINNAME0`)" - - "traefik.http.routers.guacamole-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.guacamole-rtr.middlewares=chain-authelia@file,guacamole-remove-bypass-cache,add-guacamole" - - "traefik.http.middlewares.guacamole-remove-bypass-cache.stripprefix.prefixes=/bypass_cache" - - "traefik.http.middlewares.add-guacamole.addPrefix.prefix=/guacamole" - ## HTTP Services - - "traefik.http.routers.guacamole-rtr.service=guacamole-svc" - - "traefik.http.services.guacamole-svc.loadbalancer.server.port=8080" - - ## Guacamole Daemon - Needed for Guacamole - guacd: - <<: *common-keys-core # See EXTENSION FIELDS at the top - image: guacamole/guacd:latest - container_name: guacd - - ## Dozzle - Real-time Docker Log Viewer - dozzle: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: amir20/dozzle:latest - container_name: dozzle - networks: - - t2_proxy - - socket_proxy - depends_on: - - socket-proxy - healthcheck: - test: ["CMD", "/dozzle", "healthcheck"] - interval: 3s - timeout: 30s - retries: 5 - start_period: 30s - # ports: - # - "$DOZZLE_PORT:$DOZZLE_PORT" - environment: - DOZZLE_ADDR: ":$DOZZLE_PORT" - DOCKER_HOST: tcp://socket-proxy:2375 - DOZZLE_FILTER: "status=running" - ## limits logs displayed to containers with this label - # DOZZLE_FILTER: "label=log_me" - DOZZLE_LEVEL: info - DOZZLE_NO_ANALYTICS: true - # volumes: - # ## Use Docker Socket Proxy instead for improved security - # - /var/run/docker.sock:/var/run/docker.sock - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.dozzle-rtr.entrypoints=https" - - "traefik.http.routers.dozzle-rtr.rule=Host(`dozzle.$DOMAINNAME0`)" - - "traefik.http.routers.dozzle-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.dozzle-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.dozzle-rtr.service=dozzle-svc" - - "traefik.http.services.dozzle-svc.loadbalancer.server.port=$DOZZLE_PORT" - - ## Glances - System Information - glances: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: nicolargo/glances:latest - container_name: glances - privileged: true - # network_mode: host - networks: - - t2_proxy - - socket_proxy - depends_on: - - socket-proxy - # ports: - # - "$GLANCES_PORT:61208" - pid: host - volumes: - ## Use this if you want to add a glances.conf file - # - $APPDIR/glances/config/glances.conf:/glances/conf/glances.conf - - $USERDIR:/data/home:ro - # - /media/hdd1:/data/hdd1:ro - ## Use Docker Socket Proxy instead for improved security - # - /var/run/docker.sock:/var/run/docker.sock:ro - environment: - # GLANCES_OPT: "-C /glances/conf/glances.conf --quiet --export influxdb" - # GLANCES_OPT: "--export influxdb" - GLANCES_OPT: "-w" # Run in "w" or Web Server mode - DOCKER_HOST: tcp://socket-proxy:2375 - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.glances-rtr.entrypoints=https" - - "traefik.http.routers.glances-rtr.rule=Host(`glances.$DOMAINNAME0`)" - - "traefik.http.routers.glances-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.glances-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.glances-rtr.service=glances-svc" - - "traefik.http.services.glances-svc.loadbalancer.server.port=61208" - - ## DupeGuru - Duplicate File/Folder Remover - dupeguru: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: jlesage/dupeguru:latest - container_name: dupeguru - # ports: - # - "$DUPEGURU_PORT:5800" - volumes: - - $DATADIR:/storage:rw - - $USERDIR:/data/home:ro - - $APPDIR/dupeguru/config:/config:rw - environment: - <<: *default-tz-puid-pgid - USER_ID: $PUID - GROUP_ID: $PGID - UMASK: 002 - KEEP_APP_RUNNING: 1 - CLEAN_TMP_DIR: 1 - DISPLAY_WIDTH: 1600 - DISPLAY_HEIGHT: 960 - VNC_PASSWORD: $DUPEGURU_VNC_PASSWD - WEB_LISTENING_PORT: $DUPEGURU_PORT - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.dupeguru-rtr.entrypoints=https" - - "traefik.http.routers.dupeguru-rtr.rule=Host(`dupe.$DOMAINNAME0`)" - - "traefik.http.routers.dupeguru-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.dupeguru-rtr.middlewares=chain-authelia@file,dupeguru-remove-bypass-cache" - - "traefik.http.middlewares.dupeguru-remove-bypass-cache.stripprefix.prefixes=/bypass_cache" - ## HTTP Services - - "traefik.http.routers.dupeguru-rtr.service=dupeguru-svc" - - "traefik.http.services.dupeguru-svc.loadbalancer.server.port=$DUPEGURU_PORT" - - ## Tdarr - Distributed transcode automation - tdarr: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - container_name: tdarr - image: ghcr.io/haveagitgat/tdarr:latest - privileged: true - # devices: - # ## AMD hardware transcoding? - # - /dev/dri:/dev/dri - # - /dev/dri/renderD128:/dev/dri/renderD128 - # - /dev/dri/card0:/dev/dri/card0 - ports: - # - $TDARR_WEBUI_PORT:$TDARR_WEBUI_PORT # WebUI port - - $TDARR_SERVER_PORT:$TDARR_SERVER_PORT # Server port - # - 8267:8267 # Internal node port - # - 8268:8268 # Example extra node port - environment: - UMASK_SET: 002 - serverIP: tdarr - serverPort: $TDARR_SERVER_PORT - webUIPort: $TDARR_WEBUI_PORT - internalNode: "false" - # nodeID: MyInternalNode - volumes: - - $APPDIR/tdarr/server:/app/server - - $APPDIR/tdarr/configs:/app/configs - - $APPDIR/tdarr/logs:/app/logs - - $APPDIR/tdarr/scripts:/home/Tdarr/scripts - ## Map single folder for `/data` and use `/data/media` and - ## `/data/temp/transcode` to allow for move operation instead of copy - - $DATADIR:/data - # - $DATADIR/temp/transcode:/data/temp/transcode - # - /dev/shm:/temp # Perform transcoding in RAM - logging: - options: - max-size: "2m" - max-file: "3" - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.tdarr-rtr.entrypoints=https" - - "traefik.http.routers.tdarr-rtr.rule=Host(`tdarr.$DOMAINNAME0`)" - - "traefik.http.routers.tdarr-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.tdarr-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.tdarr-rtr.service=tdarr-svc" - - "traefik.http.services.tdarr-svc.loadbalancer.server.port=$TDARR_WEBUI_PORT" - - ## Tdarr - Distributed transcode automation - tdarr-node: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - container_name: tdarr-node - image: ghcr.io/haveagitgat/tdarr_node:latest - privileged: true - devices: - ## AMD hardware transcoding - - /dev/dri:/dev/dri - # - /dev/dri/renderD128:/dev/dri/renderD128 - # - /dev/dri/card0:/dev/dri/card0 - ports: - - $TDARR_NODE_PORT:$TDARR_NODE_PORT # Node port - environment: - UMASK_SET: 02 - serverIP: tdarr - serverPort: $TDARR_SERVER_PORT - nodeID: NucNode - nodeIP: tdarr-node # Container name of the node - nodePort: $TDARR_NODE_PORT - volumes: - - $APPDIR/tdarr/configs:/app/configs - - $APPDIR/tdarr/logs:/app/logs - ## Map single folder for `/data` and use `/data/media` and - ## `/data/temp/transcode` to allow for move operation instead of copy - - $DATADIR:/data - # - $DATADIR/temp/transcode:/data/temp/transcode - # - /dev/shm:/temp # Perform transcoding in RAM - logging: - options: - max-size: "2m" - max-file: "3" - # labels: # Not needed for the node - # - "traefik.enable=true" - # ## HTTP Routers - # - "traefik.http.routers.tdarr-node-rtr.entrypoints=https" - # - "traefik.http.routers.tdarr-node-rtr.rule=Host(`tdarr-node.$DOMAINNAME0`)" - # ## Middlewares - # - "traefik.http.routers.tdarr-node-rtr.middlewares=chain-authelia@file" - # ## HTTP Services - # - "traefik.http.routers.tdarr-node-rtr.service=tdarr-node-svc" - # - "traefik.http.services.tdarr-node-svc.loadbalancer.server.port=$TDARR_NODE_PORT" - - ## Gotify - A simple server for sending and receiving messages - gotify: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - container_name: gotify - image: gotify/server:latest - # ports: - # - $GOTIFY_PORT:9267 # Node port - volumes: - - $APPDIR/gotify/app:/app/data - ## Allows passing the hijacked entrypoint.sh - - $APPDIR/gotify/config:/config:ro - environment: - <<: *default-tz-puid-pgid - GOTIFY_SERVER_PORT: $GOTIFY_SERVER_PORT - # GOTIFY_SERVER_KEEPALIVEPERIODSECONDS: 0 - # GOTIFY_SERVER_LISTENADDR: - GOTIFY_SERVER_SSL_ENABLED: "false" - # GOTIFY_SERVER_SSL_REDIRECTTOHTTPS: true - # GOTIFY_SERVER_SSL_LISTENADDR: - # GOTIFY_SERVER_SSL_PORT: 443 - # GOTIFY_SERVER_SSL_CERTFILE: - # GOTIFY_SERVER_SSL_CERTKEY: - # GOTIFY_SERVER_SSL_LETSENCRYPT_ENABLED: false - # GOTIFY_SERVER_SSL_LETSENCRYPT_ACCEPTTOS: false - # GOTIFY_SERVER_SSL_LETSENCRYPT_CACHE: certs - # lists are a little weird but do-able (: - # GOTIFY_SERVER_SSL_LETSENCRYPT_HOSTS: - mydomain.tld\n- myotherdomain.tld - # GOTIFY_SERVER_RESPONSEHEADERS: "X-Custom-Header: \"custom value\"" - # GOTIFY_SERVER_CORS_ALLOWORIGINS: "- \".+.example.com\"\n- \"otherdomain.com\"" - # GOTIFY_SERVER_CORS_ALLOWMETHODS: "- \"GET\"\n- \"POST\"" - # GOTIFY_SERVER_CORS_ALLOWHEADERS: "- \"Authorization\"\n- \"content-type\"" - # GOTIFY_SERVER_STREAM_ALLOWEDORIGINS: "- \".+.example.com\"\n- \"otherdomain.com\"" - # GOTIFY_SERVER_STREAM_PINGPERIODSECONDS: 45 - GOTIFY_DATABASE_DIALECT: mysql - ## Hijack default entrypoint to pass in Docker secrets - GOTIFY_DATABASE_CONNECTION__FILE: /run/secrets/gotify_database_connection - # GOTIFY_DATABASE_CONNECTION: data/gotify.db - ## Hijack default entrypoint to pass in Docker secrets - GOTIFY_DEFAULTUSER_NAME__FILE: /run/secrets/gotify_defaultuser_name - # GOTIFY_DEFAULTUSER_NAME: admin - ## Hijack default entrypoint to pass in Docker secrets - GOTIFY_DEFAULTUSER_PASS__FILE: /run/secrets/gotify_defaultuser_pass - # GOTIFY_DEFAULTUSER_PASS: admin - GOTIFY_PASSSTRENGTH: 10 - GOTIFY_UPLOADEDIMAGESDIR: data/images - GOTIFY_PLUGINSDIR: data/plugins - # GOTIFY_REGISTRATION: false - secrets: - - gotify_database_connection - - gotify_defaultuser_name - - gotify_defaultuser_pass - entrypoint: - - /config/entrypoint.sh - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.gotify-rtr.entrypoints=https" - - "traefik.http.routers.gotify-rtr.rule=Host(`gotify.$DOMAINNAME0`)" - - "traefik.http.routers.gotify-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.gotify-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.gotify-rtr.service=gotify-svc" - - "traefik.http.services.gotify-svc.loadbalancer.server.port=$GOTIFY_SERVER_PORT" - - ############################## WEB - - ## Vaultwarden - Unofficial Bitwarden compatible server written in Rust - vaultwarden: - <<: *common-keys-apps - container_name: vaultwarden - image: vaultwarden/server:latest - ## Run Vaultwarden as non-root user; Currently doesn't work with docker - ## secrets - # user: $PUID:$PGID - # ports: - # - $VAULTWARDEN_PORT:$VAULTWARDEN_PORT - # - $VAULTWARDEN_WEBSOCKET_PORT:$VAULTWARDEN_WEBSOCKET_PORT - # depends_on: - # - mariadb - environment: - ## Note: can append '_FILE' to any env variable to read from a file - ## (including /run/secrets/my_secret) - # DATA_FOLDER: data - DATABASE_URL_FILE: /run/secrets/vaultwarden_mysql_url - # DATABASE_MAX_CONNS: 10 - # DATABASE_CONN_INIT: "" - # RSA_KEY_FILENAME: data/rsa_key - # ICON_CACHE_FOLDER: data/icon_cache - # ATTACHMENTS_FOLDER: data/attachments - # SENDS_FOLDER: data/sends - # TMP_FOLDER: data/tmp - # TEMPLATES_FOLDER: /path/to/templates - # RELOAD_TEMPLATES: "false" - # IP_HEADER: X-Real-IP - # ICON_CACHE_TTL: 2592000 - # ICON_CACHE_NEGTTL: 259200 - # WEB_VAULT_FOLDER: web-vault/ - WEB_VAULT_ENABLED: "true" - WEBSOCKET_ENABLED: "true" - # WEBSOCKET_ADDRESS: 0.0.0.0 - WEBSOCKET_PORT: $VAULTWARDEN_WEBSOCKET_PORT - SENDS_ALLOWED: "true" - EMERGENCY_ACCESS_ALLOWED: "true" - # JOB_POLL_INTERVAL_MS: 30000 - # SEND_PURGE_SCHEDULE: "0 5 * * * *" - # TRASH_PURGE_SCHEDULE: "0 5 0 * * *" - # INCOMPLETE_2FA_SCHEDULE: "30 * * * * *" - # EMERGENCY_NOTIFICATION_REMINDER_SCHEDULE: "0 5 * * * *" - # EMERGENCY_REQUEST_TIMEOUT_SCHEDULE: "0 5 * * * *" - ## Enable extended logging, which shows timestamps and targets in the logs - EXTENDED_LOGGING: "true" - # LOG_TIMESTAMP_FORMAT: %Y-%m-%d %H:%M:%S.%3f - # LOG_FILE: /data/vaultwarden.log - # USE_SYSLOG: "false" - ## LOG_LEVEL options are: trace, debug, info, warn, error, or off - LOG_LEVEL: info - # ENABLE_DB_WAL: "true" - # DB_CONNECTION_RETRIES: 15 - ICON_SERVICE: bitwarden # internal, bitwarden, duckduckgo, google - ## 301 (legacy permanent), 302 (legacy temporary), 307 (temporary), - ## 308 (permanent); Currently legacy redirects work best with - ## Vaultwarden. Consider permanent redirect for caching - ICON_REDIRECT_CODE: 308 - # DISABLE_ICON_DOWNLOAD: "false" - # ICON_DOWNLOAD_TIMEOUT: 10 - # ICON_BLACKLIST_REGEX: '^(192\.168\.0\.[0-9]+|192\.168\.1\.[0-9]+)$' - ICON_BLACKLIST_NON_GLOBAL_IPS: "true" - DISABLE_2FA_REMEMBER: "false" - # EMAIL_ATTEMPTS_LIMIT: 3 - # EMAIL_EXPIRATION_TIME: 600 - EMAIL_TOKEN_SIZE: 12 - SIGNUPS_ALLOWED: "false" - SIGNUPS_VERIFY: "true" - # SIGNUPS_VERIFY_RESEND_TIME: 3600 - # SIGNUPS_VERIFY_RESEND_LIMIT: 6 - # ORG_CREATION_USERS: - ADMIN_TOKEN_FILE: /run/secrets/vaultwarden_admin_token - DISABLE_ADMIN_TOKEN: "false" - INVITATIONS_ALLOWED: "true" - INVITATION_ORG_NAME: Vaultwarden - # ORG_ATTACHMENT_LIMIT: - # USER_ATTACHMENT_LIMIT: - TRASH_AUTO_DELETE_DAYS: 60 - # INCOMPLETE_2FA_TIME_LIMIT: 3 # Minutes - PASSWORD_ITERATIONS: 250000 - # SHOW_PASSWORD_HINT: "false" - DOMAIN: https://vault.$DOMAINNAME0 - # ALLOWED_IFRAME_ANCESTORS: - # LOGIN_RATELIMIT_SECONDS: 60 - # LOGIN_RATELIMIT_MAX_BURST: 10 - # ADMIN_RATELIMIT_SECONDS: 300 - # ADMIN_RATELIMIT_MAX_BURST: 3 - YUBICO_CLIENT_ID_FILE: /run/secrets/vaultwarden_yubico_client_id - YUBICO_SECRET_KEY_FILE: /run/secrets/vaultwarden_yubico_secret_key - YUBICO_SERVER: https://api.yubico.com/wsapi/2.0/verify - DUO_IKEY_FILE: /run/secrets/vaultwarden_duo_ikey - DUO_SKEY_FILE: /run/secrets/vaultwarden_duo_skey - DUO_HOST_FILE: /run/secrets/vaultwarden_duo_host - # AUTHENTICATOR_DISABLE_TIME_DRIFT: "false" - # ROCKET_ADDRESS: 0.0.0.0 - ROCKET_PORT: $VAULTWARDEN_PORT - # ROCKET_WORKERS: 10 - # ROCKET_TLS: {certs: "/path/to/certs.pem",key: "/path/to/key.pem"} - ## Mail specific settings, set SMTP_HOST and SMTP_FROM to enable the mail - ## service. - SMTP_HOST: $EMAIL_SERVER - SMTP_FROM: admin@vault.$DOMAINNAME0 - SMTP_FROM_NAME: Vaultwarden - SMTP_SECURITY: force_tls # starttls, force_tls, off; Default is starttls - SMTP_PORT: $EMAIL_SERVER_PORT - SMTP_USERNAME: $EMAIL_ADDRESS - SMTP_PASSWORD_FILE: /run/secrets/vaultwarden_smtp_password - # SMTP_TIMEOUT: 15 - SMTP_AUTH_MECHANISM: Plain # Plain, Login, Xoauth2 - # HELO_NAME: - # SMTP_DEBUG: "false" - SMTP_ACCEPT_INVALID_HOSTNAMES: "false" - SMTP_ACCEPT_INVALID_CERTS: "false" - REQUIRE_DEVICE_EMAIL: "true" - # HIBP_API_KEY: - # RUST_BACKTRACE: full - volumes: - - $APPDIR/vaultwarden/data:/data - secrets: - - vaultwarden_mysql_url - - vaultwarden_admin_token - - vaultwarden_yubico_client_id - - vaultwarden_yubico_secret_key - - vaultwarden_duo_ikey - - vaultwarden_duo_skey - - vaultwarden_duo_host - - vaultwarden_smtp_password - labels: - - "traefik.enable=true" - ## UI Labels - ## HTTP Routers - - "traefik.http.routers.vaultwarden-rtr.entrypoints=https" - - "traefik.http.routers.vaultwarden-rtr.rule=Host(`vault.$DOMAINNAME0`)" - - "traefik.http.routers.vaultwarden-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.vaultwarden-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.vaultwarden-rtr.service=vaultwarden-svc" - - "traefik.http.services.vaultwarden-svc.loadbalancer.server.port=$VAULTWARDEN_PORT" - ## Websocket Labels - ## HTTP Routers - - "traefik.http.routers.vaultwarden-websocket-rtr.entrypoints=https" - - "traefik.http.routers.vaultwarden-websocket-rtr.rule=Host(`vault.$DOMAINNAME0`) && Path(`/notifications/hub`)" - - "traefik.http.routers.vaultwarden-websocket-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.vaultwarden-websocket-rtr.middlewares=chain-no-auth@file" - ## HTTP Services - - "traefik.http.routers.vaultwarden-websocket-rtr.service=vaultwarden-websocket-svc" - - "traefik.http.services.vaultwarden-websocket-svc.loadbalancer.server.port=$VAULTWARDEN_WEBSOCKET_PORT" - - ## Nextcloud - A safe home for all your data - nextcloud: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - container_name: nextcloud - image: nextcloud:29 - # ports: - # - 443:443 - volumes: - - $APPDIR/nextcloud:/var/www/html - - $APPDIR/nextcloud/custom_apps:/var/www/html/custom_apps - - $APPDIR/nextcloud/config:/var/www/html/config - - $DATADIR/nextcloud:/var/www/html/data - environment: - <<: *default-tz-puid-pgid - NEXTCLOUD_UPDATE: 1 - NEXTCLOUD_ADMIN_USER_FILE: /run/secrets/nextcloud_admin_user - NEXTCLOUD_ADMIN_PASSWORD_FILE: /run/secrets/nextcloud_admin_password - SERVERNAME: drive.$DOMAINNAME0 - MYSQL_USER_FILE: /run/secrets/nextcloud_mysql_user - MYSQL_PASSWORD_FILE: /run/secrets/nextcloud_mysql_password - MYSQL_DATABASE: nextcloud - MYSQL_HOST: $MARIADB_HOST - ## Have to set manually in the config.php for whatever reason, setting - ## this with environmental variables messes things up - # REDIS_HOST: redis - REDIS_HOST_PORT: $REDIS_PORT - REDIS_HOST_PASSWORD_FILE: /run/secrets/redis_password - SMTP_HOST: $EMAIL_SERVER - SMTP_SECURE: ssl - SMTP_PORT: $EMAIL_SERVER_PORT - SMTP_AUTHTYPE: PLAIN - ## Currently unsupported - # SMTP_NAME_FILE: /run/secrets/nextcloud_smtp_name - SMTP_NAME: $EMAIL_SERVER_USER - SMTP_PASSWORD_FILE: /run/secrets/nextcloud_smtp_password - MAIL_FROM_ADDRESS: admin@drive.$DOMAINNAME0 - # MAIL_DOMAIN: - NEXTCLOUD_TRUSTED_DOMAINS: drive.$DOMAINNAME0 - TRUSTED_PROXIES: $T2_PROXY_SUBNET - secrets: - - nextcloud_admin_user - - nextcloud_admin_password - - nextcloud_mysql_user - - nextcloud_mysql_password - - nextcloud_smtp_name - - nextcloud_smtp_password - - redis_password - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.nextcloud-rtr.entrypoints=https" - - "traefik.http.routers.nextcloud-rtr.rule=Host(`drive.$DOMAINNAME0`)" - - "traefik.http.routers.nextcloud-rtr.tls.options=tls-opts@file" - ## Middlewares - #- "traefik.http.routers.nextcloud-rtr.middlewares=chain-basic-auth@file" - - "traefik.http.routers.nextcloud-rtr.middlewares=chain-nextcloud@file,nextcloud-remove-bypass-cache" - - "traefik.http.middlewares.nextcloud-remove-bypass-cache.stripprefix.prefixes=/bypass_cache" - ## HTTP Services - - "traefik.http.routers.nextcloud-rtr.service=nextcloud-svc" - - "traefik.http.services.nextcloud-svc.loadbalancer.server.port=80" - - ## Firefly III - Finance Manager - ## Create a unique App Key which is a random 32 character string - ## `date +%s | sha256sum | base64 | head -c 32 ; echo` - firefly: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - container_name: firefly - image: fireflyiii/core:latest - # ports: - # - "$FIREFLY_PORT:8080" - hostname: money.$DOMAINNAME0 - volumes: - - $APPDIR/firefly/export:/var/www/firefly-iii/storage/export - - $APPDIR/firefly/upload:/var/www/firefly-iii/storage/upload - environment: - ## https://github.com/firefly-iii/firefly-iii/blob/main/.env.example - <<: *default-tz-puid-pgid - APP_ENV: local # testing, local, production - APP_DEBUG: "false" - SITE_OWNER: admin@money.$DOMAINNAME0 - APP_KEY: $FIREFLY_APP_KEY - DEFAULT_LANGUAGE: en_US - DEFAULT_LOCALE: equal - ## TRUSTED_PROXIES is a useful variable when using Docker and/or a - ## reverse proxy. Set it to ** and reverse proxies work just fine. - TRUSTED_PROXIES: "**" - ## "single" for one big fat error log (not recommended); "syslog", - ## "errorlog" and "stdout" which will log to the system itself; "daily", - ## creates 5 files that (surprise) rotate; "papertrail" for cloud - ## logging; "stack" will log to "daily" and to "stdout" at the same time - LOG_CHANNEL: stack - # PAPERTRAIL_HOST: - # PAPERTRAIL_PORT: - ## debug, info, notice, warning, error, critical, alert, emergency - APP_LOG_LEVEL: debug - AUDIT_LOG_LEVEL: debug # info, emergency - DB_CONNECTION: mysql # pgsql, mysql, sqlite - DB_HOST: $MARIADB_HOST - DB_PORT: $MARIADB_PORT - DB_DATABASE_FILE: /run/secrets/firefly_mysql_db_name - DB_USERNAME_FILE: /run/secrets/firefly_mysql_user - DB_PASSWORD_FILE: /run/secrets/firefly_mysql_password - # DB_SOCKET: - # MYSQL_USE_SSL: - # MYSQL_SSL_VERIFY_SERVER_CERT: - # MYSQL_SSL_CAPATH: /etc/ssl/certs/ - # MYSQL_SSL_CA: - # MYSQL_SSL_CERT: - # MYSQL_SSL_KEY: - # MYSQL_SSL_CIPHER: - # PGSQL_SSL_MODE: prefer - # PGSQL_SSL_ROOT_CERT: null - # PGSQL_SSL_CERT: null - # PGSQL_SSL_KEY: null - # PGSQL_SSL_CRL_FILE: null - # PGSQL_SCHEMA: - CACHE_DRIVER: redis - SESSION_DRIVER: redis - REDIS_SCHEME: tcp - # REDIS_PATH: # For use with "unix" REDIS_SCHEME only - REDIS_HOST: $REDIS_HOST - REDIS_PORT: $REDIS_PORT - REDIS_PASSWORD_FILE: /run/secrets/redis_password - REDIS_DB: "0" - REDIS_CACHE_DB: "1" - # COOKIE_PATH: "/" - # COOKIE_DOMAIN: $DOMAINNAME0 - # COOKIE_SECURE: false - # COOKIE_SAMESITE: lax - ## https://docs.firefly-iii.org/firefly-iii/advanced-installation/email/ - MAIL_MAILER: smtp - MAIL_HOST: $EMAIL_SERVER - MAIL_PORT: $EMAIL_SERVER_PORT - MAIL_FROM: server@money.$DOMAINNAME0 - MAIL_USERNAME: $EMAIL_SERVER_USER - MAIL_PASSWORD_FILE: /run/secrets/firefly_mail_server_password - MAIL_ENCRYPTION: ssl - # MAILGUN_DOMAIN: - # MAILGUN_SECRET: - # MAILGUN_ENDPOINT: - # MANDRILL_SECRET: - # SPARKPOST_SECRET: - SEND_REGISTRATION_MAIL: "true" - SEND_ERROR_MESSAGE: "true" - SEND_LOGIN_NEW_IP_WARNING: "true" - SEND_REPORT_JOURNALS: "true" - ENABLE_EXTERNAL_MAP: "true" - MAP_DEFAULT_LAT: $DEFAULT_LATITUDE - MAP_DEFAULT_LONG: $DEFAULT_LONGITUDE - # MAP_DEFAULT_ZOOM: 6 - ## https://docs.firefly-iii.org/advanced-installation/authentication - AUTHENTICATION_GUARD: web - AUTHENTICATION_GUARD_HEADER: HTTP_REMOTE_USER - AUTHENTICATION_GUARD_EMAIL: HTTP_REMOTE_EMAIL - # CUSTOM_LOGOUT_URL: - # DISABLE_FRAME_HEADER: "true" - # DISABLE_CSP_HEADER: "true" - # TRACKER_SITE_ID: - # TRACKER_URL: - ALLOW_WEBHOOKS: "true" # default false - ## https://docs.firefly-iii.org/firefly-iii/advanced-installation/cron/ - # STATIC_CRON_TOKEN_FILE: - ## Use this at your own risk. Disabling certain checks and features may - ## result in lost of inconsistent data. - # DKR_BUILD_LOCALE: - # DKR_CHECK_SQLITE: - # DKR_RUN_MIGRATION: - # DKR_RUN_UPGRADE: - # DKR_RUN_VERIFY: - # DKR_RUN_REPORT: - # DKR_RUN_PASSPORT_INSTALL: - ## Leave the following configuration vars as is. Unless you like to - ## tinker and know what you're doing. - # APP_NAME: FireflyIII - # BROADCAST_DRIVER: log - # QUEUE_DRIVER: sync - # CACHE_PREFIX: firefly - # PUSHER_KEY: - # IPINFO_TOKEN: - # PUSHER_SECRET: - # PUSHER_ID: - # DEMO_USERNAME: - # DEMO_PASSWORD: - # IS_HEROKU: false - # FIREFLY_III_LAYOUT: v1 - APP_URL: "https://money.$DOMAINNAME0" - secrets: - - firefly_mysql_db_name - - firefly_mysql_user - - firefly_mysql_password - - redis_password - - firefly_mail_server_password - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.firefly-rtr.entrypoints=https" - - "traefik.http.routers.firefly-rtr.rule=Host(`money.$DOMAINNAME0`)" - - "traefik.http.routers.firefly-rtr.tls.options=tls-opts@file" - ## Middlewares - ## Note: possible issue before using Authelia, would need to configure - ## /path for importer to bypass Authelia (/api/v1) - or just use - ## http://firefly:$FIREFLY_PORT - - "traefik.http.routers.firefly-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.firefly-rtr.service=firefly-svc" - - "traefik.http.services.firefly-svc.loadbalancer.server.port=8080" - - ## Firefly III Data Importer - importer: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - container_name: importer - image: fireflyiii/data-importer:latest - depends_on: - - firefly - hostname: import.$DOMAINNAME0 - # ports: - # - "8080:8080" - environment: - <<: *default-tz-puid-pgid - # FIREFLY_III_URL: https://money.$DOMAINNAME0 - FIREFLY_III_URL: http://firefly:$FIREFLY_PORT - VANITY_URL: https://money.$DOMAINNAME0 - FIREFLY_III_ACCESS_TOKEN_FILE: /run/secrets/firefly_iii_access_token - # FIREFLY_III_ACCESS_TOKEN: $FIREFLY_III_ACCESS_TOKEN - # FIREFLY_III_CLIENT_ID: $FIREFLY_III_CLIENT_ID - # NORDIGEN_ID_FILE: - # NORDIGEN_KEY_FILE: - # NORDIGEN_SANDBOX: "false" - # SPECTRE_APP_ID_FILE: - # SPECTRE_SECRET_FILE: - # USE_CACHE: "false" - # IGNORE_DUPLICATE_ERRORS: "false" - # AUTO_IMPORT_SECRET_FILE: - # CAN_POST_AUTOIMPORT: - # CAN_POST_FILES: - # IMPORT_DIR_WHITELIST_FILE: - VERIFY_TLS_SECURITY: "false" - # JSON_CONFIGURATION_DIR_FILE: - CONNECTION_TIMEOUT: 31.41 # π*10 seconds is usually fine. - # APP_ENV: local # These three are good for debugging - APP_DEBUG: "false" - # LOG_CHANNEL: stack - ## debug, info, notice, warning, error, critical, alert, emergency - LOG_LEVEL: info - ## TRUSTED_PROXIES is a useful variable when using Docker and/or a - ## reverse proxy. Set it to ** and reverse proxies work just fine. - TRUSTED_PROXIES: "**" - # ASSET_URL: - ENABLE_MAIL_REPORT: "true" - EXPECT_SECURE_URL: "true" - MAIL_MAILER: smtp - MAIL_DESTINATION: importer-admin@money.$DOMAINNAME0 - MAIL_FROM_ADDRESS: import@money.$DOMAINNAME0 - MAIL_HOST: $EMAIL_SERVER - MAIL_PORT: $EMAIL_SERVER_PORT - MAIL_USERNAME: $EMAIL_SERVER_USER - MAIL_PASSWORD_FILE: /run/secrets/firefly_mail_server_password - MAIL_ENCRYPTION: ssl - ## You probably won't need to change these settings. - # BROADCAST_DRIVER: log - # CACHE_DRIVER: redis # Not working - # QUEUE_CONNECTION: sync - # SESSION_DRIVER: redis # Not working - # SESSION_LIFETIME: 120 - # IS_EXTERNAL: "false" - REDIS_HOST: $REDIS_HOST - REDIS_PASSWORD: $REDIS_PASSWORD - REDIS_PORT: $REDIS_PORT - REDIS_DB: "0" # always use quotes - REDIS_CACHE_DB: "1" # always use quotes - # TRACKER_SITE_ID: - # TRACKER_URL: - # APP_NAME: - APP_URL: "https://import.$DOMAINNAME0" - secrets: - - firefly_iii_access_token - - firefly_mail_server_password - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.firefly-importer-rtr.entrypoints=https" - - "traefik.http.routers.firefly-importer-rtr.rule=Host(`import.$DOMAINNAME0`)" - - "traefik.http.routers.firefly-importer-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.firefly-importer-rtr.middlewares=chain-authelia@file" # Note: issue when using Authelia, default buffer size of 4096 not large enough, currently set to 8192 - ## HTTP Services - - "traefik.http.routers.firefly-importer-rtr.service=firefly-importer-svc" - - "traefik.http.services.firefly-importer-svc.loadbalancer.server.port=8080" - - ## Portfolio Performance - ## Issue with installation - /startapp.sh: cd: line 2: can't cd to - ## /opt/portfolio/workspace: No such file or directory - ## Need to change the startapp.sh to reference something other than - ## /workspace because /opt/portfolio exists - # portfolio: - # <<: *common-keys-apps - # image: ghcr.io/devben-io/docker-portfolio/docker-portfolio:latest - # container_name: portfolio - # hostname: portfolio.$DOMAINNAME0 - # # ports: - # # - "$PORTFOLIO_PORT:5800" - # environment: - # <<: *default-tz-puid-pgid - # APP_NAME: "Portfolio Performance" - # # VERSION: "0.46.6" # Default is "latest" - # LOCALE: en_us - # # APP_ICON_URL: https://www.portfolio-performance.info/images/logo.png - # KEEP_APP_RUNNING: 1 - # # USER_ID: $PUID - # # GROUP_ID: $PGID - # labels: - # - "traefik.enable=true" - # ## HTTP Routers - # - "traefik.http.routers.portfolio-rtr.entrypoints=https" - # - "traefik.http.routers.portfolio-rtr.rule=Host(`portfolio.$DOMAINNAME0`)" - # ## Middlewares - # - "traefik.http.routers.portfolio-rtr.middlewares=chain-authelia@file" - # ## HTTP Services - # - "traefik.http.routers.portfolio-rtr.service=portfolio-svc" - # - "traefik.http.services.portfolio-svc.loadbalancer.server.port=$PORTFOLIO_PORT" - - ## Whoami - ## Tiny Go webserver that prints os information and HTTP request to output - whoami: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - container_name: whoami - image: containous/whoami - environment: - ## Not currently working on port other than 80 - WHOAMI_PORT_NUMBER: $WHOAMI_PORT - WHOAMI_NAME: WhoAmI - labels: - - "traefik.enable=true" - ## HTTP Routers # Set to respond on multiple `whoami` domains - - "traefik.http.routers.whoami-authelia-rtr.entrypoints=https" - - "traefik.http.routers.whoami-authelia-rtr.rule=Host(`whoami-authelia.$DOMAINNAME0`)" - - "traefik.http.routers.whoami-authelia-rtr.tls.options=tls-opts@file" - - "traefik.http.routers.whoami-keycloak-rtr.entrypoints=https" - - "traefik.http.routers.whoami-keycloak-rtr.rule=Host(`whoami-keycloak.$DOMAINNAME0`)" - - "traefik.http.routers.whoami-keycloak-rtr.tls.options=tls-opts@file" - - "traefik.http.routers.whoami-authentik-rtr.entrypoints=https" - - "traefik.http.routers.whoami-authentik-rtr.rule=Host(`whoami-authentik.$DOMAINNAME0`)" - - "traefik.http.routers.whoami-authentik-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.whoami-authelia-rtr.middlewares=chain-authelia@file" - - "traefik.http.routers.whoami-keycloak-rtr.middlewares=chain-keycloak@file" - - "traefik.http.routers.whoami-authentik-rtr.middlewares=chain-authentik@file" - ## HTTP Services - - "traefik.http.routers.whoami-authelia-rtr.service=whoami-svc" - - "traefik.http.routers.whoami-keycloak-rtr.service=whoami-svc" - - "traefik.http.routers.whoami-authentik-rtr.service=whoami-svc" - - "traefik.http.services.whoami-svc.loadbalancer.server.port=$WHOAMI_PORT" - - ############################## VPN - - ## Wireguard - Fast, modern, secure VPN tunnel - wireguard: - <<: *common-keys-core # See EXTENSION FIELDS at the top - container_name: wireguard - image: lscr.io/linuxserver/wireguard:latest - restart: unless-stopped - security_opt: - - no-new-privileges:true - cap_add: - - NET_ADMIN - - SYS_MODULE - environment: - <<: *default-tz-puid-pgid - SERVERURL: vpn.$DOMAINNAME0 - SERVERPORT: $WIREGUARD_PORT - PEERS: $WIREGUARD_PEERS - PEERDNS: 192.168.1.2 - INTERNAL_SUBNET: 10.13.13.0 - volumes: - - $APPDIR/wireguard/config:/config - - /usr/src:/usr/src - - /lib/modules:/lib/modules - # ports: - # - $WIREGUARD_PORT:51820/udp - sysctls: - - net.ipv4.conf.all.src_valid_mark=1 - - net.ipv6.conf.all.disable_ipv6=0 - # - net.ipv4.ip_forward=1 - # - net.ipv6.conf.default.forwarding=1 - # - net.ipv6.conf.all.forwarding=1 - # - net.ipv6.conf.all.proxy_ndp = 1 - # - net.ipv6.conf.all.accept_ra = 1 - labels: - - "traefik.enable=true" - ## UDP Routers - - "traefik.udp.routers.wireguard-udp.entrypoints=wireguard" - ## Rules cannot be used with UDP routers at this time - ## https://doc.traefik.io/traefik/routing/routers/#configuring-udp-routers - # - "traefik.udp.routers.wireguard-udp.rule=Host(`vpn.$DOMAINNAME0`)" - ## Middlewares - # - "traefik.udp.routers.wireguard-udp.middlewares=chain-no-auth@file" - ## UDP Services - - "traefik.udp.routers.wireguard-udp.service=wireguard-udp-svc" - - "traefik.udp.services.wireguard-udp-svc.loadbalancer.server.port=51820" - - ## Gluetun - VPN client in a thin Docker container - gluetun: - image: ghcr.io/qdm12/gluetun:v3 - container_name: gluetun - networks: - gluetun_net: - ipv4_address: $GLUETUN_IPV4 - cap_add: - - NET_ADMIN - devices: - - /dev/net/tun:/dev/net/tun - ports: - - $GLUETUN_HTTP_CONTROL_SERVER_PORT:$GLUETUN_HTTP_CONTROL_SERVER_PORT - ## qBittorrent web UI - - $QBITTORRENT_PORT:$QBITTORRENT_PORT - # volumes: - # - $APPDIR/gluetun:/gluetun - environment: - <<: *default-tz-puid-pgid - VPN_SERVICE_PROVIDER: $GLUETUN_VPN_SERVICE_PROVIDER - VPN_TYPE: "openvpn" - # OpenVPN: - OPENVPN_USER_SECRETFILE: /run/secrets/gluetun_openvpn_user - OPENVPN_PASSWORD_SECRETFILE: /run/secrets/gluetun_openvpn_password - ## Fix "WARN [openvpn] 'link-mtu' is used inconsistently" - ## See https://github.com/qdm12/gluetun/discussions/666 - OPENVPN_FLAGS: "--comp-lzo" - VPN_PORT_FORWARDING: "on" - PORT_FORWARD_ONLY: "on" - VPN_PORT_FORWARDING_PROVIDER: $GLUETUN_VPN_SERVICE_PROVIDER - # Wireguard: - # WIREGUARD_PRIVATE_KEY: - # WIREGUARD_ADDRESSES: - SERVER_COUNTRIES: $GLUETUN_SERVER_COUNTRIES - SERVER_CITIES: $GLUETUN_SERVER_CITIES - SERVER_HOSTNAMES: $GLUETUN_SERVER_HOSTNAMES - TZ: $TZ - ## See https://github.com/qdm12/gluetun-wiki/blob/main/setup/servers.md#update-the-vpn-servers-list - UPDATER_PERIOD: "24h" - HTTP_CONTROL_SERVER_ADDRESS: ":$GLUETUN_HTTP_CONTROL_SERVER_PORT" - HEALTH_VPN_DURATION_INITIAL: "120s" - HEALTH_VPN_DURATION_ADDITION: "120s" - HEALTH_SUCCESS_WAIT_DURATION: "120s" - secrets: - - gluetun_openvpn_user - - gluetun_openvpn_password - labels: - ## Connectivity issue when restarted with Watchtower. See https://github.com/qdm12/gluetun/issues/641 - - "com.centurylinklabs.watchtower.enable=false" - - ## Gluetun - VPN client in a thin Docker container - ## gluetun-private is used for private trackers - gluetun-private: - image: ghcr.io/qdm12/gluetun:v3 - container_name: gluetun-private - networks: - gluetun_net: - ipv4_address: $GLUETUN_PRIVATE_IPV4 - t2_proxy: - cap_add: - - NET_ADMIN - devices: - - /dev/net/tun:/dev/net/tun - ports: - - $GLUETUN_PRIVATE_HTTP_CONTROL_SERVER_PORT:$GLUETUN_PRIVATE_HTTP_CONTROL_SERVER_PORT - ## qBittorrent web UI - - $QBITTORRENT_PRIVATE_PORT:$QBITTORRENT_PRIVATE_PORT - # volumes: - # - $APPDIR/gluetun-private:/gluetun - environment: - <<: *default-tz-puid-pgid - VPN_SERVICE_PROVIDER: $GLUETUN_VPN_SERVICE_PROVIDER - VPN_TYPE: "openvpn" - # OpenVPN: - OPENVPN_USER_SECRETFILE: /run/secrets/gluetun_openvpn_user - OPENVPN_PASSWORD_SECRETFILE: /run/secrets/gluetun_openvpn_password - ## Fix "WARN [openvpn] 'link-mtu' is used inconsistently" - ## See https://github.com/qdm12/gluetun/discussions/666 - OPENVPN_FLAGS: "--comp-lzo" - VPN_PORT_FORWARDING: "on" - PORT_FORWARD_ONLY: "on" - VPN_PORT_FORWARDING_PROVIDER: $GLUETUN_PRIVATE_VPN_SERVICE_PROVIDER - # Wireguard: - # WIREGUARD_PRIVATE_KEY: - # WIREGUARD_ADDRESSES: - SERVER_COUNTRIES: $GLUETUN_PRIVATE_SERVER_COUNTRIES - SERVER_CITIES: $GLUETUN_PRIVATE_SERVER_CITIES - SERVER_HOSTNAMES: $GLUETUN_PRIVATE_SERVER_HOSTNAMES - TZ: $TZ - ## See https://github.com/qdm12/gluetun-wiki/blob/main/setup/servers.md#update-the-vpn-servers-list - UPDATER_PERIOD: "24h" - HTTP_CONTROL_SERVER_ADDRESS: ":$GLUETUN_PRIVATE_HTTP_CONTROL_SERVER_PORT" - HEALTH_VPN_DURATION_INITIAL: "120s" - HEALTH_VPN_DURATION_ADDITION: "120s" - HEALTH_SUCCESS_WAIT_DURATION: "120s" - secrets: - - gluetun_openvpn_user - - gluetun_openvpn_password - labels: - ## Connectivity issue when restarted with Watchtower. See https://github.com/qdm12/gluetun/issues/641 - - "com.centurylinklabs.watchtower.enable=false" - - ## Gluetun - VPN client in a thin Docker container - ## gluetun-temp is used for temporary files - gluetun-temp: - image: ghcr.io/qdm12/gluetun:v3 - container_name: gluetun-temp - networks: - gluetun_net: - ipv4_address: $GLUETUN_TEMP_IPV4 - t2_proxy: - cap_add: - - NET_ADMIN - devices: - - /dev/net/tun:/dev/net/tun - ports: - - $GLUETUN_TEMP_HTTP_CONTROL_SERVER_PORT:$GLUETUN_TEMP_HTTP_CONTROL_SERVER_PORT - ## qBittorrent web UI - - $QBITTORRENT_TEMP_PORT:$QBITTORRENT_TEMP_PORT - # volumes: - # - $APPDIR/gluetun-temp:/gluetun - environment: - <<: *default-tz-puid-pgid - VPN_SERVICE_PROVIDER: $GLUETUN_VPN_SERVICE_PROVIDER - VPN_TYPE: "openvpn" - # OpenVPN: - OPENVPN_USER_SECRETFILE: /run/secrets/gluetun_openvpn_user - OPENVPN_PASSWORD_SECRETFILE: /run/secrets/gluetun_openvpn_password - ## Fix "WARN [openvpn] 'link-mtu' is used inconsistently" - ## See https://github.com/qdm12/gluetun/discussions/666 - OPENVPN_FLAGS: "--comp-lzo" - VPN_PORT_FORWARDING: "on" - PORT_FORWARD_ONLY: "on" - VPN_PORT_FORWARDING_PROVIDER: $GLUETUN_TEMP_VPN_SERVICE_PROVIDER - # Wireguard: - # WIREGUARD_PRIVATE_KEY: - # WIREGUARD_ADDRESSES: - SERVER_COUNTRIES: $GLUETUN_TEMP_SERVER_COUNTRIES - SERVER_CITIES: $GLUETUN_TEMP_SERVER_CITIES - SERVER_HOSTNAMES: $GLUETUN_TEMP_SERVER_HOSTNAMES - TZ: $TZ - ## See https://github.com/qdm12/gluetun-wiki/blob/main/setup/servers.md#update-the-vpn-servers-list - UPDATER_PERIOD: "24h" - HTTP_CONTROL_SERVER_ADDRESS: ":$GLUETUN_TEMP_HTTP_CONTROL_SERVER_PORT" - HEALTH_VPN_DURATION_INITIAL: "120s" - HEALTH_VPN_DURATION_ADDITION: "120s" - HEALTH_SUCCESS_WAIT_DURATION: "120s" - secrets: - - gluetun_openvpn_user - - gluetun_openvpn_password - labels: - ## Connectivity issue when restarted with Watchtower. See https://github.com/qdm12/gluetun/issues/641 - - "com.centurylinklabs.watchtower.enable=false" - - ############################## NETWORK SERVICES - - ## Pi-Hole - Network-wide ad blocking - # pihole: - # ## Note: several steps must be taken to ensure compatability - # ## https://www.smarthomebeginner.com/run-pihole-in-docker-on-ubuntu-with-reverse-proxy/ - # <<: *common-keys-apps # See EXTENSION FIELDS at the top - # image: pihole/pihole:latest - # container_name: pihole - # ports: - # - $PIHOLE_PORT:53 - # - $PIHOLE_PORT:53/udp - # # - $PIHOLE_WEB_PORT:80 - # volumes: - # - $APPDIR/pihole/etc/pihole:/etc/pihole - # - $APPDIR/pihole/etc/dnsmasq.d:/etc/dnsmasq.d - # ## touch pihole.log first - # - $APPDIR/pihole/var/log/pihole.log:/var/log/pihole.log - # # cap_add: - # # - NET_ADMIN - # environment: - # <<: *default-tz-puid-pgid - # ServerIP: $IP - # PROXY_LOCATION: pihole - # VIRTUAL_HOST: pihole.$DOMAINNAME0 - # VIRTUAL_PORT: 80 - # WEBPASSWORD: $PIHOLE_WEBPASSWORD - # PIHOLE_DNS_: 127.0.0.1#8053;192.168.1.2 - # labels: - # - "traefik.enable=true" - # ## HTTP Routers - # - "traefik.http.routers.pihole-rtr.entrypoints=https" - # - "traefik.http.routers.pihole-rtr.rule=Host(`pihole.$DOMAINNAME0`)" - # - "traefik.http.routers.pihole-rtr.tls.options=tls-opts@file" - # ## Middlewares - # #- "traefik.http.routers.pihole-rtr.middlewares=chain-basic-auth@file" - # - "traefik.http.routers.pihole-rtr.middlewares=chain-authelia@file" - # ## HTTP Services - # - "traefik.http.routers.pihole-rtr.service=pihole-svc" - # - "traefik.http.services.pihole-svc.loadbalancer.server.port=80" - - ## Unbound - A validating, recursive, and caching DNS resolver - unbound: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: klutchell/unbound:latest - container_name: unbound - ports: - - $UNBOUND_PORT:53 - - $UNBOUND_PORT:53/udp - volumes: - - $APPDIR/unbound/config:/opt/unbound/etc/unbound/ - ## Update $APPDIR/unbound/config/root.hints (from $DOCKERDIR) using - ## `wget https://www.internic.net/domain/named.cache -O ./appdata/unbound/config/root.hints` - healthcheck: - test: ["CMD", "dig", "ietf.org", "@127.0.0.1", "-p", "53"] - interval: 30s - timeout: 30s - retries: 3 - start_period: 10s - - ## NTP - NTP server running in a Docker container (without the priviledged flag) - ## NTP server - ## Query the NTP server: ntpdate -q mint.home.arpa - ## Check sources: docker exec ntp chronyc sources - ## View source stats: docker exec ntp chronyc sourcestats - ## View NPT status: docker exec ntp chronyc tracking - ## Automatically update system time (Linux): - ## https://winaero.com/how-to-set-time-from-the-internet-ntp-in-linux-mint-17/ - ## Automatically update system time (Windows): - ## https://winaero.com/configure-internet-time-ntp-options-in-windows-10/ - ntp: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: cturra/ntp:latest - container_name: ntp - ports: - # - $NTP_PORT:123 - - $NTP_PORT:123/udp - environment: - NTP_SERVERS: $NTP_SERVERS - ## 0 (info), 1 (warning), 2 (non-fatal error), and 3 (fatal error) - LOG_LEVEL: 1 - - ############################## MINECRAFT - - ## Minecraft - Minecraft server - # minecraft: - # <<: *common-keys-apps # See EXTENSION FIELDS at the top - # image: itzg/minecraft-server:java8 - # container_name: minecraft - # tty: true - # ports: - # - $MINECRAFT_PORT:25565 - # deploy: - # resources: - # limits: - # memory: 8G - # networks: - # - default - # volumes: - # - $APPDIR/minecraft/technic/data:/data - # ## Mount as read-only to ensure integrity - # - $APPDIR/minecraft/technic/worlds:/worlds:ro - # ## Ensure you specify different volumes for different worlds: - # ## https://github.com/itzg/docker-minecraft-server/blob/master/README.md#data-directory - # environment: - # # UID: $PUID - # # GID: $PGID - # TZ: $TZ - # EULA: TRUE - # # MEMORY: 6G - # INIT_MEMORY: 1G # Independently sets the initial heap size - # MAX_MEMORY: 6G # Independently sets the max heap size - # VERSION: 1.12.2 # LATEST, SNAPSHOT, - # TYPE: FORGE - # FORGEVERSION: 14.23.5.2855 - # # OVERRIDE_SERVER_PROPERTIES: true - # ## Will overwrite the world on server start - # # FORCE_WORLD_COPY: TRUE - # ## Read the world from the folder my_world - # # WORLD: /worlds/backups/world_backup - # ## Read the world from a URL - # # WORLD: http://www.example.com/worlds/MySave.zip - # SERVER_NAME: NUC_Server - # ## Dangerous to change if you don't know what you're doing - # # SERVER_PORT: $MINECRAFT_PORT - # DIFFICULTY: 1 # peaceful, easy, normal, hard - # WHITELIST: $MINECRAFT_USER_LIST # Allow-listed players - # OPS: $MINECRAFT_USER_LIST # Op/Administrator players - # # ICON: https://oldschool.runescape.wiki/images/c/ce/Gnome_child_chathead.png # Set the server icon - # # OVERRIDE_ICON: TRUE # Override the icon on server startup - # MAX_PLAYERS: 10 # Default : 20 - # # MAX_WORLD_SIZE: 10000 # Max world radius in chunks - # # ALLOW_NETHER: true - # ANNOUNCE_PLAYER_ACHIEVEMENTS: true - # ENABLE_COMMAND_BLOCK: false - # # FORCE_GAMEMODE: false - # GENERATE_STRUCTURES: true - # ## If set to true, players will be set to spectator mode if they die - # HARDCORE: false - # ## If set to false, the server will not send data to snoop.minecraft.net - # ## server. - # SNOOPER_ENABLED: false - # ## Terrain may still naturally generate above a low height limit - # MAX_BUILD_HEIGHT: 256 - # ## In milliseconds, -1 to disable. Should be max 50 (0.05s). Considering - # ## it to be crashed, server will forcibly shutdown. - # MAX_TICK_TIME: -1 - # SPAWN_ANIMALS: true - # SPAWN_MONSTERS: true - # SPAWN_NPCS: true - # SPAWN_PROTECTION: 50 - # ## Sets the amount of world data the server sends the client, measured in - # ## chunks in each direction of the player (radius, not diameter). It - # ## determines the server-side viewing distance. - # VIEW_DISTANCE: 10 - # SEED: "-9075357542416790126" # Ensure quotes are used if negative - # # MODE: survival # creative, survival, adventure. Default: survival - # MOTD: "The §c§lspiceest§r Minecraft server" - # PVP: true - # ## DEFAULT, FLAT, LARGEBIOMES, AMPLIFIED, CUSTOMIZED, BUFFET - # LEVEL_TYPE: BIOMESOP - # ## Can be paired with GENERATOR_SETTINGS for further customization - # # GENERATOR_SETTINGS: '3;minecraft:bedrock,3*minecraft:stone,52*minecraft:sandstone;2;' - # ## NOTE: : and : must be escaped using \. The checksum is plain-text - # ## hexadecimal - # # RESOURCE_PACK: 'http\://link.com/to/pack.zip?\: 1' - # # RESOURCE_PACK_SHA1: 'd5db29cd03a2ed055086cef9c31c252b4587d6d0' - # ## Use the LEVEL option to specify multiple worlds. NOTE: if running - # ## multiple containers be sure to specify a different -v host directory - # ## for each LEVEL - # ## Default: world. You can either switch between world saves or run - # ## multiple containers with different saves by using the LEVEL option, - # ## where the default is "world" - # LEVEL: world - # ONLINE_MODE: TRUE - # ALLOW_FLIGHT: TRUE - # ## Set RCON settings - # ENABLE_RCON: true - # RCON_PASSWORD: $MINECRAFT_RCON_PASSWORD - # RCON_PORT: $MINECRAFT_RCON_PORT - # ## Other server settings - # PLAYER_IDLE_TIMEOUT: 0 - # # BROADCAST_CONSOLE_TO_OPS: - # # BROADCAST_RCON_TO_OPS: - # # ENABLE_JMX: - # USE_AIKAR_FLAGS: true - # # SYNC_CHUNK_WRITES: - # # ENABLE_STATUS: - # # ENTITY_BROADCAST_RANGE_PERCENTAGE: - # # FUNCTION_PERMISSION_LEVEL: - # NETWORK_COMPRESSION_THRESHOLD: 256 - # OP_PERMISSION_LEVEL: 4 - # # PREVENT_PROXY_CONNECTIONS: - # # USE_NATIVE_TRANSPORT: - # # ENFORCE_WHITELIST: - # # ENABLE_WHITELIST: - # # STOP_SERVER_ANNOUNCE_DELAY: 30 - # ENABLE_ROLLING_LOGS: true - # ## Set up autopause for server usage optimization - # ## See https://github.com/itzg/docker-minecraft-server/blob/master/README.md#autopause - # ## MAX_TICK_TIME must be set to an arbitrarily large number or disabled - # ## (-1) to allow for autopause - # ENABLE_AUTOPAUSE: TRUE - # ## Default: 3600. Time between the last client disconnect and the pausing - # ## of the process - # # AUTOPAUSE_TIMEOUT_EST: 3600 - # ## Default: 600. Time between server start and the pausing of the - # ## process, when no client connects inbetween - # # AUTOPAUSE_TIMEOUT_INIT: 600 - # ## Default: 120. Time between knocking of the port (e.g. by the main menu - # # ping) and the pausing of the process, when no client connects inbetween - # # AUTOPAUSE_TIMEOUT_KN: 120 - # ## Default: 10. Period of the daemonized state machine, that handles the - # ## pausing of the process (resuming is done independently) - # # AUTOPAUSE_PERIOD: 10 - # ## See https://github.com/itzg/docker-minecraft-server/blob/master/README.md#enabling-autopause - # # AUTOPAUSE_KNOCK_INTERFACE: eth0 - # ## enp4s0, eth0, lo, eno1, docker0, br-ab276aa20945, br-4d480c1adff5, t2_proxy - # # labels: - # # - "traefik.enable=true" - # # ## HTTP Routers - # # - "traefik.http.routers.minecraft-rtr.entrypoints=minecraft" - # # - "traefik.http.routers.minecraft-rtr.rule=Host(`vanilla.mc.$DOMAINNAME0`)" - # # ## Middlewares - # # - "traefik.http.routers.minecraft-rtr.middlewares=chain-no-auth@file,minecraft-remove-bypass-cache" - # # - "traefik.http.middlewares.minecraft-remove-bypass-cache.stripprefix.prefixes=/bypass_cache" - # # ## HTTP Services - # # - "traefik.http.routers.minecraft-rtr.service=minecraft-svc" - # # - "traefik.http.services.minecraft-svc.loadbalancer.server.port=$MINECRAFT_PORT" - - ## Minecraft Backup - Backup Minecraft worlds - # mc-backup: - # <<: *common-keys-apps # See EXTENSION FIELDS at the top - # image: itzg/mc-backup:latest - # container_name: mc-backup - # # depends_on: - # # - minecraft - # environment: - # RCON_HOST: minecraft - # RCON_PORT: $MINECRAFT_RCON_PORT - # RCON_PASSWORD: $MINECRAFT_RCON_PASSWORD - # EXCLUDES: *.jar,cache,logs - # BACKUP_METHOD: tar - # SRC_DIR: /data - # BACKUP_NAME: world - # INITIAL_DELAY: 15m - # BACKUP_INTERVAL: 2h - # PRUNE_BACKUPS_DAYS: 7 - # PRUNE_RESTIC_RETENTION: "--keep-daily 7 --keep-weekly 5 --keep-monthly 3" - # LINK_LATEST: true - # volumes: - # - $APPDIR/minecraft/technic/data:/data:ro - # - $APPDIR/minecraft/mc-backups:/backups - - ## Minecraft RCON - ## Issue commands issued to the server via a "remote console", or RCON - # minecraft-rcon: - # <<: *common-keys-apps # See EXTENSION FIELDS at the top - # image: itzg/rcon:latest - # container_name: minecraft-rcon - # depends_on: - # - minecraft - # environment: - # RWA_USERNAME: $MINECRAFT_RWA_USERNAME - # RWA_PASSWORD: $MINECRAFT_RWA_PASSWORD - # RWA_ADMIN: "TRUE" - # # is referring to the hostname of 'mc' compose service above - # RWA_RCON_HOST: minecraft - # # needs to match the password configured for the container, which is 'minecraft' by default - # RWA_RCON_PASSWORD: $MINECRAFT_RCON_PASSWORD - # # ports: - # # - $MINECRAFT_RCON_PORT:4326 - # # - $MINECRAFT_RCON_WEBSOCKET_PORT:4327 - # labels: - # - "traefik.enable=true" - # ## HTTP Routers - # - "traefik.http.routers.minecraft-rcon-rtr.entrypoints=https" - # - "traefik.http.routers.minecraft-rcon-websocket-rtr.entrypoints=minecraft-rcon-websocket" - # - "traefik.http.routers.minecraft-rcon-rtr.rule=Host(`vanilla-rcon.mc.$DOMAINNAME0`)" - # ## Middlewares - # - "traefik.http.routers.minecraft-rcon-rtr.middlewares=chain-no-auth@file" - # - "traefik.http.routers.minecraft-rcon-websocket-rtr.middlewares=chain-no-auth@file" - # ## HTTP Services - # - "traefik.http.routers.minecraft-rcon-rtr.service=minecraft-rcon-svc" - # - "traefik.http.services.minecraft-rcon-svc.loadbalancer.server.port=4326" - # - "traefik.http.routers.minecraft-rcon-websocket-rtr.service=minecraft-rcon-websocket-svc" - # - "traefik.http.services.minecraft-rcon-websocket-svc.loadbalancer.server.port=4327" - - ## BlueBubbles - Bringing iMessage to Windows, Linux, and Android - ## Stopped due to issues with keeping the container alive and usable - # bluebubbles-setup: - # <<: *common-keys-apps - # security_opt: - # - no-new-privileges:false - # image: sickcodes/docker-osx:ventura - # container_name: bluebubbles-setup - # # privileged: true - # # network_mode: "host" - # # cap_add: - # # - ALL - # user: "${PUID}:${PGID}" - # devices: - # - /dev/kvm - # ports: - # - $BLUEBUBBLES_VNC_PORT:5999 - # # dns: - # # - 1.1.1.1 - # environment: - # IMAGE_PATH: /image - # EXTRA: -display none -vnc 0.0.0.0:99,password-secret=secvnc0 -object secret,id=secvnc0,data=$BLUEBUBBLES_VNC_PASSWORD - # DISPLAY: ":99" - # WIDTH: 1920 - # HEIGHT: 1080 - # GENERATE_UNIQUE: true - # volumes: - # - /tmp/.X11-unix:/tmp/.X11-unix - # - $DATADIR/docker/bluebubbles/maindisk.qcow2:/image - - ## BlueBubbles - Bringing iMessage to Windows, Linux, and Android - ## Stopped due to issues with keeping the container alive and usable - # bluebubbles: - # <<: *common-keys-apps - # security_opt: - # - no-new-privileges:false - # image: sickcodes/docker-osx:naked - # container_name: bluebubbles - # # privileged: true - # # network_mode: "host" - # # cap_add: - # # - ALL - # user: "${PUID}:${PGID}" - # devices: - # - /dev/kvm - # ports: - # ## Must connect to the server via VPN to have access to VNC - # - $BLUEBUBBLES_VNC_PORT:$BLUEBUBBLES_VNC_PORT - # - $BLUEBUBBLES_SERVER_PORT:$BLUEBUBBLES_SERVER_PORT - # - 50922:10022 - # # dns: - # # - 1.1.1.1 - # environment: - # DISPLAY: ${DISPLAY:-:0.0} - # IMAGE_PATH: /image - # BOOTDISK: /bootdisk - # EXTRA: -display none -vnc 0.0.0.0:99,password-secret=secvnc0 -object secret,id=secvnc0,data=$BLUEBUBBLES_VNC_PASSWORD - # ADDITIONAL_PORTS: "hostfwd=tcp::$BLUEBUBBLES_SERVER_PORT-:$BLUEBUBBLES_SERVER_PORT," - # DISPLAY: ":99" - # WIDTH: 1920 - # HEIGHT: 1080 - # NOPICKER: true - # volumes: - # - /tmp/.X11-unix:/tmp/.X11-unix - # - $DATADIR/docker/bluebubbles/maindisk.qcow2:/image - # - $DATADIR/docker/bluebubbles/bootdisk.qcow2:/bootdisk - # labels: - # - "traefik.enable=true" - # ## HTTP Routers - # - "traefik.http.routers.bluebubbles-rtr.entrypoints=https" - # - "traefik.http.routers.bluebubbles-rtr.rule=Host(`bluebubbles.$DOMAINNAME0`)" - # ## Middlewares - # #- "traefik.http.routers.bluebubbles-rtr.middlewares=chain-basic-auth@file" - # - "traefik.http.routers.bluebubbles-rtr.middlewares=chain-no-auth@file" - # ## HTTP Services - # - "traefik.http.routers.bluebubbles-rtr.service=bluebubbles-svc" - # - "traefik.http.services.bluebubbles-svc.loadbalancer.server.port=$BLUEBUBBLES_SERVER_PORT" - - ############################## MEDIA SERVER - - ## qBittorrent - an open-source software alternative to µTorrent - qbit: - ## We do not want this to be able to communicate locally (except as - ## specified) - # <<: *common-keys-apps - image: lscr.io/linuxserver/qbittorrent:latest - container_name: qbit - security_opt: - - no-new-privileges:true - network_mode: "service:gluetun" - environment: - # Built-in env variables - <<: *default-tz-puid-pgid - WEBUI_PORT: $QBITTORRENT_PORT - # Custom env variables - LOG_LEVEL: "WARN" # "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" - FILE__QBITTORRENT_USERNAME: /run/secrets/qbittorrent_user - FILE__QBITTORRENT_PASSWORD: /run/secrets/qbittorrent_pass - GLUETUN_IPV4: $GLUETUN_IPV4 - GLUETUN_HTTP_CONTROL_SERVER_PORT: $GLUETUN_HTTP_CONTROL_SERVER_PORT - volumes: - - $APPDIR/qbittorrent/config:/config - ## Add scripts - - $APPDIR/qbittorrent/scripts:/scripts:ro - ## Space for persistent storage - - $APPDIR/qbittorrent/persistent:/persistent - ## Add init scripts - - $APPDIR/qbittorrent/custom-cont-init.d:/custom-cont-init.d:ro - - $APPDIR/qbittorrent/custom-services.d:/custom-services.d:ro - ## Final home for data - - $DATADIR/torrents:/data/torrents - ## Allows for local download before transfer - - $DOCKERDIR/temp-data/torrents:/temp-data/torrents - secrets: - - qbittorrent_user - - qbittorrent_pass - labels: - ## Ensure constant connectivity is prioritized for trackers - - "com.centurylinklabs.watchtower.enable=false" - - ## qBittorrent - an open-source software alternative to µTorrent - ## qbit-private is used for private trackers - qbit-private: - ## We do not want this to be able to communicate locally (except as - ## specified) - # <<: *common-keys-apps - image: lscr.io/linuxserver/qbittorrent:5.0.4 - container_name: qbit-private - security_opt: - - no-new-privileges:true - network_mode: "service:gluetun-private" - environment: - # Built-in env variables - <<: *default-tz-puid-pgid - WEBUI_PORT: $QBITTORRENT_PRIVATE_PORT - # Custom env variables - LOG_LEVEL: "WARN" # "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" - FILE__QBITTORRENT_USERNAME: /run/secrets/qbittorrent_user - FILE__QBITTORRENT_PASSWORD: /run/secrets/qbittorrent_pass - GLUETUN_IPV4: $GLUETUN_PRIVATE_IPV4 - GLUETUN_HTTP_CONTROL_SERVER_PORT: $GLUETUN_PRIVATE_HTTP_CONTROL_SERVER_PORT - volumes: - - $APPDIR/qbittorrent-private/config:/config - ## Add scripts - - $APPDIR/qbittorrent-private/scripts:/scripts:ro - ## Space for persistent storage - - $APPDIR/qbittorrent-private/persistent:/persistent - ## Add init scripts - - $APPDIR/qbittorrent-private/custom-cont-init.d:/custom-cont-init.d:ro - - $APPDIR/qbittorrent-private/custom-services.d:/custom-services.d:ro - ## Final home for data - - $DATADIR/torrents-private:/data/torrents-private - ## Allows for local download before transfer - - $DOCKERDIR/temp-data/torrents:/temp-data/torrents - secrets: - - qbittorrent_user - - qbittorrent_pass - labels: - ## Ensure constant connectivity is prioritized for trackers - - "com.centurylinklabs.watchtower.enable=false" - - ## qBittorrent - an open-source software alternative to µTorrent - ## qbit-private is used for private trackers - qbit-temp: - ## We do not want this to be able to communicate locally (except as - ## specified) - # <<: *common-keys-apps - image: lscr.io/linuxserver/qbittorrent:5.0.4 - container_name: qbit-temp - security_opt: - - no-new-privileges:true - network_mode: "service:gluetun-temp" - environment: - # Built-in env variables - <<: *default-tz-puid-pgid - WEBUI_PORT: $QBITTORRENT_TEMP_PORT - # Custom env variables - LOG_LEVEL: "WARN" # "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" - FILE__QBITTORRENT_USERNAME: /run/secrets/qbittorrent_user - FILE__QBITTORRENT_PASSWORD: /run/secrets/qbittorrent_pass - GLUETUN_IPV4: $GLUETUN_TEMP_IPV4 - GLUETUN_HTTP_CONTROL_SERVER_PORT: $GLUETUN_TEMP_HTTP_CONTROL_SERVER_PORT - volumes: - - $APPDIR/qbittorrent-temp/config:/config - ## Add scripts - - $APPDIR/qbittorrent-temp/scripts:/scripts:ro - ## Space for persistent storage - - $APPDIR/qbittorrent-temp/persistent:/persistent - ## Add init scripts - - $APPDIR/qbittorrent-temp/custom-cont-init.d:/custom-cont-init.d:ro - - $APPDIR/qbittorrent-temp/custom-services.d:/custom-services.d:ro - ## Final home for data - - $DATADIR/torrents-private:/data/torrents-private - ## Allows for local download before transfer - - $DOCKERDIR/temp-data/torrents:/temp-data/torrents - secrets: - - qbittorrent_user - - qbittorrent_pass - labels: - ## Ensure constant connectivity is prioritized for trackers - - "com.centurylinklabs.watchtower.enable=false" - - ## Tautulli - Plex Media Server monitoring, analytics, and notifications - tautulli: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: lscr.io/linuxserver/tautulli:latest - container_name: tautulli - networks: - t2_proxy: - ipv4_address: $TAUTULLI_IPV4 - # ports: - # - "$TAUTULLI_PORT:8181" - volumes: - - $APPDIR/tautulli/config:/config - - "$DATADIR/docker/plex/Library/Application Support/Plex Media Server/Logs:/plexlogs:ro" # Give read-only access to Plex logs for monitoring via Tautulli - environment: - <<: *default-tz-puid-pgid - labels: - - "traefik.enable=true" - ## HTTP Bypass Routers - - "traefik.http.routers.tautulli-rtr-bypass.entrypoints=https" - - "traefik.http.routers.tautulli-rtr-bypass.rule=Host(`tautulli.$DOMAINNAME0`) && Query(`apikey`, `$TAUTULLI_API_KEY`)" - - "traefik.http.routers.tautulli-rtr-bypass.tls.options=tls-opts@file" - - "traefik.http.routers.tautulli-rtr-bypass.priority=100" - ## HTTP Routers - - "traefik.http.routers.tautulli-rtr.entrypoints=https" - - "traefik.http.routers.tautulli-rtr.rule=Host(`tautulli.$DOMAINNAME0`)" - - "traefik.http.routers.tautulli-rtr.tls.options=tls-opts@file" - - "traefik.http.routers.tautulli-rtr-bypass.priority=99" - ## Middlewares - - "traefik.http.routers.tautulli-rtr-bypass.middlewares=chain-no-auth@file" - - "traefik.http.routers.tautulli-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.tautulli-rtr-bypass.service=tautulli-svc" - - "traefik.http.routers.tautulli-rtr.service=tautulli-svc" - - "traefik.http.services.tautulli-svc.loadbalancer.server.port=8181" - - ############################# INDEXERS - - # Prowlarr - Torrent proxy - prowlarr: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: lscr.io/linuxserver/prowlarr:develop - container_name: prowlarr - networks: - t2_proxy: - ipv4_address: $PROWLARR_IPV4 - # ports: - # - "$PROWLARR_PORT:9696" - volumes: - - $APPDIR/prowlarr/config:/config - environment: - <<: *default-tz-puid-pgid - labels: - - "traefik.enable=true" - ## HTTP Routers API Auth Bypass - - "traefik.http.routers.prowlarr-rtr-bypass.entrypoints=https" - - "traefik.http.routers.prowlarr-rtr-bypass.rule=Host(`prowlarr.$DOMAINNAME0`) && ( Header(`X-Api-Key`, `$PROWLARR_API_KEY`) || Query(`apikey`, `$PROWLARR_API_KEY`) )" - - "traefik.http.routers.prowlarr-rtr-bypass.tls.options=tls-opts@file" - - "traefik.http.routers.prowlarr-rtr-bypass.priority=100" - ## HTTP Routers Auth - - "traefik.http.routers.prowlarr-rtr.entrypoints=https" - - "traefik.http.routers.prowlarr-rtr.rule=Host(`prowlarr.$DOMAINNAME0`)" - - "traefik.http.routers.prowlarr-rtr.tls.options=tls-opts@file" - - "traefik.http.routers.prowlarr-rtr.priority=99" - ## Middlewares - - "traefik.http.routers.prowlarr-rtr-bypass.middlewares=chain-no-auth@file" - - "traefik.http.routers.prowlarr-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.prowlarr-rtr-bypass.service=prowlarr-svc" - - "traefik.http.routers.prowlarr-rtr.service=prowlarr-svc" - - "traefik.http.services.prowlarr-svc.loadbalancer.server.port=9696" - - # FlareSolverr - Proxy server to bypass Cloudflare protection - # Not sure if I need this or not. Just testing. - # flaresolverr: - # <<: *common-keys-apps # See EXTENSION FIELDS at the top - # image: ghcr.io/flaresolverr/flaresolverr:latest - # container_name: flaresolverr - # networks: - # t2_proxy: - # ipv4_address: $FLARESOLVERR_IPV4 - # environment: - # <<: *default-tz-puid-pgid - # LOG_LEVEL: info - # LOG_HTML: "false" - # CAPTCHA_SOLVER: none - # # TEST_URL: "www.eff.org" - # ports: - # - "$FLARESOLVERR_PORT:8191" - # restart: unless-stopped - - ############################# PVRS - - # Radarr - Movie management - # Set url_base in radarr settings if using PathPrefix - radarr: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: lscr.io/linuxserver/radarr:latest # latest was causing "Error parsing column 45" - container_name: radarr - networks: - t2_proxy: - ipv4_address: $RADARR_IPV4 - # ports: - # - "$RADARR_PORT:7878" - volumes: - - $APPDIR/radarr/config:/config - # Optional. See why MediaCover is mounted as volume https://github.com/htpcBeginner/docker-traefik/discussions/147 - # - $DATADIR/temp/appdata/radarr/MediaCover:/config/MediaCover - - $DATADIR:/data - - "/etc/localtime:/etc/localtime:ro" - environment: - <<: *default-tz-puid-pgid - labels: - - "traefik.enable=true" - ## HTTP Routers API Auth Bypass - - "traefik.http.routers.radarr-rtr-bypass.entrypoints=https" - - "traefik.http.routers.radarr-rtr-bypass.rule=Host(`radarr.$DOMAINNAME0`) && (Header(`X-Api-Key`, `$RADARR_API_KEY`) || Query(`apikey`, `$RADARR_API_KEY`))" - - "traefik.http.routers.radarr-rtr-bypass.tls.options=tls-opts@file" - - "traefik.http.routers.radarr-rtr-bypass.priority=100" - ## HTTP Routers Auth - - "traefik.http.routers.radarr-rtr.entrypoints=https" - - "traefik.http.routers.radarr-rtr.rule=Host(`radarr.$DOMAINNAME0`)" - - "traefik.http.routers.radarr-rtr.tls.options=tls-opts@file" - - "traefik.http.routers.radarr-rtr.priority=99" - ## Middlewares - - "traefik.http.routers.radarr-rtr-bypass.middlewares=chain-no-auth@file" - - "traefik.http.routers.radarr-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.radarr-rtr-bypass.service=radarr-svc" - - "traefik.http.routers.radarr-rtr.service=radarr-svc" - - "traefik.http.services.radarr-svc.loadbalancer.server.port=7878" - - # Radarr - Movie management - # Set url_base in radarr settings if using PathPrefix - radarr-4k: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: lscr.io/linuxserver/radarr:latest # latest was causing "Error parsing column 45" - container_name: radarr-4k - networks: - t2_proxy: - ipv4_address: $RADARR_4K_IPV4 - # ports: - # - "$RADARR_PORT:7878" - volumes: - - $APPDIR/radarr-4k/config:/config - # Optional. See why MediaCover is mounted as volume https://github.com/htpcBeginner/docker-traefik/discussions/147 - # - $DATADIR/temp/appdata/radarr/MediaCover:/config/MediaCover - - $DATADIR:/data - - "/etc/localtime:/etc/localtime:ro" - environment: - <<: *default-tz-puid-pgid - labels: - - "traefik.enable=true" - ## HTTP Routers API Auth Bypass - - "traefik.http.routers.radarr-4k-rtr-bypass.entrypoints=https" - - "traefik.http.routers.radarr-4k-rtr-bypass.rule=Host(`radarr-4k.$DOMAINNAME0`) && (Header(`X-Api-Key`, `$RADARR_API_KEY`) || Query(`apikey`, `$RADARR_API_KEY`))" - - "traefik.http.routers.radarr-4k-rtr-bypass.tls.options=tls-opts@file" - - "traefik.http.routers.radarr-4k-rtr-bypass.priority=100" - ## HTTP Routers Auth - - "traefik.http.routers.radarr-4k-rtr.entrypoints=https" - - "traefik.http.routers.radarr-4k-rtr.rule=Host(`radarr-4k.$DOMAINNAME0`)" - - "traefik.http.routers.radarr-4k-rtr.tls.options=tls-opts@file" - - "traefik.http.routers.radarr-4k-rtr.priority=99" - ## Middlewares - - "traefik.http.routers.radarr-4k-rtr-bypass.middlewares=chain-no-auth@file" - - "traefik.http.routers.radarr-4k-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.radarr-4k-rtr-bypass.service=radarr-4k-svc" - - "traefik.http.routers.radarr-4k-rtr.service=radarr-4k-svc" - - "traefik.http.services.radarr-4k-svc.loadbalancer.server.port=7878" - - # Sonarr - TV Shows management - # Set url_base in sonarr settings if using PathPrefix - sonarr: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: lscr.io/linuxserver/sonarr - container_name: sonarr - networks: - t2_proxy: - ipv4_address: $SONARR_IPV4 - # ports: - # - "$SONARR_PORT:8989" - volumes: - - $APPDIR/sonarr/config:/config - # Optional. See why MediaCover is mounted as volume https://github.com/htpcBeginner/docker-traefik/discussions/147 - # - $DATADIR/temp/appdata/sonarr/MediaCover:/config/MediaCover - - $DATADIR:/data - - "/etc/localtime:/etc/localtime:ro" - environment: - <<: *default-tz-puid-pgid - labels: - - "traefik.enable=true" - ## HTTP Routers Auth Bypass - - "traefik.http.routers.sonarr-rtr-bypass.entrypoints=https" - - "traefik.http.routers.sonarr-rtr-bypass.rule=Host(`sonarr.$DOMAINNAME0`) && (Header(`X-Api-Key`, `$SONARR_API_KEY`) || Query(`apikey`, `$SONARR_API_KEY`))" - - "traefik.http.routers.sonarr-rtr-bypass.tls.options=tls-opts@file" - - "traefik.http.routers.sonarr-rtr-bypass.priority=100" - ## HTTP Routers Auth - - "traefik.http.routers.sonarr-rtr.entrypoints=https" - - "traefik.http.routers.sonarr-rtr.rule=Host(`sonarr.$DOMAINNAME0`)" - - "traefik.http.routers.sonarr-rtr.tls.options=tls-opts@file" - - "traefik.http.routers.sonarr-rtr.priority=99" - ## Middlewares - - "traefik.http.routers.sonarr-rtr-bypass.middlewares=chain-no-auth@file" - - "traefik.http.routers.sonarr-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.sonarr-rtr.service=sonarr-svc" - - "traefik.http.routers.sonarr-rtr-bypass.service=sonarr-svc" - - "traefik.http.services.sonarr-svc.loadbalancer.server.port=8989" - - # Sonarr - TV Shows management - # Set url_base in sonarr settings if using PathPrefix - sonarr-4k: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: lscr.io/linuxserver/sonarr - container_name: sonarr-4k - networks: - t2_proxy: - ipv4_address: $SONARR_4K_IPV4 - # ports: - # - "$SONARR_PORT:8989" - volumes: - - $APPDIR/sonarr-4k/config:/config - # Optional. See why MediaCover is mounted as volume https://github.com/htpcBeginner/docker-traefik/discussions/147 - # - $DATADIR/temp/appdata/sonarr/MediaCover:/config/MediaCover - - $DATADIR:/data - - "/etc/localtime:/etc/localtime:ro" - environment: - <<: *default-tz-puid-pgid - labels: - - "traefik.enable=true" - ## HTTP Routers Auth Bypass - - "traefik.http.routers.sonarr-4k-rtr-bypass.entrypoints=https" - - "traefik.http.routers.sonarr-4k-rtr-bypass.rule=Host(`sonarr-4k.$DOMAINNAME0`) && (Header(`X-Api-Key`, `$SONARR_API_KEY`) || Query(`apikey`, `$SONARR_API_KEY`))" - - "traefik.http.routers.sonarr-4k-rtr-bypass.tls.options=tls-opts@file" - - "traefik.http.routers.sonarr-4k-rtr-bypass.priority=100" - ## HTTP Routers Auth - - "traefik.http.routers.sonarr-4k-rtr.entrypoints=https" - - "traefik.http.routers.sonarr-4k-rtr.rule=Host(`sonarr-4k.$DOMAINNAME0`)" - - "traefik.http.routers.sonarr-4k-rtr.tls.options=tls-opts@file" - - "traefik.http.routers.sonarr-4k-rtr.priority=99" - ## Middlewares - - "traefik.http.routers.sonarr-4k-rtr-bypass.middlewares=chain-no-auth@file" - - "traefik.http.routers.sonarr-4k-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.sonarr-4k-rtr.service=sonarr-4k-svc" - - "traefik.http.routers.sonarr-4k-rtr-bypass.service=sonarr-4k-svc" - - "traefik.http.services.sonarr-4k-svc.loadbalancer.server.port=8989" - - ## Lidarr - Music Management - lidarr: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: lscr.io/linuxserver/lidarr:latest - container_name: lidarr - networks: - t2_proxy: - ipv4_address: $LIDARR_IPV4 - # ports: - # - "$LIDARR_PORT:8686" - volumes: - - $APPDIR/lidarr/config:/config - - $DATADIR:/data - environment: - <<: *default-tz-puid-pgid - UMASK: 002 - #ARGS: "" - labels: - - "traefik.enable=true" - ## HTTP Routers Auth Bypass - - "traefik.http.routers.lidarr-rtr-bypass.entrypoints=https" - - "traefik.http.routers.lidarr-rtr-bypass.rule=Host(`lidarr.$DOMAINNAME0`) && (Header(`X-Api-Key`, `$LIDARR_API_KEY`) || Query(`apikey`, `$LIDARR_API_KEY`))" - - "traefik.http.routers.lidarr-rtr-bypass.tls.options=tls-opts@file" - - "traefik.http.routers.lidarr-rtr-bypass.priority=100" - ## HTTP Routers Auth - - "traefik.http.routers.lidarr-rtr.entrypoints=https" - - "traefik.http.routers.lidarr-rtr.rule=Host(`lidarr.$DOMAINNAME0`)" - - "traefik.http.routers.lidarr-rtr.tls.options=tls-opts@file" - - "traefik.http.routers.lidarr-rtr.priority=99" - ## Middlewares - - "traefik.http.routers.lidarr-rtr-bypass.middlewares=chain-no-auth@file" - - "traefik.http.routers.lidarr-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.lidarr-rtr.service=lidarr-svc" - - "traefik.http.routers.lidarr-rtr-bypass.service=lidarr-svc" - - "traefik.http.services.lidarr-svc.loadbalancer.server.port=8686" - - ## Overseerr - Request Management System (Plex Only) - overseerr: - <<: *common-keys-apps - image: lscr.io/linuxserver/overseerr:latest - container_name: overseerr - # ports: - # - $OVERSEERR_PORT:5055 - environment: - <<: *default-tz-puid-pgid - volumes: - - $APPDIR/overseerr/config:/config - healthcheck: - test: wget "http://localhost:$OVERSEERR_PORT/api/v1/status" -qO /dev/null || exit 1 # https://github.com/sct/overseerr/issues/411#issuecomment-755083037 - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.overseerr-rtr.entrypoints=https" - - "traefik.http.routers.overseerr-rtr.rule=Host(`overseerr.$DOMAINNAME0`) || Host(`request.$DOMAINNAME0`)" - - "traefik.http.routers.overseerr-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.overseerr-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.overseerr-rtr.service=overseerr-svc" - - "traefik.http.services.overseerr-svc.loadbalancer.server.port=5055" - - ## Ombi - Request Management System - ombi: - <<: *common-keys-apps - image: lscr.io/linuxserver/ombi:latest - container_name: ombi - # ports: - # - $OMBI_PORT:3579 - environment: - <<: *default-tz-puid-pgid - # BASE_URL: /ombi # Optional - volumes: - - $APPDIR/ombi/config:/config - # - $DATADIR/downloads:/data/downloads - # - $DATADIR/media:/data/media - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.ombi-rtr.entrypoints=https" - - "traefik.http.routers.ombi-rtr.rule=Host(`ombi.$DOMAINNAME0`)" - - "traefik.http.routers.ombi-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.ombi-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.ombi-rtr.service=ombi-svc" - - "traefik.http.services.ombi-svc.loadbalancer.server.port=3579" - - ## Recyclarr - A (dockerized) command-line application that will automatically synchronize recommended settings from TRaSH guides to your Sonarr/Radarr instances. - ## https://trash-guides.info/Misc/trash-sync/ - recyclarr: - <<: *common-keys-apps - image: recyclarr/recyclarr:latest - container_name: recyclarr - environment: - <<: *default-tz-puid-pgid - CRON_SCHEDULE: "0 12 * * 1" # Optional - Default "@daily" - https://cron.help/ - volumes: - - $APPDIR/recyclarr/config:/config - - ## Maintainerr - maintainerr: - <<: *common-keys-apps - image: ghcr.io/jorenn92/maintainerr:latest - container_name: maintainerr - volumes: - - $APPDIR/maintainerr/config:/opt/data - environement: - API_PORT: 3001 - UI_PORT: 6246 - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.maintainerr-rtr.entrypoints=https" - - "traefik.http.routers.maintainerr-rtr.rule=Host(`maintainerr.$DOMAINNAME0`)" - - "traefik.http.routers.maintainerr-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.maintainerr-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.maintainerr-rtr.service=maintainerr-svc" - - "traefik.http.services.maintainerr-svc.loadbalancer.server.port=6246" - - ############################# MEDIA - ## Jellyfin - Free Software Media System - jellyfin: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: jellyfin/jellyfin:latest # Issues with hardware transcoding with linuxserver.io image - container_name: jellyfin - devices: - # - /dev/dri:/dev/dri # AMD hardware transcoding? - - /dev/dri/renderD128:/dev/dri/renderD128 - - /dev/dri/card1:/dev/dri/card0 - group_add: - - $RENDER_GROUP # Add render group permission to allow GPU render access - ports: - - $JELLYFIN_PORT:8096 - # - 8920:8920 # optional - HTTPS WebUI - - 7359:7359/udp # optional - Allows clients to discover Jellyfin on the local network - - 1900:1900/udp # optional - Service discovery used by DNLA and clients - volumes: - - $APPDIR/jellyfin/config:/config - - $APPDIR/jellyfin/config/web-config.json:/jellyfin/jellyfin-web/config.json - - $DATADIR/temp/appdata/jellyfin/metadata:/config/metadata - - $DATADIR/downloads:/data/downloads - - $DATADIR/media:/data/media - # - /dev/shm:/data/transcode # Perform transcoding in RAM - - /$APPDIR/jellyfin/transcodes:/data/transcode # Perform transcoding on SSD - environment: - <<: *default-tz-puid-pgid - UMASK: 022 - # JELLYFIN_PublishedServerUrl: "https://$DOMAINNAME0" # optional - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.jellyfin-rtr.entrypoints=https" - - "traefik.http.routers.jellyfin-rtr.rule=Host(`jellyfin.$DOMAINNAME0`)" - - "traefik.http.routers.jellyfin-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.jellyfin-rtr.middlewares=chain-authelia@file,jellyfin-remove-bypass-cache" - - "traefik.http.middlewares.jellyfin-remove-bypass-cache.stripPrefix.prefixes=/bypass_cache" - # - "traefik.http.middlewares.jellyfin-add-slash.addPrefix.prefix=/" - ## HTTP Services - - "traefik.http.routers.jellyfin-rtr.service=jellyfin-svc" - - "traefik.http.services.jellyfin-svc.loadbalancer.server.port=8096" - - # Plex - Media Server - # Moved to Synology hosted (Intel QuickSync) - # plex: - # <<: *common-keys-apps # See EXTENSION FIELDS at the top - # image: lscr.io/linuxserver/plex:latest - # container_name: plex - # ports: - # # - "$PLEX_PORT:32400/tcp" # Web host proxied via Traefik - # # - "1900:1900/udp" # DLNA - Conflicts with Jellyfin, xTeVe, and Synology default ports - # - "3005:3005/tcp" - # # - "5353:5353/udp" - # - "8324:8324/tcp" - # - "32410:32410/udp" - # - "32412:32412/udp" - # - "32413:32413/udp" - # - "32414:32414/udp" - # - "32469:32469/tcp" - # # - "33400:33400" # If you use Plex Web Tools - # devices: - # - /dev/dri:/dev/dri # AMD hardware transcoding? - # - /dev/dri/renderD128:/dev/dri/renderD128 - # - /dev/dri/card0:/dev/dri/card0 - # volumes: - # - $DOCKERDIR/appdata/plex:/config - # - $DATADIR/media:/media - # - /dev/shm:/transcode # Perform transcoding in RAM - # environment: - # <<: *default-tz-puid-pgid - # PLEX_CLAIM: /run/secrets/plex_claim - # VERSION: docker - # secrets: - # - plex_claim - # labels: - # - "traefik.enable=true" - # ## HTTP Routers - # - "traefik.http.routers.plex-rtr.entrypoints=https" - # - "traefik.http.routers.plex-rtr.rule=Host(`plex.$DOMAINNAME0`)" - # ## Middlewares - # - "traefik.http.routers.plex-rtr.middlewares=chain-authelia@file,plex-remove-bypass-cache" - # - "traefik.http.middlewares.plex-remove-bypass-cache.stripPrefix.prefixes=/bypass_cache" - # ## HTTP Services - # - "traefik.http.routers.plex-rtr.service=plex-svc" - # - "traefik.http.services.plex-svc.loadbalancer.server.port=32400" - - calibre: - <<: *common-keys-apps - image: lscr.io/linuxserver/calibre:latest - container_name: calibre - devices: - - /dev/dri:/dev/dri - # ports: - # - $CALIBRE_PORT:$CALIBRE_PORT - # - $CALIBRE_HTTPS_PORT:$CALIBRE_HTTPS_PORT - # - $CALIBRE_WEB_PORT:8081 - security_opt: - - seccomp:unconfined # Required for some setups - environment: - <<: *default-tz-puid-pgid - # CLI_ARGS: # Optional - CUSTOM_PORT: $CALIBRE_PORT - # CUSTOM_HTTPS_PORT: $CALIBRE_HTTPS_PORT - # CUSTOM_USER: - # PASSWORD: # Use reverse proxy authentication instead - # SUBFOLDER: - TITLE: Calibre - FM_HOME: /import - START_DOCKER: # Set to FALSE to disable DinD Docker setup - DRI_NODE: /dev/dri/renderD128 - volumes: - - $APPDIR/calibre/config:/config - - "$DATADIR/media/Calibre Library:/books" - - $DATADIR/torrents-private/books:/import:ro - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.calibre-rtr.entrypoints=https" - - "traefik.http.routers.calibre-rtr.rule=Host(`calibre.$DOMAINNAME0`)" - - "traefik.http.routers.calibre-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.calibre-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.calibre-rtr.service=calibre-svc" - - "traefik.http.services.calibre-svc.loadbalancer.server.port=$CALIBRE_PORT" - - ## Calibre-Web - A web app that offers a clean and intuitive interface for browsing, reading, and downloading eBooks using a valid Calibre database - calibre-web: - <<: *common-keys-apps - image: lscr.io/linuxserver/calibre-web:latest - container_name: calibre-web - # ports: - # - $CALIBRE_WEB_PORT:8083 - environment: - <<: *default-tz-puid-pgid - DOCKER_MODS: linuxserver/mods:universal-calibre - volumes: - - $APPDIR/calibre-web/config:/config - - "$DATADIR/media/Calibre Library:/books" - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.calibre-web-rtr.entrypoints=https" - - "traefik.http.routers.calibre-web-rtr.rule=Host(`calibre-web.$DOMAINNAME0`)" - - "traefik.http.routers.calibre-web-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.calibre-web-rtr.middlewares=chain-no-auth@file" - ## HTTP Services - - "traefik.http.routers.calibre-web-rtr.service=calibre-web-svc" - - "traefik.http.services.calibre-web-svc.loadbalancer.server.port=8083" - - # audiobookshelf - Self-hosted audiobook and podcast server - audiobookshelf: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: ghcr.io/advplyr/audiobookshelf:latest - container_name: audiobookshelf - # ports: - # - $AUDIOBOOKSHELF_PORT:13378 - volumes: - - $APPDIR/audiobookshelf/config:/config - - $DATADIR/media/audiobooks:/audiobooks - - $DATADIR/media/podcasts:/podcasts - - $APPDIR/audiobookshelf/metadata:/metadata # Could be in $DATADIR to minimize storage usage on host - environment: - # HOST: 127.0.0.1 - PORT: $AUDIOBOOKSHELF_PORT - SOURCE: docker - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.audiobookshelf-rtr.entrypoints=https" - - "traefik.http.routers.audiobookshelf-rtr.rule=Host(`abs.$DOMAINNAME0`)" - - "traefik.http.routers.audiobookshelf-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.audiobookshelf-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.audiobookshelf-rtr.service=audiobookshelf-svc" - - "traefik.http.services.audiobookshelf-svc.loadbalancer.server.port=$AUDIOBOOKSHELF_PORT" - - ############################# MEDIA FILE MANAGEMENT - - # Bazarr - Subtitle Management - bazarr: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: lscr.io/linuxserver/bazarr - container_name: bazarr - networks: - t2_proxy: - ipv4_address: $BAZARR_IPV4 - # ports: - # - $BAZARR_PORT:6767 - volumes: - - $APPDIR/bazarr/config:/config - - $DATADIR/media:/data/media - environment: - <<: *default-tz-puid-pgid - labels: - - "traefik.enable=true" - ## HTTP Routers API Auth Bypass - - "traefik.http.routers.bazarr-rtr-bypass.entrypoints=https" - - "traefik.http.routers.bazarr-rtr-bypass.rule=Host(`bazarr.$DOMAINNAME0`) && (Header(`X-Api-Key`, `$BAZARR_API_KEY`) || Query(`apikey`, `$BAZARR_API_KEY`))" - - "traefik.http.routers.bazarr-rtr-bypass.tls.options=tls-opts@file" - - "traefik.http.routers.bazarr-rtr-bypass.priority=100" - ## HTTP Routers - - "traefik.http.routers.bazarr-rtr.entrypoints=https" - - "traefik.http.routers.bazarr-rtr.rule=Host(`bazarr.$DOMAINNAME0`)" - - "traefik.http.routers.bazarr-rtr.tls.options=tls-opts@file" - - "traefik.http.routers.bazarr-rtr.priority=99" - ## Middlewares - - "traefik.http.routers.bazarr-rtr-bypass.middlewares=chain-no-auth@file" - - "traefik.http.routers.bazarr-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.bazarr-rtr-bypass.service=bazarr-svc" - - "traefik.http.routers.bazarr-rtr.service=bazarr-svc" - - "traefik.http.services.bazarr-svc.loadbalancer.server.port=6767" - - # Handbrake - Video Conversion (Transcoding and compression) - handbrake: - <<: *common-keys-apps # See EXTENSION FIELDS at the top - image: jlesage/handbrake:latest - container_name: handbrake - # ports: - # - "$HANDBRAKE_PORT:$HANDBRAKE_PORT" - volumes: - - $DATADIR:/data - - $APPDIR/handbrake/config:/config - # - $APPDIR/handbrake/watch:/watch - environment: - <<: *default-tz-puid-pgid - USER_ID: $PUID - GROUP_ID: $PGID - UMASK: 002 - KEEP_APP_RUNNING: 1 - CLEAN_TMP_DIR: 1 - DISPLAY_WIDTH: 1600 - DISPLAY_HEIGHT: 960 - AUTOMATED_CONVERSION_KEEP_SOURCE: 1 - # VNC_PASSWORD: $HANDBRAKE_VNC_PASSWD - WEB_LISTENING_PORT: $HANDBRAKE_PORT - labels: - - "traefik.enable=true" - ## HTTP Routers - - "traefik.http.routers.handbrake-rtr.entrypoints=https" - - "traefik.http.routers.handbrake-rtr.rule=Host(`handbrake.$DOMAINNAME0`)" - - "traefik.http.routers.handbrake-rtr.tls.options=tls-opts@file" - ## Middlewares - - "traefik.http.routers.handbrake-rtr.middlewares=chain-authelia@file" - ## HTTP Services - - "traefik.http.routers.handbrake-rtr.service=handbrake-svc" - - "traefik.http.services.handbrake-svc.loadbalancer.server.port=$HANDBRAKE_PORT" - - ############################## MONITORING - - # New Relic - Infrastructure and container monitoring - # https://docs.newrelic.com/docs/infrastructure/install-infrastructure-agent/linux-installation/container-infrastructure-monitoring/ - newrelic-infra: - image: newrelic/infrastructure:latest - container_name: newrelic-infra - cap_add: - - SYS_PTRACE # Allows the agent to gather data about processes running on the host - network_mode: host # Allows the agent to collect the network metrics about the host. - pid: host # Required to monitor host processes / performance - privileged: true # Required to monitor host processes / performance - restart: unless-stopped - volumes: - - "/:/host:ro" # Allows the agent to collect process and storage metrics as well as Inventory data from the host - - "/var/run/docker.sock:/var/run/docker.sock" # Allows the agent to connect to the Engine API via the Docker daemon socket to collect the host's container data - environment: - NRIA_LICENSE_KEY: $NRIA_LICENSE_KEY +include: + ############################## SERVICES + ## Frontends + - compose/traefik.yml + - compose/socket-proxy.yml + - compose/heimdall.yml + # - compose/organizr.yml + ## Security + - compose/authelia.yml + # - compose/keycloak.yml + - compose/authentik.yml + ## Databases + - compose/mariadb.yml + - compose/postgres.yml + - compose/phpmyadmin.yml + - compose/adminer.yml + - compose/redis.yml + - compose/rediscommander.yml + ## Media server + ### Downloads + - compose/qbit.yml + - compose/qbit-private.yml + - compose/qbit-temp.yml + ### Indexers + - compose/prowlarr.yml + # - compose/flaresolverr.yml + ### Monitoring + - compose/tautulli.yml + ### Personal media recorders + - compose/radarr.yml + - compose/radarr-4k.yml + - compose/sonarr.yml + - compose/sonarr-4k.yml + - compose/bazarr.yml + - compose/recyclarr.yml + - compose/maintainerr.yml + - compose/audiobookshelf.yml + - compose/calibre.yml + - compose/calibre-web.yml + - compose/lidarr.yml + ### Requests + - compose/overseerr.yml + - compose/ombi.yml + ### Servers + - compose/jellyfin.yml + ## Moved plex to Synology hosted (Intel QuickSync) + # - compose/plex.yml + ## Services + - compose/cf-ddns.yml + - compose/duckdns.yml + - compose/docker-gc.yml + - compose/watchtower.yml + - compose/vscode.yml + - compose/filebrowser.yml + - compose/guacamole.yml + - compose/dozzle.yml + - compose/glances.yml + - compose/dupeguru.yml + - compose/tdarr.yml + - compose/tdarr-node.yml + - compose/handbrake.yml + - compose/gotify.yml + ## Web + - compose/vaultwarden.yml + - compose/nextcloud.yml + - compose/firefly.yml + # - compose/portfolio.yml + - compose/whoami.yml + ## VPN + - compose/wireguard.yml + - compose/gluetun.yml + - compose/gluetun-private.yml + - compose/gluetun-temp.yml + ## Network services + # - compose/pi-hole.yml + - compose/unbound.yml + - compose/ntp.yml + ## Minecraft + # - compose/minecraft.yml + # - compoase/mc-backup.yml + # - compose/minecraft-rcon.yml + ## Miscellaneous + # - compose/bluebubbles.yml + - compose/newrelic-infra.yml