From e29203f374550a985f65f860b0503a8852428af3 Mon Sep 17 00:00:00 2001 From: Mike McFetridge <91107715+mmcfetridge1969@users.noreply.github.com> Date: Mon, 20 Jul 2026 09:23:01 -0400 Subject: [PATCH] migrate --- ArrStack/.env | 150 ++++++++++++ ArrStack/docker-compose.yml | 444 ++++++++++++++++++++++++++++++++++ Ittools/docker-compose.yml | 20 ++ Mealie/docker-compose.yml | 43 ++++ README.md | 2 +- Semaphore/docker-compose.yml | 51 ++++ Sencho/docker-compose.yml | 17 ++ Watchtower/.env | 17 ++ Watchtower/docker-compose.yml | 36 +++ deploy-Template.yml | 48 ++++ 10 files changed, 827 insertions(+), 1 deletion(-) create mode 100644 ArrStack/.env create mode 100644 ArrStack/docker-compose.yml create mode 100644 Ittools/docker-compose.yml create mode 100644 Mealie/docker-compose.yml create mode 100644 Semaphore/docker-compose.yml create mode 100644 Sencho/docker-compose.yml create mode 100644 Watchtower/.env create mode 100644 Watchtower/docker-compose.yml create mode 100644 deploy-Template.yml diff --git a/ArrStack/.env b/ArrStack/.env new file mode 100644 index 0000000..79b70cc --- /dev/null +++ b/ArrStack/.env @@ -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 \ No newline at end of file diff --git a/ArrStack/docker-compose.yml b/ArrStack/docker-compose.yml new file mode 100644 index 0000000..63b06a1 --- /dev/null +++ b/ArrStack/docker-compose.yml @@ -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: \ No newline at end of file diff --git a/Ittools/docker-compose.yml b/Ittools/docker-compose.yml new file mode 100644 index 0000000..2b1e89f --- /dev/null +++ b/Ittools/docker-compose.yml @@ -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. diff --git a/Mealie/docker-compose.yml b/Mealie/docker-compose.yml new file mode 100644 index 0000000..22c046f --- /dev/null +++ b/Mealie/docker-compose.yml @@ -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 \ No newline at end of file diff --git a/README.md b/README.md index ce4d510..0b22d6d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# Docker-01 +# Docker-Deployments diff --git a/Semaphore/docker-compose.yml b/Semaphore/docker-compose.yml new file mode 100644 index 0000000..7d82a25 --- /dev/null +++ b/Semaphore/docker-compose.yml @@ -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 \ No newline at end of file diff --git a/Sencho/docker-compose.yml b/Sencho/docker-compose.yml new file mode 100644 index 0000000..5febff6 --- /dev/null +++ b/Sencho/docker-compose.yml @@ -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 + + \ No newline at end of file diff --git a/Watchtower/.env b/Watchtower/.env new file mode 100644 index 0000000..8e7bfea --- /dev/null +++ b/Watchtower/.env @@ -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 \ No newline at end of file diff --git a/Watchtower/docker-compose.yml b/Watchtower/docker-compose.yml new file mode 100644 index 0000000..eb503d5 --- /dev/null +++ b/Watchtower/docker-compose.yml @@ -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 \ No newline at end of file diff --git a/deploy-Template.yml b/deploy-Template.yml new file mode 100644 index 0000000..a29cd63 --- /dev/null +++ b/deploy-Template.yml @@ -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