Snapshot both servers: the VPS catalog moves to server/vps, the home server joins as server/home

The catalog in server/containers had drifted from the VPS. Eleven compose
files and twelve units no longer matched what runs, and two running
services, Gbrown_Agent and BillTracker, were missing. server/vps is now a
copy of the live files, and panama-server reads from it.

server/home holds the home server's services in the same shape. They still
run under Docker, so the podman units there are drafts for a later move, and
nothing installs from that tree. PostHog, Sentry and Plausible are checkouts
of upstream repositories. Only their local files are kept, next to an
UPSTREAM file naming the repository and the exact commit.

Every secret in both trees is a ${VAR} reference named in .env.example, or
CHANGE_ME in files that are not compose files. The live servers still hold
some of those values inline, so a live file can differ from its copy on
those lines alone. Existing .env.example files keep their comments, with new
keys appended at the end.

The ignore rules and the secrets contract now cover both trees, plus the
volume/ and volumes/ directories the home server uses.
This commit is contained in:
Gabriel Brown committed 2026-10-06 10:52:47 -04:00
1 parent a664cf68f5
commit 913a57f8a6
146 files changed
+5258 -354

No files matched your search

+9
View File
@@ -0,0 +1,9 @@
PLEX_CLAIM=CHANGE_ME
PLEX_TOKEN=CHANGE_ME
JELLYFIN_TOKEN=CHANGE_ME
OPENVPN_PASSWORD=CHANGE_ME
QBIT_PASS=CHANGE_ME
SONARR_API_KEY=CHANGE_ME
RADARR_API_KEY=CHANGE_ME
UN_SONARR_0_API_KEY=CHANGE_ME
UN_RADARR_0_API_KEY=CHANGE_ME
+429
View File
@@ -0,0 +1,429 @@
networks:
nginx-bridge:
external: true
services:
plex:
image: plexinc/pms-docker:latest
container_name: plex
hostname: plex
domainname: plex.gbrown.org
networks: [nginx-bridge]
group_add: [105, 39]
ports:
- 32400:32400/tcp # REQUIRED
#- 5353:5353/udp # For older Bonjour/Avahi network discovery
#- 8324:8324/tcp # For Plex Roku App
- 32410:32410/udp # For network discovery
- 32412:32412/udp # For network discovery
- 32413:32413/udp # For network discovery
- 32414:32414/udp # For network discovery
#- 1900:1900/udp # For DLNA
- 32469:32469/tcp # For DLNA
environment:
- TZ=America/New_York
- PLEX_UID=1000
- PLEX_GID=1000
- PLEX_CLAIM=${PLEX_CLAIM}
- ADVERTISE_IP=http://192.168.0.43
- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=compute,video,utility
labels: ["com.centurylinklabs.watchtower.enable=true"]
volumes:
- /run:/run
- ./volumes/plex/config:/config
- ./volumes/plex/transcode:/transcode
- /home/gib/Public/Movies:/data/movies
- /home/gib/Public/TV:/data/tvshows
- /home/gib/Public/Music:/data/music
- /home/gib/Public/Audiobooks:/data/audiobooks
- /home/gib/Public/Podcasts:/data/podcasts
devices: [/dev/dri:/dev/dri]
tty: true
stdin_open: true
restart: unless-stopped
security_opt: ["seccomp:unconfined"]
runtime: nvidia
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
hostname: jellyfin
domainname: jellyfin.gbrown.org
networks: [nginx-bridge]
group_add: [105, 39]
ports: [7359:7359/udp]
user: 1000:1000
environment:
- JELLYFIN_PublishedServerUrl=https://jellyfin.gbrown.org
labels: [com.centurylinklabs.watchtower.enable=true]
volumes:
- ./volumes/jellyfin/config:/config
- ./volumes/jellyfin/cache:/cache
- /home/gib/Public/Movies:/data/movies
- /home/gib/Public/TV:/data/tvshows
- /home/gib/Public/Music:/data/music
- /home/gib/Public/Audiobooks:/data/audiobooks
- /home/gib/Public/Podcasts:/data/podcasts
- /home/gib/.local/share/fonts:/usr/local/share/fonts/custom:ro
tty: true
stdin_open: true
restart: unless-stopped
devices: [/dev/dri:/dev/dri]
security_opt: [seccomp:unconfined]
runtime: nvidia
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
audiobookshelf:
image: ghcr.io/advplyr/audiobookshelf:latest
container_name: audiobookshelf
hostname: audiobookshelf
domainname: audio.gbrown.org
networks: [nginx-bridge]
#ports: [80:80]
environment: [TZ=America/New_York, PUID=1000, PGID=1000]
labels: ["com.centurylinklabs.watchtower.enable=true"]
volumes:
- ./volumes/audiobookshelf/config:/config
- ./volumes/audiobookshelf/metadata:/metadata
- /home/gib/Public/Audiobooks:/audiobooks
- /home/gib/Public/Podcasts:/podcasts
tty: true
stdin_open: true
restart: unless-stopped
jellyplex-watched:
image: luigi311/jellyplex-watched:latest
container_name: jellyplex-watched
hostname: jellyplex-watched
networks: [nginx-bridge]
environment:
DRYRUN: False
DEBUG_LEVEL: INFO # Or debug for verbose logging
RUN_ONLY_ONCE: False
SLEEP_DURATION: 3600
REQUEST_TIMEOUT: 300
MAX_THREADS: 2
GENERATE_GUIDS: False
GENERATE_LOCATIONS: True
USER_MAPPING: '{ "gib": "gibby_b", "adrian": "Adrian"}'
LIBRARY_MAPPING: '{ "TV Shows": "Shows"}'
PLEX_BASEURL: http://plex:32400
PLEX_TOKEN: ${PLEX_TOKEN}
SSL_BYPASS: False
JELLYFIN_BASEURL: http://jellyfin:8096
JELLYFIN_TOKEN: ${JELLYFIN_TOKEN}
SYNC_FROM_PLEX_TO_JELLYFIN: True
SYNC_FROM_JELLYFIN_TO_PLEX: True
tty: true
stdin_open: true
restart: unless-stopped
gluetun:
image: qmcgaw/gluetun:latest
container_name: gluetun
hostname: gluetun
networks: [nginx-bridge]
cap_add: [NET_ADMIN]
devices: [/dev/net/tun:/dev/net/tun]
#ports:
#- 8000:8000 # HTTP control server
#- 8080:8080 # For SABnzbd
#- 6969:6969 # For qBittorrent
#- 6881:6881 # For torrent connectivity
#- 6881:6881/udp # For torrent connectivity
environment:
- VPN_SERVICE_PROVIDER=private internet access
- VPN_TYPE=openvpn
- SERVER_REGIONS=US East
- OPENVPN_USER=p7671057
- OPENVPN_PASSWORD=${OPENVPN_PASSWORD}
- TZ=America/New_York
- PUID=1000
- PGID=100
labels: [com.centurylinklabs.watchtower.enable=true]
restart: unless-stopped
tty: true
stdin_open: true
sabnzbd:
image: lscr.io/linuxserver/sabnzbd:latest
container_name: sabnzbd
domainname: sabnzbd.gbrown.org
network_mode: service:gluetun
environment: [PUID=1000, PGID=1000, TZ=America/New_York]
labels: [com.centurylinklabs.watchtower.enable=true]
volumes:
- ./volumes/sabnzbd:/config
- /home/gib/Public/Downloads:/downloads
- /home/gib/Public/Downloads/incomplete:/incomplete-downloads
depends_on: [gluetun]
restart: unless-stopped
tty: true
stdin_open: true
qbittorrent:
image: linuxserver/qbittorrent:latest
container_name: qbittorrent
network_mode: service:gluetun
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
- WEBUI_PORT=6969
labels: [com.centurylinklabs.watchtower.enable=true]
volumes:
- ./volumes/qbittorrent:/config
- /home/gib/Public/Downloads:/downloads
depends_on: [gluetun]
tty: true
stdin_open: true
restart: unless-stopped
qbit-guard:
image: ghcr.io/gengines/qbit-guard:latest
container_name: qbitguard
hostname: qbitguard
networks: [nginx-bridge]
labels: [com.centurylinklabs.watchtower.enable=true]
environment:
- QBIT_HOST=http://gluetun:6969
- QBIT_USER=gib
- QBIT_PASS=${QBIT_PASS}
- QBIT_ALLOWED_CATEGORIES=tv-sonarr,radarr
- ENABLE_PREAIR_CHECK=1
- SONARR_URL=http://sonarr:8989
- SONARR_API_KEY=${SONARR_API_KEY}
- SONARR_CATEGORIES=tv-sonarr
- RADARR_URL=http://radarr:7878
- RADARR_API_KEY=${RADARR_API_KEY}
- RADARR_CATEGORIES=radarr
- ENABLE_ISO_CHECK=1
tty: true
stdin_open: true
restart: unless-stopped
seerr:
image: ghcr.io/seerr-team/seerr:latest
container_name: seerr
init: true
hostname: seerr
domainname: seerr.gbrown.org
networks: [nginx-bridge]
#ports: [5055:5055]
environment: [LOG_LEVEL=debug, TZ=America/New_York]
volumes: [./volumes/seerr:/app/config]
labels: [com.centurylinklabs.watchtower.enable=true]
depends_on: [radarr, sonarr]
healthcheck:
test: wget --no-verbose --tries=1 --spider http://localhost:5055/api/v1/status || exit 1
start_period: 20s
timeout: 3s
interval: 15s
retries: 3
tty: true
stdin_open: true
restart: unless-stopped
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
container_name: prowlarr
hostname: prowlarr
domainname: prowlarr.gbrown.org
networks: [nginx-bridge]
#ports: [9696:9696]
environment: [PUID=1000, PGID=1000, TZ=America/New_York]
volumes: [./volumes/prowlarr:/config]
labels: [com.centurylinklabs.watchtower.enable=true]
depends_on: [qbittorrent, sabnzbd]
tty: true
stdin_open: true
restart: unless-stopped
lidarr:
image: lscr.io/linuxserver/lidarr:latest
container_name: lidarr
hostname: lidarr
domainname: lidarr.gbrown.org
networks: [nginx-bridge]
#ports: [8686:8686]
environment: [PUID=1000, PGID=1000, TZ=America/New_York]
volumes:
- ./volumes/lidarr:/config
- /home/gib/Public/Music:/music
- /home/gib/Public/Downloads:/downloads
labels: [com.centurylinklabs.watchtower.enable=true]
depends_on: [prowlarr, qbittorrent, sabnzbd]
tty: true
stdin_open: true
restart: unless-stopped
radarr:
image: ghcr.io/linuxserver/radarr:latest
container_name: radarr
hostname: radarr
domainname: radarr.gbrown.org
networks: [nginx-bridge]
#ports: [7878:7878]
environment: [PUID=1000, PGID=1000, TZ=America/New_York]
volumes:
- ./volumes/radarr:/config
- /home/gib/Public/Movies:/movies
- /home/gib/Public/Downloads:/downloads
labels: [com.centurylinklabs.watchtower.enable=true]
depends_on: [prowlarr, qbittorrent, sabnzbd]
tty: true
stdin_open: true
restart: unless-stopped
sonarr:
image: ghcr.io/linuxserver/sonarr:latest
container_name: sonarr
hostname: sonarr
domainname: sonarr.gbrown.org
networks: [nginx-bridge]
#ports: [8989:8989]
environment: [PUID=1000, PGID=1000, TZ=America/New_York]
labels: [com.centurylinklabs.watchtower.enable=true]
volumes:
- ./volumes/sonarr:/config
- /home/gib/Public/TV:/tv
- /home/gib/Public/Downloads:/downloads
depends_on: [prowlarr, qbittorrent, sabnzbd]
tty: true
stdin_open: true
restart: unless-stopped
bazarr:
image: lscr.io/linuxserver/bazarr:latest
container_name: bazarr
hostname: bazarr
domainname: bazarr.gbrown.org
networks: [nginx-bridge]
#ports: [6767:6767]
environment: [PUID=1000, PGID=1000, TZ=America/New_York]
volumes:
- ./volumes/bazarr:/config
- /home/gib/Public/Movies:/movies
- /home/gib/Public/TV:/tv
labels: [com.centurylinklabs.watchtower.enable=true]
tty: true
stdin_open: true
restart: unless-stopped
whisperasr:
image: onerahmet/openai-whisper-asr-webservice:latest-gpu
container_name: whisperasr
hostname: whisperasr
networks: [nginx-bridge]
#ports: [9000:9000]
environment: [TZ=America/New_York, PUID=1000, PGID=1000, ASR_MODEL=small]
labels: [com.centurylinklabs.watchtower.enable=true]
devices: [/dev/dri:/dev/dri]
tty: true
stdin_open: true
restart: unless-stopped
security_opt: ["seccomp:unconfined"]
runtime: nvidia
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
unpackerr:
image: golift/unpackerr:latest
container_name: unpackerr
hostname: unpackerr
networks: [nginx-bridge]
volumes:
- /home/gib/Public/Downloads:/downloads
- /home/gib/Server/Media/volumes/unpackerr:/config
environment:
- TZ=America/New_York
# log lives in its own volume, NOT in /downloads where the *arr apps scan
- UN_LOG_FILE=/config/unpackerr.log
- UN_LOG_FILES=4
- UN_LOG_FILE_MB=5
- UN_SONARR_0_URL=http://sonarr:8989
- UN_SONARR_0_API_KEY=${UN_SONARR_0_API_KEY}
- UN_RADARR_0_URL=http://radarr:7878
- UN_RADARR_0_API_KEY=${UN_RADARR_0_API_KEY}
labels: [com.centurylinklabs.watchtower.enable=true]
tty: true
stdin_open: true
restart: always
metube:
image: ghcr.io/alexta69/metube:latest
container_name: metube
hostname: metube
domainname: metube.gbrown.org
networks: [nginx-bridge]
#ports: [8081:8081]
environment:
- TZ=America/New_York
- PUID=1000
- PGID=1000
- YTDL_OPTIONS={"cookiefile":"/cookies/cookies.txt"}
volumes:
- ./volumes/metube:/cookies:rw
- /home/gib/Public/Downloads:/downloads:rw
labels: [com.centurylinklabs.watchtower.enable=true]
tty: true
stdin_open: true
restart: unless-stopped
pinchflat:
image: ghcr.io/kieraneglin/pinchflat:latest
container_name: pinchflat
hostname: pinchflat
domainname: pinchflat.gbrown.org
networks: [nginx-bridge]
#ports: [8945:8945]
environment: [TZ=America/New_York, PUID=1000, PGID=1000]
volumes:
- ./volumes/pinchflat:/config:rw
- /home/gib/Public/Downloads:/downloads:rw
labels: [com.centurylinklabs.watchtower.enable=true]
tty: true
stdin_open: true
restart: unless-stopped
configarr:
image: ghcr.io/raydak-labs/configarr:latest
container_name: configarr
hostname: configarr
domainname: configarr.gbrown.org
networks: [nginx-bridge]
environment: [TZ=America/New_York, PUID=1000, PGID=1000]
labels: [com.centurylinklabs.watchtower.enable=true]
volumes:
- ./volumes/configarr/config:/app/config
- ./volumes/configarr/repos:/app/repos
- ./volumes/configarr/cfs:/app/cfs
- ./volumes/configarr/templates:/app/templates
depends_on: [radarr, sonarr]
tty: true
stdin_open: true
# Run-to-completion: configarr syncs TRaSH guides into Sonarr/Radarr,
# prints an execution summary, and exits 0. It has no built-in scheduler
# (upstream points at Ofelia or cron for that), so `unless-stopped` here
# meant a completed sync was immediately restarted -- a hot loop of ~9
# full syncs every 3 minutes. `no` lets it run once per `up` and stop.
restart: "no"
+18
View File
@@ -0,0 +1,18 @@
[Unit]
Description=Podman Compose: Media
After=network-online.target podman.socket
Wants=network-online.target
[Service]
Type=oneshot
WorkingDirectory=%h/Server/Media
ExecStart=/usr/bin/podman compose up -d
ExecStop=/usr/bin/podman compose down
RemainAfterExit=yes
TimeoutStartSec=900
TimeoutStopSec=90
Restart=on-failure
RestartSec=30
[Install]
WantedBy=default.target