455 lines
18 KiB
YAML
455 lines
18 KiB
YAML
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 # ACTUALLY DUMB FUCK! gluetun itself DOES NOT NEED DNS! # the comment afterwards is stupid, if gluetun can't resolve some DNS name, then the other services can't either, they need to be able to look up databases # dont use google.com, since that requires DNS. if it fails to resolve, the container is forced to restart. This is bad, since we mostly don't need dns for things such as qbittorrent, or prowlarr itself
|
|
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}/downloads
|
|
- ${DISK2}:${DISK2}/downloads
|
|
- ./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}:/media # too dangerous to change this
|
|
- ${DISK2}:/11tb_ext # too dangerous to change this
|
|
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}:/media # too dangerous to change this
|
|
- ${DISK2}:/11tb_ext # too dangerous to change this
|
|
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}
|
|
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
|
|
environment:
|
|
- "HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev,192.168.50.2:3000,shaan-server:3000,100.76.249.110:3000,ss:3000,shaan-server.tail:${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}"
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
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
|
|
environment:
|
|
- GLANCES_OPT=-w
|
|
- PUID=1000
|
|
- PGID=1000
|
|
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
|
|
restart: always
|
|
|
|
seerr:
|
|
image: ghcr.io/seerr-team/seerr:latest
|
|
init: true
|
|
container_name: seerr
|
|
ports:
|
|
- ${SEERR_PORT}:${SEERR_PORT}
|
|
environment:
|
|
- LOG_LEVEL=debug
|
|
- TZ=${TIMEZONE}
|
|
- PUID=1000
|
|
- PGID=1000
|
|
volumes:
|
|
- "./seerr:/app/config"
|
|
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=Etc/UTC"
|
|
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"
|
|
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}"
|
|
networks:
|
|
- termix-net
|
|
restart: unless-stopped
|
|
|
|
networks:
|
|
tdarr-net:
|
|
driver: bridge
|
|
termix-net:
|
|
driver: bridge
|
|
|
|
volumes:
|
|
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
|