From 153ff43cf572c1e260ce431deeb460d2517ce6a2 Mon Sep 17 00:00:00 2001 From: shaan Date: Thu, 6 Aug 2026 17:17:10 -0700 Subject: [PATCH] refactor (by Qwen) --- compose.yml | 1189 ++++++++++++++++++++++++--------------------------- 1 file changed, 556 insertions(+), 633 deletions(-) diff --git a/compose.yml b/compose.yml index 45d7a9b..7fbc726 100644 --- a/compose.yml +++ b/compose.yml @@ -1,668 +1,591 @@ +# ============================================================================= +# Torrent Stack - Docker Compose +# ============================================================================= + networks: - caddy_net: - external: true - tdarr-net: - driver: bridge - default: - name: portainer_network + caddy_net: + external: true + tdarr-net: + driver: bridge + default: + name: portainer_network volumes: - meilisearch: - karakeep-data: - caddy_config: - caddy_data: - external: true - 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... - portainer_data: - name: portainer_data + meilisearch: + karakeep-data: + caddy_config: + caddy_data: + external: true + myspeed: + external: true + portainer_data: -##### ORGANIZATION FOR EVERY CONTAINER -# services: -# container: -# image: <...> -# container_name: <...> -# env_file: <...> -# networks: <...> -# cap_add: <...> -# ports: <...> -# volumes: <...> -# environment: <...> -# labels: <...> -# healthcheck: <...> -# extra_hosts: <...> -# restart: <...> -# +# ============================================================================= +# Key ordering per service: +# image → container_name → env_file → networks/network_mode → cap_add +# → ports → volumes → environment → labels → healthcheck +# → extra_hosts → devices → pid → restart +# ============================================================================= services: - gluetun: - image: qmcgaw/gluetun:latest - container_name: gluetun - cap_add: - - NET_ADMIN - ports: # YOU MUST SPECIFY A PORT PER SERVICE ROUTED THROUGH GLUETUN! - - 8888:8000/tcp # gluetun control server, i dont think you should change this - - ${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 - volumes: - - ./gluetun-data:/tmp/gluetun:rw - 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). - healthcheck: - test: wget --spider -q http://1.1.1.1 || exit 1 - interval: 30s - timeout: 15s - retries: 3 - start_period: 1m - 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. - devices: - - /dev/net/tun:/dev/net/tun - restart: always + # --------------------------------------------------------------------------- + # VPN & Download + # --------------------------------------------------------------------------- - qbittorrent: - image: lscr.io/linuxserver/qbittorrent:latest - container_name: qbittorrent - network_mode: "container:gluetun" # vpn bunker - depends_on: - gluetun: - condition: service_healthy - labels: - - "autoheal=true" - volumes: - - ./qbittorrent:/config - - ${DISK1}:${DISK1} - - ${DISK2}:${DISK2} - - ./gluetun-data:/tmp/gluetun - - /etc/localtime:/etc/localtime:ro - - /etc/timezone:/etc/timezone:ro - environment: - - PUID=${HOST_PUID:-1000} - - PGID=${HOST_PGID:-1000} - - TZ=${TIMEZONE} - - WEBUI_PORT=${QBITTORRENT_PORT} - 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 + gluetun: + image: qmcgaw/gluetun:latest + container_name: gluetun + cap_add: + - NET_ADMIN + ports: + - 8888:8000/tcp + - ${QBITTORRENT_PORT}:${QBITTORRENT_PORT} + - ${PROWLARR_PORT}:${PROWLARR_PORT} + - ${SONARR_PORT}:${SONARR_PORT} + - ${RADARR_PORT}:${RADARR_PORT} + - ${LIDARR_PORT}:${LIDARR_PORT} + volumes: + - ./gluetun-data:/tmp/gluetun:rw + environment: + - VPN_SERVICE_PROVIDER=protonvpn + - VPN_TYPE=wireguard + - HTTP_CONTROL_SERVER=ON + - HTTP_CONTROL_SERVER_AUTH_DEFAULT_ROLE='{"auth":"apikey","apikey":"${GLUETUN_KEY}"}' + - WIREGUARD_PRIVATE_KEY=${VPN_PRIVATE_KEY} + - WIREGUARD_MTU=1280 + - VPN_PORT_FORWARDING=on + - VPN_PORT_FORWARDING_PROVIDER=protonvpn + - SERVER_COUNTRIES=Netherlands + - 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 + healthcheck: + test: wget --spider -q http://1.1.1.1 || exit 1 + interval: 30s + timeout: 15s + retries: 3 + start_period: 1m + extra_hosts: + - "host.docker.internal:host-gateway" + devices: + - /dev/net/tun:/dev/net/tun + restart: always - 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 + qbittorrent: + image: lscr.io/linuxserver/qbittorrent:latest + container_name: qbittorrent + network_mode: "container:gluetun" + depends_on: + gluetun: + condition: service_healthy + volumes: + - ./qbittorrent:/config + - ${DISK1}:${DISK1} + - ${DISK2}:${DISK2} + - ./gluetun-data:/tmp/gluetun + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + environment: + - PUID=${HOST_PUID:-1000} + - PGID=${HOST_PGID:-1000} + - TZ=${TIMEZONE} + - WEBUI_PORT=${QBITTORRENT_PORT} + labels: + - "autoheal=true" + healthcheck: + test: ["CMD-SHELL", "wget --spider -q https://1.1.1.1 || exit 1"] + interval: 1m + timeout: 10s + retries: 3 + start_period: 30s + restart: unless-stopped - # 2. Read and clean the port - read -r PORT_VAL < /tmp/gluetun/forwarded_port; - CLEAN_PORT=$$(echo "$$PORT_VAL" | tr -d '\r\n '); + port-updater: + image: curlimages/curl:latest + container_name: port-updater + network_mode: "container:gluetun" + depends_on: + gluetun: + condition: service_healthy + volumes: + - ./gluetun-data:/tmp/gluetun:ro + entrypoint: ["/bin/sh", "-c"] + command: + - | + trap 'exit 0' SIGTERM; + while true; do + while [ ! -s /tmp/gluetun/forwarded_port ]; do + echo "Waiting for Gluetun to provide a port..." + sleep 5 + done - # 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; + read -r PORT_VAL < /tmp/gluetun/forwarded_port; + CLEAN_PORT=$$(echo "$$PORT_VAL" | tr -d '\r\n '); - # 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 + if [ -n "$$CLEAN_PORT" ]; then + echo "Updating qBit to port: $$CLEAN_PORT"; + sleep 10; + curl -s -X POST -d "json={\"listen_port\":$$CLEAN_PORT}" http://localhost:${QBITTORRENT_PORT}/api/v2/app/setPreferences; + sleep 3600 & wait $$!; + else + sleep 10 + fi + done + labels: + - "autoheal=true" + 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 - network_mode: "container:gluetun" - depends_on: - gluetun: - condition: service_healthy - labels: - - "autoheal=true" - volumes: - - ./prowlarr:/config - - ./notify.sh:/notify.sh:ro - - /etc/localtime:/etc/localtime:ro - - /etc/timezone:/etc/timezone:ro - environment: - - PUID=${HOST_PUID:-1000} - - PGID=${HOST_PGID:-1000} - - TZ=${TIMEZONE} - 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 + # --------------------------------------------------------------------------- + # *arr Stack + # --------------------------------------------------------------------------- - sonarr: - image: lscr.io/linuxserver/sonarr:latest - container_name: sonarr - network_mode: "container:gluetun" - depends_on: - gluetun: - condition: service_healthy - labels: - - "autoheal=true" - volumes: - - /var/lib/sonarr:/config # had migrated into docker compose - - ${DISK1}:${DISK1} - - ${DISK2}:${DISK2} - - /etc/localtime:/etc/localtime:ro - - /etc/timezone:/etc/timezone:ro - environment: - - PUID=${HOST_PUID:-1000} - - PGID=${HOST_PGID:-1000} - - TZ=${TIMEZONE} - healthcheck: - test: ["CMD-SHELL", "curl -f http://1.1.1.1 || exit 1"] - interval: 5m - timeout: 60s - retries: 3 - start_period: 60s - restart: always + prowlarr: + image: lscr.io/linuxserver/prowlarr:latest + container_name: prowlarr + network_mode: "container:gluetun" + depends_on: + gluetun: + condition: service_healthy + volumes: + - ./prowlarr:/config + - ./notify.sh:/notify.sh:ro + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + environment: + - PUID=${HOST_PUID:-1000} + - PGID=${HOST_PGID:-1000} + - TZ=${TIMEZONE} + labels: + - "autoheal=true" + healthcheck: + test: ["CMD-SHELL", "wget --spider -q https://google.com || exit 1"] + interval: 5m + timeout: 60s + retries: 3 + start_period: 30s + restart: always - radarr: - image: lscr.io/linuxserver/radarr:latest - container_name: radarr - network_mode: "container:gluetun" - labels: - - "autoheal=true" - depends_on: - gluetun: - condition: service_healthy - volumes: - - /var/lib/radarr:/config # had migrated into docker compose - - ${DISK1}:${DISK1} - - ${DISK2}:${DISK2} - - /etc/localtime:/etc/localtime:ro - - /etc/timezone:/etc/timezone:ro - environment: - - PUID=${HOST_PUID:-1000} - - PGID=${HOST_PGID:-1000} - - TZ=${TIMEZONE} - healthcheck: - test: ["CMD-SHELL", "curl -f http://1.1.1.1 || exit 1"] - interval: 1m - timeout: 10s - retries: 3 - start_period: 30s - restart: always + sonarr: + image: lscr.io/linuxserver/sonarr:latest + container_name: sonarr + network_mode: "container:gluetun" + depends_on: + gluetun: + condition: service_healthy + volumes: + - /var/lib/sonarr:/config + - ${DISK1}:${DISK1} + - ${DISK2}:${DISK2} + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + environment: + - PUID=${HOST_PUID:-1000} + - PGID=${HOST_PGID:-1000} + - TZ=${TIMEZONE} + labels: + - "autoheal=true" + healthcheck: + test: ["CMD-SHELL", "curl -f http://1.1.1.1 || exit 1"] + interval: 5m + timeout: 60s + retries: 3 + start_period: 60s + restart: always - lidarr: - image: lscr.io/linuxserver/lidarr:latest - container_name: lidarr - network_mode: "container:gluetun" - depends_on: - gluetun: - condition: service_healthy - labels: - - "autoheal=true" - volumes: - - ./lidarr:/music - - /var/lib/lidarr:/config - - ${DISK1}:${DISK1} - - ${DISK2}:${DISK2} - - /etc/localtime:/etc/localtime:ro - - /etc/timezone:/etc/timezone:ro - environment: - - PUID=${HOST_PUID:-1000} - - PGID=${HOST_PGID:-1000} - - TZ=${TIMEZONE} - 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 + radarr: + image: lscr.io/linuxserver/radarr:latest + container_name: radarr + network_mode: "container:gluetun" + depends_on: + gluetun: + condition: service_healthy + volumes: + - /var/lib/radarr:/config + - ${DISK1}:${DISK1} + - ${DISK2}:${DISK2} + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + environment: + - PUID=${HOST_PUID:-1000} + - PGID=${HOST_PGID:-1000} + - TZ=${TIMEZONE} + labels: + - "autoheal=true" + healthcheck: + test: ["CMD-SHELL", "curl -f http://1.1.1.1 || exit 1"] + interval: 1m + timeout: 10s + retries: 3 + start_period: 30s + restart: always - 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 - networks: - - caddy_net - ports: - - ${TAUTULLI_PORT}:${TAUTULLI_PORT} - volumes: - #- /mnt/media/media:/config - - ./tautulli:/config - environment: - - PUID=${HOST_PUID:-1000} - - PGID=${HOST_PGID:-1000} - - TZ=${TIMEZONE} - restart: unless-stopped + lidarr: + image: lscr.io/linuxserver/lidarr:latest + container_name: lidarr + network_mode: "container:gluetun" + depends_on: + gluetun: + condition: service_healthy + volumes: + - ./lidarr:/music + - /var/lib/lidarr:/config + - ${DISK1}:${DISK1} + - ${DISK2}:${DISK2} + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + environment: + - PUID=${HOST_PUID:-1000} + - PGID=${HOST_PGID:-1000} + - TZ=${TIMEZONE} + labels: + - "autoheal=true" + 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 - tdarr: - image: haveagitgat/tdarr:latest - container_name: tdarr - networks: - - tdarr-net - ports: - - ${TDARR_PORT}:${TDARR_PORT} # WebUI - - ${TDARR_NODE_PORT}:${TDARR_NODE_PORT} # local tdarr-node - volumes: - - ./tdarr/server:/app/server - - ./tdarr/configs:/app/configs - - ./tdarr/temp:/temp - - ${DISK1}:${DISK1} - - ${DISK2}:${DISK2} - environment: - - TZ=${TIMEZONE} - - PUID=${HOST_PUID:-1000} - - PGID=${HOST_PGID:-100} - - UMASK_SET=002 - - serverIP=0.0.0.0 - # dont put temp files onto a HARD DISK DRIVE! > - ${DISK1}/tdarr-temp:/temp - #devices: #? I don't think this is needed - # - /dev/dri:/dev/dri # Intel UHD Graphics 710 - restart: unless-stopped + # --------------------------------------------------------------------------- + # Media + # --------------------------------------------------------------------------- - tdarr-node: - image: haveagitgat/tdarr_node:latest - container_name: tdarr-node - networks: - - tdarr-net - volumes: - - ./tdarr/configs:/app/configs - - ./tdarr/logs:/app/logs - - /home/shaan/torrent-stack/tdarr/temp:/temp - - ${DISK1}:${DISK1} - - ${DISK2}:${DISK2} - environment: - - TZ=${TIMEZONE} - - PUID=${HOST_PUID:-1000} - - PGID=${HOST_PGID:-1000} - - nodeID=${TDARR_NODE_ID} - - nodeIP=0.0.0.0 - - serverIP=tdarr # Points to the server container - - serverPort=${TDARR_NODE_PORT} - devices: - - /dev/dri/:/dev/dri/ # only works if user 'shaan' is a part of the 'video' or 'render' group. - restart: unless-stopped + tautulli: + image: ghcr.io/tautulli/tautulli + container_name: tautulli + networks: + - caddy_net + ports: + - ${TAUTULLI_PORT}:${TAUTULLI_PORT} + volumes: + - ./tautulli:/config + environment: + - PUID=${HOST_PUID:-1000} + - PGID=${HOST_PGID:-1000} + - TZ=${TIMEZONE} + restart: unless-stopped - homepage: - image: ghcr.io/gethomepage/homepage:latest - container_name: homepage - networks: - - caddy_net - 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: - # INIT - - "HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev,${LOCAL_IPV4}:${HOMEPAGE_PORT},${SERVER_NAME}:${HOMEPAGE_PORT},${SERVER_NAME}.${TAILNET_NAME}:${HOMEPAGE_PORT}" # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts - #\- "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}" - # KEYS - - "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}" - # WEB ADDRESSES - - "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_ODYSSEUS_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${ODYSSEUS_PORT}" - # WEB NAMES - - "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}" - - "HOMEPAGE_VAR_ODYSSEUS_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${ODYSSEUS_PORT}" - - TZ=${TIMEZONE} - extra_hosts: - - "host.docker.internal:host-gateway" - restart: always + tdarr: + image: haveagitgat/tdarr:latest + container_name: tdarr + networks: + - tdarr-net + ports: + - ${TDARR_PORT}:${TDARR_PORT} + - ${TDARR_NODE_PORT}:${TDARR_NODE_PORT} + volumes: + - ./tdarr/server:/app/server + - ./tdarr/configs:/app/configs + - ./tdarr/temp:/temp + - ${DISK1}:${DISK1} + - ${DISK2}:${DISK2} + environment: + - TZ=${TIMEZONE} + - PUID=${HOST_PUID:-1000} + - PGID=${HOST_PGID:-100} + - UMASK_SET=002 + - serverIP=0.0.0.0 + restart: unless-stopped - glances: - image: nicolargo/glances:latest-full - container_name: glances - pid: host - network_mode: host - 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=${HOST_PUID:-1000} - - PGID=${HOST_PGID:-1000} - - TZ=${TIMEZONE} - devices: - - /dev/dri:/dev/dri - restart: unless-stopped + tdarr-node: + image: haveagitgat/tdarr_node:latest + container_name: tdarr-node + networks: + - tdarr-net + volumes: + - ./tdarr/configs:/app/configs + - ./tdarr/logs:/app/logs + - ./tdarr/temp:/temp + - ${DISK1}:${DISK1} + - ${DISK2}:${DISK2} + environment: + - TZ=${TIMEZONE} + - PUID=${HOST_PUID:-1000} + - PGID=${HOST_PGID:-1000} + - nodeID=${TDARR_NODE_ID} + - nodeIP=0.0.0.0 + - serverIP=tdarr + - serverPort=${TDARR_NODE_PORT} + devices: + - /dev/dri/:/dev/dri/ + restart: unless-stopped - autoheal: - image: willfarrell/autoheal:latest - container_name: autoheal - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - /etc/localtime:/etc/localtime:ro - - /etc/timezone:/etc/timezone:ro - environment: - - AUTOHEAL_CONTAINER_LABEL=all - - AUTOHEAL_INTERVAL=30 - - AUTOHEAL_START_PERIOD=60 - restart: always + seerr: + image: ghcr.io/seerr-team/seerr:latest + container_name: seerr + networks: + - caddy_net + ports: + - ${SEERR_PORT}:${SEERR_PORT} + volumes: + - ./seerr:/app/config + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + environment: + - LOG_LEVEL=debug + - TZ=America/Los_Angeles + - PUID=${HOST_PUID:-1000} + - PGID=${HOST_PGID:-1000} + labels: + - "autoheal=true" + init: true + working_dir: "/app" + 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 - seerr: - image: ghcr.io/seerr-team/seerr:latest - container_name: seerr - working_dir: "/app" # something idk - init: true - networks: - - caddy_net - labels: - - "autoheal=true" - ports: - - ${SEERR_PORT}:${SEERR_PORT} - volumes: - - "./seerr:/app/config" - - /etc/localtime:/etc/localtime:ro - - /etc/timezone:/etc/timezone:ro - environment: - - LOG_LEVEL=debug - - TZ=America/Los_Angeles - - PUID=${HOST_PUID:-1000} - - PGID=${HOST_PGID:-1000} - 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 + seerr-anubis: + image: ghcr.io/techarohq/anubis:latest + container_name: seerr_anubis + networks: + - caddy_net + environment: + - BIND=:55055 + - TARGET=http://seerr:${SEERR_PORT} + restart: unless-stopped - seerr-anubis: - image: ghcr.io/techarohq/anubis:latest - container_name: seerr_anubis - networks: - - caddy_net - environment: - BIND: ":55055" - TARGET: http://seerr:${SEERR_PORT} - restart: unless-stopped + # --------------------------------------------------------------------------- + # Monitoring + # --------------------------------------------------------------------------- - MySpeed: - image: "germannewsmaker/myspeed" - container_name: "MySpeed" - network_mode: "bridge" - ports: - - "${MYSPEED_PORT}:${MYSPEED_PORT}/tcp" - volumes: - - "myspeed:/myspeed/data" - - /etc/localtime:/etc/localtime:ro - - /etc/timezone:/etc/timezone:ro - 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" - ipc: "private" - logging: - driver: "json-file" - options: {} - mac_address: "02:42:ac:11:00:03" - working_dir: "/myspeed" - entrypoint: - - "docker-entrypoint.sh" - command: - - "node" - - "server" - restart: unless-stopped + homepage: + image: ghcr.io/gethomepage/homepage:latest + container_name: homepage + networks: + - caddy_net + ports: + - ${HOMEPAGE_PORT}:${HOMEPAGE_PORT} + volumes: + - ./homepage:/app/config + - ./homepage/images:/app/public/images + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./gluetun-data:/tmp/gluetun:ro + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + environment: + - "HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev,${LOCAL_IPV4}:${HOMEPAGE_PORT},${SERVER_NAME}:${HOMEPAGE_PORT},${SERVER_NAME}.${TAILNET_NAME}:${HOMEPAGE_PORT}" + - "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_ODYSSEUS_ADDRESS=${WEB_PROTOCOL}://${LOCAL_IPV4}:${ODYSSEUS_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}" + - "HOMEPAGE_VAR_ODYSSEUS_HOST=${WEB_PROTOCOL}://${SERVER_NAME}:${ODYSSEUS_PORT}" + - TZ=${TIMEZONE} + extra_hosts: + - "host.docker.internal:host-gateway" + restart: always -# termix: -# image: ghcr.io/lukegus/termix:latest -# container_name: termix -# cap_add: -# - NET_ADMIN -# - SYS_ADMIN -# networks: -# - termix-net -# ports: -# - "${TERMIX_PORT}:${TERMIX_PORT}" -# volumes: -# - termix-data:/app/data -# environment: -# - "PORT: ${TERMIX_PORT}" -# - "TZ: {TIMEZONE}" -# restart: unless-stopped + glances: + image: nicolargo/glances:latest-full + container_name: glances + network_mode: host + 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=${HOST_PUID:-1000} + - PGID=${HOST_PGID:-1000} + - TZ=${TIMEZONE} + devices: + - /dev/dri:/dev/dri + pid: host + restart: unless-stopped - pihole: - image: pihole/pihole:latest - container_name: pihole - cap_add: - - NET_ADMIN - network_mode: "host" - ports: - - "53:53/tcp" - - "53:53/udp" - - "67:67/udp" - - "6060:6060/tcp" # original port '80' changed to '6060' within in the webui, be careful changing this - volumes: - - "./etc-pihole:/etc/pihole" - - "./etc-dnsmasq.d:/etc/dnsmasq.d" - - /etc/localtime:/etc/localtime:ro - - /etc/timezone:/etc/timezone:ro - environment: - TZ: "America/Los_Angeles" - WEBPASSWORD: "password123" - FTLCONF_misc_etc_dnsmasq_d: "true" - restart: unless-stopped + autoheal: + image: willfarrell/autoheal:latest + container_name: autoheal + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + environment: + - AUTOHEAL_CONTAINER_LABEL=all + - AUTOHEAL_INTERVAL=30 + - AUTOHEAL_START_PERIOD=60 + restart: always - cloudflared: - image: cloudflare/cloudflared:latest - container_name: cloudflared - command: tunnel --no-autoupdate run --token ${CLOUDFLARED_KEY} - restart: always + myspeed: + image: germannewsmaker/myspeed + container_name: myspeed + ports: + - ${MYSPEED_PORT}:${MYSPEED_PORT}/tcp + volumes: + - myspeed:/myspeed/data + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + environment: + - TZ=${TIMEZONE} + restart: unless-stopped -# torrents-csv: -# image: dessalines/torrents-csv-server:latest -# container_name: torrents-csv -# depends_on: -# - db # search at 'http://shaan-server:8902/service/search?q={SEARCH_TERM' -# ports: -# - "8902:8902" -# environment: -# TORRENTS_CSV_DB_HOST: "postgres://postgres:password@db" -# TORRENTS_CSV_FRONT_END_DIR: /app/dist -# RUST_LOG: DEBUG -# TIMEZONE: ${TIMEZONE} -# restart: unless-stopped + scrutiny: + image: ghcr.io/analogj/scrutiny:nightly-omnibus + container_name: scrutiny + cap_add: + - SYS_RAWIO + ports: + - ${SCRUTINY_PORT:-54321}:8080 + - ${SCRUTINY_ADMIN_PORT:-12345}:8086 + volumes: + - /run/udev:/run/udev:ro + - ./config:/opt/scrutiny/config + - ./influxdb:/opt/scrutiny/influxdb + devices: + - /dev/nvme0n1 + - /dev/sda + restart: unless-stopped -# db: -# image: pgautoupgrade/pgautoupgrade:17-alpine -# container_name: torrents-csv-db -# shm_size: 4gb -# ports: -# - "127.0.0.1:5433:5432" -# 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 -# environment: -# POSTGRES_PASSWORD: password -# POSTGRES_USER: postgres -# TIMEZONE: ${TIMEZONE} -# restart: unless-stopped + # --------------------------------------------------------------------------- + # Infrastructure + # --------------------------------------------------------------------------- - portainer: - image: portainer/portainer-ce:lts - container_name: portainer - restart: always - ports: - - ${PORTAINER_PORT}:${PORTAINER_PORT} - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - portainer_data:/data + pihole: + image: pihole/pihole:latest + container_name: pihole + cap_add: + - NET_ADMIN + network_mode: host + ports: + - 53:53/tcp + - 53:53/udp + - 67:67/udp + - 6060:6060/tcp + volumes: + - ./etc-pihole:/etc/pihole + - ./etc-dnsmasq.d:/etc/dnsmasq.d + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + environment: + - TZ=America/Los_Angeles + - WEBPASSWORD=password123 + - FTLCONF_misc_etc_dnsmasq_d=true + restart: unless-stopped - caddy: - image: caddy:latest - container_name: caddy - networks: - - caddy_net - ports: - - 80:80 - - 443:443 - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - /home/shaan/torrent-stack/caddy/Caddyfile:/etc/caddy/Caddyfile - - /home/shaan/torrent-stack/caddy/site:/srv - - /home/shaan/torrent-stack/caddy/caddy_data:/data - - /home/shaan/torrent-stack/caddy/caddy_config:/config - restart: unless-stopped + cloudflared: + image: cloudflare/cloudflared:latest + container_name: cloudflared + command: tunnel --no-autoupdate run --token ${CLOUDFLARED_KEY} + restart: always - scrutiny: - image: ghcr.io/analogj/scrutiny:nightly-omnibus - container_name: scrutiny - cap_add: - - SYS_RAWIO - ports: - - "${SCRUTINY_PORT:-54321}:8080" # webapp - - "${SCRUTINY_ADMIN_PORT:-12345}:8086" # influxDB admin - volumes: - - /run/udev:/run/udev:ro - - ./config:/opt/scrutiny/config - - ./influxdb:/opt/scrutiny/influxdb - devices: - - "/dev/nvme0n1" - - "/dev/sda" - #- "/dev/sdb" - restart: unless-stopped + portainer: + image: portainer/portainer-ce:lts + container_name: portainer + ports: + - ${PORTAINER_PORT}:${PORTAINER_PORT} + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - portainer_data:/data + restart: always - karakeep: - image: ghcr.io/karakeep-app/karakeep:${KARAKEEP_VERSION:-release} - container_name: karakeep - env_file: - - .env - ports: - - 4621:3000 - volumes: - # By default, the data is stored in a docker volume called "data". - # If you want to mount a custom directory, change the volume mapping to: - # - /path/to/your/directory:/data - - karakeep-data:/data - environment: - MEILI_ADDR: http://meilisearch:7700 - BROWSER_WEB_URL: http://chrome:9222 - # OPENAI_API_KEY: ... - # You almost never want to change the value of the DATA_DIR variable. - # If you want to mount a custom directory, change the volume mapping above instead. - DATA_DIR: /data # DON'T CHANGE THIS - restart: unless-stopped + caddy: + image: caddy:latest + container_name: caddy + networks: + - caddy_net + ports: + - 80:80 + - 443:443 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./caddy/Caddyfile:/etc/caddy/Caddyfile + - ./caddy/site:/srv + - ./caddy/caddy_data:/data + - ./caddy/caddy_config:/config + restart: unless-stopped - chrome: - image: gcr.io/zenika-hub/alpine-chrome:124 - container_name: karakeep-chromebrowser - command: - - --no-sandbox - - --disable-gpu - - --disable-dev-shm-usage - - --remote-debugging-address=0.0.0.0 - - --remote-debugging-port=9222 - - --hide-scrollbars - - --disable-blink-features=AutomationControlled - - --window-size=1440,900 - restart: unless-stopped + # --------------------------------------------------------------------------- + # Karakeep + # --------------------------------------------------------------------------- - meilisearch: # karakeep vector coord. support for karakeep. allows semantic search - image: getmeili/meilisearch:v1.41.0 - container_name: karakeep-meilisearch - env_file: - - .env - volumes: - - meilisearch:/meili_data - environment: - MEILI_NO_ANALYTICS: "true" - restart: unless-stopped + karakeep: + image: ghcr.io/karakeep-app/karakeep:${KARAKEEP_VERSION:-release} + container_name: karakeep + env_file: + - .env + ports: + - 4621:3000 + volumes: + - karakeep-data:/data + environment: + - MEILI_ADDR=http://meilisearch:7700 + - BROWSER_WEB_URL=http://chrome:9222 + - DATA_DIR=/data + restart: unless-stopped + + chrome: + image: gcr.io/zenika-hub/alpine-chrome:124 + container_name: karakeep-chromebrowser + command: + - --no-sandbox + - --disable-gpu + - --disable-dev-shm-usage + - --remote-debugging-address=0.0.0.0 + - --remote-debugging-port=9222 + - --hide-scrollbars + - --disable-blink-features=AutomationControlled + - --window-size=1440,900 + restart: unless-stopped + + meilisearch: + image: getmeili/meilisearch:v1.41.0 + container_name: karakeep-meilisearch + env_file: + - .env + volumes: + - meilisearch:/meili_data + environment: + - MEILI_NO_ANALYTICS="true" + restart: unless-stopped