arr fleet: FrankBook-Pro is the sole deployment, all egress VPN-gated
FrankBook-Pro becomes the only *arr/qBittorrent deployment. Every fleet container (qB + five arrs) now shares gluetun's netns, so all egress — torrent, indexer APIs, metadata lookups — exits the WireGuard tunnel by construction (AllowedIPs=0.0.0.0/0); the arrs' own ports publish on the gluetun unit, none on the arr units themselves. - dankserver/compose.yaml: remove the six arr services (the Aug 20 compose copy — never healthy, superseded; config dirs trashed on the host) - dankclaw/Caddyfile + shared/homepage/services.json: arr vhosts and probes repoint 192.168.0.235 -> 192.168.0.112 (FrankBook-Pro) - frankbook-pro units: five arrs join gluetun netns (Wants/After/Network); gluetun publishes 9696/8989/7878/8686/8787 alongside 8080/6881 - tests/frankbook_quadlet.bats: new VPN egress seam — every arr+qB unit must share gluetun's netns and publish no port; gluetun must publish the whole fleet's ports - deploy-plan.py: gluetun changes carry the whole netns family (a gluetun recreation kills all six joiners); dankserver compose set loses the arrs - AGENTS.md: deployment is complete only when unit tests AND the Playwright E2E suite both pass
This commit is contained in:
@@ -130,6 +130,18 @@ Set `FRANK_SUDO_PW` for headless runs on a host without passwordless sudo
|
||||
(remote sudo reads it from stdin via `sudo -S`). The value is never stored
|
||||
in this repo.
|
||||
|
||||
### Deployment completeness (MANDATORY)
|
||||
|
||||
A deployment is **not complete** when `deploy.sh` exits green. It is complete
|
||||
only when BOTH of the following pass:
|
||||
|
||||
1. **Unit/config tests** — `./tests/run.sh` (all seams green), and
|
||||
2. **Playwright end-to-end tests** — `tests/e2e/run.sh` drives the LIVE fleet
|
||||
(homepage, Anubis/Authentik guard chain, guarded vhosts) in a real
|
||||
browser. The E2E suite is deliberately excluded from `./tests/run.sh`
|
||||
because it needs live hosts and credentials, so it MUST be invoked
|
||||
explicitly after every behavior-affecting deploy.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[Edit locally] --> B[Tests pass]
|
||||
|
||||
+12
-12
@@ -241,27 +241,27 @@ jelly.franksdank.cloud {
|
||||
# --- *arr Stack (exempt by construction: own auth) ---
|
||||
|
||||
prowlarr.franksdank.cloud {
|
||||
reverse_proxy 192.168.0.235:9696
|
||||
reverse_proxy 192.168.0.112:9696
|
||||
}
|
||||
|
||||
radarr.franksdank.cloud {
|
||||
reverse_proxy 192.168.0.235:7878
|
||||
reverse_proxy 192.168.0.112:7878
|
||||
}
|
||||
|
||||
sonarr.franksdank.cloud {
|
||||
reverse_proxy 192.168.0.235:8989
|
||||
reverse_proxy 192.168.0.112:8989
|
||||
}
|
||||
|
||||
lidarr.franksdank.cloud {
|
||||
reverse_proxy 192.168.0.235:8686
|
||||
reverse_proxy 192.168.0.112:8686
|
||||
}
|
||||
|
||||
readarr.franksdank.cloud {
|
||||
reverse_proxy 192.168.0.235:8787
|
||||
reverse_proxy 192.168.0.112:8787
|
||||
}
|
||||
|
||||
qbittorrent.franksdank.cloud {
|
||||
reverse_proxy 192.168.0.235:8080
|
||||
reverse_proxy 192.168.0.112:8080
|
||||
}
|
||||
|
||||
# --- Internal listener: auth decision layer ---------------------------------
|
||||
@@ -354,32 +354,32 @@ http://:8017 {
|
||||
|
||||
@prowlarr host prowlarr.franksdank.cloud
|
||||
handle @prowlarr {
|
||||
reverse_proxy 192.168.0.235:9696
|
||||
reverse_proxy 192.168.0.112:9696
|
||||
}
|
||||
|
||||
@radarr host radarr.franksdank.cloud
|
||||
handle @radarr {
|
||||
reverse_proxy 192.168.0.235:7878
|
||||
reverse_proxy 192.168.0.112:7878
|
||||
}
|
||||
|
||||
@sonarr host sonarr.franksdank.cloud
|
||||
handle @sonarr {
|
||||
reverse_proxy 192.168.0.235:8989
|
||||
reverse_proxy 192.168.0.112:8989
|
||||
}
|
||||
|
||||
@lidarr host lidarr.franksdank.cloud
|
||||
handle @lidarr {
|
||||
reverse_proxy 192.168.0.235:8686
|
||||
reverse_proxy 192.168.0.112:8686
|
||||
}
|
||||
|
||||
@readarr host readarr.franksdank.cloud
|
||||
handle @readarr {
|
||||
reverse_proxy 192.168.0.235:8787
|
||||
reverse_proxy 192.168.0.112:8787
|
||||
}
|
||||
|
||||
@qbittorrent host qbittorrent.franksdank.cloud
|
||||
handle @qbittorrent {
|
||||
reverse_proxy 192.168.0.235:8080
|
||||
reverse_proxy 192.168.0.112:8080
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,5 +20,3 @@ COPAY_PASS=changeme
|
||||
# Jellyfin
|
||||
JELLYFIN_PUBLISH_SERVER_URL=http://192.168.0.235:8096
|
||||
|
||||
# *arr Stack
|
||||
ARR_TZ=America/New_York
|
||||
|
||||
@@ -146,109 +146,6 @@ services:
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
# ═══════════════════════════════════════════════
|
||||
# *arr Stack — automated media download
|
||||
# ═══════════════════════════════════════════════
|
||||
prowlarr:
|
||||
image: lscr.io/linuxserver/prowlarr:latest
|
||||
container_name: prowlarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=0
|
||||
- PGID=0
|
||||
- TZ=America/Los_Angeles
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /mnt/entropy/downloads:/downloads:ro
|
||||
- /opt/prowlarr/config:/config
|
||||
networks: [appnet]
|
||||
ports:
|
||||
- "9696:9696"
|
||||
|
||||
qbittorrent:
|
||||
image: lscr.io/linuxserver/qbittorrent:latest
|
||||
container_name: qbittorrent
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=0
|
||||
- PGID=0
|
||||
- TZ=America/Los_Angeles
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/qbittorrent/config:/config
|
||||
- /mnt/entropy/downloads:/downloads
|
||||
- /mnt/entropy/downloads/incomplete:/downloads/incomplete
|
||||
ports:
|
||||
- "8080:8080"
|
||||
networks: [appnet]
|
||||
|
||||
radarr:
|
||||
image: lscr.io/linuxserver/radarr:latest
|
||||
container_name: radarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=0
|
||||
- PGID=0
|
||||
- TZ=America/Los_Angeles
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/radarr/config:/config
|
||||
- /mnt/entropy/Movies:/movies
|
||||
- /mnt/entropy/downloads:/downloads
|
||||
ports:
|
||||
- "7878:7878"
|
||||
networks: [appnet]
|
||||
|
||||
sonarr:
|
||||
image: lscr.io/linuxserver/sonarr:latest
|
||||
container_name: sonarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=0
|
||||
- PGID=0
|
||||
- TZ=America/Los_Angeles
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/sonarr/config:/config
|
||||
- /mnt/entropy/TVShows:/tv
|
||||
- /mnt/entropy/downloads:/downloads
|
||||
ports:
|
||||
- "8989:8989"
|
||||
networks: [appnet]
|
||||
|
||||
lidarr:
|
||||
image: lscr.io/linuxserver/lidarr:latest
|
||||
container_name: lidarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=0
|
||||
- PGID=0
|
||||
- TZ=America/Los_Angeles
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/lidarr/config:/config
|
||||
- /mnt/entropy/Music:/music
|
||||
- /mnt/entropy/downloads:/downloads
|
||||
ports:
|
||||
- "8686:8686"
|
||||
networks: [appnet]
|
||||
|
||||
readarr:
|
||||
image: lscr.io/linuxserver/readarr:amd64-1.0.980
|
||||
container_name: readarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=0
|
||||
- PGID=0
|
||||
- TZ=America/Los_Angeles
|
||||
- UMASK_SET=022
|
||||
volumes:
|
||||
- /opt/readarr/config:/config
|
||||
- /mnt/entropy/eBooks:/books
|
||||
- /mnt/entropy/downloads:/downloads
|
||||
ports:
|
||||
- "8787:8787"
|
||||
networks: [appnet]
|
||||
|
||||
# ═══════════════════════════════════════════════
|
||||
# Node Exporter — host metrics
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
# (installed by the frankbook-pro handler in scripts/deploy-remote.sh —
|
||||
# install_quadlet targets the Linux hosts' systemctl --user, not the VM).
|
||||
#
|
||||
# WireGuard tunnel to ProtonVPN. qBittorrent shares this container's network
|
||||
# namespace (Network=gluetun.container) so torrent egress never touches the
|
||||
# residential IP. qBittorrent's WebUI and BitTorrent ports publish HERE — a
|
||||
# netns-sharer publishes no ports of its own (same invariant as the dankclaw
|
||||
# searxng/gluetun pair). Credentials live in
|
||||
# WireGuard tunnel to ProtonVPN. qBittorrent and all five *arrs share this
|
||||
# container's network namespace (Network=gluetun.container) so every fleet
|
||||
# container's egress — torrent traffic, indexer APIs, metadata lookups —
|
||||
# exits ONLY through the tunnel (AllowedIPs=0.0.0.0/0). Every fleet port
|
||||
# publishes HERE; a netns-sharer publishes no ports of its own (same
|
||||
# invariant as the dankclaw searxng/gluetun pair). Credentials live in
|
||||
# /home/core/Containers/gluetun/env inside the VM (mode 0600, never
|
||||
# committed); the private key is Mac-tunnel-specific and MUST NOT be copied
|
||||
# from dankclaw — one WireGuard peer key cannot serve two machines at once.
|
||||
@@ -33,6 +34,11 @@ Environment=WIREGUARD_PERSISTENT_KEEPALIVE_INTERVAL=${WIREGUARD_PERSISTENT_KEEPA
|
||||
PublishPort=8080:8080
|
||||
PublishPort=6881:6881
|
||||
PublishPort=6881:6881/udp
|
||||
PublishPort=9696:9696
|
||||
PublishPort=8989:8989
|
||||
PublishPort=7878:7878
|
||||
PublishPort=8686:8686
|
||||
PublishPort=8787:8787
|
||||
|
||||
[Service]
|
||||
EnvironmentFile=/home/core/Containers/gluetun/env
|
||||
|
||||
@@ -3,10 +3,15 @@
|
||||
# Install path is INSIDE the machine VM:
|
||||
# /home/core/.config/containers/systemd/lidarr.container
|
||||
#
|
||||
#
|
||||
# Joins gluetun's network namespace: all egress exits through the WireGuard
|
||||
# tunnel; 8686 publishes on the gluetun unit.
|
||||
# Grab-only: no media binds; config migrated from dankserver's retired
|
||||
# bare container.
|
||||
[Unit]
|
||||
Description=Lidarr (FrankBook-Pro)
|
||||
Wants=gluetun.service
|
||||
After=gluetun.service
|
||||
|
||||
[Container]
|
||||
ContainerName=lidarr
|
||||
@@ -16,7 +21,7 @@ Environment=PGID=0
|
||||
Environment=TZ=America/Los_Angeles
|
||||
Environment=UMASK_SET=022
|
||||
Volume=/Volumes/COMPLETE/lidarr-data:/config
|
||||
PublishPort=8686:8686
|
||||
Network=gluetun.container
|
||||
|
||||
[Service]
|
||||
TimeoutStartSec=900
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
# Install path is INSIDE the machine VM:
|
||||
# /home/core/.config/containers/systemd/prowlarr.container
|
||||
#
|
||||
#
|
||||
# Joins gluetun's network namespace: all egress (indexer APIs, metadata
|
||||
# lookups) exits through the WireGuard tunnel; 9696 publishes on the
|
||||
# gluetun unit. Same-netns targets (qB, the arrs) are loopback addresses.
|
||||
# Arr on the Mac is grab-only: indexer + app-sync management lives here, the
|
||||
# arrs never auto-import media (the user reviews completed torrents in
|
||||
# /Volumes/COMPLETE/"Finished Torrents" and moves files manually into the
|
||||
@@ -11,9 +15,12 @@
|
||||
# Config is migrated from dankserver's retired bare container
|
||||
# (tar-archived first, per the Phase 4 cutover note) — indexers and app
|
||||
# settings survive; stale host pointers (old qbit at 192.168.0.235:8080)
|
||||
# are re-pointed to the Mac's qbit via its API after first boot.
|
||||
# are re-pointed to loopback qBittorrent (127.0.0.1:8080, same netns) via
|
||||
# its API after first boot.
|
||||
[Unit]
|
||||
Description=Prowlarr (FrankBook-Pro)
|
||||
Wants=gluetun.service
|
||||
After=gluetun.service
|
||||
|
||||
[Container]
|
||||
ContainerName=prowlarr
|
||||
@@ -23,7 +30,7 @@ Environment=PGID=0
|
||||
Environment=TZ=America/Los_Angeles
|
||||
Environment=UMASK_SET=022
|
||||
Volume=/Volumes/COMPLETE/prowlarr-data:/config
|
||||
PublishPort=9696:9696
|
||||
Network=gluetun.container
|
||||
|
||||
[Service]
|
||||
TimeoutStartSec=900
|
||||
|
||||
@@ -3,10 +3,15 @@
|
||||
# Install path is INSIDE the machine VM:
|
||||
# /home/core/.config/containers/systemd/radarr.container
|
||||
#
|
||||
#
|
||||
# Joins gluetun's network namespace: all egress exits through the WireGuard
|
||||
# tunnel; 7878 publishes on the gluetun unit.
|
||||
# Grab-only: no media binds; config migrated from dankserver's retired
|
||||
# bare container.
|
||||
[Unit]
|
||||
Description=Radarr (FrankBook-Pro)
|
||||
Wants=gluetun.service
|
||||
After=gluetun.service
|
||||
|
||||
[Container]
|
||||
ContainerName=radarr
|
||||
@@ -16,7 +21,7 @@ Environment=PGID=0
|
||||
Environment=TZ=America/Los_Angeles
|
||||
Environment=UMASK_SET=022
|
||||
Volume=/Volumes/COMPLETE/radarr-data:/config
|
||||
PublishPort=7878:7878
|
||||
Network=gluetun.container
|
||||
|
||||
[Service]
|
||||
TimeoutStartSec=900
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
# Install path is INSIDE the machine VM:
|
||||
# /home/core/.config/containers/systemd/readarr.container
|
||||
#
|
||||
#
|
||||
# Joins gluetun's network namespace: all egress exits through the WireGuard
|
||||
# tunnel; 8787 publishes on the gluetun unit.
|
||||
# Grab-only: no media binds; config migrated from dankserver's retired
|
||||
# bare container.
|
||||
#
|
||||
@@ -11,6 +14,8 @@
|
||||
# of a broken 1.x nightly for Readarr; the pin avoids surprises.
|
||||
[Unit]
|
||||
Description=Readarr (FrankBook-Pro)
|
||||
Wants=gluetun.service
|
||||
After=gluetun.service
|
||||
|
||||
[Container]
|
||||
ContainerName=readarr
|
||||
@@ -20,7 +25,7 @@ Environment=PGID=0
|
||||
Environment=TZ=America/Los_Angeles
|
||||
Environment=UMASK_SET=022
|
||||
Volume=/Volumes/COMPLETE/readarr-data:/config
|
||||
PublishPort=8787:8787
|
||||
Network=gluetun.container
|
||||
|
||||
[Service]
|
||||
TimeoutStartSec=900
|
||||
|
||||
@@ -3,11 +3,16 @@
|
||||
# Install path is INSIDE the machine VM:
|
||||
# /home/core/.config/containers/systemd/sonarr.container
|
||||
#
|
||||
#
|
||||
# Joins gluetun's network namespace: all egress exits through the WireGuard
|
||||
# tunnel; 8989 publishes on the gluetun unit.
|
||||
# Grab-only: no media binds (the TV library lives on dankserver's entropy
|
||||
# disk, which the Mac never mounts); config migrated from dankserver's
|
||||
# retired bare container.
|
||||
[Unit]
|
||||
Description=Sonarr (FrankBook-Pro)
|
||||
Wants=gluetun.service
|
||||
After=gluetun.service
|
||||
|
||||
[Container]
|
||||
ContainerName=sonarr
|
||||
@@ -17,7 +22,7 @@ Environment=PGID=0
|
||||
Environment=TZ=America/Los_Angeles
|
||||
Environment=UMASK_SET=022
|
||||
Volume=/Volumes/COMPLETE/sonarr-data:/config
|
||||
PublishPort=8989:8989
|
||||
Network=gluetun.container
|
||||
|
||||
[Service]
|
||||
TimeoutStartSec=900
|
||||
|
||||
@@ -147,12 +147,6 @@ DANKSERVER_COMPOSE_SERVICES = {
|
||||
"copyparty",
|
||||
"jellyfin",
|
||||
"calibre-web",
|
||||
"prowlarr",
|
||||
"qbittorrent",
|
||||
"radarr",
|
||||
"sonarr",
|
||||
"lidarr",
|
||||
"readarr",
|
||||
}
|
||||
COMPOSE_NAME_MAP = {"mariadb": "romm-mariadb", "redis": "romm-redis"}
|
||||
|
||||
@@ -341,9 +335,11 @@ def services_for_path(path: str, target: str) -> set[str]:
|
||||
if len(parts) >= 3 and parts[2] == "quadlet":
|
||||
name = parts[3].removesuffix(".container")
|
||||
if name == "gluetun":
|
||||
# qBittorrent shares gluetun's network namespace; a gluetun
|
||||
# recreation requires both units to be restarted.
|
||||
_add(services, "gluetun", "qbittorrent")
|
||||
# Every *arr + qBittorrent container shares gluetun's
|
||||
# network namespace; a gluetun recreation kills all of
|
||||
# them, so the plan restarts the whole netns family.
|
||||
_add(services, "gluetun", "qbittorrent",
|
||||
"prowlarr", "sonarr", "radarr", "lidarr", "readarr")
|
||||
elif name in FRANKBOOK_SERVICES:
|
||||
_add(services, name)
|
||||
return services
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
"description": "TV series library and automation.",
|
||||
"url": "http://sonarr.franksdank.cloud",
|
||||
"docs": "",
|
||||
"probe": "192.168.0.235:8989",
|
||||
"probe": "192.168.0.112:8989",
|
||||
"method": "http",
|
||||
"wip": false,
|
||||
"showLink": true
|
||||
@@ -259,7 +259,7 @@
|
||||
"description": "Indexer manager.",
|
||||
"url": "http://prowlarr.franksdank.cloud",
|
||||
"docs": "",
|
||||
"probe": "192.168.0.235:9696",
|
||||
"probe": "192.168.0.112:9696",
|
||||
"method": "http",
|
||||
"wip": false,
|
||||
"showLink": true
|
||||
@@ -270,7 +270,7 @@
|
||||
"description": "Movie library and automation.",
|
||||
"url": "http://radarr.franksdank.cloud",
|
||||
"docs": "",
|
||||
"probe": "192.168.0.235:7878",
|
||||
"probe": "192.168.0.112:7878",
|
||||
"method": "http",
|
||||
"wip": false,
|
||||
"showLink": true
|
||||
@@ -281,7 +281,7 @@
|
||||
"description": "Book library and automation.",
|
||||
"url": "http://readarr.franksdank.cloud",
|
||||
"docs": "",
|
||||
"probe": "192.168.0.235:8787",
|
||||
"probe": "192.168.0.112:8787",
|
||||
"method": "http",
|
||||
"wip": false,
|
||||
"showLink": true
|
||||
@@ -292,7 +292,7 @@
|
||||
"description": "Music library and automation.",
|
||||
"url": "http://lidarr.franksdank.cloud",
|
||||
"docs": "",
|
||||
"probe": "192.168.0.235:8686",
|
||||
"probe": "192.168.0.112:8686",
|
||||
"method": "http",
|
||||
"wip": false,
|
||||
"showLink": true
|
||||
@@ -303,7 +303,7 @@
|
||||
"description": "Torrent client.",
|
||||
"url": "http://qbittorrent.franksdank.cloud",
|
||||
"docs": "",
|
||||
"probe": "192.168.0.235:8080",
|
||||
"probe": "192.168.0.112:8080",
|
||||
"method": "http",
|
||||
"wip": false,
|
||||
"showLink": true
|
||||
|
||||
@@ -111,11 +111,11 @@ REMOTE_DEPLOY="$REPO_ROOT/scripts/deploy-remote.sh"
|
||||
[ "$output" = $'gitea-postgres\ngitea-server' ]
|
||||
}
|
||||
|
||||
@test "frankbook-pro gluetun changes carry qbittorrent; arr changes stay scoped" {
|
||||
@test "frankbook-pro gluetun changes carry the whole netns family; arr changes stay scoped" {
|
||||
run python3 "$PLANNER" --target frankbook-pro --paths \
|
||||
frankbook-pro/gluetun/quadlet/gluetun.container
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = $'gluetun\nqbittorrent' ]
|
||||
[ "$output" = $'gluetun\nprowlarr\nqbittorrent\nradarr\nsonarr\nlidarr\nreadarr' ]
|
||||
run python3 "$PLANNER" --target frankbook-pro --paths \
|
||||
frankbook-pro/sonarr/quadlet/sonarr.container
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
# Seam: the FrankBook-Pro quadlet units (gluetun, qbittorrent, five *arrs).
|
||||
# These units are installed INSIDE the Mac's podman machine VM by the
|
||||
# frankbook-pro handler in deploy-remote.sh. The contract pinned here:
|
||||
# boot persistence, self-healing, the gluetun netns invariant (qBittorrent
|
||||
# publishes no port of its own; gluetun publishes both), the verbatim
|
||||
# plan-locked data-root mounts, and zero literal secrets in tracked files.
|
||||
# boot persistence, self-healing, the VPN egress invariant (the whole
|
||||
# *arr fleet + qBittorrent share gluetun's netns and publish no ports of
|
||||
# their own, so ALL egress exits through the WireGuard tunnel —
|
||||
# AllowedIPs=0.0.0.0/0 — by construction; gluetun publishes every fleet
|
||||
# port), the verbatim plan-locked data-root mounts, and zero literal
|
||||
# secrets in tracked files.
|
||||
|
||||
load helpers
|
||||
|
||||
@@ -31,18 +34,22 @@ FRANKBOOK_UNITS=(
|
||||
done
|
||||
}
|
||||
|
||||
@test "qbittorrent joins gluetun's netns and publishes no port of its own" {
|
||||
local unit="$REPO_ROOT/frankbook-pro/qbittorrent/quadlet/qbittorrent.container"
|
||||
grep -q '^Network=gluetun.container$' "$unit" || return 1
|
||||
grep -q '^Wants=gluetun.service$' "$unit" || return 1
|
||||
grep -q '^After=gluetun.service$' "$unit" || return 1
|
||||
! grep -q '^PublishPort=' "$unit" || return 1
|
||||
@test "every arr and qbittorrent joins gluetun's netns and publishes no port" {
|
||||
local svc unit
|
||||
for svc in qbittorrent prowlarr sonarr radarr lidarr readarr; do
|
||||
unit="$REPO_ROOT/frankbook-pro/$svc/quadlet/$svc.container"
|
||||
grep -q '^Network=gluetun.container$' "$unit" || return 1
|
||||
grep -q '^Wants=gluetun.service$' "$unit" || return 1
|
||||
grep -q '^After=gluetun.service$' "$unit" || return 1
|
||||
! grep -q '^PublishPort=' "$unit" || return 1
|
||||
done
|
||||
}
|
||||
|
||||
@test "gluetun publishes qbittorrent's WebUI and torrent ports and needs NET_ADMIN+tun" {
|
||||
@test "gluetun publishes the whole fleet's ports and needs NET_ADMIN+tun" {
|
||||
local unit="$REPO_ROOT/frankbook-pro/gluetun/quadlet/gluetun.container"
|
||||
grep -q '^PublishPort=8080:8080$' "$unit" || return 1
|
||||
grep -q '^PublishPort=6881:6881$' "$unit" || return 1
|
||||
for port in 8080 6881 9696 8989 7878 8686 8787; do
|
||||
grep -q "^PublishPort=$port:$port\$" "$unit" || return 1
|
||||
done
|
||||
grep -q '^PublishPort=6881:6881/udp$' "$unit" || return 1
|
||||
grep -q '^AddCapability=NET_ADMIN$' "$unit" || return 1
|
||||
grep -q '^AddDevice=/dev/net/tun:/dev/net/tun$' "$unit" || return 1
|
||||
@@ -69,12 +76,7 @@ FRANKBOOK_UNITS=(
|
||||
grep -q '^Volume=/Volumes/INCOMPLETE:/Volumes/INCOMPLETE$' "$unit" || return 1
|
||||
}
|
||||
|
||||
@test "every arr serves its standard port and readarr keeps its pinned image" {
|
||||
grep -q '^PublishPort=9696:9696$' "$REPO_ROOT/frankbook-pro/prowlarr/quadlet/prowlarr.container" || return 1
|
||||
grep -q '^PublishPort=8989:8989$' "$REPO_ROOT/frankbook-pro/sonarr/quadlet/sonarr.container" || return 1
|
||||
grep -q '^PublishPort=7878:7878$' "$REPO_ROOT/frankbook-pro/radarr/quadlet/radarr.container" || return 1
|
||||
grep -q '^PublishPort=8686:8686$' "$REPO_ROOT/frankbook-pro/lidarr/quadlet/lidarr.container" || return 1
|
||||
grep -q '^PublishPort=8787:8787$' "$REPO_ROOT/frankbook-pro/readarr/quadlet/readarr.container" || return 1
|
||||
@test "readarr keeps its pinned image" {
|
||||
grep -q '^Image=lscr.io/linuxserver/readarr:amd64-1.0.980$' \
|
||||
"$REPO_ROOT/frankbook-pro/readarr/quadlet/readarr.container" || return 1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user