services: gluetun: image: qmcgaw/gluetun:latest container_name: gluetun cap_add: - NET_ADMIN devices: - /dev/net/tun:/dev/net/tun environment: - VPN_SERVICE_PROVIDER=protonvpn # Or mullvad, protonvpn, surfshark, etc. - VPN_TYPE=wireguard # WireGuard, openvpn - HTTP_CONTROL_SERVER=ON - HTTP_CONTROL_SERVER_AUTH_DEFAULT_ROLE='{"auth":"apikey","apikey":"${GLUETUN_KEY}"}' # generate by running `docker run --rm qmcgaw/gluetun genkey`, then adding this to your `.env` file - WIREGUARD_PRIVATE_KEY=${VPN_PRIVATE_KEY} - WIREGUARD_MTU=1280 - VPN_PORT_FORWARDING=on - VPN_PORT_FORWARDING_PROVIDER=protonvpn #- OPENVPN_USER=user #- OPENVPN_PASSWORD=password - SERVER_COUNTRIES=Netherlands # choose fast P2P friendly countries - NETWORK_LOCAL_ADDRESSES=192.168.50.0/24,172.16.0.0/12 - FIREWALL_OUTBOUND_SUBNETS=192.168.50.0/24 - TZ=${TIMEZONE} - DNS_UPSTREAM_RESOLVER_TYPE=doh # DNS over TLS is an extra layer of security so your isp can not look at what you're doing through your DNS requests, even if your using a vpn (very vague, I don't know how this syustem works with a vpn). ports: # YOU MUST SPECIFY A PORT PER SERVICE ROUTED THROUGH GLUETUN! - 8888:8000/tcp # gluetun control server, i dont think you should change this - 6881:6881 # Default port for qbit - 6881:6881/udp # Default port for qbit, if udp > tcp - ${QBITTORRENT_PORT}:${QBITTORRENT_PORT} # qBittorrent Web UI - ${PROWLARR_PORT}:${PROWLARR_PORT} # Prowlarr - ${SONARR_PORT}:${SONARR_PORT} # Sonarr - ${RADARR_PORT}:${RADARR_PORT} # Radarr - ${LIDARR_PORT}:${LIDARR_PORT} # Lidarr #- ${SEERR_PORT}:${SEERR_PORT}/tcp # Seerr # took this out of gluetun, as it could cause issues with starting the container, and it was unecessary healthcheck: test: wget --spider -q http://1.1.1.1 || exit 1 interval: 30s timeout: 15s retries: 3 start_period: 1m volumes: - ./gluetun-data:/tmp/gluetun:rw extra_hosts: - "host.docker.internal:host-gateway" # host-gateway is a docker variable that automatically grabs the 172.XX.0.1 address, this is to be used by prowlarr to communicate with sonarr and radarr. restart: always qbittorrent: image: lscr.io/linuxserver/qbittorrent:latest container_name: qbittorrent network_mode: "container:gluetun" # vpn bunker environment: - PUID=1000 - PGID=1000 - TZ=${TIMEZONE} - WEBUI_PORT=${QBITTORRENT_PORT} volumes: - ./qbittorrent:/config - ${DISK1}:${DISK1} - ${DISK2}:${DISK2} - ./gluetun-data:/tmp/gluetun - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro labels: - "autoheal=true" depends_on: gluetun: condition: service_healthy healthcheck: # if gluetun is slow to start, it's over test: ["CMD-SHELL", wget --spider -q https://1.1.1.1 || exit 1] # use 1.1.1.1, we don't need dns around here interval: 1m timeout: 10s retries: 3 start_period: 30s restart: unless-stopped port-updater: # use an image that already has curl/wget to skip the 'apk add' step image: curlimages/curl:latest container_name: port-updater volumes: - ./gluetun-data:/tmp/gluetun:ro # using 'exec' format and 'trap' allows the container to stop instantly entrypoint: ["/bin/sh", "-c"] command: # loololloloolol gemini did this for me - | trap 'exit 0' SIGTERM; while true; do # 1. Wait for Gluetun to actually create the file with a number while [ ! -s /tmp/gluetun/forwarded_port ]; do echo "Waiting for Gluetun to provide a port..." sleep 5 done # 2. Read and clean the port read -r PORT_VAL < /tmp/gluetun/forwarded_port; CLEAN_PORT=$$(echo "$$PORT_VAL" | tr -d '\r\n '); # 3. Only update if the port isn't empty if [ -n "$$CLEAN_PORT" ]; then echo "Updating qBit to port: $$CLEAN_PORT"; sleep 10; echo "Updated to $$CLEAN_PORT" curl -s -X POST -d "json={\"listen_port\":$$CLEAN_PORT}" http://localhost:${QBITTORRENT_PORT}/api/v2/app/setPreferences; # 4. Success! Now sleep for a long time (e.g., 1 hour) sleep 3600 & wait $$!; else # If for some reason it's still blank, retry quickly sleep 10 fi done labels: - "autoheal=true" network_mode: "container:gluetun" depends_on: gluetun: condition: service_healthy healthcheck: test: ["CMD-SHELL", "curl -f https://1.1.1.1 || exit 1"] interval: 1m timeout: 10s retries: 3 start_period: 30s restart: always prowlarr: image: lscr.io/linuxserver/prowlarr:latest container_name: prowlarr environment: - PUID=1000 - PGID=1000 - TZ=${TIMEZONE} volumes: - ./prowlarr:/config - ./notify.sh:/notify.sh:ro - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro labels: - "autoheal=true" network_mode: "container:gluetun" depends_on: gluetun: condition: service_healthy healthcheck: test: ["CMD-SHELL", wget --spider -q https://google.com || exit 1] # needs DNS interval: 5m timeout: 60s retries: 3 start_period: 30s restart: always sonarr: image: lscr.io/linuxserver/sonarr:latest container_name: sonarr environment: - PUID=1000 - PGID=1000 - TZ=${TIMEZONE} volumes: - /var/lib/sonarr:/config # had migrated into docker compose - ${DISK1}:${DISK1} - ${DISK2}:${DISK2} - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro labels: - "autoheal=true" network_mode: "container:gluetun" depends_on: gluetun: condition: service_healthy healthcheck: test: ["CMD-SHELL", "curl -f http://1.1.1.1 || exit 1"] interval: 5m timeout: 60s retries: 3 start_period: 60s restart: always radarr: image: lscr.io/linuxserver/radarr:latest container_name: radarr environment: - PUID=1000 - PGID=1000 - TZ=${TIMEZONE} volumes: - /var/lib/radarr:/config # had migrated into docker compose - ${DISK1}:${DISK1} - ${DISK2}:${DISK2} - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro labels: - "autoheal=true" network_mode: "container:gluetun" depends_on: gluetun: condition: service_healthy healthcheck: test: ["CMD-SHELL", "curl -f http://1.1.1.1 || exit 1"] interval: 1m timeout: 10s retries: 3 start_period: 30s restart: always lidarr: image: lscr.io/linuxserver/lidarr:latest container_name: lidarr environment: - PUID=1000 - PGID=1000 - TZ=${TIMEZONE} volumes: - /home/shaan/torrent-stack/lidarr:/music - /var/lib/lidarr:/config - ${DISK1}:${DISK1} - ${DISK2}:${DISK2} - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro labels: - "autoheal=true" network_mode: "container:gluetun" depends_on: gluetun: condition: service_healthy healthcheck: test: ["CMD-SHELL", "curl -f http://1.1.1.1 || exit 1"] interval: 1m timeout: 10s retries: 3 start_period: 30s restart: unless-stopped tautulli: # has no network bridge between containers. this is fine, as it only needs to get from plex, which is outside this container image: ghcr.io/tautulli/tautulli container_name: tautulli volumes: #- /mnt/media/media:/config - ./tautulli:/config environment: - PUID=1000 - PGID=1000 - TZ=${TIMEZONE} ports: - ${TAUTULLI_PORT}:${TAUTULLI_PORT} restart: always tdarr: container_name: tdarr image: haveagitgat/tdarr:latest networks: - tdarr-net ports: - ${TDARR_PORT}:${TDARR_PORT} # WebUI - ${TDARR_NODE_PORT}:${TDARR_NODE_PORT} # local tdarr-node environment: - TZ=${TIMEZONE} - PUID=1000 - PGID=1000 - UMASK_SET=002 - serverIP=0.0.0.0 volumes: - ./tdarr/server:/app/server - ./tdarr/configs:/app/configs - ./tdarr/temp:/temp - ${DISK1}:${DISK1} - ${DISK2}:${DISK2} # dont put temp files onto a HARD DISK DRIVE! > - ${DISK1}/tdarr-temp:/temp devices: - /dev/dri:/dev/dri # Intel UHD Graphics 710 restart: always tdarr-node: container_name: tdarr-node image: haveagitgat/tdarr_node:latest networks: - tdarr-net environment: - TZ=${TIMEZONE} - PUID=1000 - PGID=1000 - nodeID=${TDARR_NODE_ID} - nodeIP=0.0.0.0 - serverIP=tdarr # Points to the server container - serverPort=${TDARR_NODE_PORT} volumes: - ./tdarr/configs:/app/configs - ./tdarr/logs:/app/logs - /home/shaan/torrent-stack/tdarr/temp:/temp - ${DISK1}:${DISK1} - ${DISK2}:${DISK2} devices: - /dev/dri:/dev/dri # only works if user 'shaan' is a part of the 'video' or 'render' group. restart: always homepage: image: ghcr.io/gethomepage/homepage:latest container_name: homepage ports: - ${HOMEPAGE_PORT}:${HOMEPAGE_PORT} volumes: - ./homepage:/app/config - ./homepage/images:/app/public/images - /var/run/docker.sock:/var/run/docker.sock:ro # (optional) For docker integrations - ./gluetun-data:/tmp/gluetun:ro # get the port from port-updater - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro environment: - "HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev,${LOCAL_IPV4}:${HOMEPAGE_PORT},${SERVER_NAME}:${HOMEPAGE_PORT},100.76.249.110:${HOMEPAGE_PORT},${SERVER_NAME}.tail:${HOMEPAGE_PORT},${EXTERNAL_IPV4}:${HOMEPAGE_PORT},${WEB_NAME}:${HOMEPAGE_PORT},${WEB_NAME},172.17.0.1:${HOMEPAGE_PORT}" # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts - "HOMEPAGE_VAR_DISK1=${DISK1}" - "HOMEPAGE_VAR_DISK2=${DISK2}" - "HOMEPAGE_VAR_DISK3=${DISK3}" - "HOMEPAGE_VAR_WEB_PROTOCOL=${WEB_PROTOCOL}" - "HOMEPAGE_VAR_LOCAL_IPV4=${LOCAL_IPV4}" - "HOMEPAGE_VAR_SERVER_NAME=${SERVER_NAME}" - "HOMEPAGE_VAR_PLEX_KEY=${PLEX_KEY}" - "HOMEPAGE_VAR_PROWLARR_KEY=${PROWLARR_KEY}" - "HOMEPAGE_VAR_RADARR_KEY=${RADARR_KEY}" - "HOMEPAGE_VAR_SONARR_KEY=${SONARR_KEY}" - "HOMEPAGE_VAR_LIDARR_KEY=${LIDARR_KEY}" - "HOMEPAGE_VAR_TAUTULLI_KEY=${TAUTULLI_KEY}" - "HOMEPAGE_VAR_SEERR_KEY=${SEERR_KEY}" - "HOMEPAGE_VAR_QBITTORRENT_KEY=${QBITTORRENT_KEY}" - "HOMEPAGE_VAR_TAILSCALE_KEY=${TAILSCALE_KEY}" - "HOMEPAGE_VAR_TAILSCALE_DEVICE_KEY=${TAILSCALE_DEVICE_KEY}" - "HOMEPAGE_VAR_PLEX_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${PLEX_PORT}" - "HOMEPAGE_VAR_QBITTORRENT_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${QBITTORRENT_PORT}" - "HOMEPAGE_VAR_PROWLARR_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${PROWLARR_PORT}" - "HOMEPAGE_VAR_SONARR_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${SONARR_PORT}" - "HOMEPAGE_VAR_RADARR_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${RADARR_PORT}" - "HOMEPAGE_VAR_LIDARR_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${LIDARR_PORT}" - "HOMEPAGE_VAR_TAUTULLI_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${TAUTULLI_PORT}" - "HOMEPAGE_VAR_TDARR_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${TDARR_PORT}" - "HOMEPAGE_VAR_HOMEPAGE_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${HOMEPAGE_PORT}" - "HOMEPAGE_VAR_GLANCES_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${GLANCES_PORT}" - "HOMEPAGE_VAR_SEERR_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${SEERR_PORT}" - "HOMEPAGE_VAR_MYSPEED_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${MYSPEED_PORT}" - "HOMEPAGE_VAR_TERMIX_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${TERMIX_PORT}" - "HOMEPAGE_VAR_PLEX_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${PLEX_PORT}" - "HOMEPAGE_VAR_QBITTORRENT_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${QBITTORRENT_PORT}" - "HOMEPAGE_VAR_PROWLARR_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${PROWLARR_PORT}" - "HOMEPAGE_VAR_SONARR_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${SONARR_PORT}" - "HOMEPAGE_VAR_RADARR_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${RADARR_PORT}" - "HOMEPAGE_VAR_LIDARR_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${LIDARR_PORT}" - "HOMEPAGE_VAR_TAUTULLI_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${TAUTULLI_PORT}" - "HOMEPAGE_VAR_TDARR_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${TDARR_PORT}" - "HOMEPAGE_VAR_HOMEPAGE_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${HOMEPAGE_PORT}" - "HOMEPAGE_VAR_GLANCES_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${GLANCES_PORT}" - "HOMEPAGE_VAR_SEERR_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${SEERR_PORT}" - "HOMEPAGE_VAR_MYSPEED_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${MYSPEED_PORT}" - "HOMEPAGE_VAR_TERMIX_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${TERMIX_PORT}" - TZ=${TIMEZONE} extra_hosts: - "host.docker.internal:host-gateway" #networks: # staticaddress: # ipv4_address: 172.200.0.2 restart: always glances: image: nicolargo/glances:latest-full container_name: glances pid: host network_mode: host devices: - /dev/dri:/dev/dri volumes: - /var/run/docker.sock:/var/run/docker.sock - /etc/os-release:/etc/os-release:ro - /:/host:ro - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro environment: - GLANCES_OPT=-w - PUID=1000 - PGID=1000 - TZ=${TIMEZONE} restart: unless-stopped autoheal: image: willfarrell/autoheal:latest container_name: autoheal environment: - AUTOHEAL_CONTAINER_LABEL=all - AUTOHEAL_INTERVAL=30 - AUTOHEAL_START_PERIOD=60 volumes: - /var/run/docker.sock:/var/run/docker.sock - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro restart: always seerr: image: ghcr.io/seerr-team/seerr:latest init: true container_name: seerr ports: - 5055:${SEERR_PORT} environment: - LOG_LEVEL=debug - TZ=America/Los_Angeles - PUID=1000 - PGID=1000 volumes: - "./seerr:/app/config" - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro working_dir: "/app" labels: - "autoheal=true" healthcheck: test: ["CMD-SHELL", "wget --spider -q http://1.1.1.1 || exit 1"] interval: 1m timeout: 10s retries: 3 start_period: 60s restart: unless-stopped MySpeed: command: - "node" - "server" container_name: "MySpeed" entrypoint: - "docker-entrypoint.sh" environment: - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - "NODE_VERSION=18.20.3" - "YARN_VERSION=1.22.19" - "NODE_ENV=production" - TZ=${TIMEZONE} hostname: "4b5e3178fcc4" image: "germannewsmaker/myspeed" ipc: "private" logging: driver: "json-file" options: {} mac_address: "02:42:ac:11:00:03" network_mode: "bridge" ports: - "${MYSPEED_PORT}:${MYSPEED_PORT}/tcp" volumes: - "myspeed:/myspeed/data" - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro working_dir: "/myspeed" restart: unless-stopped termix: image: ghcr.io/lukegus/termix:latest container_name: termix cap_add: - NET_ADMIN - SYS_ADMIN ports: - "${TERMIX_PORT}:${TERMIX_PORT}" volumes: - termix-data:/app/data environment: - "PORT: ${TERMIX_PORT}" - "TZ: {TIMEZONE}" networks: - termix-net restart: unless-stopped # pihole: # container_name: pihole # image: pihole/pihole:latest # network_mode: "host" # ports: # - "53:53/tcp" # - "53:53/udp" # - "67:67/udp" # - "80:80/tcp" # environment: # TZ: "America/Los_Angeles" # #WEBPASSWORD: "password123" # volumes: # - "./etc-pihole:/etc/pihole" # - "./etc-dnsmasq.d:/etc/dnsmasq.d" # - /etc/localtime:/etc/localtime:ro # - /etc/timezone:/etc/timezone:ro # cap_add: # - NET_ADMIN # restart: unless-stopped cloudflared: container_name: cloudflared-tunnel image: cloudflare/cloudflared:latest restart: always command: tunnel --no-autoupdate run --token eyJhIjoiMjUyZjQ3MWZkMzE2ZTg5NjI2ZjEzYzI1YzYwMTJiYzciLCJ0IjoiNWFhMDJlNmEtNDE2Ni00YTJkLTk1YzktMGFmMGY3MjM3YjIzIiwicyI6Ik5tWmhOR1V6WVRZdE5HRXdOaTAwT1RjekxXSTFPV1V0T0RrMU1UWTRabVl4WkRZeCJ9 torrents-csv: image: dessalines/torrents-csv-server:latest restart: unless-stopped ports: - "8902:8902" environment: TORRENTS_CSV_DB_HOST: "postgres://postgres:password@db" TORRENTS_CSV_FRONT_END_DIR: /app/dist RUST_LOG: DEBUG TIMEZONE: ${TIMEZONE} depends_on: - db # search at 'http://shaan-server:8902/service/search?q={SEARCH_TERM' db: image: pgautoupgrade/pgautoupgrade:17-alpine restart: unless-stopped shm_size: 1gb volumes: - ./init-database.sh:/docker-entrypoint-initdb.d/init-database.sh - ./init-database.sql:/var/lib/postgresql/init-database.sql - ./torrents.csv:/var/lib/postgresql/torrents.csv - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro ports: - "127.0.0.1:5433:5432" environment: POSTGRES_PASSWORD: password POSTGRES_USER: postgres TIMEZONE: ${TIMEZONE} # caddy: # build: # context: . # dockerfile_inline: | # FROM caddy:2.11-builder AS builder # RUN xcaddy build --with github.com/caddyserver/nginx-adapter --with github.com/caddy-dns/cloudflare # FROM caddy:2.11-builder # COPY --from=builder /usr/bin/caddy /usr/bin/caddy # container_name: caddy # restart: unless-stopped # ports: # - "80:80" # - "443:443" # - "443:443/udp" # environment: # - CLOUDFLARE_API_TOKEN=eyJhIjoiMjUyZjQ3MWZkMzE2ZTg5NjI2ZjEzYzI1YzYwMTJiYzciLCJ0IjoiNWFhMDJlNmEtNDE2Ni00YTJkLTk1YzktMGFmMGY3MjM3YjIzIiwicyI6Ik5tWmhOR1V6WVRZdE5HRXdOaTAwT1RjekxXSTFPV1V0T0RrMU1UWTRabVl4WkRZeCJ9 # volumes: # - ./conf:/etc/caddy # - ./site:/srv # - caddy_data:/data # - caddy_config:/config # networks: # - server-mesh networks: tdarr-net: driver: bridge termix-net: driver: bridge server-mesh: external: true staticaddress: ipam: config: - subnet: "172.200.0.0/16" volumes: # open-webui: # caddy_data: # caddy_config: myspeed: external: true # docker compose will fail creating myspeed if the volume hasn't been manually created, which we have done. unless you deleted it... termix-data: driver: local