migrate
This commit is contained in:
+150
@@ -0,0 +1,150 @@
|
||||
# ============================================================
|
||||
# Tom Spark's ARR Stack — Environment Configuration
|
||||
# https://github.com/loponai/arrstack
|
||||
#
|
||||
# INSTRUCTIONS:
|
||||
# 1. Copy this file: cp .env.example .env
|
||||
# 2. Fill in your VPN credentials below
|
||||
# 3. Adjust timezone and user IDs if needed
|
||||
# 4. Run: docker compose up -d
|
||||
# ============================================================
|
||||
|
||||
# ============================================================
|
||||
# SYSTEM SETTINGS
|
||||
# ============================================================
|
||||
|
||||
# Your timezone (list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
|
||||
TZ=America/New_York
|
||||
|
||||
# Your Linux user/group ID. Find yours with: id
|
||||
# Most systems default to 1000. If yours is different, change these.
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
|
||||
# ============================================================
|
||||
# VPN SETTINGS — Pick your provider and fill in credentials
|
||||
# Full provider list: https://github.com/qdm12/gluetun-wiki/tree/main/setup/providers
|
||||
#
|
||||
# IMPORTANT: VPN credentials are NOT your login email/password!
|
||||
# You need service credentials from your VPN provider's manual
|
||||
# setup or API section. See the provider examples at the bottom of this file.
|
||||
# ============================================================
|
||||
|
||||
# Your VPN provider (surfshark, nordvpn, protonvpn, airvpn, mullvad, private internet access, windscribe, etc.)
|
||||
VPN_SERVICE_PROVIDER=airvpn
|
||||
|
||||
# Protocol: wireguard (recommended, faster) or openvpn
|
||||
VPN_TYPE=wireguard
|
||||
|
||||
# --- WIREGUARD CREDENTIALS ---
|
||||
# For Surfshark: go to https://my.surfshark.com/vpn/manual-setup/main → WireGuard
|
||||
# For other providers: see the examples at the bottom of this file
|
||||
WIREGUARD_PRIVATE_KEY=eDgf3GPFy2ltgx2RkD/Vx5wKZ4dVi28YbQmSJOrbWmk=
|
||||
WIREGUARD_ADDRESSES=10.175.23.30
|
||||
# Only needed for some providers (AirVPN). Leave blank if not required.
|
||||
# WIREGUARD_PUBLIC_KEY=
|
||||
WIREGUARD_PRESHARED_KEY=+0+hrSdzRUxKDNk1Q37PNmNJ2jsj2EzF45JtbZad4lI=
|
||||
# --- OPENVPN CREDENTIALS ---
|
||||
# Only needed if VPN_TYPE=openvpn. Leave blank if using WireGuard.
|
||||
# OPENVPN_USER=
|
||||
# OPENVPN_PASSWORD=
|
||||
|
||||
# --- SERVER SELECTION ---
|
||||
# Pick a country close to you for best speeds
|
||||
SERVER_COUNTRIES=Canada
|
||||
|
||||
# --- PORT FORWARDING ---
|
||||
# Supported by: ProtonVPN, AirVPN, PIA. Can help with upload speeds and seeding.
|
||||
# Not required for downloading. Most users don't need this.
|
||||
# Set to "on" if your provider supports it, leave blank otherwise (Surfshark, NordVPN, etc.).
|
||||
#VPN_PORT_FORWARDING=
|
||||
# If your provider requires manually specifying a port (e.g. AirVPN):
|
||||
FIREWALL_VPN_INPUT_PORTS=29261
|
||||
|
||||
# ============================================================
|
||||
# NETWORK — Static IPs for each service
|
||||
# You shouldn't need to change these unless you have a conflict.
|
||||
# ============================================================
|
||||
IP_GLUETUN=172.39.0.2
|
||||
IP_RADARR=172.39.0.3
|
||||
IP_SONARR=172.39.0.4
|
||||
IP_LIDARR=172.39.0.5
|
||||
IP_BAZARR=172.39.0.6
|
||||
IP_JELLYFIN=172.39.0.7
|
||||
IP_SEERR=172.39.0.8
|
||||
IP_AUDIO=172.39.0.9
|
||||
IP_NAVI=172.39.0.10
|
||||
IP_LIST=172.39.0.11
|
||||
IP_WATCH=172.39.0.12
|
||||
# ============================================================
|
||||
# PROVIDER-SPECIFIC EXAMPLES
|
||||
# Uncomment and fill in the section for your VPN provider.
|
||||
# ============================================================
|
||||
|
||||
# --- NORDVPN ---
|
||||
# 1. Go to: https://my.nordaccount.com/dashboard/nordvpn/manual-configuration/
|
||||
# 2. Generate a WireGuard private key (NordLynx)
|
||||
# 3. Paste the private key below
|
||||
# VPN_SERVICE_PROVIDER=nordvpn
|
||||
# VPN_TYPE=wireguard
|
||||
# WIREGUARD_PRIVATE_KEY=your_nordvpn_private_key_here
|
||||
# WIREGUARD_ADDRESSES=10.5.0.2/16
|
||||
# SERVER_COUNTRIES=United States
|
||||
# --- PROTONVPN ---
|
||||
# 1. Go to: https://account.protonvpn.com/ → Downloads → WireGuard configuration
|
||||
# 2. Generate a config, open the file, copy the PrivateKey and Address
|
||||
# 3. Port forwarding is supported on paid plans
|
||||
# VPN_SERVICE_PROVIDER=protonvpn
|
||||
# VPN_TYPE=wireguard
|
||||
# WIREGUARD_PRIVATE_KEY=your_proton_private_key_here
|
||||
# WIREGUARD_ADDRESSES=10.2.0.2/32
|
||||
# SERVER_COUNTRIES=United States
|
||||
# VPN_PORT_FORWARDING=on
|
||||
|
||||
# --- SURFSHARK ---
|
||||
# 1. Go to: https://my.surfshark.com/vpn/manual-setup/main
|
||||
# 2. Get WireGuard credentials
|
||||
# VPN_SERVICE_PROVIDER=surfshark
|
||||
# VPN_TYPE=wireguard
|
||||
# WIREGUARD_PRIVATE_KEY=your_surfshark_private_key_here
|
||||
# WIREGUARD_ADDRESSES=10.14.0.2/16
|
||||
# SERVER_COUNTRIES=United States
|
||||
|
||||
# --- AIRVPN ---
|
||||
# 1. Go to: https://airvpn.org/ → Client Area → Config Generator
|
||||
# 2. Select Linux → WireGuard → pick a server → Generate
|
||||
# 3. Copy all keys and the assigned IP
|
||||
# VPN_SERVICE_PROVIDER=airvpn
|
||||
# VPN_TYPE=wireguard
|
||||
# WIREGUARD_PRIVATE_KEY=your_airvpn_private_key_here
|
||||
# WIREGUARD_PUBLIC_KEY=your_airvpn_public_key_here
|
||||
# WIREGUARD_PRESHARED_KEY=your_airvpn_preshared_key_here
|
||||
# WIREGUARD_ADDRESSES=your_assigned_ip/32
|
||||
# FIREWALL_VPN_INPUT_PORTS=your_forwarded_port
|
||||
# VPN_PORT_FORWARDING=on
|
||||
|
||||
# --- MULLVAD ---
|
||||
# 1. Go to: https://mullvad.net/en/account → WireGuard configuration
|
||||
# VPN_SERVICE_PROVIDER=mullvad
|
||||
# VPN_TYPE=wireguard
|
||||
# WIREGUARD_PRIVATE_KEY=your_mullvad_private_key_here
|
||||
# WIREGUARD_ADDRESSES=your_assigned_ip/32
|
||||
# SERVER_COUNTRIES=United States
|
||||
|
||||
# --- Watchtower ---
|
||||
WATCHTOWER_CLEANUP=true
|
||||
WATCHTOWER_INCLUDE_RESTARTING=true
|
||||
WATCHTOWER_ROLLING_RESTARTING=true
|
||||
WATCHTOWER_SCHEDULE=0 0 4 * * *
|
||||
WATCHTOWER_INCLUDE_STOPPED=true
|
||||
WATCHTOWER_NOTIFICATIONS=email
|
||||
WATCHTOWER_NOTIFICATIONS_HOSTNAME=Docker-Deply # Add Server Name or IP Address
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_FROM=miker@mmcfetridge.net
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_TO=miker@mmcfetridge.net
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_SERVER=mail.mmcfetridge.net
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=465
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=miker@mmcfetridge.net
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=!Sucyetat123
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_DELAY=2
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
@@ -0,0 +1,444 @@
|
||||
# Tom Spark's ARR Stack — Automated Media Server
|
||||
# https://github.com/loponai/arrstack
|
||||
#
|
||||
# Comment this out if you are not deploying this through Gitea CI/CD process.
|
||||
# echo "Setting up directory nd ownership"
|
||||
# Create the directory if it doesn't exist yet
|
||||
# sudo mkdir -p /opt/Docker-Deployments
|
||||
# Usage:
|
||||
# 1. Copy .env.example to .env and fill in your VPN credentials
|
||||
# 2. Run: bash setup-folders.sh
|
||||
# 3. Run: docker compose up -d
|
||||
#
|
||||
# All VPN-protected services (qBittorrent, Prowlarr, FlareSolverr) run
|
||||
# through Gluetun. If the VPN drops, traffic stops. Zero leaks.
|
||||
#
|
||||
# Radarr, Sonarr, Lidarr, Bazarr, Jellyfin, and Seerr do NOT run through
|
||||
# the VPN — they need direct network access for speed and local connectivity.
|
||||
|
||||
networks:
|
||||
arrnetwork:
|
||||
name: arrnetwork
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.39.0.0/24
|
||||
|
||||
services:
|
||||
|
||||
# ============================================================
|
||||
# GLUETUN — VPN Container (kill switch + tunnel)
|
||||
# All VPN-protected services route through this container.
|
||||
# Ports for those services are mapped HERE, not on the services themselves.
|
||||
# Docs: https://github.com/qdm12/gluetun-wiki
|
||||
# ============================================================
|
||||
gluetun:
|
||||
image: qmcgaw/gluetun:latest
|
||||
container_name: gluetun
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
devices:
|
||||
- /dev/net/tun:/dev/net/tun
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_GLUETUN}
|
||||
ports:
|
||||
- 8000:8000 # Gluetun Control Server
|
||||
- 8080:8080 # qBittorrent WebUI
|
||||
- 6881:6881 # qBittorrent torrenting port
|
||||
- 6881:6881/udp
|
||||
- 9696:9696 # Prowlarr
|
||||
- 8191:8191 # FlareSolverr
|
||||
volumes:
|
||||
- gluetun_volume:/gluetun
|
||||
environment:
|
||||
- VPN_SERVICE_PROVIDER=${VPN_SERVICE_PROVIDER}
|
||||
- VPN_TYPE=${VPN_TYPE}
|
||||
# --- WireGuard credentials (most providers) ---
|
||||
- WIREGUARD_PRIVATE_KEY=${WIREGUARD_PRIVATE_KEY}
|
||||
- WIREGUARD_ADDRESSES=${WIREGUARD_ADDRESSES}
|
||||
# - WIREGUARD_PUBLIC_KEY=${WIREGUARD_PUBLIC_KEY}
|
||||
- WIREGUARD_PRESHARED_KEY=${WIREGUARD_PRESHARED_KEY}
|
||||
# --- OpenVPN credentials (if using OpenVPN instead) ---
|
||||
# - OPENVPN_USER=${OPENVPN_USER}
|
||||
# - OPENVPN_PASSWORD=${OPENVPN_PASSWORD}
|
||||
# --- Server selection ---
|
||||
- SERVER_COUNTRIES=${SERVER_COUNTRIES}
|
||||
# --- Port forwarding (ProtonVPN, AirVPN, PIA) ---
|
||||
# - VPN_PORT_FORWARDING=${VPN_PORT_FORWARDING}
|
||||
- FIREWALL_VPN_INPUT_PORTS=${FIREWALL_VPN_INPUT_PORTS}
|
||||
- FIREWALL_OUTBOUND_SUBNETS=192.168.0.0/22
|
||||
# --- General ---
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
- BLOCK_MALICIOUS=off
|
||||
- HTTP_CONTROL_SERVER_ADDRESS=:8000
|
||||
- HTTP_CONTROL_SERVER_LOG=on
|
||||
- HTTP_CONTROL_SERVER_AUTH_DEFAULT_ROLE={"auth":"none"}
|
||||
healthcheck:
|
||||
test: wget -qO /dev/null http://127.0.0.1:9999 || exit 1
|
||||
interval: 20s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# QBITTORRENT — Torrent Client (runs through Gluetun VPN)
|
||||
# ALL traffic goes through the VPN tunnel. No direct internet.
|
||||
# ============================================================
|
||||
qbittorrent:
|
||||
image: lscr.io/linuxserver/qbittorrent:latest
|
||||
container_name: qbittorrent
|
||||
network_mode: service:gluetun
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
labels:
|
||||
- deunhealth.restart.on.unhealthy=true
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
- WEBUI_PORT=8080
|
||||
- TORRENTING_PORT=${FIREWALL_VPN_INPUT_PORTS}
|
||||
volumes:
|
||||
- qbittorrent_volume:/config
|
||||
- /data:/data
|
||||
healthcheck:
|
||||
test: wget -q --spider http://localhost:8080 || exit 1
|
||||
interval: 60s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# DEUNHEALTH — Auto-restarts unhealthy containers
|
||||
# If qBittorrent loses VPN connection, this restarts it automatically.
|
||||
# ============================================================
|
||||
deunhealth:
|
||||
image: qmcgaw/deunhealth
|
||||
container_name: deunhealth
|
||||
network_mode: none
|
||||
environment:
|
||||
- LOG_LEVEL=info
|
||||
- HEALTH_SERVER_ADDRESS=127.0.0.1:9999
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- deunhealth_volume:/config
|
||||
restart: always
|
||||
|
||||
# ============================================================
|
||||
# PROWLARR — Indexer Manager (runs through Gluetun VPN)
|
||||
# Manages torrent/usenet indexers. Syncs to Radarr/Sonarr/Lidarr.
|
||||
# ============================================================
|
||||
prowlarr:
|
||||
image: lscr.io/linuxserver/prowlarr:latest
|
||||
container_name: prowlarr
|
||||
network_mode: service:gluetun
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- prowlarr_volume:/config
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# FLARESOLVERR — Cloudflare Bypass (runs through Gluetun VPN)
|
||||
# Some indexers use Cloudflare protection. This gets around it.
|
||||
# ============================================================
|
||||
flaresolverr:
|
||||
image: ghcr.io/flaresolverr/flaresolverr:latest
|
||||
container_name: flaresolverr
|
||||
network_mode: service:gluetun
|
||||
depends_on:
|
||||
gluetun:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
volumes:
|
||||
- flaresolverr_volume:/config
|
||||
environment:
|
||||
- LOG_LEVEL=info
|
||||
- TZ=${TZ}
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# RADARR — Movie Manager (NOT behind VPN)
|
||||
# Searches via Prowlarr, sends downloads to qBittorrent,
|
||||
# renames and hard-links completed files to media folder.
|
||||
# ============================================================
|
||||
radarr:
|
||||
image: lscr.io/linuxserver/radarr:latest
|
||||
container_name: radarr
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- radarr_volume:/config
|
||||
- /data:/data
|
||||
ports:
|
||||
- 7878:7878
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_RADARR}
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# SONARR — TV Show Manager (NOT behind VPN)
|
||||
# Same pattern as Radarr but for TV series.
|
||||
# ============================================================
|
||||
sonarr:
|
||||
image: lscr.io/linuxserver/sonarr:latest
|
||||
container_name: sonarr
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- sonarr_volume:/config
|
||||
- /data:/data
|
||||
ports:
|
||||
- 8989:8989
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_SONARR}
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# LIDARR — Music Manager (NOT behind VPN)
|
||||
# Optional. Comment out if you don't need music automation.
|
||||
# ============================================================
|
||||
lidarr:
|
||||
image: lscr.io/linuxserver/lidarr:latest
|
||||
container_name: lidarr
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- lidarr_volume:/config
|
||||
- /data:/data
|
||||
ports:
|
||||
- 8686:8686
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_LIDARR}
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# BAZARR — Subtitle Manager (NOT behind VPN)
|
||||
# Automatically downloads subtitles for movies and TV shows.
|
||||
# ============================================================
|
||||
bazarr:
|
||||
image: lscr.io/linuxserver/bazarr:latest
|
||||
container_name: bazarr
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- bazarr_volume:/config
|
||||
- /data:/data
|
||||
ports:
|
||||
- 6767:6767
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_BAZARR}
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# JELLYFIN — Media Server (NOT behind VPN)
|
||||
# Your personal streaming service. Plays movies, TV, music.
|
||||
# Needs full bandwidth — never put this behind the VPN.
|
||||
# ============================================================
|
||||
jellyfin:
|
||||
image: lscr.io/linuxserver/jellyfin:latest
|
||||
container_name: jellyfin
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- jellyfin_volume:/config
|
||||
- /data/media:/data/media
|
||||
ports:
|
||||
- 8096:8096
|
||||
# Uncomment the lines below to enable hardware transcoding (Intel Quick Sync / VAAPI).
|
||||
# Only works if your system has Intel/AMD integrated graphics (/dev/dri must exist).
|
||||
# If you get an error about /dev/dri not found, leave these commented out.
|
||||
# devices:
|
||||
# - /dev/dri:/dev/dri
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_JELLYFIN}
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================================
|
||||
# SEERR — Request System (NOT behind VPN)
|
||||
# Netflix-like UI for requesting movies and TV shows.
|
||||
# Share this with family — they never need to touch Radarr.
|
||||
#
|
||||
# Seerr is the unified successor to Overseerr and Jellyseerr
|
||||
# (merged under seerr-team). Supports Plex, Jellyfin, and Emby.
|
||||
#
|
||||
# Config uses a NAMED Docker volume (not a bind mount). This is
|
||||
# required: Seerr runs as the `node` user (UID 1000) and a
|
||||
# bind-mounted host folder is created root-owned, causing a
|
||||
# permission-denied crash loop. On Windows/WSL, bind mounts also
|
||||
# corrupt the SQLite DB over SMB. Named volumes fix both cases
|
||||
# (matches upstream Seerr docs).
|
||||
#
|
||||
# Migrating from ./jellyseerr or ./seerr bind mount? See README
|
||||
# troubleshooting "Migrating Seerr config to a named volume".
|
||||
# ============================================================
|
||||
seerr:
|
||||
image: ghcr.io/seerr-team/seerr:v3.0.1
|
||||
init: true
|
||||
container_name: seerr
|
||||
environment:
|
||||
- LOG_LEVEL=info
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
- PORT=5055
|
||||
volumes:
|
||||
- seerr_volume:/app/config # <--- Needed or will cause a permissions issue.
|
||||
ports:
|
||||
- 5055:5055
|
||||
healthcheck:
|
||||
test: wget --no-verbose --tries=1 --spider http://localhost:5055/api/v1/settings/public || exit 1
|
||||
start_period: 20s
|
||||
timeout: 3s
|
||||
interval: 15s
|
||||
retries: 3
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_SEERR}
|
||||
restart: unless-stopped
|
||||
|
||||
listenarr:
|
||||
image: ghcr.io/listenarrs/listenarr:canary
|
||||
container_name: listenarr
|
||||
ports:
|
||||
- "4545:4545"
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- listenarr_volume:/app/config
|
||||
- /data/media/audiobookshelf/books:/audiobooks
|
||||
- /data/torrents/books:/downloads
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_LIST}
|
||||
|
||||
audiobookshelf:
|
||||
image: ghcr.io/advplyr/audiobookshelf:latest
|
||||
container_name: audiobookshelf
|
||||
ports:
|
||||
- 13378:80
|
||||
environment:
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- /data/media/books/audiobookshelf/books:/audiobooks
|
||||
- /data/media/books/audiobookshelf/podcasts:/podcasts
|
||||
- /data/media/books/audiobookshelf/metadata:/metadata
|
||||
- audiobookshelf_volume:/config
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_AUDIO}
|
||||
navidrome:
|
||||
image: deluan/navidrome:latest
|
||||
container_name: navidrome
|
||||
ports:
|
||||
- 4533:4533
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- ND_SCANSCHEDULE=1h
|
||||
- ND_LOGLEVEL=info
|
||||
- ND_SESSIONTIMEOUT=24h
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- UMASK=002
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- navidrome_volume:/data
|
||||
- /data/media/music:/music:ro
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_NAVI}
|
||||
|
||||
watchtower:
|
||||
image: containrrr/watchtower
|
||||
container_name: watchtower
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
environment:
|
||||
- DOCKER_API_VERSION=1.44
|
||||
- TZ=${TZ}
|
||||
- PUID:=${PUID} # Reference PUID from .env
|
||||
- PGID=${PGID} # Reference PGID from .env
|
||||
- WATCHTOWER_CLEANUP=${WATCHTOWER_CLEANUP}
|
||||
- WATCHTOWER_INCLUDE_RESTARTING=${WATCHTOWER_INCLUDE_RESTARTING}
|
||||
- WATCHTOWER_ROLLING_RESTARTING=${WATCHTOWER_ROLLING_RESTARTING}
|
||||
- WATCHTOWER_SCHEDULE=${WATCHTOWER_SCHEDULE}
|
||||
- WATCHTOWER_INCLUDE_STOPPED=${WATCHTOWER_INCLUDE_STOPPED}
|
||||
- WATCHTOWER_NOTIFICATIONS=${WATCHTOWER_NOTIFICATIONS}
|
||||
- WATCHTOWER_NOTIFICATIONS_HOSTNAME=${WATCHTOWER_NOTIFICATIONS_HOSTNAME}
|
||||
- WATCHTOWER_NOTIFICATION_EMAIL_FROM=${WATCHTOWER_NOTIFICATION_EMAIL_FROM}
|
||||
- WATCHTOWER_NOTIFICATION_EMAIL_TO=${WATCHTOWER_NOTIFICATION_EMAIL_TO}
|
||||
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER=${WATCHTOWER_NOTIFICATION_EMAIL_SERVER}
|
||||
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=${WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT}
|
||||
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=${WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER}
|
||||
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=${WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD}
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
volumes:
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- watchtower_volume:/config
|
||||
networks:
|
||||
arrnetwork:
|
||||
ipv4_address: ${IP_WATCH}
|
||||
# Go to the VERY BOTTOM of your file (outside of services) and add this:
|
||||
volumes:
|
||||
gluetun_volume:
|
||||
qbittorrent_volume:
|
||||
deunhealth_volume:
|
||||
prowlarr_volume:
|
||||
flaresolverr_volume:
|
||||
radarr_volume:
|
||||
sonarr_volume:
|
||||
lidarr_volume:
|
||||
bazarr_volume:
|
||||
jellyfin_volume:
|
||||
seerr_volume:
|
||||
listenarr_volume:
|
||||
audiobookshelf_volume:
|
||||
navidrome_volume:
|
||||
watchtower_volume:
|
||||
@@ -0,0 +1,20 @@
|
||||
services:
|
||||
it-tools:
|
||||
image: 'corentinth/it-tools:latest'
|
||||
ports:
|
||||
- '8150:80'
|
||||
restart: unless-stopped
|
||||
container_name: it-tools
|
||||
networks:
|
||||
- external
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:80"]
|
||||
interval: 10s
|
||||
retries: 3
|
||||
timeout: 10s
|
||||
start_period: 30s
|
||||
|
||||
networks:
|
||||
external:
|
||||
external: true # Tells Compose not to create this network.
|
||||
@@ -0,0 +1,43 @@
|
||||
services:
|
||||
mealie:
|
||||
image: ghcr.io/mealie-recipes/mealie:latest # Specifies the Mealie Docker i>
|
||||
container_name: mealie # Names the container for easier>
|
||||
ports:
|
||||
- "9200:9000" # Maps port 9925 on the host to >
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1000M # Limits the container to use a >
|
||||
volumes:
|
||||
- /opt/Docker-Deployments/Mealie/data:/app/data/ # Persists data in>
|
||||
- /opt/Docker-Deployments/Mealie/config/addons_config/mealie/config.yaml:/config/config.yanl
|
||||
environment:
|
||||
- ALLOW_SIGNUP=false # Allows new user signups on the>
|
||||
- PUID=1000 # Sets the user ID for the conta>
|
||||
- PGID=1000 # Sets the group ID for the cont>
|
||||
- TZ=America/New_York # Sets the timezone for the cont>
|
||||
- MAX_WORKERS=1 # Limits the number of workers t>
|
||||
- WEB_CONCURRENCY=1 # Sets the concurrency level for>
|
||||
- BASE_URL=mealie.mikemcfetridge.com # The base URL where Mealie is a>
|
||||
# Email Settings
|
||||
- SMTP_HOST=mail.mmcfetridge.net
|
||||
- SMTP_PORT=465
|
||||
- SMTP_FROM_NAME=miker@mmcfetridge.net
|
||||
- SMTP_AUTH_STRATEGY=TLS
|
||||
- SMTP_FROM_EMAIL=miker@mmcfetridge.net
|
||||
- SMTP_USER=miker@mmcfetridge.net
|
||||
- SMTP_PASSWORD="!Sucyetat123"
|
||||
networks:
|
||||
- external
|
||||
restart: unless-stopped
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:9000"]
|
||||
interval: 10s
|
||||
retries: 3
|
||||
timeout: 10s
|
||||
start_period: 30s
|
||||
|
||||
networks:
|
||||
external:
|
||||
external: true # Tells Compose not to create this network
|
||||
@@ -0,0 +1,51 @@
|
||||
volumes:
|
||||
semaphore_data:
|
||||
semaphore_config:
|
||||
semaphore_tmp:
|
||||
|
||||
services:
|
||||
semaphore:
|
||||
image: semaphoreui/semaphore:latest
|
||||
container_name: semaphore
|
||||
ports:
|
||||
- "3020:3020" # Web UI accessed via port 3020
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- SEMAPHORE_DB_DIALECT=sqlite
|
||||
- SEMAPHORE_ADMIN_PASSWORD=Dy7zxAyDqdYN443g4pI3 # Change this on first boot!
|
||||
- SEMAPHORE_ADMIN_NAME=Mike McFetridge
|
||||
- SEMAPHORE_ADMIN_EMAIL=mmcfetridg@aol.com
|
||||
- SEMAPHORE_ADMIN=mmcfetridge
|
||||
# Point Semaphore to our secure local Docker Proxy instead of raw socket
|
||||
- DOCKER_HOST=tcp://docker_proxy:2375
|
||||
- SEMAPHORE_PORT=3020
|
||||
- ANSIBLE_HOST_KEY_CHECKING=False
|
||||
- SEMAPHORE_ACCESS_KEY_ENCRYPTION=mrmKv7EztqRCnlGo34IvlvoilXqvDKYnFIWX2lg+hZc=
|
||||
# Email Configuration
|
||||
- SEMAPHORE_EMAIL_ALERT=True
|
||||
- SEMAPHORE_EMAIL_HOST=mail.mmcfetridge.net
|
||||
- SEMAPHORE_EMAIL_PORT=465
|
||||
- SEMAPHORE_EMAIL_SENDER=miker@mmcfetridge.net
|
||||
- SEMAPHORE_EMAIL_USERNAME=miker@mmcfetridge.net
|
||||
- SEMAPHORE_EMAIL_PASSWORD="!Sucyetat123"
|
||||
- SEMAPHORE_EMAIL_SECURE=true
|
||||
- SEMAPHORE_EMAIL_TLS=true
|
||||
volumes:
|
||||
- semaphore_data:/var/lib/semaphore
|
||||
- semaphore_config:/etc/semaphore
|
||||
- semaphore_tmp:/tmp/semaphore
|
||||
networks:
|
||||
- external
|
||||
restart: unless-stopped
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3020"]
|
||||
interval: 10s
|
||||
retries: 3
|
||||
timeout: 10s
|
||||
start_period: 30s
|
||||
|
||||
networks:
|
||||
external:
|
||||
external: true # Tells Compose not to create this network
|
||||
@@ -0,0 +1,17 @@
|
||||
services:
|
||||
sencho:
|
||||
image: saelix/sencho:latest
|
||||
container_name: sencho
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "1852:1852"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /opt/Docker-Deployments/Sencho/data:/app/data
|
||||
# Change this line so the container path matches the host path:
|
||||
- /opt/Docker-Deployments:/opt/Docker-Deployments
|
||||
environment:
|
||||
- COMPOSE_DIR=/opt/Docker-Deployments
|
||||
- DATA_DIR=/app/data
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
TZ=America/New_York
|
||||
WATCHTOWER_CLEANUP=true
|
||||
WATCHTOWER_INCLUDE_RESTARTING=true
|
||||
WATCHTOWER_ROLLING_RESTARTING=true
|
||||
WATCHTOWER_SCHEDULE=0 0 4 * * *
|
||||
WATCHTOWER_INCLUDE_STOPPED=true
|
||||
WATCHTOWER_NOTIFICATIONS=email
|
||||
WATCHTOWER_NOTIFICATIONS_HOSTNAME=Docker-Deply # Add Server Name or IP Address
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_FROM=miker@mmcfetridge.net
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_TO=miker@mmcfetridge.net
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_SERVER=mail.mmcfetridge.net
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=465
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=miker@mmcfetridge.net
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=!Sucyetat123
|
||||
WATCHTOWER_NOTIFICATION_EMAIL_DELAY=2
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
@@ -0,0 +1,36 @@
|
||||
services:
|
||||
watchtower:
|
||||
image: containrrr/watchtower
|
||||
container_name: watchtower
|
||||
restart: unless-stopped
|
||||
env_file: .env
|
||||
environment:
|
||||
- DOCKER_API_VERSION=1.44
|
||||
- TZ=America/New_York
|
||||
- PUID:=1000 # Reference PUID from .env
|
||||
- PGID=1000 # Reference PGID from .env
|
||||
- WATCHTOWER_CLEANUP=true
|
||||
- WATCHTOWER_INCLUDE_RESTARTING=true
|
||||
- WATCHTOWER_ROLLING_RESTARTING=true
|
||||
- WATCHTOWER_SCHEDULE=0 0 4 * * *
|
||||
- WATCHTOWER_INCLUDE_STOPPED=true
|
||||
- WATCHTOWER_NOTIFICATIONS=email
|
||||
- WATCHTOWER_NOTIFICATIONS_HOSTNAME=Docker-Deployment # Add Server Name or IP Address
|
||||
- WATCHTOWER_NOTIFICATION_EMAIL_FROM=miker@mmcfetridge.net
|
||||
- WATCHTOWER_NOTIFICATION_EMAIL_TO=miker@mmcfetridge.net
|
||||
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER=mail.mmcfetridge.net
|
||||
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=465
|
||||
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=miker@mmcfetridge.net
|
||||
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=!Sucyetat123
|
||||
- WATCHTOWER_NOTIFICATION_EMAIL_DELAY=2
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
volumes:
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- external
|
||||
networks:
|
||||
external:
|
||||
external: true # Tells Compose not to create this network
|
||||
@@ -0,0 +1,48 @@
|
||||
name: Validate and Deploy Homelab
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
test-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Verify Compose File Validity
|
||||
env:
|
||||
DB_ROOT_PASSWORD: ${{ secrets.MYSQL_ROOT_PASSWORD }}
|
||||
DB_PASSWORD: ${{ secrets.MYSQL_PASSWORD }}
|
||||
run: docker compose config
|
||||
|
||||
# --- DEPLOYMENT PHASE ---
|
||||
|
||||
- name: Set up SSH Private Key
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "${{ secrets.DEPLOY_SSH_KEY }}" > ~/.ssh/id_ed25519
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
# Scan the host key to prevent SSH hanging on a manual confirmation prompt
|
||||
ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts
|
||||
|
||||
- name: Create Remote Docker Context
|
||||
run: |
|
||||
# Define a remote endpoint pointing to your live server over SSH
|
||||
docker context create homelab-target \
|
||||
--docker "host=ssh://${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}"
|
||||
|
||||
- name: Deploy Containers to Live Server
|
||||
env:
|
||||
# Pass your production secrets to the live deployment step
|
||||
DB_ROOT_PASSWORD: ${{ secrets.MYSQL_ROOT_PASSWORD }}
|
||||
DB_PASSWORD: ${{ secrets.MYSQL_PASSWORD }}
|
||||
run: |
|
||||
echo "Switching Docker context to live server..."
|
||||
docker context use homelab-target
|
||||
|
||||
echo "Pulling latest images and starting services remotely..."
|
||||
# The --project-directory . flag ensures it reads the docker-compose file fetched by Git
|
||||
docker compose --project-directory . up -d --remove-orphans
|
||||
Reference in New Issue
Block a user