Skip to content

Instantly share code, notes, and snippets.

@mil1i
Last active June 6, 2024 06:53
Show Gist options
  • Save mil1i/7436a19274b1b1469bf9d94b90afe4d6 to your computer and use it in GitHub Desktop.
Save mil1i/7436a19274b1b1469bf9d94b90afe4d6 to your computer and use it in GitHub Desktop.
Media Server Configs
{
# Global options block. Entirely optional, https is on by default
# Optional email key for lets encrypt
email {env.CLOUDFLARE_EMAIL}
acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}
acme_ca https://acme-v02.api.letsencrypt.org/directory
# Optional staging lets encrypt for testing. Comment out for production.
# acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
key_type p384
admin off
}
(headers) {
header / {
Strict-Transport-Security “max-age=31536000;”
X-XSS-Protection “1; mode=block”
X-Content-Type-Options “nosniff”
X-Frame-Options “DENY”
X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"
Referrer-Policy “strict-origin-when-cross-origin”
-Server
}
}
(tls) {
tls {
protocols tls1.2 tls1.3
}
}
(encoding) {
encode zstd gzip
}
(websockets) {
header / {
Connection *Upgrade*
Upgrade websocket
}
}
(caddy) {
tls {
protocols tls1.2 tls1.3
}
header / {
header_upstream X-Real-IP {remote}
header_upstream X-Forward-For {remote}
header_upstream X-Forward-Proto {scheme}
}
encode zstd gzip
}
# encode zstd gzip
(docker) {
tls {
protocols tls1.2 tls1.3
}
header / {
Strict-Transport-Security “max-age=31536000;”
X-XSS-Protection “1; mode=block”
X-Content-Type-Options “nosniff”
X-Frame-Options “DENY”
X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"
Referrer-Policy “strict-origin-when-cross-origin”
header_upstream X-Real-IP {remote}
header_upstream X-Forward-For {remote}
header_upstream X-Forward-Proto {scheme}
-Server
}
}
plex.{env.DOMAIN} {
import docker
rewrite / /web
reverse_proxy https://{env.PLEX_DIRECT_SSL_IP}.plex.direct:32400
}
dsm.{env.DOMAIN} {
@internal {
remote_ip private_ranges
}
@external {
not remote_ip private_ranges
}
import docker
handle @internal {
reverse_proxy http://{env.DSM_SERVER_IP}:5000 {
header_up Host {upstream_hostport}
}
}
handle {
respond /* "You are not permitted." 403
}
}
dlo.{env.DOMAIN} {
@internal {
remote_ip private_ranges
}
@external {
not remote_ip private_ranges
}
import docker
redir / /overview
handle @internal {
reverse_proxy http://{env.DSM_SERVER_IP}:3000 {
header_up Host {upstream_hostport}
transport http {
dial_timeout 3s
}
}
}
handle {
respond /* "You are not permitted." 403
}
}
cockpit.{env.DOMAIN} {
@internal {
remote_ip private_ranges
}
@external {
not remote_ip private_ranges
}
import docker
handle @internal {
reverse_proxy http://{env.MEDIA_SERVER_IP}:9090
}
handle {
respond /* "You are not permitted." 403
}
}
version: "3.8"
services:
# traefik:
# container_name: traefik
# hostname: traefik.internal
# # The official v2 Traefik docker image
# image: docker.io/traefik:v2.11
# # Enables the web UI and tells Traefik to listen to docker
# # command: --api.insecure=true --providers.docker
# restart: unless-stopped
# cap_add:
# - NET_BIND_SERVICE
# environment:
# PUID: 1000
# PGID: 100
# CF_API_EMAIL: ${CLOUDFLARE_EMAIL}
# CF_DNS_API_TOKEN: ${CLOUDFLARE_API_KEY}
# ports:
# # The HTTP port
# - "80:80"
# # The HTTPS port
# - "443:443"
# # The Web UI (enabled by --api.insecure=true)
# - "8081:8080"
# volumes:
# # Config
# - ${BASE_DOCKER_DIR}/traefik/traefik.yml:/etc/traefik/traefik.yml:rw,Z
# - ${BASE_DOCKER_DIR}/traefik/config.yml:/etc/traefik/config.yml:rw,Z
# - ${BASE_DOCKER_DIR}/traefik/certs:/certs:rw,Z
# # So that Traefik can listen to the Docker events
# - ${DOCKER_SOCK_PATH}:/var/run/docker.sock
# sysctls:
# - net.ipv6.conf.all.disable_ipv6=1
# # - net.core.rmem_max=2500000
# networks:
# traefik:
# aliases:
# - traefik
# - traefik.internal
# - reverse_proxy_traefik
# - reverse_proxy_traefik.internal
caddy:
container_name: caddy
hostname: caddy.internal
image: localhost/caddy-cloudflare:latest
build:
context: ${BASE_DOCKER_DIR}/caddy
dockerfile_inline: |
FROM docker.io/caddy:builder-alpine AS builder
RUN xcaddy build \
--with github.com/caddy-dns/cloudflare \
--with github.com/lucaslorentz/caddy-docker-proxy/v2
FROM docker.io/caddy:latest
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
CMD ["caddy", "docker-proxy"]
restart: unless-stopped
# security_opt:
# - label=disable
cap_add:
- NET_BIND_SERVICE
ports:
- 80:80
- 443:443
volumes:
- ${DOCKER_SOCK_PATH}:/var/run/docker.sock
- ${BASE_DOCKER_DIR}/caddy/Caddyfile:/etc/caddy/Caddyfile:ro,Z
- caddy_data:/data:Z
- caddy_config:/config:Z
environment:
- PUID=${PUID}
- PGID=${PGID}
- CLOUDFLARE_EMAIL=${CLOUDFLARE_EMAIL}
- CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_KEY}
- ACME_AGREE=true
- CADDY_INGRESS_NETWORKS=caddy
- CADDY_DOCKER_CADDYFILE_PATH=/etc/caddy/Caddyfile
# - CADDY_DOCKER_NO_SCOPE=true
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- caddy
- caddy.internal
- reverse_proxy
- reverse_proxy.internal
jellyfin:
container_name: jellyfin
hostname: jellyfin.internal
image: docker.io/jellyfin/jellyfin:latest
restart: unless-stopped
depends_on:
- caddy
# - traefik
labels:
# Caddy Configuration
caddy: jf.${DOMAIN_NAME}, jfl.${DOMAIN_NAME}
caddy.import: docker
caddy.reverse_proxy: "{{upstreams http 8096}}"
caddy.reverse_proxy.health_uri: /health
caddy.reverse_proxy.health_interval: 15s
# Traefik Configuration
traefik.enable: true
traefik.docker.network: traefik
## HTTP Router
#### Entry point where Jellyfin is accessible via
#### Change secure to https in the line below to have accessible without needing to specify a port and change the SSLHost option below
traefik.http.routers.jellyfin.entryPoints: https
#### Host or Path where Jellyfin is accessible
#### Remove (or change) this rule if youd rather have Jellyfin accessible at a PathPrefix URI
traefik.http.routers.jellyfin.rule: Host(`jf.${DOMAIN_NAME}`, `jfl.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
#### Enable TLS with the ACME/LetsEncrypt resolver for HOSTNAME.DOMAIN_NAME
traefik.http.routers.jellyfin.tls: true
traefik.http.routers.jellyfin.tls.certResolver: le
"traefik.http.routers.jellyfin.tls.domains[0].main": jf.${DOMAIN_NAME}
"traefik.http.routers.jellyfin.tls.domains[0].sans": jf.${DOMAIN_NAME}, jfl.${DOMAIN_NAME}
## Middleware
traefik.http.routers.jellyfin.middlewares: jellyfin-mw
#### The customResponseHeaders option lists the Header names and values to apply to the response.
traefik.http.middlewares.jellyfin-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
#### The sslRedirect is set to true, then only allow https requests.
traefik.http.middlewares.jellyfin-mw.headers.SSLRedirect: true
#### The sslHost option is the host name that is used to redirect http requests to https.
#### This is the exact URL that will be redirected to, so you can remove the :9999 port if using default SSL port
# traefik.http.middlewares.jellyfin-mw.headers.SSLHost: jf.${DOMAIN_NAME}
#### Set sslForceHost to true and set SSLHost to forced requests to use SSLHost even the ones that are already using SSL.
#### Note that this uses SSLHost verbatim, so add the port to SSLHost if you are using an alternate port.
# traefik.http.middlewares.jellyfin-mw.headers.SSLForceHost: true
#### The stsSeconds is the max-age of the Strict-Transport-Security header. If set to 0, would NOT include the header.
traefik.http.middlewares.jellyfin-mw.headers.STSSeconds: 315360000
#### The stsIncludeSubdomains is set to true, the includeSubDomains directive will be
#### appended to the Strict-Transport-Security header.
traefik.http.middlewares.jellyfin-mw.headers.STSIncludeSubdomains: true
#### Set stsPreload to true to have the preload flag appended to the Strict-Transport-Security header.
traefik.http.middlewares.jellyfin-mw.headers.STSPreload: true
#### Set forceSTSHeader to true, to add the STS header even when the connection is HTTP.
traefik.http.middlewares.jellyfin-mw.headers.forceSTSHeader: true
#### Set frameDeny to true to add the X-Frame-Options header with the value of DENY.
traefik.http.middlewares.jellyfin-mw.headers.frameDeny: true
#### Set contentTypeNosniff to true to add the X-Content-Type-Options header with the value nosniff.
traefik.http.middlewares.jellyfin-mw.headers.contentTypeNosniff: true
#### Set browserXssFilter to true to add the X-XSS-Protection header with the value 1; mode: block.
traefik.http.middlewares.jellyfin-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
#### The customFrameOptionsValue allows the X-Frame-Options header value to be set with a custom value. This
#### overrides the FrameDeny option.
# traefik.http.middlewares.jellyfin-mw.headers.customFrameOptionsValue: "allow-from https://DOMAIN_NAME"
## HTTP Service
# We define the port here as a port is required, but note that the service is pointing to the service defined in @file
# traefik.http.routers.jellyfin.service: jellyfin-svc@file
traefik.http.services.jellyfin-svc.loadBalancer.server.port: 8096
traefik.http.services.jellyfin-svc.loadBalancer.passHostHeader: true
traefik.http.services.jellyfin-svc.loadBalancer.healthCheck.path: /health
traefik.http.services.jellyfin-svc.loadBalancer.healthCheck.interval: 15s
## Redirection of HTTP on port 9999 to HTTPS on port 9999 (consistent protocol)
traefik.http.routers.jellyfin-insecure.entryPoints: https
traefik.http.routers.jellyfin-insecure.rule: Host(`jf.${DOMAIN_NAME}`, `jfl.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
traefik.http.routers.jellyfin-insecure.middlewares: jellyfin-insecure-mw
traefik.http.middlewares.jellyfin-insecure-mw.redirectscheme.scheme: https
traefik.http.middlewares.jellyfin-insecure-mw.redirectscheme.permanent: false
traefik.http.routers.jellyfin-insecure.service: noop@internal
user: ${PUID}:${PGID}
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=Etc/UTC
# - JELLYFIN_PublishedServerUrl=https://jf.${DOMAIN_NAME},https://jfl.${DOMAIN_NAME}
volumes:
- ${BASE_DOCKER_DIR}/jellyfin/config:/config:rw,Z
- jellyfin-cache:/cache:rw,Z
- nfs-data-ro:/data:ro,nocopy,z
devices:
# Intel QuickSync
- /dev/dri/renderD128:/dev/dri/renderD128
- /dev/dri/card0:/dev/dri/card0
ports:
- 7359:7359/udp # Client Discovery
- 8096:8096/tcp # http web
# - 8920:8920/tcp # https web
- 1900:1900/udp # Service Discovery
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- jellyfin
- jellyfin.internal
# traefik:
# aliases:
# - jellyfin
# - jellyfin.internal
jellystat:
container_name: jellystat
hostname: jellystat.internal
# domainname: lan
image: docker.io/cyfershepard/jellystat:latest
restart: unless-stopped
depends_on:
- caddy
- postgres15
labels:
# Caddy Configuration
caddy: jfstats.${DOMAIN_NAME}
[email protected]_ip: private_ranges
[email protected]_ip: private_ranges
caddy.import: docker
caddy.0_handle: "@internal"
caddy.1_handle: "@external"
caddy.0_handle.reverse_proxy: "{{upstreams http 3000}}"
# caddy.0_handle.reverse_proxy.health_uri: /ping
# caddy.0_handle.reverse_proxy.health_interval: 15s
caddy.1_handle.respond: /* "You are not permitted." 403
# Traefik Configuration
traefik.enable: true
traefik.docker.network: traefik
## HTTP Router
traefik.http.routers.jfstats.entryPoints: https
traefik.http.routers.jfstats.rule: Host(`jfstats.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
traefik.http.routers.jfstats.tls: true
traefik.http.routers.jfstats.tls.certResolver: le
"traefik.http.routers.jfstats.tls.domains[0].main": jfstats.${DOMAIN_NAME}
"traefik.http.routers.jfstats.tls.domains[0].sans": jfstats.${DOMAIN_NAME}
## Middleware
traefik.http.routers.jfstats.middlewares: jfstats-mw
traefik.http.middlewares.jfstats-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
traefik.http.middlewares.jfstats-mw.headers.SSLRedirect: true
traefik.http.middlewares.jfstats-mw.headers.STSSeconds: 315360000
traefik.http.middlewares.jfstats-mw.headers.STSIncludeSubdomains: true
traefik.http.middlewares.jfstats-mw.headers.STSPreload: true
traefik.http.middlewares.jfstats-mw.headers.forceSTSHeader: true
traefik.http.middlewares.jfstats-mw.headers.frameDeny: true
traefik.http.middlewares.jfstats-mw.headers.contentTypeNosniff: true
traefik.http.middlewares.jfstats-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
traefik.http.services.jfstats-svc.loadBalancer.server.port: 3000
traefik.http.services.jfstats-svc.loadBalancer.passHostHeader: true
traefik.http.routers.jfstats-insecure.entryPoints: https
traefik.http.routers.jfstats-insecure.rule: Host(`jfstats.${DOMAIN_NAME}`)
traefik.http.routers.jfstats-insecure.middlewares: jfstats-insecure-mw
traefik.http.middlewares.jfstats-insecure-mw.redirectscheme.scheme: https
traefik.http.middlewares.jfstats-insecure-mw.redirectscheme.permanent: false
traefik.http.routers.jfstats-insecure.service: noop@internal
# user: ${PUID}:${PGID}
environment:
POSTGRES_USER: ${POSTGRES_DB_USER}
POSTGRES_PASSWORD: ${POSTGRES_DB_PASSWORD}
POSTGRES_IP: postgres15
POSTGRES_PORT: ${POSTGRES_DB_PORT:-5432}
JWT_SECRET: ${POSTGRES_DB_JWT_SECRET}
TZ: Etc/UTC
volumes:
- ${BASE_DOCKER_DIR}/jellystat:/app/backend/backup-data:rw,Z
ports:
- 3000:3000 # Server port
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- jellystat
- jellystat.internal
data:
aliases:
- jellystat
- jellystat.internal
# traefik:
# aliases:
# - jellystat
# - jellystat.internal
postgres15:
container_name: postgres15
hostname: postgres15.internal
# domainname: lan
image: docker.io/postgres:15.5-alpine
restart: unless-stopped
user: ${PUID}:${PGID}
environment:
POSTGRES_DB: ${POSTGRES_DB_NAME:-jstat}
POSTGRES_USER: ${POSTGRES_DB_USER}
POSTGRES_PASSWORD: ${POSTGRES_DB_PASSWORD}
PUID: ${PUID}
PGID: ${PGID}
TZ: Etc/UTC
volumes:
- ${BASE_DOCKER_DIR}/postgres:/var/lib/postgresql/data:rw,Z
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
data:
aliases:
- postgres15
jfvue:
container_name: jfvue
hostname: jfvue.internal
# domainname: lan
image: ghcr.io/jellyfin/jellyfin-vue:unstable
restart: unless-stopped
depends_on:
- caddy
# - traefik
labels:
# Caddy Configuration
caddy: jfvue.${DOMAIN_NAME}
caddy.import: docker
caddy.reverse_proxy: "{{upstreams http 80}}"
# Traefik Configuration
traefik.enable: true
traefik.docker.network: traefik
## HTTP Router
traefik.http.routers.jfvue.entryPoints: https
traefik.http.routers.jfvue.rule: Host(`jfvue.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
traefik.http.routers.jfvue.tls: true
traefik.http.routers.jfvue.tls.certResolver: le
"traefik.http.routers.jfvue.tls.domains[0].main": jfvue.${DOMAIN_NAME}
"traefik.http.routers.jfvue.tls.domains[0].sans": jfvue.${DOMAIN_NAME}
## Middleware
traefik.http.routers.jfvue.middlewares: jfvue-mw
traefik.http.middlewares.jfvue-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
traefik.http.middlewares.jfvue-mw.headers.SSLRedirect: true
traefik.http.middlewares.jfvue-mw.headers.STSSeconds: 315360000
traefik.http.middlewares.jfvue-mw.headers.STSIncludeSubdomains: true
traefik.http.middlewares.jfvue-mw.headers.STSPreload: true
traefik.http.middlewares.jfvue-mw.headers.forceSTSHeader: true
traefik.http.middlewares.jfvue-mw.headers.frameDeny: true
traefik.http.middlewares.jfvue-mw.headers.contentTypeNosniff: true
traefik.http.middlewares.jfvue-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
traefik.http.services.jfvue-svc.loadBalancer.server.port: 80
traefik.http.services.jfvue-svc.loadBalancer.passHostHeader: true
traefik.http.routers.jfvue-insecure.entryPoints: https
traefik.http.routers.jfvue-insecure.rule: Host(`jfvue.${DOMAIN_NAME}`)
traefik.http.routers.jfvue-insecure.middlewares: jfvue-insecure-mw
traefik.http.middlewares.jfvue-insecure-mw.redirectscheme.scheme: https
traefik.http.middlewares.jfvue-insecure-mw.redirectscheme.permanent: false
traefik.http.routers.jfvue-insecure.service: noop@internal
environment:
- DEFAULT_SERVERS=https://jf.${DOMAIN_NAME}
- TZ=Etc/UTC
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- jfvue
- jfvue.internal
# traefik:
# aliases:
# - jfvue
# - jfvue.internal
plex:
container_name: plex
hostname: plex.internal
# domainname: lan
image: docker.io/plexinc/pms-docker:plexpass
restart: unless-stopped
depends_on:
- caddy
# - traefik
labels:
# Caddy Configuration
# caddy: plex.${DOMAIN_NAME}
# # [email protected]_ip: private_ranges
# caddy.import: headers
# caddy.import: encoding
# caddy.import: tls
# [email protected]_header: Connection *Upgrade*
# [email protected]_header: Upgrade websocket
# # caddy.0_reverse_proxy: "{{upstreams http 32400}}"
# # caddy.1_reverse_proxy: "@ws {{upstreams http 32400}}"
# caddy.0_reverse_proxy: "${PLEX_DIRECT_SSL_IP}.plex.direct:32400 https 32400"
# caddy.1_reverse_proxy: "@ws ${PLEX_DIRECT_SSL_IP}.plex.direct:32400 https 32400"
# # caddy.0_reverse_proxy: "{{${PLEX_DIRECT_SSL_IP}.plex.direct https 32400}}"
# # caddy.1_reverse_proxy: "@ws {{${PLEX_DIRECT_SSL_IP}.plex.direct https 32400}}"
# Traefik Configuration
traefik.enable: true
traefik.docker.network: traefik
## HTTP Router
traefik.http.routers.plex.entryPoints: https
traefik.http.routers.plex.rule: Host(`plex.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
traefik.http.routers.plex.tls: true
traefik.http.routers.plex.tls.certResolver: le
"traefik.http.routers.plex.tls.domains[0].main": plex.${DOMAIN_NAME}
"traefik.http.routers.plex.tls.domains[0].sans": plex.${DOMAIN_NAME}
## Middleware
traefik.http.routers.plex.middlewares: plex-mw
traefik.http.middlewares.plex-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
traefik.http.middlewares.plex-mw.headers.SSLRedirect: true
traefik.http.middlewares.plex-mw.headers.STSSeconds: 315360000
traefik.http.middlewares.plex-mw.headers.STSIncludeSubdomains: true
traefik.http.middlewares.plex-mw.headers.STSPreload: true
traefik.http.middlewares.plex-mw.headers.forceSTSHeader: true
traefik.http.middlewares.plex-mw.headers.frameDeny: true
traefik.http.middlewares.plex-mw.headers.contentTypeNosniff: true
traefik.http.middlewares.plex-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
traefik.http.routers.plex.service: plex-secure-internal-svc@file
# traefik.http.services.plex-svc.loadBalancer.server.url: https://${PLEX_DIRECT_SSL_IP}.plex.direct
# traefik.http.services.plex-svc.loadBalancer.server.port: 32400
# traefik.http.services.plex-svc.loadBalancer.passHostHeader: true
traefik.http.routers.plex-insecure.entryPoints: https
traefik.http.routers.plex-insecure.rule: Host(`plex.${DOMAIN_NAME}`)
traefik.http.routers.plex-insecure.middlewares: plex-insecure-mw
traefik.http.middlewares.plex-insecure-mw.redirectscheme.scheme: https
traefik.http.middlewares.plex-insecure-mw.redirectscheme.permanent: false
traefik.http.routers.plex-insecure.service: noop@internal
environment:
- HOSTNAME=plex.internal
- PLEX_UID=${PUID}
- PLEX_GID=${PGID}
- TZ=Etc/UTC
- PLEX_CLAIM=${PLEX_CLAIM_CODE}
- ADVERTISE_IP=https://plex.${DOMAIN_NAME}
# - VIRTUAL_HOST=plex.${DOMAIN_NAME}
# - VIRTUAL_PORT=443
# - VIRTUAL_PROTO=https
- CHANGE_CONFIG_DIR_OWNERSHIP=false
- ALLOWED_NETWORKS=${NETWORK_CADDY_SUBNET}.0/24,${NETWORK_TRAEFIK_SUBNET}.0/24
devices:
# Intel QuickSync
- /dev/dri:/dev/dri
volumes:
- ${BASE_DOCKER_DIR}/plex/config:/config:rw,z
- plex-transcode:/transcode:rw,Z
- nfs-data-ro:/data:ro,nocopy,z
ports:
- 32410:32410/udp # GDM Discovery
- 32412:32412/udp # GDM Discovery
- 32413:32413/udp # GDM Discovery
- 32414:32414/udp # GDM Discovery
- 32400:32400/tcp # Plex WebUI
# - 8324:8324/tcp # Roku
# - 5353:5353/udp # Bonjour/Avahi
# - 1900:1900/udp # DLNA
# - 32469:32469/tcp # DLNA
# - 3005:3005/tcp # ??
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- plex
- plex.internal
ipv4_address: ${NETWORK_CADDY_SUBNET}.25
# traefik:
# aliases:
# - plex
# - plex.internal
# ipv4_address: ${NETWORK_TRAEFIK_SUBNET}.25
prowlarr:
container_name: prowlarr
hostname: prowlarr.internal
image: ghcr.io/hotio/prowlarr:release
restart: unless-stopped
labels:
# Caddy Configuration
caddy: prowlarr.${DOMAIN_NAME}
[email protected]_ip: private_ranges
[email protected]_ip: private_ranges
caddy.import: docker
caddy.0_handle: "@internal"
caddy.1_handle: "@external"
caddy.0_handle.reverse_proxy: "{{upstreams http 9696}}"
caddy.0_handle.reverse_proxy.health_uri: /ping
caddy.0_handle.reverse_proxy.health_interval: 15s
caddy.1_handle.respond: /* "You are not permitted." 403
# Traefik Configuration
traefik.enable: true
traefik.docker.network: traefik
## HTTP Router
traefik.http.routers.prowlarr.entryPoints: https
traefik.http.routers.prowlarr.rule: Host(`prowlarr.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
traefik.http.routers.prowlarr.tls: true
traefik.http.routers.prowlarr.tls.certResolver: le
"traefik.http.routers.prowlarr.tls.domains[0].main": prowlarr.${DOMAIN_NAME}
"traefik.http.routers.prowlarr.tls.domains[0].sans": prowlarr.${DOMAIN_NAME}
## Middleware
traefik.http.routers.prowlarr.middlewares: prowlarr-mw
traefik.http.middlewares.prowlarr-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
traefik.http.middlewares.prowlarr-mw.headers.SSLRedirect: true
traefik.http.middlewares.prowlarr-mw.headers.STSSeconds: 315360000
traefik.http.middlewares.prowlarr-mw.headers.STSIncludeSubdomains: true
traefik.http.middlewares.prowlarr-mw.headers.STSPreload: true
traefik.http.middlewares.prowlarr-mw.headers.forceSTSHeader: true
traefik.http.middlewares.prowlarr-mw.headers.frameDeny: true
traefik.http.middlewares.prowlarr-mw.headers.contentTypeNosniff: true
traefik.http.middlewares.prowlarr-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
traefik.http.services.prowlarr-svc.loadBalancer.server.port: 9696
traefik.http.services.prowlarr-svc.loadBalancer.passHostHeader: true
traefik.http.services.prowlarr-svc.loadBalancer.healthCheck.path: /ping
traefik.http.services.prowlarr-svc.loadBalancer.healthCheck.interval: 15s
traefik.http.routers.prowlarr-insecure.entryPoints: https
traefik.http.routers.prowlarr-insecure.rule: Host(`prowlarr.${DOMAIN_NAME}`)
traefik.http.routers.prowlarr-insecure.middlewares: prowlarr-insecure-mw
traefik.http.middlewares.prowlarr-insecure-mw.redirectscheme.scheme: https
traefik.http.middlewares.prowlarr-insecure-mw.redirectscheme.permanent: false
traefik.http.routers.prowlarr-insecure.service: noop@internal
depends_on:
- caddy
# - traefik
- flaresolverr
environment:
- PUID=${PUID}
- PGID=${PGID}
- UMASK=002
- TZ=Etc/UTC
volumes:
- prowlarr:/config
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- prowlarr
- prowlarr.internal
# traefik:
# aliases:
# - prowlarr
# - prowlarr.internal
sonarr:
container_name: sonarr
image: ghcr.io/hotio/sonarr:release
restart: unless-stopped
labels:
# Caddy Configuration
caddy: sonarr.${DOMAIN_NAME}
[email protected]_ip: private_ranges
[email protected]_ip: private_ranges
caddy.import: docker
caddy.0_handle: "@internal"
caddy.1_handle: "@external"
caddy.0_handle.reverse_proxy: "{{upstreams http 8989}}"
caddy.0_handle.reverse_proxy.health_uri: /ping
caddy.0_handle.reverse_proxy.health_interval: 15s
caddy.1_handle.respond: /* "You are not permitted." 403
# Traefik Configuration
traefik.enable: true
traefik.docker.network: traefik
## HTTP Router
traefik.http.routers.sonarr.entryPoints: https
traefik.http.routers.sonarr.rule: Host(`sonarr.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
traefik.http.routers.sonarr.tls: true
traefik.http.routers.sonarr.tls.certResolver: le
"traefik.http.routers.sonarr.tls.domains[0].main": sonarr.${DOMAIN_NAME}
"traefik.http.routers.sonarr.tls.domains[0].sans": sonarr.${DOMAIN_NAME}
## Middleware
traefik.http.routers.sonarr.middlewares: sonarr-mw
traefik.http.middlewares.sonarr-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
traefik.http.middlewares.sonarr-mw.headers.SSLRedirect: true
traefik.http.middlewares.sonarr-mw.headers.STSSeconds: 315360000
traefik.http.middlewares.sonarr-mw.headers.STSIncludeSubdomains: true
traefik.http.middlewares.sonarr-mw.headers.STSPreload: true
traefik.http.middlewares.sonarr-mw.headers.forceSTSHeader: true
traefik.http.middlewares.sonarr-mw.headers.frameDeny: true
traefik.http.middlewares.sonarr-mw.headers.contentTypeNosniff: true
traefik.http.middlewares.sonarr-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
traefik.http.services.sonarr-svc.loadBalancer.server.port: 8989
traefik.http.services.sonarr-svc.loadBalancer.passHostHeader: true
traefik.http.services.sonarr-svc.loadBalancer.healthCheck.path: /ping
traefik.http.services.sonarr-svc.loadBalancer.healthCheck.interval: 15s
traefik.http.routers.sonarr-insecure.entryPoints: https
traefik.http.routers.sonarr-insecure.rule: Host(`sonarr.${DOMAIN_NAME}`)
traefik.http.routers.sonarr-insecure.middlewares: sonarr-insecure-mw
traefik.http.middlewares.sonarr-insecure-mw.redirectscheme.scheme: https
traefik.http.middlewares.sonarr-insecure-mw.redirectscheme.permanent: false
traefik.http.routers.sonarr-insecure.service: noop@internal
depends_on:
- caddy
# - traefik
environment:
- PUID=${PUID}
- PGID=${PGID}
- UMASK=002
- TZ=Etc/UTC
volumes:
- sonarr:/config:rw,Z
- nfs-data-rw:/data:rw,nocopy,z
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- sonarr
- sonarr.internal
# traefik:
# aliases:
# - sonarr
# - sonarr.internal
radarr:
container_name: radarr
hostname: radarr.internal
image: ghcr.io/hotio/radarr:release
restart: unless-stopped
labels:
# Caddy Configuration
caddy: radarr.${DOMAIN_NAME}
[email protected]_ip: private_ranges
[email protected]_ip: private_ranges
caddy.import: docker
caddy.0_handle: "@internal"
caddy.1_handle: "@external"
caddy.0_handle.reverse_proxy: "{{upstreams http 7878}}"
caddy.0_handle.reverse_proxy.health_uri: /ping
caddy.0_handle.reverse_proxy.health_interval: 15s
caddy.1_handle.respond: /* "You are not permitted." 403
# Traefik Configuration
traefik.enable: true
traefik.docker.network: traefik
## HTTP Router
traefik.http.routers.radarr.entryPoints: https
traefik.http.routers.radarr.rule: Host(`radarr.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
traefik.http.routers.radarr.tls: true
traefik.http.routers.radarr.tls.certResolver: le
"traefik.http.routers.radarr.tls.domains[0].main": radarr.${DOMAIN_NAME}
"traefik.http.routers.radarr.tls.domains[0].sans": radarr.${DOMAIN_NAME}
## Middleware
traefik.http.routers.radarr.middlewares: radarr-mw
traefik.http.middlewares.radarr-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
traefik.http.middlewares.radarr-mw.headers.SSLRedirect: true
traefik.http.middlewares.radarr-mw.headers.STSSeconds: 315360000
traefik.http.middlewares.radarr-mw.headers.STSIncludeSubdomains: true
traefik.http.middlewares.radarr-mw.headers.STSPreload: true
traefik.http.middlewares.radarr-mw.headers.forceSTSHeader: true
traefik.http.middlewares.radarr-mw.headers.frameDeny: true
traefik.http.middlewares.radarr-mw.headers.contentTypeNosniff: true
traefik.http.middlewares.radarr-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
traefik.http.services.radarr-svc.loadBalancer.server.port: 7878
traefik.http.services.radarr-svc.loadBalancer.passHostHeader: true
traefik.http.services.radarr-svc.loadBalancer.healthCheck.path: /ping
traefik.http.services.radarr-svc.loadBalancer.healthCheck.interval: 15s
traefik.http.routers.radarr-insecure.entryPoints: https
traefik.http.routers.radarr-insecure.rule: Host(`radarr.${DOMAIN_NAME}`)
traefik.http.routers.radarr-insecure.middlewares: radarr-insecure-mw
traefik.http.middlewares.radarr-insecure-mw.redirectscheme.scheme: https
traefik.http.middlewares.radarr-insecure-mw.redirectscheme.permanent: false
traefik.http.routers.radarr-insecure.service: noop@internal
depends_on:
- caddy
# - traefik
environment:
- PUID=${PUID}
- PGID=${PGID}
- UMASK=002
- TZ=Etc/UTC
volumes:
- radarr:/config:rw,Z
- nfs-data-rw:/data:rw,nocopy,z
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- radarr
- radarr.internal
# traefik:
# aliases:
#- radarr
#- radarr.internal
lidarr:
container_name: lidarr
hostname: lidarr.internal
image: ghcr.io/hotio/lidarr:release
restart: unless-stopped
depends_on:
- caddy
# - traefik
labels:
# Caddy Configuration
caddy: lidarr.${DOMAIN_NAME}
[email protected]_ip: private_ranges
[email protected]_ip: private_ranges
caddy.import: docker
# caddy.0_import: headers
# caddy.1_import: encoding
# caddy.2_import: tls
caddy.0_handle: "@internal"
caddy.1_handle: "@external"
caddy.0_handle.reverse_proxy: "{{upstreams http 8686}}"
caddy.0_handle.reverse_proxy.health_uri: /ping
caddy.0_handle.reverse_proxy.health_interval: 15s
caddy.1_handle.respond: /* "You are not permitted." 403
# Traefik Configuration
traefik.enable: true
traefik.docker.network: traefik
## HTTP Router
traefik.http.routers.lidarr.entryPoints: https
traefik.http.routers.lidarr.rule: Host(`lidarr.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
traefik.http.routers.lidarr.tls: true
traefik.http.routers.lidarr.tls.certResolver: le
"traefik.http.routers.lidarr.tls.domains[0].main": lidarr.${DOMAIN_NAME}
"traefik.http.routers.lidarr.tls.domains[0].sans": lidarr.${DOMAIN_NAME}
## Middleware
traefik.http.routers.lidarr.middlewares: lidarr-mw
traefik.http.middlewares.lidarr-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
traefik.http.middlewares.lidarr-mw.headers.SSLRedirect: true
traefik.http.middlewares.lidarr-mw.headers.STSSeconds: 315360000
traefik.http.middlewares.lidarr-mw.headers.STSIncludeSubdomains: true
traefik.http.middlewares.lidarr-mw.headers.STSPreload: true
traefik.http.middlewares.lidarr-mw.headers.forceSTSHeader: true
traefik.http.middlewares.lidarr-mw.headers.frameDeny: true
traefik.http.middlewares.lidarr-mw.headers.contentTypeNosniff: true
traefik.http.middlewares.lidarr-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
traefik.http.services.lidarr-svc.loadBalancer.server.port: 8686
traefik.http.services.lidarr-svc.loadBalancer.passHostHeader: true
traefik.http.services.lidarr-svc.loadBalancer.healthCheck.path: /ping
traefik.http.services.lidarr-svc.loadBalancer.healthCheck.interval: 15s
traefik.http.routers.lidarr-insecure.entryPoints: https
traefik.http.routers.lidarr-insecure.rule: Host(`lidarr.${DOMAIN_NAME}`)
traefik.http.routers.lidarr-insecure.middlewares: lidarr-insecure-mw
traefik.http.middlewares.lidarr-insecure-mw.redirectscheme.scheme: https
traefik.http.middlewares.lidarr-insecure-mw.redirectscheme.permanent: false
traefik.http.routers.lidarr-insecure.service: noop@internal
# ports:
# - "8686:8686"
environment:
- PUID=${PUID}
- PGID=${PGID}
- UMASK=002
- TZ=Etc/UTC
volumes:
- lidarr:/config:rw,Z
- nfs-data-rw:/data:rw,nocopy,z
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- lidarr
- lidarr.internal
# traefik:
# aliases:
# - lidarr
# - lidarr.internal
autobrr:
container_name: autobrr
hostname: autobrr.internal
image: ghcr.io/autobrr/autobrr:latest
restart: unless-stopped
labels:
# Caddy Configuration
caddy: autobrr.${DOMAIN_NAME}
[email protected]_ip: private_ranges
[email protected]_ip: private_ranges
caddy.import: docker
# caddy.0_import: headers
# caddy.1_import: encoding
# caddy.2_import: tls
caddy.0_handle: "@internal"
caddy.1_handle: "@external"
caddy.0_handle.reverse_proxy: "{{upstreams http 7474}}"
caddy.1_handle.respond: /* "You are not permitted." 403
# Traefik Configuration
traefik.enable: true
traefik.docker.network: traefik
## HTTP Router
traefik.http.routers.autobrr.entryPoints: https
traefik.http.routers.autobrr.rule: Host(`autobrr.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
traefik.http.routers.autobrr.tls: true
traefik.http.routers.autobrr.tls.certResolver: le
"traefik.http.routers.autobrr.tls.domains[0].main": autobrr.${DOMAIN_NAME}
"traefik.http.routers.autobrr.tls.domains[0].sans": autobrr.${DOMAIN_NAME}
## Middleware
traefik.http.routers.autobrr.middlewares: autobrr-mw
traefik.http.middlewares.autobrr-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
traefik.http.middlewares.autobrr-mw.headers.SSLRedirect: true
traefik.http.middlewares.autobrr-mw.headers.STSSeconds: 315360000
traefik.http.middlewares.autobrr-mw.headers.STSIncludeSubdomains: true
traefik.http.middlewares.autobrr-mw.headers.STSPreload: true
traefik.http.middlewares.autobrr-mw.headers.forceSTSHeader: true
traefik.http.middlewares.autobrr-mw.headers.frameDeny: true
traefik.http.middlewares.autobrr-mw.headers.contentTypeNosniff: true
traefik.http.middlewares.autobrr-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
traefik.http.services.autobrr-svc.loadBalancer.server.port: 7474
traefik.http.services.autobrr-svc.loadBalancer.passHostHeader: true
traefik.http.routers.autobrr-insecure.entryPoints: https
traefik.http.routers.autobrr-insecure.rule: Host(`autobrr.${DOMAIN_NAME}`)
traefik.http.routers.autobrr-insecure.middlewares: autobrr-insecure-mw
traefik.http.middlewares.autobrr-insecure-mw.redirectscheme.scheme: https
traefik.http.middlewares.autobrr-insecure-mw.redirectscheme.permanent: false
traefik.http.routers.autobrr-insecure.service: noop@internal
user: ${PUID}:${PGID}
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=UTC
- AUTOBRR__HOST=0.0.0.0
- AUTOBRR__LOG_LEVEL=INFO
volumes:
- autobrr:/config:rw,Z
ports:
- 7474:7474
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- autobrr
- autobrr.internal
# traefik:
# aliases:
# - autobrr
# - autobrr.internal
overseerr:
container_name: overseerr
hostname: overseerr.internal
image: docker.io/sctx/overseerr:latest
restart: unless-stopped
labels:
# Caddy Configuration
caddy: overseerr.${DOMAIN_NAME}
[email protected]_ip: private_ranges
[email protected]_ip: private_ranges
caddy.import: docker
# caddy.0_import: headers
# caddy.1_import: encoding
# caddy.2_import: tls
caddy.0_handle: "@internal"
caddy.1_handle: "@external"
caddy.0_handle.reverse_proxy: "{{upstreams http 5055}}"
caddy.1_handle.respond: /* "You are not permitted." 403
# Traefik Configuration
traefik.enable: true
traefik.docker.network: traefik
## HTTP Router
traefik.http.routers.overseerr.entryPoints: https
traefik.http.routers.overseerr.rule: Host(`overseerr.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
traefik.http.routers.overseerr.tls: true
traefik.http.routers.overseerr.tls.certResolver: le
"traefik.http.routers.overseerr.tls.domains[0].main": overseerr.${DOMAIN_NAME}
"traefik.http.routers.overseerr.tls.domains[0].sans": overseerr.${DOMAIN_NAME}
## Middleware
traefik.http.routers.overseerr.middlewares: overseerr-mw
traefik.http.middlewares.overseerr-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
traefik.http.middlewares.overseerr-mw.headers.SSLRedirect: true
traefik.http.middlewares.overseerr-mw.headers.STSSeconds: 315360000
traefik.http.middlewares.overseerr-mw.headers.STSIncludeSubdomains: true
traefik.http.middlewares.overseerr-mw.headers.STSPreload: true
traefik.http.middlewares.overseerr-mw.headers.forceSTSHeader: true
traefik.http.middlewares.overseerr-mw.headers.frameDeny: true
traefik.http.middlewares.overseerr-mw.headers.contentTypeNosniff: true
traefik.http.middlewares.overseerr-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
traefik.http.services.overseerr-svc.loadBalancer.server.port: 5055
traefik.http.services.overseerr-svc.loadBalancer.passHostHeader: true
traefik.http.services.overseerr-svc.loadBalancer.healthCheck.path: /api/v1/status
traefik.http.services.overseerr-svc.loadBalancer.healthCheck.interval: 15s
traefik.http.routers.overseerr-insecure.entryPoints: https
traefik.http.routers.overseerr-insecure.rule: Host(`overseerr.${DOMAIN_NAME}`)
traefik.http.routers.overseerr-insecure.middlewares: overseerr-insecure-mw
traefik.http.middlewares.overseerr-insecure-mw.redirectscheme.scheme: https
traefik.http.middlewares.overseerr-insecure-mw.redirectscheme.permanent: false
traefik.http.routers.overseerr-insecure.service: noop@internal
depends_on:
- caddy
# - traefik
environment:
- LOG_LEVEL=debug
- TZ=UTC
- PORT=5055 #optional
# ports:
# - 5055:5055
volumes:
- overseerr:/app/config:rw,Z
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- overseerr
- overseerr.internal
# traefik:
# aliases:
# - overseerr
# - overseerr.internal
#
# unpackerr:
# container_name: unpackerr
# hostname: unpackerr.internal
# image: ghcr.io/hotio/unpackerr:latest
# # image: docker.io/golift/unpackerr:latest
# restart: unless-stopped
# labels:
# caddy: unpackerr.${DOMAIN_NAME}
# [email protected]_ip: private_ranges
# [email protected]_ip: private_ranges
# caddy.import: docker
# caddy.0_import: headers
# caddy.1_import: encoding
# caddy.2_import: tls
# caddy.0_handle: "@internal"
# caddy.1_handle: "@external"
# caddy.0_handle.reverse_proxy: "{{upstreams http 5656}}"
# caddy.1_handle.respond: /* "You are not permitted." 403
# # user: ${PUID}:${PGID}
# environment:
# # General Config
# - UN_DEBUG=false
# - PUID=${PUID}
# - PGID=${PGID}
# - UMASK=002
# - TZ=Etc/UTC
# - UN_INTERVAL=2m
# - UN_START_DELAY=1m
# - UN_RETRY_DELAY=5m
# - UN_MAX_RETRIES=3
# - UN_PARALLEL=1
# - UN_FILE_MODE=0644
# - UN_DIR_MODE=0755
# # Sonarr Config
# - UN_SONARR_0_URL=http://sonarr:8989
# - UN_SONARR_0_API_KEY=${SONARR_API_KEY}
# - UN_SONARR_0_PATHS_0=/data/downloads/completed/sonarr
# - UN_SONARR_0_PROTOCOLS=torrent
# - UN_SONARR_0_TIMEOUT=10s
# - UN_SONARR_0_DELETE_ORIG=false
# # - UN_SONARR_0_DELETE_DELAY=5m
# # Radarr Config
# - UN_RADARR_0_URL=http://radarr:7878
# - UN_RADARR_0_API_KEY=${RADARR_API_KEY}
# - UN_RADARR_0_PATHS_0=/data/downloads/completed/radarr
# - UN_RADARR_0_PROTOCOLS=torrent
# - UN_RADARR_0_TIMEOUT=10s
# - UN_RADARR_0_DELETE_ORIG=false
# # - UN_RADARR_0_DELETE_DELAY=5m
# # Lidarr Config
# - UN_LIDARR_0_URL=http://lidarr:8686
# - UN_LIDARR_0_API_KEY=${LIDARR_API_KEY}
# - UN_LIDARR_0_PATHS_0=/data/downloads/completed/lidarr
# - UN_LIDARR_0_PROTOCOLS=torrent
# - UN_LIDARR_0_TIMEOUT=10s
# - UN_LIDARR_0_DELETE_ORIG=false
# # - UN_LIDARR_0_DELETE_DELAY=5m
# # Folder Config
# # - UN_FOLDER_0_PATH=
# # - UN_FOLDER_0_EXTRACT_PATH=
# - UN_FOLDER_0_DELETE_AFTER=0
# - UN_FOLDER_0_EXTRACT_ISOS=true
# - UN_FOLDER_0_DELETE_ORIGINAL=false
# - UN_FOLDER_0_DELETE_FILES=false
# - UN_FOLDER_0_MOVE_BACK=true
# # Web Server Config
# - UN_WEBSERVER_METRICS=true
# - UN_WEBSERVER_LISTEN_ADDR=0.0.0.0:5656
# - UN_WEBSERVER_URLBASE=/
# - UN_WEBSERVER_UPSTREAMS=${NETWORK_CADDY_SUBNET}.0/24,127.0.0.1/32,${NETWORK_HOME_SUBNET}.62/32
# security_opt:
# - no-new-privileges:true
# volumes:
# - unpackerr:/config:rw,Z
# - nfs-data-rw:/data:rw,z
# sysctls:
# - net.ipv6.conf.all.disable_ipv6=1
# networks:
# caddy:
# aliases:
# - unpackerr
flaresolverr:
# DockerHub mirror flaresolverr/flaresolverr:latest
container_name: flaresolverr
hostname: flaresolverr.internal
image: ghcr.io/flaresolverr/flaresolverr:latest
restart: unless-stopped
environment:
- LOG_LEVEL=info
- LOG_HTML=true
- CAPTCHA_SOLVER=none
- TZ=Etc/UTC
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- flaresolverr
- flaresolverr.internal
# traefik:
# aliases:
# - flaresolverr
# - flaresolverr.internal
tautulli:
container_name: tautulli
hostname: tautulli.internal
# domainname: lan
image: ghcr.io/tautulli/tautulli:latest
restart: unless-stopped
labels:
# Caddy Configuration
caddy: tautulli.${DOMAIN_NAME}
[email protected]_ip: private_ranges
[email protected]_ip: private_ranges
caddy.import: docker
caddy.0_handle: "@internal"
caddy.1_handle: "@external"
caddy.0_handle.reverse_proxy: "{{upstreams http 8181}}"
caddy.1_handle.respond: /* "You are not permitted." 403
# Traefik Configuration
traefik.enable: true
traefik.docker.network: traefik
## HTTP Router
traefik.http.routers.tautulli.entryPoints: https
traefik.http.routers.tautulli.rule: Host(`tautulli.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
traefik.http.routers.tautulli.tls: true
traefik.http.routers.tautulli.tls.certResolver: le
"traefik.http.routers.tautulli.tls.domains[0].main": tautulli.${DOMAIN_NAME}
"traefik.http.routers.tautulli.tls.domains[0].sans": tautulli.${DOMAIN_NAME}
## Middleware
traefik.http.routers.tautulli.middlewares: tautulli-mw
traefik.http.middlewares.tautulli-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
traefik.http.middlewares.tautulli-mw.headers.SSLRedirect: true
traefik.http.middlewares.tautulli-mw.headers.STSSeconds: 315360000
traefik.http.middlewares.tautulli-mw.headers.STSIncludeSubdomains: true
traefik.http.middlewares.tautulli-mw.headers.STSPreload: true
traefik.http.middlewares.tautulli-mw.headers.forceSTSHeader: true
traefik.http.middlewares.tautulli-mw.headers.frameDeny: true
traefik.http.middlewares.tautulli-mw.headers.contentTypeNosniff: true
traefik.http.middlewares.tautulli-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
traefik.http.services.tautulli-svc.loadBalancer.server.port: 8181
traefik.http.services.tautulli-svc.loadBalancer.passHostHeader: true
traefik.http.routers.tautulli-insecure.entryPoints: https
traefik.http.routers.tautulli-insecure.rule: Host(`tautulli.${DOMAIN_NAME}`)
traefik.http.routers.tautulli-insecure.middlewares: tautulli-insecure-mw
traefik.http.middlewares.tautulli-insecure-mw.redirectscheme.scheme: https
traefik.http.middlewares.tautulli-insecure-mw.redirectscheme.permanent: false
traefik.http.routers.tautulli-insecure.service: noop@internal
depends_on:
- plex
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=Etc/UTC
volumes:
- tautulli:/config:rw,Z
- ${BASE_DOCKER_DIR}/plex/config/Library/Application Support/Plex Media Server/Logs:/logs:ro,z
# ports:
# - 8181:8181
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- tautulli
- tautulli.internal
rflood:
container_name: rflood
hostname: rflood.internal
image: ghcr.io/hotio/rflood:release
restart: unless-stopped
labels:
# Caddy Configuration
caddy: dl.${DOMAIN_NAME}
[email protected]_ip: private_ranges
[email protected]_ip: private_ranges
caddy.import: docker
# caddy.0_import: headers
# caddy.1_import: encoding
# caddy.2_import: tls
caddy.0_handle: "@internal"
caddy.1_handle: "@external"
caddy.0_handle.reverse_proxy: "{{upstreams http 3000}}"
# caddy.0_handle.reverse_proxy.health_uri: /ping
# caddy.0_handle.reverse_proxy.health_interval: 15s
caddy.1_handle.respond: /* "You are not permitted." 403
# Traefik Configuration
traefik.enable: true
traefik.docker.network: traefik
## HTTP Router
traefik.http.routers.rflood.entryPoints: https
traefik.http.routers.rflood.rule: Host(`dl.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
traefik.http.routers.rflood.tls: true
traefik.http.routers.rflood.tls.certResolver: le
"traefik.http.routers.rflood.tls.domains[0].main": dl.${DOMAIN_NAME}
"traefik.http.routers.rflood.tls.domains[0].sans": dl.${DOMAIN_NAME}
## Middleware
traefik.http.routers.rflood.middlewares: rflood-mw
traefik.http.middlewares.rflood-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
traefik.http.middlewares.rflood-mw.headers.SSLRedirect: true
traefik.http.middlewares.rflood-mw.headers.STSSeconds: 315360000
traefik.http.middlewares.rflood-mw.headers.STSIncludeSubdomains: true
traefik.http.middlewares.rflood-mw.headers.STSPreload: true
traefik.http.middlewares.rflood-mw.headers.forceSTSHeader: true
traefik.http.middlewares.rflood-mw.headers.frameDeny: true
traefik.http.middlewares.rflood-mw.headers.contentTypeNosniff: true
traefik.http.middlewares.rflood-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
traefik.http.services.rflood-svc.loadBalancer.server.port: 3000
traefik.http.services.rflood-svc.loadBalancer.passHostHeader: true
# traefik.http.services.rflood-svc.loadBalancer.healthCheck.path: /ping
# traefik.http.services.rflood-svc.loadBalancer.healthCheck.interval: 15s
traefik.http.routers.rflood-insecure.entryPoints: https
traefik.http.routers.rflood-insecure.rule: Host(`dl.${DOMAIN_NAME}`)
traefik.http.routers.rflood-insecure.middlewares: rflood-insecure-mw
traefik.http.middlewares.rflood-insecure-mw.redirectscheme.scheme: https
traefik.http.middlewares.rflood-insecure-mw.redirectscheme.permanent: false
traefik.http.routers.rflood-insecure.service: noop@internal
# ports:
# - "3000:3000"
# - "8118:8118"
# - "5002:5000"
environment:
- PUID=${PUID}
- PGID=${PGID}
- UMASK=002
- TZ=Etc/UTC
- VPN_ENABLED=true
- VPN_PROVIDER=proton
- VPN_KEEP_LOCAL_DNS=true
- VPN_LAN_NETWORK=192.168.0.0/16,172.16.0.0/16
- VPN_CONF=wg0
- VPN_FIREWALL_TYPE=auto
- VPN_AUTO_PORT_FORWARD=true
- VPN_EXPOSE_PORTS_ON_LAN=7359/udp,8096/tcp,8920/tcp,1900/udp,3000/tcp,3000/udp,5432/tcp,5432/udp,32410/udp,32412/udp,32413/udp,32414/udp,32400/tcp,8324/tcp,9000/tcp,5353/udp,32469/tcp,3005/tcp,9696/tcp,8989/tcp,7878/tcp,7474/tcp,5055/tcp,8181/tcp,5000/tcp,5000/udp,8118/tcp,8118/udp,80/tcp,80/udp,443/tcp,443/udp
- PRIVOXY_ENABLED=false
- UNBOUND_ENABLED=true
- FLOOD_AUTH=false
volumes:
- ${BASE_DOCKER_DIR}/rflood:/config:rw,Z
- dsm-data-nfs-rw:/data:rw,nocopy,z
cap_add:
- NET_ADMIN
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
- net.ipv6.conf.all.disable_ipv6=1
devices:
- /dev/net/tun:/dev/net/tun
dns:
- ${DNS_SERVER_PRIMARY}
- ${DNS_SERVER_SECONDARY}
networks:
caddy:
aliases:
- rflood
- rflood.internal
#
# transmission:
# image: haugene/transmission-openvpn:latest
# container_name: transmission
# hostname: transmission.internal
# restart: unless-stopped
# cap_add:
# - NET_ADMIN
# - MKNOD
# labels:
# # Caddy Configuration
# caddy: transmission.${DOMAIN_NAME}
# [email protected]_ip: private_ranges
# [email protected]_ip: private_ranges
# caddy.import: docker
# caddy.0_handle: "@internal"
# caddy.1_handle: "@external"
# caddy.0_handle.reverse_proxy: "{{upstreams http 9091}}"
# # caddy.0_handle.reverse_proxy.health_uri: /ping
# # caddy.0_handle.reverse_proxy.health_interval: 15s
# caddy.1_handle.respond: /* "You are not permitted." 403
# # Traefik Configuration
# traefik.enable: true
# traefik.docker.network: traefik
# ## HTTP Router
# traefik.http.routers.transmission.entryPoints: https
# traefik.http.routers.transmission.rule: Host(`transmission.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
# traefik.http.routers.transmission.tls: true
# traefik.http.routers.transmission.tls.certResolver: le
# "traefik.http.routers.transmission.tls.domains[0].main": transmission.${DOMAIN_NAME}
# "traefik.http.routers.transmission.tls.domains[0].sans": transmission.${DOMAIN_NAME}
# ## Middleware
# traefik.http.routers.transmission.middlewares: transmission-mw
# traefik.http.middlewares.transmission-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
# traefik.http.middlewares.transmission-mw.headers.SSLRedirect: true
# traefik.http.middlewares.transmission-mw.headers.STSSeconds: 315360000
# traefik.http.middlewares.transmission-mw.headers.STSIncludeSubdomains: true
# traefik.http.middlewares.transmission-mw.headers.STSPreload: true
# traefik.http.middlewares.transmission-mw.headers.forceSTSHeader: true
# traefik.http.middlewares.transmission-mw.headers.frameDeny: true
# traefik.http.middlewares.transmission-mw.headers.contentTypeNosniff: true
# traefik.http.middlewares.transmission-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
# traefik.http.services.transmission-svc.loadBalancer.server.port: 9091
# traefik.http.services.transmission-svc.loadBalancer.passHostHeader: true
# # traefik.http.services.transmission-svc.loadBalancer.healthCheck.path: /ping
# # traefik.http.services.transmission-svc.loadBalancer.healthCheck.interval: 15s
# traefik.http.routers.transmission-insecure.entryPoints: https
# traefik.http.routers.transmission-insecure.rule: Host(`dltest.${DOMAIN_NAME}`)
# traefik.http.routers.transmission-insecure.middlewares: transmission-insecure-mw
# traefik.http.middlewares.transmission-insecure-mw.redirectscheme.scheme: https
# traefik.http.middlewares.transmission-insecure-mw.redirectscheme.permanent: false
# traefik.http.routers.transmission-insecure.service: noop@internal
# volumes:
# - /var/data/dsm2/data/downloads:/data:rw,z
# - ${BASE_DOCKER_DIR}/transmission/config:/config:rw,Z
# - ${BASE_DOCKER_DIR}/transmission/vpn:/etc/openvpn/custom:rw,Z
# environment:
# PUID: 1000
# PGID: 100
# OPENVPN_PROVIDER: custom
# OPENVPN_CONFIG: my-openvpn-config.udp
# OPENVPN_OPTS: --inactive 3600 --ping 10 --ping-exit 300 --mute-replay-warnings
# PEER_DNS: true
# LOCAL_NETWORK: 192.168.0.0/16,172.16.0.0/16
# CREATE_TUN_DEVICE: false
# TZ: UTC
# LOG_TO_STDOUT: true
# GLOBAL_APPLY_PERMISSIONS: false
# TRANSMISSION_WEB_UI: flood-for-transmission
# TRANSMISSION_DOWNLOAD_DIR: /data/downloads/completed
# TRANSMISSION_INCOMPLETE_DIR: /data/downloads/incomplete
# TRANSMISSION_WATCH_DIR: /data/downloads/watch
# # TRANSMISSION_SCRAPE_PAUSED_TORRENTS_ENABLED: false
# # TRANSMISSION_WATCH_DIR_FORCE_GENERIC: true
# DROP_DEFAULT_ROUTE: true
# UFW_ALLOW_GW_NET: false
# ENABLE_UFW: true
# # UFW_EXTRA_PORTS: 443,80
# UFW_DISABLE_IPTABLES_REJECT: false
# HEALTH_CHECK_HOST: icanhazip.com
# # logging:
# # driver: local
# devices:
# - /dev/net/tun:/dev/net/tun
# sysctls:
# - net.ipv6.conf.all.disable_ipv6=1
# # ports:
# # - 9091:9091
# dns:
# - ${DNS_SERVER_PRIMARY}
# - ${DNS_SERVER_SECONDARY}
# networks:
# caddy:
# aliases:
# - transmission
# - transmission.internal
# - torrents
# - torrents.internal
# traefik:
# aliases:
# - tautulli
#
# ntfy:
# image: docker.io/binwiederhier/ntfy:latest
# container_name: ntfy
# hostname: ntfy.internal
# labels:
# caddy: ntfy.${DOMAIN_NAME}
# caddy.import: docker
# caddy.0_import: headers
# caddy.1_import: encoding
# caddy.2_import: tls
# [email protected]_header: Connection *Upgrade*
# [email protected]_header: Upgrade websocket
# caddy.0_reverse_proxy: "{{upstreams http 80}}"
# caddy.1_reverse_proxy: "@ws {{upstreams http 80}}"
# command:
# - serve
# environment:
# - PUID=${PUID}
# - PGID=${PGID}
# - TZ=UTC # optional: set desired timezone
# - NTFY_BASE_URL=https://ntfy.${DOMAIN_NAME}
# - NTFY_CACHE_FILE=/var/lib/ntfy/cache.db
# - NTFY_AUTH_FILE=/var/lib/ntfy/auth.db
# - NTFY_AUTH_DEFAULT_ACCESS=deny-all
# - NTFY_BEHIND_PROXY=true
# - NTFY_ATTACHMENT_CACHE_DIR=/var/lib/ntfy/attachments
# - NTFY_ENABLE_LOGIN=true
# - NTFY_UPSTREAM_BASE_URL=https://ntfy.sh
# - NTFY_VISITOR_REQUEST_LIMIT_EXEMPT_HOSTS=127.0.0.1,${HOME_NETWORK_SUBNET}.5,localhost,sonarr,radarr,lidarr,prowlarr,plex,jellyfin,tautulli
# # - NTFY_WEB_PUSH_PUBLIC_KEY=<public_key>
# # - NTFY_WEB_PUSH_PRIVATE_KEY=<private_key>
# # - NTFY_WEB_PUSH_FILE=/var/lib/ntfy/webpush.db
# # - NTFY_WEB_PUSH_EMAIL_ADDRESS=<email>
# user: ${PUID}:${PGID} # optional: replace with your own user/group or uid/gid
# volumes:
# - ntfy-config:/var/lib/ntfy
# # ports:
# # - 80:80
# healthcheck:
# # optional: remember to adapt the host:port to your environment
# test:
# [
# "CMD-SHELL",
# "wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Eo '\"healthy\"\\s*:\\s*true' || exit 1"
# ]
# interval: 60s
# timeout: 10s
# retries: 3
# start_period: 40s
# restart: unless-stopped
# sysctls:
# - net.ipv6.conf.all.disable_ipv6=1
# networks:
# caddy:
# aliases:
# - ntfy
# - ntfy.internal
# znc:
# image: lscr.io/linuxserver/znc:latest
# container_name: znc
# hostname: znc.internal
# restart: unless-stopped
# labels:
# caddy: znc.${DOMAIN_NAME}
# [email protected]_ip: private_ranges
# [email protected]_ip: private_ranges
# caddy.import: docker
# caddy.0_import: headers
# caddy.1_import: encoding
# caddy.2_import: tls
# caddy.0_handle: "@internal"
# caddy.1_handle: "@external"
# caddy.0_handle.reverse_proxy: "{{upstreams http 6501}}"
# caddy.1_handle.respond: /* "You are not permitted." 403
# environment:
# - PUID=${PUID}
# - PGID=${PGID}
# - TZ=Etc/UTC
# volumes:
# - znc:/config:rw,Z
# ports:
# - 6501:6501
# sysctls:
# - net.ipv6.conf.all.disable_ipv6=1
# networks:
# caddy:
# aliases:
# - znc
# - znc.internal
portainer:
container_name: portainer
hostname: portainer.internal
image: docker.io/portainer/portainer-ce:latest
restart: unless-stopped
privileged: true
labels:
# Caddy Configuration
caddy: portainer.${DOMAIN_NAME}
[email protected]_ip: private_ranges
[email protected]_ip: private_ranges
caddy.import: docker
caddy.0_handle: "@internal"
caddy.1_handle: "@external"
caddy.0_handle.reverse_proxy: "{{upstreams http 9000}}"
caddy.1_handle.respond: /* "You are not permitted." 403
# Traefik Configuration
traefik.enable: true
traefik.docker.network: traefik
## HTTP Router
traefik.http.routers.portainer.entryPoints: https
traefik.http.routers.portainer.rule: Host(`portainer.${DOMAIN_NAME}`) # OPTIONAL: && PathPrefix(`/jellyfin`)
traefik.http.routers.portainer.tls: true
traefik.http.routers.portainer.tls.certResolver: le
"traefik.http.routers.portainer.tls.domains[0].main": portainer.${DOMAIN_NAME}
"traefik.http.routers.portainer.tls.domains[0].sans": portainer.${DOMAIN_NAME}
## Middleware
traefik.http.routers.portainer.middlewares: portainer-mw
traefik.http.middlewares.portainer-mw.headers.customResponseHeaders.X-Robots-Tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex
traefik.http.middlewares.portainer-mw.headers.SSLRedirect: true
traefik.http.middlewares.portainer-mw.headers.STSSeconds: 315360000
traefik.http.middlewares.portainer-mw.headers.STSIncludeSubdomains: true
traefik.http.middlewares.portainer-mw.headers.STSPreload: true
traefik.http.middlewares.portainer-mw.headers.forceSTSHeader: true
traefik.http.middlewares.portainer-mw.headers.frameDeny: true
traefik.http.middlewares.portainer-mw.headers.contentTypeNosniff: true
traefik.http.middlewares.portainer-mw.headers.customresponseheaders.X-XSS-PROTECTION: 0
traefik.http.services.portainer-svc.loadBalancer.server.port: 9000
traefik.http.services.portainer-svc.loadBalancer.passHostHeader: true
traefik.http.routers.portainer-insecure.entryPoints: https
traefik.http.routers.portainer-insecure.rule: Host(`portainer.${DOMAIN_NAME}`)
traefik.http.routers.portainer-insecure.middlewares: portainer-insecure-mw
traefik.http.middlewares.portainer-insecure-mw.redirectscheme.scheme: https
traefik.http.middlewares.portainer-insecure-mw.redirectscheme.permanent: false
traefik.http.routers.portainer-insecure.service: noop@internal
depends_on:
- caddy
# - traefik
environment:
- TZ=UTC
# ports:
# - 9443:9443
# - 9000:9000
# - 8000:8000
volumes:
- ${DOCKER_SOCK_PATH}:/var/run/docker.sock
- portainer_data:/data:rw,Z
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
networks:
caddy:
aliases:
- portainer
# traefik:
# aliases:
# - portainer
volumes:
# NFS media mounts read+write
nfs-data-rw:
driver_opts:
type: nfs
o: addr=${DSM_SERVER_IP},clientaddr=${NFS_CLIENT_IP},nfsvers=4.1,rw,noatime,noacl,nocto,rsize=65536,wsize=65536,tcp,port=0,soft,nolock,noexec,timeo=300,retrans=3
device: :${DSM_NFS_MOUNT_PATH}
# NFS media mounts read-only
nfs-data-ro:
driver_opts:
type: nfs
o: addr=${DSM_SERVER_IP},clientaddr=${NFS_CLIENT_IP},nfsvers=4.1,ro,noatime,noacl,nocto,rsize=65536,wsize=65536,tcp,port=0,soft,nolock,noexec,timeo=300,retrans=3
device: :${DSM_NFS_MOUNT_PATH}
caddy_data:
external: true
caddy_config:
external: true
tautulli:
external: true
jellyfin-cache:
external: true
plex-transcode:
external: true
radarr:
external: true
sonarr:
external: true
lidarr:
external: true
prowlarr:
external: true
overseerr:
external: true
autobrr:
external: true
portainer_data:
external: true
# unpackerr:
# external: true
# znc:
# external: true
# ntfy-cache:
# external: true
# ntfy-config:
# external: true
# autoscan:
# external: true
# transmission:
# external: true
# pihole_data:
# external: true
# dnsmasq_data:
# external: true
networks:
caddy:
name: caddy
driver: bridge
ipam:
config:
- subnet: ${NETWORK_CADDY_SUBNET}.0/24
gateway: ${NETWORK_CADDY_SUBNET}.1
traefik:
name: traefik
driver: bridge
ipam:
config:
- subnet: ${NETWORK_TRAEFIK_SUBNET}.0/24
gateway: ${NETWORK_TRAEFIK_SUBNET}.1
data:
name: data
driver: bridge
ipam:
config:
- subnet: ${NETWORK_DATA_SUBNET}.0/24
gateway: ${NETWORK_DATA_SUBNET}.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment