Docker Implementation Guide¶
v2.2 | Build 013.20260815.180509Z
Implementation guide for Docker in the McGuckin.Net environment.
McGuckin Docker Environment
Docker Implementation Guide
Version 0.13 | August 15, 2026
| PURPOSE The authoritative implementation, deployment, capacity-planning, operations, and recovery reference for Docker Desktop and the approved JUKEBOX container portfolio. |
|---|
Table of Contents
1. Document Metadata 4
2. Purpose and Scope 5
2.1 Purpose 5
2.2 Scope 5
3. Design Principles 5
3.1 Reproducibility 5
3.2 Separation of Roles 5
3.3 Least Necessary Exposure 5
3.4 Durable State 5
4. Host and Runtime Baseline 6
5. Current Docker Projects 6
5.1 Caddy 6
5.2 FlareSolverr 6
6. Caddy Architecture 7
6.1 Request Path 7
6.2 Certificate Path 7
6.3 Current and Approved Service Routes 7
7. Configuration and Persistence 9
7.1 Project Layout 9
7.2 Runtime Controls 9
8. Network and Security Boundaries 10
9. Operations and Change Control 11
10. Backup and Recovery 13
10.2 Immutable Offsite Backup - Arq 7 and Backblaze B2 14
11. Current Deviations and Decisions 17
12. Approved Application Portfolio 19
13. Installation and Compose Templates 21
14. Resource Capacity Planning 29
Appendix A - Ports and Endpoints 35
Appendix B - Recovery Checklist 36
Appendix C - Revision History 37
1. Document Metadata¶
| Property | Value |
|---|---|
| Document ID | NET-004 |
| Title | McGuckin Docker Implementation Guide |
| Document Owner | Todd McGuckin |
| Status | Draft - Arq 7 and Backblaze B2 immutable offsite backup approved; UniFi DNS pending |
| Version | 0.13 |
| Applies To | JUKEBOX (jukebox.mcguckin.net / 10.10.10.10) |
| Host Platform | Apple iMac M4 running macOS 26.6.1 |
| Container Runtime | Docker Desktop 29.7.2 |
| Compose Version | Docker Compose v5.3.1 |
| Primary Project Root | /Users/toddmcguckin/Containers |
| Active Projects | Caddy; FlareSolverr; approved portfolio pending deployment |
| Related Standards | NET-002 Network Architecture; NET-003 Container Platform Standard |
| Classification | Internal |
| Time Zone | America/New_York |
| DOCUMENT ROLE NET-003 defines the intended platform standard. NET-004 records the present implementation, operational dependencies, justified choices, and known deviations so the environment can be understood and reconstructed. |
|---|
2. Purpose and Scope¶
2.1 Purpose¶
This guide documents the Docker environment currently operating on JUKEBOX and the approved portfolio planned for deployment. It records what each component does, how it is deployed, how much capacity it is expected to consume, and how it is operated and recovered.
2.2 Scope¶
-
Docker Desktop runtime and host dependencies on JUKEBOX.
-
The Caddy and FlareSolverr Compose projects and Caddy-routed JUKEBOX applications.
-
Caddy TLS, DNS, proxy, logging, secret, and persistence design.
-
Routine validation, deployment, backup, rollback, recovery, and resource-capacity expectations.
-
The approved application portfolio, permanent three-letter keys, standardized deployment patterns, and planning resource budgets.
-
Known differences between the current implementation and NET-003.
Native macOS application configuration, media-library administration, and general network addressing remain outside this guide except where Docker depends on them.
3. Design Principles¶
3.1 Reproducibility¶
A running container is not the system of record. Compose definitions, configuration files, secrets references, and persistent state must be sufficient to recreate the service.
3.2 Separation of Roles¶
Docker provides isolated runtime packaging; Caddy provides the HTTPS edge; UniFi and Cloudflare provide different DNS functions; native macOS applications remain independent backends.
3.3 Least Necessary Exposure¶
Only ports needed for an intentional client or integration are published. Administrative applications use UniFi VPN as the approved remote-access boundary while Caddy provides HTTPS routing for LAN and VPN clients. Public Caddy exposure is reserved for services explicitly approved for access without the VPN. Local appliances such as Home Assistant and HDHomeRun are not proxied merely to make their names shorter.
3.4 Durable State¶
Containers and images are replaceable. Configuration, certificates, keys, logs, and application state must persist outside the disposable container filesystem.
4. Host and Runtime Baseline¶
| Component | Current Baseline | Why It Matters |
|---|---|---|
| Host | JUKEBOX / Apple iMac M4 | Provides the continuously available compute and LAN identity. |
| Operating system | macOS 26.6.1 | Docker Desktop and the native Plex/Servarr applications share this host. |
| Docker engine | 29.7.2 | Creates and isolates the active containers. |
| Docker Compose | v5.3.1 | Makes each deployment reproducible from declarative files. |
| Docker VM allocation | 10 CPUs; approximately 7.75 GiB RAM | Defines the resources available to all containers. |
| Docker VM disk | Docker.raw on the macOS system-data volume | Stores images, layers, containers, networks, and Docker-managed volumes. |
| PlexDB | 1.7 TiB volume; approximately 1.3 TiB available | NET-003 designates this SSD for future Docker platform state. |
5. Current Docker Projects¶
| Project | Purpose | Compose File | Runtime State |
|---|---|---|---|
| Caddy | HTTPS reverse proxy for Plex and Servarr applications | ~/Containers/infrastructure/caddy/docker-compose.yml | Running; healthy |
| FlareSolverr | Browser-automation helper used by compatible indexer workflows | ~/Containers/flaresolverr/compose.yaml | Running; no Docker health check |
| WHY TWO PROJECTS Each service is independently deployable and receives its own Compose network. A Caddy change therefore does not require recreating FlareSolverr, and a FlareSolverr change does not disturb the HTTPS edge. |
|---|
6. Caddy Architecture¶
6.1 Request Path¶
-
A client resolves a service name through UniFi split-horizon DNS on the LAN or Cloudflare public DNS remotely.
-
The client connects to JUKEBOX on TCP 443; TCP 80 is retained only for automatic redirection to HTTPS.
-
Caddy selects a site block from the requested hostname and presents that hostname's certificate.
-
Caddy connects through host.docker.internal to the application running directly on macOS.
-
The application response returns through Caddy over the established encrypted client connection.
-
IMPLEMENTED STATE — Docker Desktop presents inbound connections to Caddy through its gateway address, so Caddy source-address matching is not used as the security boundary. JUKEBOX TCP 443 is the private listener for all documented HTTPS routes. UniFi WAN TCP 443 forwards to JUKEBOX TCP 8443, and Caddy TCP 8443 contains only the plex.mcguckin.net application route. Administrative services, including plexstats.mcguckin.net, remain available through TCP 443 from the LAN or UniFi VPN and are absent from the WAN-forwarded listener.
-
VERIFICATION RECORD — On August 14, 2026, every private Caddy route reached its expected login or application endpoint from the LAN. The WAN-forwarded listener reached Plex and returned no application content for tested administrative hostnames. Public DNS returned no AAAA records for the Caddy service names, preventing an IPv6 bypass of the IPv4 forwarding boundary. A live connection from a remote UniFi VPN client remains an operational follow-up.
6.2 Certificate Path¶
The standard Caddy image does not contain the Cloudflare DNS provider. A pinned, multi-stage Docker build compiles Caddy 2.11.4 with that module, then copies only the resulting binary into the production image. This keeps build tooling out of the runtime while enabling DNS-01 certificate validation.
DNS-01 proves control of mcguckin.net through temporary Cloudflare TXT records. It does not require the backend application to answer an internet certificate challenge, and it permits certificates for split-horizon service names.
6.3 Current and Approved Service Routes¶
| Service | Hostname | Backend | Reason for Caddy |
|---|---|---|---|
| Plex | plex.mcguckin.net | host.docker.internal:32400 | Encrypted friendly web entry point; explicit public exception through the Plex-only TCP 8443 listener. |
| Tautulli | plexstats.mcguckin.net | host.docker.internal:44444 | Plex monitoring through the verified private TCP 443 listener. |
| Sonarr | television.mcguckin.net | host.docker.internal:8989 | Authenticated administration through the verified private TCP 443 listener. |
| Radarr | movies.mcguckin.net | host.docker.internal:7878 | Authenticated administration through the verified private TCP 443 listener. |
| Lidarr | music.mcguckin.net | host.docker.internal:8686 | Authenticated administration through the verified private TCP 443 listener. |
| Prowlarr | indexers.mcguckin.net | host.docker.internal:9696 | Authenticated administration through the verified private TCP 443 listener. |
| SABnzbd | downloads.mcguckin.net | host.docker.internal:8888 | Authenticated administration through the verified private TCP 443 listener. |
The following names are approved for planned Docker containers that need stable identity. UniFi DNS publishes each name as an internal CNAME to jukebox.mcguckin.net. Caddy receives only supported HTTP endpoints; background workers retain a stable DNS identity without a false web route. Transmission remains native and retains its existing local access path; no qbittorrent.mcguckin.net record is approved.
| APP KEY | CONTAINER | APPROVED HOSTNAME | DNS / CADDY DISPOSITION |
|---|---|---|---|
| RES | Restic | restic.mcguckin.net | CNAME reserved; background backup worker has no Caddy route. |
| POR | Portainer | portainer.mcguckin.net | Private Caddy route after deployment. |
| HOM | Homepage | homepage.mcguckin.net | Private Caddy route after deployment. |
| BAZ | Bazarr | bazarr.mcguckin.net | Private Caddy route after deployment. |
| CLN | Cleanuparr | cleanuparr.mcguckin.net | Private Caddy route after deployment. |
| KOM | Kometa | kometa.mcguckin.net | CNAME reserved; scheduled worker has no Caddy route. |
| MTR | Maintainerr | maintainerr.mcguckin.net | Private Caddy route after deployment. |
| REC | Recyclarr | recyclarr.mcguckin.net | CNAME reserved; scheduled worker has no Caddy route. |
| SEE | Seerr | seerr.mcguckin.net | Private Caddy route after deployment. |
| CAV | cAdvisor | cadvisor.mcguckin.net | Private metrics endpoint after deployment. |
| GRA | Grafana | grafana.mcguckin.net | Private Caddy route after deployment. |
| NDE | Node Exporter | nodeexporter.mcguckin.net | Private metrics endpoint after deployment. |
| PRM | Prometheus | prometheus.mcguckin.net | Private Caddy route after deployment. |
| SCR | Scrutiny | scrutiny.mcguckin.net | Private Caddy route after deployment if the feasibility gate passes. |
| KUM | Uptime Kuma | uptime.mcguckin.net | Private Caddy route after deployment. |
| NTF | Notifiarr | notifiarr.mcguckin.net | Private Caddy route after deployment. |
| DOZ | Dozzle | dozzle.mcguckin.net | Private Caddy route after deployment. |
| WUD | What's Up Docker (WUD) | wud.mcguckin.net | Private Caddy route after deployment. |
7. Configuration and Persistence¶
7.1 Caddy Project Layout¶
| Path or File | Role | Why It Persists |
|---|---|---|
| Caddyfile | Hostname-to-backend routing and TLS policy | Executable configuration and authoritative proxy intent. |
| docker-compose.yml | Container lifecycle, ports, mounts, health, logging, and security | Recreates the deployment consistently. |
| Dockerfile | Builds Caddy with the Cloudflare module | The provider is not included in the standard image. |
| docker-entrypoint-custom.sh | Loads the token file into CF_API_TOKEN and execs Caddy | Bridges Compose file secrets to the module without embedding the token. |
| data/ | Certificates, private keys, ACME accounts, and access logs | Avoids certificate churn and preserves security/audit state. |
| config/ | Caddy runtime configuration storage | Retains runtime-managed configuration across replacement. |
| secrets/cloudflare_api_token | Restricted Cloudflare API credential | Required for DNS-01; stored separately with mode 600. |
| docs/, scripts/, Makefile | Validated procedures and automation | Reduces undocumented, non-repeatable changes. |
7.2 Runtime Controls¶
| Control | Current Setting | Why |
|---|---|---|
| Restart policy | unless-stopped (current); change to no before startup orchestrator activation | Current behavior restores Caddy independently. The documented migration must transfer boot authority to the orchestrator before it is enabled. |
| Graceful stop | 30 seconds | Allows Caddy to close connections and persist state cleanly. |
| Health check | Admin API on container-local port 2019 | Proves the process and configuration API respond without exposing the API to the LAN. |
| Log rotation | 10 MiB × 5 Docker JSON files | Bounds Docker engine log growth. |
| Access logs | 25 MiB × 10; retained up to 720 hours | Preserves request evidence without unbounded disk use. |
| Privilege control | no-new-privileges:true | Prevents setuid/setgid escalation inside the container. |
8. Network and Security Boundaries¶
The gateway forwards WAN TCP 80 to JUKEBOX TCP 80 and WAN TCP 443 to JUKEBOX TCP 8443. Docker publishes TCP 80, private TCP 443, UDP 443, and the Plex-only TCP 8443 listener for Caddy. JUKEBOX TCP 443 is not the target of a WAN port forward. Backend application ports remain native macOS listeners reached through host.docker.internal.
IMPLEMENTED BOUNDARY — The absence of a WAN forward to JUKEBOX TCP 443 is the administrative-service boundary. UniFi VPN clients use the same private TCP 443 listener as LAN clients. WAN TCP 443 reaches the Plex listener on JUKEBOX TCP 8443. Rollback restores Caddyfile.backup-before-split-listener-20260814-220959 and docker-compose.yml.backup-before-split-listener-20260814-220959, recreates Caddy, and changes the UniFi HTTPS forward from internal TCP 8443 back to internal TCP 443.
| Boundary | Current Decision | Why |
|---|---|---|
| TCP 80 | Published to Caddy | Redirects clients to HTTPS; it does not serve application content in plaintext. |
| TCP 443 | Published by Docker for LAN/VPN HTTPS; not a WAN-forward target | Carries every documented private HTTPS route without relying on Docker-obscured client addresses. |
| TCP 8443 | Published by Docker as the Plex-only WAN-forward target | Receives the UniFi WAN TCP 443 forward without exposing administrative site blocks. |
| UDP 443 | Published to Caddy | Allows HTTP/3/QUIC where supported. |
| Caddy admin API | Container-local only | Administrative control must not be reachable from the LAN or WAN. |
| Cloudflare token | Read-only Compose secret mount; host file mode 600 | Reduces accidental disclosure and limits access to the Caddy service. |
| Backend ports | Not exposed by the Caddy project | Caddy is the intended HTTPS entry point; direct WAN exposure would bypass it. |
| UniFi VPN | Approved private remote-access path to TCP 443 | Remote clients receive the same private HTTPS service access as LAN clients. |
| HDHomeRun | Direct local DNS and HTTP | A local appliance does not need a WAN-facing reverse-proxy route. |
| Home Assistant | Direct local DNS; Nabu Casa for public access | Avoids duplicate public paths and an unnecessary proxy trust relationship. |
| HSTS | Not enabled globally | A persistent include-subdomains policy could break local HTTP devices and complicate recovery. |
| AUTHENTICATION BOUNDARY Caddy provides encryption and routing, not application authorization. Application authentication remains enabled. Administrative routes are restricted to LAN and UniFi VPN clients after the approved migration; public access requires an explicit documented exception. |
|---|
8.1 Native Torrent Privacy Path¶
APPROVED DECISION Transmission remains a native macOS application. The qBittorrent container migration is cancelled because Docker Desktop presents all container egress to macOS as com.docker.backend; a PIA application rule would therefore govern Docker collectively rather than isolate one torrent container.
-
PIA split tunneling is enabled and Transmission is explicitly assigned Only VPN. All Other Apps follows the separately approved host policy; Docker Desktop is not used as the torrent privacy boundary.
-
PIA VPN Kill Switch is enabled. Allow LAN Traffic may remain enabled so the Transmission interface and local integrations remain reachable without permitting public torrent egress outside the VPN.
-
Before Transmission is released to Prowlarr or any Arr application, the startup gate verifies PIA reports Connected, PIA reports a VPN address, Transmission is running, a Transmission-originated egress check shows the PIA address, and a controlled PIA disconnect prevents Transmission internet traffic.
-
If any gate fails, Transmission pauses or stops, its network-dependent automation remains blocked, and the operator is alerted. Usenet workflows may continue through SABnzbd when independently healthy.
-
The test is repeated after every PIA, macOS, or Transmission update and after any split-tunnel rule change. No document statement substitutes for a live leak and failure test on JUKEBOX.
9. Operations and Change Control¶
9.1 Safe Caddy Configuration Change¶
-
Update the governing standard and implementation guide with the intended change, rollback path, and Pending status.
-
Create a timestamped backup of the current Caddyfile.
-
Make the smallest necessary edit and update adjacent explanatory comments.
-
Run the project validation command using the normal secret-loading entrypoint.
-
Review the exact file difference before installation.
-
Reload Caddy gracefully; do not recreate the container for a routing-only change.
-
Test every retained service and confirm removed hostnames are no longer served.
9.2 Image or Compose Change¶
A Caddy version, image, port, mount, health-check, or security change requires Compose validation and controlled container recreation. The CADDY_VERSION build argument and local image tag must remain synchronized. Rebuilds are deliberate because the Cloudflare provider is compiled into the image.
9.3 FlareSolverr Operations¶
FlareSolverr is independently managed from ~/Containers/flaresolverr. Prowlarr reaches its published host port 8191. It is not a Caddy website and must not receive public DNS or a gateway port-forward.
9.4 Routine Verification¶
-
Confirm both containers are running after a host or Docker Desktop restart.
-
Confirm Caddy reports healthy and every documented HTTPS route reaches its expected application endpoint from its approved access boundary.
-
Review Caddy logs for certificate, upstream, authentication, or repeated probing errors.
-
Verify persistent volumes are mounted before destructive cleanup or image pruning.
10. Backup and Recovery¶
| Recovery Input | Criticality | Reason |
|---|---|---|
| Compose definitions | Required | Reconstruct container lifecycle, ports, mounts, health, and security controls. |
| Caddyfile | Required | Restores the approved service routes and backend mapping. |
| Caddy data/ | High | Preserves certificates, private keys, ACME accounts, and access logs. |
| Cloudflare token | Required | Allows DNS-01 issuance and renewal; must be restored securely. |
| Dockerfile and entrypoint | Required | Rebuild the Cloudflare-enabled image and load the token correctly. |
| UniFi and public DNS | Required | Names must direct clients to the correct edge or local endpoint. |
| Backend applications | Required | Caddy cannot serve an application that is stopped or listening on another port. |
| FlareSolverr Compose and volume | Service-dependent | Recreates the helper and preserves its Docker-managed configuration state. |
| Arq 7 backup plan and settings | Required | Reconstructs the encrypted offsite backup job, protected scope, schedule, immutability, and retention controls. |
| B2 bucket, S3 endpoint, and Object Lock configuration | Required | Provides the private immutable offsite repository; the bucket must have Object Lock enabled. |
| Bucket-scoped B2 application key | Required | Allows Arq read/write access without exposing the B2 master application key. |
| Arq encryption password and offline recovery record | Required | Restores client-side encrypted data after host loss; loss of the password can make backups unrecoverable. |
| /Volumes/PlexDB/Plex | High | Preserves the complete native Plex application-data tree while excluding replaceable media libraries. |
10.1 Recovery Sequence¶
-
Restore macOS and start Docker Desktop under the normal JUKEBOX user session.
-
Restore the Caddy and FlareSolverr project directories and required persistent state.
-
Restore the Cloudflare token with directory mode 700 and file mode 600.
-
Build and validate the custom Caddy image before starting production traffic.
-
Start Caddy, wait for a healthy state, and inspect certificate logs.
-
Start FlareSolverr and verify port 8191 from the local host only.
-
Test every documented Caddy URL from its approved LAN, VPN, or public boundary and test the direct local Home Assistant and HDHomeRun names.
| RECOVERY PRINCIPLE Do not delete Caddy data/ during an ordinary rebuild. Caddy can request replacement certificates without it, but repeated issuance loses prior account state and may encounter certificate-authority rate limits. |
|---|
10.2 Immutable Offsite Backup - Arq 7 and Backblaze B2¶
OFFICIAL DECISION JUKEBOX shall use a licensed Arq 7 native macOS client with a dedicated private Backblaze B2 bucket as its immutable offsite backup platform. Arq must connect through B2's S3-compatible endpoint because Arq's native B2 storage type does not support Object Lock. The cloud copy supplements application-native exports, Restic, and Time Machine; it does not replace them.
10.2.1 Recovery Scope and Retention¶
Phase 1 protects the compact recovery set first. Phase 2 adds larger application-state datasets only after the first seed, restore test, bandwidth behavior, and monthly cost are accepted.
| PHASE / DATASET | PATH OR CONTENT | DISPOSITION | RATIONALE |
|---|---|---|---|
| Phase 1 - critical recovery kit | /Volumes/Backups/Application-Exports; /Volumes/Backups/Platform-Recovery; /Volumes/Backups/Host-Recovery; /Volumes/Backups/Recovery-Kits | Include | Small, high-value data required to rebuild native apps, Docker projects, host configuration, and credentials inventories. |
| Phase 2 - Docker state | /Volumes/PlexDB/Docker/compose; appdata; scripts; configs | Include after validation | Restores Compose definitions and durable container state without depending on the Docker Desktop VM disk. |
| Phase 2 - native Plex state | /Volumes/PlexDB/Plex | Include complete tree | Preserves library organization, databases, watch state, artwork, metadata, and customizations; media files remain excluded. |
| Operational logs | /Volumes/PlexDB/Logs | Exclude by default | Logs are useful for troubleshooting but are not required for catastrophic reconstruction; include only incident evidence or a documented exception. |
| Replaceable or recursive data | Storage media; Downloads; caches; temporary files; Docker Desktop VM disk; TARDIS; local Restic repository | Exclude | Avoids backing up replaceable media, transient data, nested backup sets, and unstable runtime artifacts. |
Plex sizing baseline: Finder reported 482.88 GB used on PlexDB on August 15, 2026. That figure is a conservative planning ceiling because it includes more than /Volumes/PlexDB/Plex; measure the exact Plex tree before commissioning. The 44 TB Storage media library is not an Arq/B2 target.
Retention baseline: enable Arq immutable backup records for a minimum of 35 days and refresh locks every 7 days. Maintain at least daily successful runs so Arq can extend locks on deduplicated objects. Arq thinning and budget cleanup cannot delete a locked object until its lock expires.
10.2.2 Dependencies and Software Requirements¶
| DEPENDENCY | STATUS | REQUIREMENT |
|---|---|---|
| Arq 7 | Required | Native macOS application; one-computer license; automatic scheduling; client-side encryption; Arq command-line status tool (arqc) for verification. |
| Backblaze B2 | Required | Active B2 account, billing method, private bucket, Object Lock enabled, recorded S3 endpoint and region, and sufficient storage. |
| B2 application key | Required | Standard bucket-scoped read/write key used only by Arq. Do not use the master application key. |
| Identity protection | Required | Unique Backblaze password and multi-factor authentication. Store recovery codes outside JUKEBOX. |
| Arq encryption material | Required | Strong client-side encryption password plus an offline recovery record. The B2 key alone cannot decrypt the backup. |
| Mounted source volumes | Required | Backups and PlexDB must be mounted and readable before the plan runs. Missing-volume detection must fail the backup gate. |
| Local backup layers | Required | Application-native exports and Restic complete before Arq so the immutable copy contains consistent recovery points. |
| Internet capacity | Required | Stable outbound HTTPS and sufficient upload bandwidth. Initial seed may span dedicated windows; routine incrementals must fit the assigned slot. |
| Restore target | Required | Separate test folder or scratch volume with sufficient capacity for monthly samples and quarterly full recovery exercises. |
| Monitoring | Required | Arq activity/status review, B2 billing and capacity alerts, backup-gate logging, and Uptime Kuma or equivalent operator notification. |
10.2.3 Implementation Procedure¶
1. Create or secure the Backblaze account: use a unique password, enable multi-factor authentication, save recovery codes offline, and add a billing method and budget alert.
2. Create a new private B2 bucket dedicated to JUKEBOX. Enable Object Lock before the production upload. Record the bucket name, S3 endpoint, and region. Object Lock cannot be treated as active until a locked test object is verified.
3. Create a standard B2 application key restricted to the JUKEBOX bucket with the read/write permissions Arq requires. Do not provide Arq the master application key. Record the key ID and secret once in the approved credential store; never place them in Compose, Git, or documentation.
4. Install Arq 7 as a native macOS application on JUKEBOX and purchase the one-computer license after the trial validates the workflow.
5. In Arq, choose New Storage Location, select S3-Compatible Server, enter https:// plus the B2 S3 endpoint, supply the bucket-scoped key ID and secret, and enter the region from the endpoint. Do not select Arq's native Backblaze B2 storage type for this plan because that path cannot enable Object Lock.
6. Create the JUKEBOX-Immutable backup plan. Enable Arq client-side encryption with a new strong password, save the password and recovery instructions offline, and verify that a second authorized device or printed recovery record can supply them after total host loss.
7. Select Phase 1 paths first. Explicitly exclude Storage media, Downloads, caches, temporary files, TARDIS, local Restic repositories, Docker Desktop VM data, and routine logs. After the Phase 1 restore test, add the Docker durable-state paths and the complete /Volumes/PlexDB/Plex tree.
8. Enable Make latest backup record immutable. Set the initial policy to a minimum 35 days with a 7-day refresh interval. Use compliance mode through Arq; do not grant the client bypass-governance authority.
9. Schedule Arq for the 3:20-4:20 a.m. Eastern slot after application-native exports and Restic. Configure the backup gate to require mounted sources, a successful Arq result, a current backup record, and no reported errors before any upgrade starts.
10. Run the initial seed as a commissioning job. Keep it outside normal update activity, allow it to continue across dedicated overnight windows if needed, and defer routine upgrades until the first complete immutable backup and sample restore pass.
11. Restore representative files from each Phase 1 path to the separate restore target. Verify hashes or application readability. Then restore one Docker application configuration and a representative Plex database or metadata item before authorizing Phase 2 as operational.
12. Record the actual protected byte count, first-seed duration, routine incremental duration, B2 stored bytes, estimated monthly charge, lock expiry range, test results, and rollback instructions in the implementation record. Reconcile NET-004 only after the production plan is verified.
10.2.4 Operating and Recovery Controls¶
-
BACKUP-BEFORE-UPGRADE GATE Application-native exports, Restic, and Arq/B2 must all report successful and current recovery points before routine application, container, Docker Desktop, or macOS upgrades begin. A failed or unverified layer changes the window to diagnostics and backup repair only.
-
Emergency security exception: an urgent security update may proceed only with documented owner approval, a verified current local recovery point, a specific rollback plan, and a post-change offsite backup. This is an exception, not the routine path.
-
Review Arq and B2 status daily. Investigate missed runs, missing source volumes, credential failures, lock-refresh failures, unexpected stored-byte growth, and cost alerts before the next maintenance window.
-
Perform a monthly sample restore from B2 and a quarterly full recovery exercise covering credentials, Arq installation, S3-compatible attachment, plan adoption, decryption, representative native application data, one Docker service, and Plex state. A backup is not accepted solely because upload completed.
-
If JUKEBOX or Arq is compromised, disconnect it from B2, preserve logs, rotate the B2 application key and Backblaze credentials from a clean device, recover hidden/deleted backup records if necessary, and restore into a clean target. Object Lock protects locked object versions but does not replace account security or client-side encryption.
10.2.5 Projected Costs¶
Pricing was verified from Arq and Backblaze on August 15, 2026 and remains subject to vendor change, taxes, actual byte-hours, transaction mix, and egress. B2 calculations below use $6.95 per TB per month and round to the nearest cent. CONSERVATIVE BUDGETING RULE — When credible official prices conflict, a published range exists, or an announced increase is relevant, planning shall use the highest credible amount. The estimate must identify the source and verification date and must be verified again before purchase or renewal.
| COST ITEM | TYPE | PROJECTED COST | ASSUMPTION / CONTROL |
|---|---|---|---|
| Arq 7 license | One-time | $59.99 per computer (conservative planning amount) | Arq currently lists $49.99 through August 31, 2026 and has announced $59.99 beginning September 1, 2026. Budget uses the higher credible amount; includes 12 months of updates. |
| Arq updates after included year | Optional recurring | $29.99/year per computer (conservative planning amount) | Arq checkout currently shows $29.99/year while its Pricing FAQ shows $25/year. Budget uses the higher official amount; verify again before renewal. |
| Backblaze B2 storage | Recurring | $6.95/TB/month | Pay-as-you-go byte-hour storage; first 10 GB is currently free. Object Lock has no separate fee. |
| Phase 1 at 10 GB | Recurring estimate | $0.07/month before free-tier effect | Represents a compact recovery kit; actual Phase 1 data must be measured. |
| Phase 1 at 25 GB | Recurring estimate | $0.17/month | Useful early planning point for exports, recipes, host recovery, and credentials inventories. |
| Phase 1 at 100 GB | Recurring estimate | $0.70/month | Upper planning example for the compact recovery set. |
| PlexDB current-used ceiling: 482.88 GB | Recurring estimate | $3.36/month | Conservative ceiling for the future Plex application-data phase; measure /Volumes/PlexDB/Plex directly before authorization. |
| PlexHD plus PlexDB used: about 806 GB | Recurring estimate | $5.60/month | Reference only; the plan does not automatically include the full system volume. |
| Storage media: 41.44 TB used | Excluded estimate | About $288/month | Economically disproportionate and replaceable; excluded from Arq/B2 scope. |
| Restore downloads | Conditional | Free through 3x average monthly storage; then $0.01/GB | Normal disaster recovery should usually remain within the published free-egress allowance. |
Cost-control rule: after commissioning, compare B2 stored bytes and the invoice to the measured protected set each month. Investigate growth above forecast before increasing the budget. Immutability can delay deletion of superseded objects until locks expire, so storage may temporarily exceed the live protected dataset.
10.2.6 Authoritative References¶
-
Arq immutable backup records: https://www.arqbackup.com/documentation/arq7/English.lproj/objectLock.html
-
Arq immutable B2 setup: https://www.arqbackup.com/documentation/arq7/English.lproj/addB2AsS3Compatible.html
-
Arq pricing: https://www.arqbackup.com/pricing/
-
Backblaze B2 Object Lock: https://www.backblaze.com/docs/cloud-storage-object-lock
-
Backblaze B2 pricing: https://www.backblaze.com/cloud-storage/pricing
-
Backblaze B2 application keys: https://www.backblaze.com/docs/en/cloud-storage-application-keys
-
Plex Media Server backup guidance: https://support.plex.tv/articles/201539237-backing-up-plex-media-server-data/
11. Current Deviations and Decisions¶
The following items document the current as-built state without silently treating it as the NET-003 target architecture. Each should be resolved deliberately rather than through opportunistic cleanup.
| Area | Current State | NET-003 Direction | Decision / Rationale |
|---|---|---|---|
| Caddy project path | ~/Containers/infrastructure/caddy | /Volumes/PlexDB/Docker/compose/\<project> | Keep current production location until a tested migration preserves secrets, certificates, scripts, and rollback paths. |
| Caddy Compose filename | docker-compose.yml | compose.yaml for new deployments | Treat as a legacy exception. Renaming a stable project provides little benefit unless performed with a broader controlled migration. |
| Docker VM disk | Docker.raw remains on the macOS system-data volume | Relocate Docker VM state to PlexDB | Migration remains pending; verify Docker Desktop support and maintain a rollback before moving approximately 460 GiB of sparse capacity. |
| FlareSolverr image | ghcr.io/flaresolverr/flaresolverr:latest | Versioned, controlled updates | Latest is convenient but non-deterministic. Pin a tested release before the environment is treated as fully reproducible. |
| FlareSolverr controls | No health check, log rotation, or no-new-privileges setting | Consistent operational controls | Add controls after validating the image's health endpoint and runtime requirements. |
| FlareSolverr state | Anonymous Docker volume at /config | Named or bind-mounted documented persistence | Replace with an explicit persistent mapping during a controlled service migration. |
| Administrative websites | Private Caddy routes on TCP 443; WAN TCP 443 forwards to Plex-only TCP 8443 | LAN/VPN-only administration through Caddy | Implemented and verified without relying on source addresses obscured by Docker Desktop. |
| CHANGE DISCIPLINE Documentation is updated first with the intended change, rollback path, and Pending status. Infrastructure changes second. After verification, the implementation guide is reconciled to the confirmed as-built state. A documented deviation is safer than an undocumented migration. |
|---|
12. Approved Application Portfolio¶
The portfolio below is the approved application scope for JUKEBOX. Installed status distinguishes the current as-built environment from future container deployments. Approval does not authorize deployment until the documentation-first change gate, prerequisites, backup, and rollback requirements are satisfied.
| APP KEY STANDARD Each application receives one permanent, unique, uppercase three-letter key. The key is used in inventories, labels, future database records, monitoring, backup records, and change logs. A retired key is never reassigned to another application. |
|---|
| APP KEY | APP NAME | DESCRIPTION | INSTALLED | RELATED TO | DEPENDENCIES | DEPLOYMENT STATE |
|---|---|---|---|---|---|---|
| BACKUP & RECOVERY | ||||||
| ARQ | Arq 7 | Native macOS backup application that encrypts, deduplicates, schedules, and maintains immutable backup records in Backblaze B2. | No | Restic; Backblaze B2; all protected recovery data | macOS; private B2 Object Lock bucket; S3-compatible endpoint; bucket-scoped application key; Arq encryption password; mounted source volumes; internet connectivity | Approved - Pending Native |
| RES | Restic | Backs up Compose recipes, configuration, databases, and application state. | No | All containerized applications | Backup repository; repository password; storage credentials; protected configuration mounts | Approved - Pending |
| CONTAINER PLATFORM & MANAGEMENT | ||||||
| DKR | Docker Desktop | Provides the Docker runtime and Linux virtual machine on JUKEBOX. | Yes - Native | All containers | macOS; Docker Desktop license acceptance; JUKEBOX CPU, memory, and storage allocation | Implemented - Native |
| POR | Portainer | Provides graphical administration of containers, images, networks, volumes, and Compose stacks. | No | Docker Desktop; Compose | Docker Desktop; Docker socket access; persistent Portainer data; administrator credentials | Approved - Pending |
| DASHBOARDS & NAVIGATION | ||||||
| HOM | Homepage | Provides a unified landing page with links and service-status widgets. | No | All user-facing applications | Configured service links; optional read-only Docker integration; Caddy for HTTPS | Approved - Pending |
| DOWNLOAD CLIENTS | ||||||
| SAB | SABnzbd | Downloads, verifies, repairs, extracts, and files Usenet content. | Yes - Native | Lidarr; Radarr; Sonarr | Download and media paths; Usenet provider credentials; category mappings | Implemented - Native |
| TRA | Transmission | Native torrent client retained as the permanent BitTorrent client; its traffic is isolated by PIA split tunneling and a failure-closed startup gate. | Yes - Native | Cleanuparr; Lidarr; Prowlarr; Radarr; Sonarr | PIA Only VPN application rule; VPN Kill Switch; preserved resume and seeding state; download paths; leak and disconnect tests | Implemented - Native |
| INDEXER & DOWNLOAD SUPPORT | ||||||
| FLR | FlareSolverr | Browser-automation helper for compatible indexers that require browser-style challenge handling. | Yes - Container | Prowlarr | Docker Desktop; outbound internet access; Prowlarr integration when required | Implemented - Container |
| PRW | Prowlarr | Centrally manages torrent and Usenet indexers and synchronizes them with media applications. | Yes - Native | FlareSolverr; Lidarr; Radarr; Sonarr | Indexer credentials; download-client APIs; Lidarr, Radarr, and Sonarr API keys | Implemented - Native |
| LIBRARY MANAGEMENT & AUTOMATION | ||||||
| BAZ | Bazarr | Finds and manages subtitles for movie and television libraries. | No | Plex; Radarr; Sonarr | Sonarr and Radarr API access; shared movie and television mounts; subtitle-provider credentials | Approved - Pending |
| CLN | Cleanuparr | Removes malicious, stalled, or unusable downloads and can request replacement searches. | No | Lidarr; Transmission; Radarr; Sonarr | Transmission and/or SABnzbd API access; Arr API keys; cleanup and replacement rules | Approved - Pending |
| KOM | Kometa | Automates Plex collections, metadata, artwork, playlists, and poster overlays. | No | Plex | Plex URL and token; persistent configuration; metadata and artwork sources; scheduled execution | Approved - Pending |
| LID | Lidarr | Automates music acquisition and library management. | Yes - Native | Prowlarr; Transmission; SABnzbd | Prowlarr; Transmission and/or SABnzbd; shared music and download paths | Implemented - Native |
| MTR | Maintainerr | Applies retention rules, creates collections, changes monitoring or quality settings, and can remove media. | No | Plex; Radarr; Seerr; Sonarr; Tautulli | Plex URL and token; Radarr and Sonarr APIs; persistent rules database; optional Seerr and Tautulli | Approved - Pending |
| APP KEY | APP NAME | DESCRIPTION | INSTALLED | RELATED TO | DEPENDENCIES | DEPLOYMENT STATE |
| RAD | Radarr | Automates movie acquisition and library management. | Yes - Native | Prowlarr; Transmission; SABnzbd | Prowlarr; Transmission and/or SABnzbd; shared movie and download paths | Implemented - Native |
| REC | Recyclarr | Synchronizes TRaSH Guides quality profiles, custom formats, naming rules, and quality definitions. | No | Radarr; Sonarr | Radarr and Sonarr URLs and API keys; version-controlled configuration; scheduled execution | Approved - Pending |
| SON | Sonarr | Automates television-series acquisition and library management. | Yes - Native | Prowlarr; Transmission; SABnzbd | Prowlarr; Transmission and/or SABnzbd; shared television and download paths | Implemented - Native |
| MEDIA REQUESTS | ||||||
| SEE | Seerr | Provides media discovery and requests and sends approved requests to Radarr or Sonarr. | No | Plex; Radarr; Sonarr | Plex authentication; Radarr and Sonarr API access; persistent database; email or notification settings | Approved - Pending |
| MEDIA SERVING | ||||||
| PLE | Plex Media Server | Organizes and streams movie, television, and music libraries. | Yes - Native | Bazarr; Kometa; Maintainerr; Seerr; Tautulli | macOS host; Plex database and metadata; media mounts; network access; account token | Implemented - Native |
| MONITORING & OBSERVABILITY | ||||||
| CAV | cAdvisor | Collects per-container CPU, memory, filesystem, and network metrics for Prometheus. | No | Docker Desktop; Prometheus | Docker socket and host filesystem access; Prometheus scrape configuration | Approved - Pending |
| GRA | Grafana | Displays historical infrastructure and container metrics in dashboards. | No | Prometheus | Prometheus data source; persistent dashboard/database storage; administrator credentials | Approved - Pending |
| NDE | Node Exporter | Collects host resource metrics; the deployment method must account for macOS and Docker Desktop. | No | Grafana; Prometheus | Compatible macOS host-exporter method or approved Docker Desktop access; Prometheus scrape configuration | Conditional |
| PRM | Prometheus | Collects and retains metrics from cAdvisor, exporters, and compatible applications. | No | cAdvisor; Grafana; Node Exporter | cAdvisor and exporter targets; persistent metrics storage; retention policy; scrape configuration | Approved - Pending |
| SCR | Scrutiny | Monitors physical-drive SMART health; direct disk access from Docker Desktop must be validated. | No | JUKEBOX storage | Direct SMART device access; supported drive interface; persistent database; feasibility approval | Conditional |
| TAU | Tautulli | Monitors Plex activity, users, playback, bandwidth, and library statistics. | Yes - Native | Plex | Plex URL and token; persistent Tautulli database; access to Plex logs where required | Implemented - Native |
| KUM | Uptime Kuma | Tests whether application websites and endpoints respond and sends outage notifications. | No | Caddy; all user-facing applications | Monitored endpoints; persistent database; notification provider credentials; Caddy for HTTPS | Approved - Pending |
| NETWORKING & ACCESS | ||||||
| CAD | Caddy | Provides HTTPS addresses, certificate management, and controlled reverse-proxy routing. | Yes - Container | Plex and JUKEBOX web applications | Docker Desktop; Cloudflare DNS token; persistent data/config; certificates; frontend/backend networks | Implemented - Container |
| NOTIFICATIONS | ||||||
| NTF | Notifiarr | Consolidates notifications and integrations from media-management and supporting services. | No | Lidarr; Plex; Prowlarr; Radarr; Sonarr | Notifiarr account/API key; application API keys; selected notification destinations | Approved - Pending |
| TROUBLESHOOTING & LOGS | ||||||
| DOZ | Dozzle | Provides searchable real-time container logs and basic runtime statistics in a web interface. | No | Docker Desktop; all containers | Read-only Docker socket access; persistent settings; Caddy for HTTPS | Approved - Pending |
| UPDATE MANAGEMENT | ||||||
| WUD | What's Up Docker (WUD) | Detects image updates, compares versions, sends notifications, and can update approved Compose projects. | No | Docker Desktop; Compose; opted-in containers | Docker socket access; Compose project labels; notification provider; explicit update allowlist | Approved - Pending |
12.1 Portfolio Status Rules¶
-
INSTALLED is factual: Yes - Native, Yes - Container, or No. It does not encode approval, feasibility, migration, or retirement intent.
-
DEPLOYMENT STATE is controlled: Implemented - Native, Implemented - Container, Approved - Pending, or Conditional. Approved - Pending still requires the documentation-first change gate before deployment.
-
Transmission is the permanent native BitTorrent client. It is not a migration source, and qBittorrent is not in the approved portfolio.
-
Docker Desktop is inventoried because it is the platform dependency, but DKR is not a container and is excluded from container totals.
-
Grafana dependencies are inventoried independently because they consume resources and require separate recovery inputs.
13. Installation and Compose Templates¶
This chapter defines the repeatable installation method for the portfolio. Application-specific values belong in the project-local .env and compose.yaml files; secrets are externalized. Templates are authoritative patterns, not permission to deploy every service simultaneously.
| SOURCE OF TRUTH The saved Compose project is the deployment recipe. Portainer may display or operate the stack, but a UI-only edit is not authoritative unless the corresponding project files are updated and preserved. |
|---|
13.1 Standard Installation Sequence¶
1. Update NET-004 with the intended app key, image version, ports, dependencies, Caddy name, resource budget, backup scope, rollback, and Pending status.
2. Create /Volumes/PlexDB/Docker/compose/\<app-name> and /Volumes/PlexDB/Docker/appdata/\<app-name>; confirm PlexDB and Storage are mounted.
3. Create the project-local .env and compose.yaml from the approved template. Use explicit stable image versions; do not use development, nightly, edge, or floating latest tags unless a documented exception exists.
4. Validate the resolved Compose configuration and confirm that no secret is printed or embedded in the recipe.
5. Take or verify the application backup, then pull the approved image and create only the intended project.
6. Complete the application setup wizard, authentication, paths, API keys, and service-to-service integrations.
7. Add the approved Caddy route and UniFi DNS alias only after the direct backend health check passes.
8. Verify application function, persistence after recreation, logs, backup capture, Uptime Kuma monitoring, and resource behavior.
9. Reconcile NET-004 from Pending to Implemented, recording the actual image, ports, paths, measured resources, result, and any deviation.
13.2 Common Environment Baseline¶
Project-local .env pattern¶
| TZ=America/New_York PUID=<JUKEBOX service-user UID> PGID=<JUKEBOX service-user GID> APP_IMAGE=<registry>/<project>/<image> APP_TAG=<explicit approved stable version> APPDATA_ROOT=/Volumes/PlexDB/Docker/appdata DOWNLOAD_ROOT=/Volumes/Storage/<confirmed-download-path> MEDIA_ROOT=/Volumes/Storage/<confirmed-media-path> |
|---|
- PUID, PGID, Storage paths, and image tags must be resolved from JUKEBOX immediately before deployment. Placeholder values are never valid production settings.
Template A - Standard web service¶
| services: app: image: ${APP_IMAGE}:${APP_TAG} container_name: app restart: "no" environment: TZ: ${TZ} PUID: ${PUID} PGID: ${PGID} volumes: - ${APPDATA_ROOT}/app:/config expose: - "<internal-port>" networks: [frontend] security_opt: [no-new-privileges:true] logging: driver: json-file options: {max-size: "10m", max-file: "5"} labels: mcguckin.app-key: "<KEY>" wud.watch: "true" networks: frontend: {external: true} healthcheck: test: ["CMD-SHELL", "<approved machine-readable readiness probe>"] interval: 30s timeout: 5s retries: 5 start_period: 60s |
|---|
Template B - Media manager or download client¶
| services: app: image: ${APP_IMAGE}:${APP_TAG} container_name: app restart: "no" environment: TZ: ${TZ} PUID: ${PUID} PGID: ${PGID} UMASK: "002" volumes: - ${APPDATA_ROOT}/app:/config - ${DOWNLOAD_ROOT}:/data/downloads - ${MEDIA_ROOT}:/data/media expose: ["<web-port>"] networks: [backend, frontend] security_opt: [no-new-privileges:true] labels: mcguckin.app-key: "<KEY>" wud.watch: "true" networks: backend: {external: true} frontend: {external: true} healthcheck: test: ["CMD-SHELL", "<approved machine-readable readiness probe>"] interval: 30s timeout: 5s retries: 5 start_period: 60s |
|---|
Template C - Scheduled job¶
| services: job: image: ${APP_IMAGE}:${APP_TAG} container_name: job restart: "no" environment: {TZ: ${TZ}} volumes: - ${APPDATA_ROOT}/job:/config networks: [backend] security_opt: [no-new-privileges:true] labels: mcguckin.app-key: "<KEY>" wud.watch: "true" networks: backend: {external: true} ## Scheduling is documented separately so heavy jobs do not overlap. ## Scheduled jobs report success by exit status and post-run verification; they do not use a perpetual health check. |
|---|
Template D - Docker control-plane service¶
| services: control: image: ${APP_IMAGE}:${APP_TAG} container_name: control restart: "no" volumes: - /var/run/docker.sock:/var/run/docker.sock - ${APPDATA_ROOT}/control:/data expose: ["<web-port>"] networks: [frontend] security_opt: [no-new-privileges:true] labels: {mcguckin.app-key: "<KEY>"} networks: frontend: {external: true} ## Docker-socket access is host-equivalent authority; never expose publicly. healthcheck: test: ["CMD-SHELL", "<approved machine-readable readiness probe>"] interval: 30s timeout: 5s retries: 5 start_period: 60s |
|---|
Template E - Monitoring service¶
| services: monitor: image: ${APP_IMAGE}:${APP_TAG} container_name: monitor restart: "no" volumes: - ${APPDATA_ROOT}/monitor:/data expose: ["<metrics-or-web-port>"] networks: [monitoring, frontend] security_opt: [no-new-privileges:true] labels: mcguckin.app-key: "<KEY>" wud.watch: "true" networks: monitoring: {external: true} frontend: {external: true} healthcheck: test: ["CMD-SHELL", "<approved machine-readable readiness probe>"] interval: 30s timeout: 5s retries: 5 start_period: 60s |
|---|
13.2.1 Required Readiness Contract¶
Every boot container must implement the health-check pattern above or declare an approved external probe in its README. The project records the probe, interval, timeout, retry budget, start period, total readiness deadline, failure effect, and rollback command. Compose service_healthy may control dependencies within one project; the JUKEBOX startup orchestrator controls cross-project order. Placeholder probes fail the deployment gate.
13.3 Application Deployment Matrix¶
Image names identify the approved upstream family. The exact stable tag must be recorded in the project .env and implementation record at deployment time. Native applications are included only when they are continuing platform or security prerequisites. Plex and Transmission have no container image or migration recipe in this guide.
| KEY | APPLICATION | IMAGE SOURCE | PORTS | TEMPLATE | PERSISTENT INPUTS | NETWORKS |
|---|---|---|---|---|---|---|
| BAZ | Bazarr | lscr.io/linuxserver/bazarr | 6767 | Media service | /config; movies; television | backend; frontend |
| CAD | Caddy | Local custom Caddy build | 80; 443; 8443 | Existing custom | Caddyfile; data; config; secrets | frontend |
| CAV | cAdvisor | gcr.io/cadvisor/cadvisor | 8080 internal | Monitoring agent | Docker VM runtime mounts | monitoring |
| CLN | Cleanuparr | ghcr.io/cleanuparr/cleanuparr | 11011 | Web service | /config | backend; frontend |
| DKR | Docker Desktop | Native macOS application | N/A | Host prerequisite | Docker.raw VM disk | N/A |
| DOZ | Dozzle | amir20/dozzle | 8080 | Docker control | /var/run/docker.sock; /data | frontend |
| FLR | FlareSolverr | ghcr.io/flaresolverr/flaresolverr | 8191 | Web service | /config if supported | backend |
| GRA | Grafana | grafana/grafana | 3000 | Monitoring service | /var/lib/grafana | monitoring; frontend |
| HOM | Homepage | ghcr.io/gethomepage/homepage | 3000 | Web service | /app/config | frontend; monitoring |
| KOM | Kometa | kometateam/kometa | None | Scheduled job | /config; media assets | backend |
| KUM | Uptime Kuma | louislam/uptime-kuma:2 | 3001 | Web service | /app/data on local APFS storage | frontend; monitoring |
| LID | Lidarr | lscr.io/linuxserver/lidarr | 8686 | Media service | /config; downloads; music | backend; frontend |
| MTR | Maintainerr | ghcr.io/maintainerr/maintainerr | 6246 | Web service | /opt/data | backend; frontend |
| NDE | Node Exporter | prom/node-exporter | 9100 | Monitoring agent | Host metric mounts when supported | monitoring |
| NTF | Notifiarr | golift/notifiarr | 5454 | Web service | /config | backend; frontend |
| POR | Portainer | portainer/portainer-ce | 9443; 8000 | Docker control | /var/run/docker.sock; /data | frontend |
| PRM | Prometheus | prom/prometheus | 9090 | Monitoring service | /etc/prometheus; /prometheus | monitoring |
| PRW | Prowlarr | lscr.io/linuxserver/prowlarr | 9696 | Media service | /config | backend; frontend |
| RAD | Radarr | lscr.io/linuxserver/radarr | 7878 | Media service | /config; downloads; movies | backend; frontend |
| REC | Recyclarr | ghcr.io/recyclarr/recyclarr:8 | None | Scheduled job | /config | backend |
| RES | Restic | restic/restic | None | Scheduled job | backup sources; repository; cache | backend |
| SAB | SABnzbd | Native macOS application | TCP 8888 | Native download prerequisite | Existing configuration and database; incomplete and completed download paths; provider and category settings | Native macOS / Caddy |
| SCR | Scrutiny | ghcr.io/analogj/scrutiny | 8080; 8086 internal | Monitoring service | /opt/scrutiny; InfluxDB; physical disks | monitoring; frontend |
| SEE | Seerr | ghcr.io/seerr-team/seerr | 5055 | Web service | /app/config | backend; frontend |
| SON | Sonarr | lscr.io/linuxserver/sonarr | 8989 | Media service | /config; downloads; television | backend; frontend |
| TAU | Tautulli | lscr.io/linuxserver/tautulli | 8181 internal; retain 44444 during migration | Web service | /config; optional Plex logs read-only | backend; frontend |
| TRA | Transmission | Native macOS application | Existing native port | Native security prerequisite | Existing configuration, resume and torrent state; download paths; PIA policy | Native macOS / PIA |
| WUD | What's Up Docker | getwud/wud:8.3.1 | 3000 | Docker control | /var/run/docker.sock; /store; Compose files | frontend |
13.4 Application-Specific Gates¶
-
TRA: retain native Transmission; require PIA Only VPN routing, VPN Kill Switch, PIA connected/VPN-IP checks, an application-originated egress-IP check, and a controlled disconnect test before enabling torrent automation.
-
PLE: Plex Media Server remains native on macOS. Containerization is not an approved present or future target in NET-004.
-
SCR: do not deploy until Docker Desktop can expose the required physical SMART devices safely; otherwise use a native collector or omit Scrutiny.
-
NDE and CAV: Node Exporter is explicitly scoped to the Docker Linux VM when containerized; cAdvisor reports per-container metrics. Dashboards must not label either source as JUKEBOX macOS host metrics.
-
WUD: begin in report/manual mode; approve automatic triggers only after Compose-file backups, application backups, tag filters, and recovery tests work.
-
RES: complete a restore test. A successful backup command without a verified restore does not satisfy the recovery gate.
-
REC and KOM: preview or dry-run configuration changes before enabling scheduled writes.
13.5 Canonical Container Recipe¶
The canonical project scaffold is stored at Templates/Docker-Container-Recipe/. Copy it into an application project directory, then resolve the approved app key, image and immutable tag, ports, paths, networks, health check, resource budget, backup scope, and rollback method before deployment. The scaffold consists of compose.yaml, .env.example, and README.md.
A template is not a deployable stack. Any REPLACE value, example image, unresolved path, absent health check, or unapproved app key fails the deployment gate.
13.6 Startup Orchestration¶
Startup is controlled by readiness gates, not elapsed time alone. The JUKEBOX startup orchestrator begins only after the non-Docker prerequisites pass, then releases containers in numbered order. A higher number does not start until its declared dependencies are healthy or an approved degraded-start branch applies.
CONTROL RULE The NUMBER field is an ordering key, not a delay in seconds. Ten-point increments preserve space for future insertions. STARTUP MODE distinguishes boot, conditional, scheduled, and manual behavior; READY WHEN is the machine-testable release gate; FAILURE EFFECT defines whether downstream work halts or continues degraded.
13.6.1 Non-Docker Startup Table¶
These host prerequisites execute before the Docker Startup Table. Storage, network, service-session, Docker Engine, and orchestrator failures stop the Docker sequence. Native Plex uses the documented degraded branch. PIA and Transmission gate torrent automation but do not block independently healthy Usenet workflows. Native SABnzbd gates Usenet-dependent automation but does not block independently healthy torrent or platform workflows.
| NUMBER | NAME | DEPENDENCIES | STARTUP MODE | READY WHEN | FAILURE EFFECT |
|---|---|---|---|---|---|
| 010 | JUKEBOX hardware and firmware | Utility power; iMac hardware; attached storage hardware | Boot | Power-on self-test completes without hardware or storage faults. | Halt all startup and alert the operator. |
| 020 | macOS | JUKEBOX hardware and firmware | Boot | macOS reaches the normal operating state with no pending restart or startup error. | Halt all Docker startup and retain native diagnostic access. |
| 030 | PlexDB and media storage | macOS; attached storage hardware | Boot gate | Every required volume is mounted at its canonical path, writable, and reports expected capacity. | Halt storage-dependent native apps and every container; never create substitute folders on MacHD. |
| 040 | LAN, UniFi DNS, gateway, and system time | macOS; JUKEBOX Ethernet; UniFi infrastructure | Boot gate | JUKEBOX has 10.10.10.10; gateway and required DNS names resolve; time synchronization is healthy. | Halt Docker startup because routing, TLS, API calls, and logs would be unreliable. |
| 050 | JUKEBOX service session | macOS; storage; LAN; approved service-user credentials | Boot | The approved user session, environment, permissions, and startup-orchestrator context are available. | Halt Docker startup; do not fall back to an interactive administrator context. |
| 060 | Native Plex Media Server | Service session; PlexDB; media storage; LAN and time | Conditional boot gate | Plex TCP 32400 and its API respond, libraries are visible, and the database is not locked or upgrading. | Continue with platform, monitoring, download, indexer, Arr, subtitle, dashboard, and diagnostic containers; hold Tautulli, Seerr, Notifiarr Plex integration, Maintainerr, and Kometa; alert the operator. |
| 070 | Private Internet Access and Transmission | Service session; storage; LAN and time; PIA credentials; Transmission state | Boot security gate | PIA is Connected and reports a VPN IP; Transmission is running; its egress shows the PIA IP; a controlled VPN disconnect blocks its internet traffic; local access remains available as approved. | Hold torrent integration and torrent-dependent automation. Permit independently healthy SABnzbd/Usenet workflows; alert the operator. |
| 080 | Native SABnzbd | Service session; storage; LAN and time; SABnzbd configuration and provider credentials | Boot dependency gate | SABnzbd TCP 8888 and API respond; configuration and queue state load; incomplete and completed folders are writable; enabled Usenet providers pass connection tests. | Continue Docker startup, but disable SABnzbd as a download client and hold Usenet-dependent automation. Permit independently healthy torrent and platform workflows; alert the operator. |
| 090 | Docker Desktop and Docker Engine | Service session; storage; LAN; sufficient Docker VM capacity | Boot | Docker Desktop reports Engine running; Docker API, Compose, networks, and required mounts pass preflight checks. | Halt the Docker Startup Table and alert the operator. |
| 100 | Container Startup Orchestrator | Docker Engine; approved startup-plan file; logging and notification path | Boot controller | The orchestrator acquires its single-run lock, records preflight success, and begins at Docker step 010. | Leave containers stopped except explicitly approved recovery services; alert the operator. |
13.6.2 Docker Startup Table¶
This table contains all 25 approved target containers, including services currently native to macOS but still planned for container migration. Docker Desktop, native Plex Media Server, native Transmission, and native SABnzbd are not containers and appear only as prerequisites or continuing native dependencies.
| NUMBER | NAME | DEPENDENCIES | STARTUP MODE | READY WHEN | FAILURE EFFECT |
|---|---|---|---|---|---|
| 010 | Caddy | Docker Engine; network; Caddy configuration, certificates, and secrets | Boot | Configuration validates; listeners bind; admin health and a proxy-independent sentinel route pass; certificates are available or issuance is healthy | Halt services that require Caddy; continue only approved backend recovery services |
| 020 | Portainer | Docker Engine; read/write Docker socket; persistent Portainer data | Boot | Portainer health/API responds and the local environment is connected | Continue degraded; alert operator |
| 030 | Dozzle | Docker Engine; read-only Docker socket | Boot | Dozzle web endpoint responds and current container logs are readable | Continue degraded; retain Docker logs |
| 040 | cAdvisor | Docker Engine; approved runtime and filesystem mounts | Boot | Metrics endpoint responds with current container series | Hold Prometheus and Grafana readiness; continue application startup |
| 050 | Node Exporter | Docker Engine; approved Docker VM metric mounts | Conditional boot | Metrics endpoint responds and every dashboard labels the source as Docker Linux VM, not macOS host | Continue without host metrics; mark monitoring degraded |
| 060 | Prometheus | cAdvisor; Node Exporter or documented degraded-monitoring exception | Boot | Prometheus is ready and required scrape targets are up or explicitly exempted | Hold Grafana readiness; continue application startup with monitoring alert |
| 070 | Grafana | Prometheus; persistent Grafana data | Boot | Grafana health API passes and Prometheus data source connects | Continue degraded; alert operator |
| 080 | What's Up Docker (WUD) | Docker socket; Compose metadata; notification configuration | Boot / scheduled checks | WUD API responds and inventory scan completes; automatic updates remain disabled at startup | Continue degraded; updates remain disabled |
| 090 | Scrutiny | Approved physical-drive access; persistent Scrutiny and time-series data | Conditional boot | Collector and web/API health pass and expected drives appear | Skip when feasibility gate is not approved; continue with storage-monitoring warning |
| 100 | FlareSolverr | Outbound network access | Boot / on demand | Health endpoint responds and browser worker can initialize | Continue; mark only dependent indexers unavailable |
| 110 | Prowlarr | Native Transmission and/or SABnzbd; FlareSolverr when required; indexer credentials | Boot | API responds and every enabled download client and required indexer passes its connection test; Transmission is enabled only after the PIA gate | Hold Lidarr, Radarr, Sonarr, Notifiarr, and downstream request/maintenance services |
| 120 | Lidarr | Prowlarr; native Transmission and/or SABnzbd; music and download mounts | Boot | API responds; root folders and required integrations pass | Hold Lidarr-dependent notification and cleanup actions |
| 130 | Radarr | Prowlarr; native Transmission and/or SABnzbd; movie and download mounts | Boot | API responds; root folders and required integrations pass | Hold Bazarr movie functions, Seerr movie requests, and dependent maintenance |
| 140 | Sonarr | Prowlarr; native Transmission and/or SABnzbd; television and download mounts | Boot | API responds; root folders and required integrations pass | Hold Bazarr television functions, Seerr television requests, and dependent maintenance |
| 150 | Tautulli | Native Plex; persistent Tautulli database; optional Plex logs | Boot | Tautulli API responds and connects to Plex | Continue; hold Tautulli-dependent Maintainerr rules and mark Plex analytics degraded |
| 160 | Bazarr | Radarr; Sonarr; movie and television mounts; provider credentials | Boot | API responds and both Arr connections and subtitle paths validate | Continue; subtitle automation remains unavailable |
| 170 | Seerr | Native Plex; Radarr; Sonarr; persistent database | Boot | Web/API responds and Plex, Radarr, and Sonarr connections pass | Continue; request intake remains unavailable |
| 180 | Notifiarr | Native Plex; Prowlarr; Lidarr; Radarr; Sonarr; credentials | Boot | Notifiarr health/API and configured application connections pass | Continue; use fallback alerts and mark notifications degraded |
| 190 | Maintainerr | Native Plex; Radarr; Sonarr; Seerr; Tautulli for enabled rules | Boot | Web/API responds and every integration required by enabled rules passes | Continue with rules disabled; do not perform deletions or metadata changes |
| 200 | Cleanuparr | Native Transmission and/or SABnzbd; Lidarr; Radarr; Sonarr | Boot | API responds and required clients connect; destructive actions remain guarded | Continue with cleanup actions disabled |
| 210 | Uptime Kuma | Monitored endpoints; persistent database; notification provider | Boot | Kuma health passes and monitors are loaded without database error | Continue; alert operator that centralized availability monitoring is unavailable |
| 220 | Homepage | User-facing applications; status integrations; optional read-only Docker access | Boot | Homepage responds and configured links/widgets load without credential errors | Continue; navigation dashboard remains unavailable |
| 230 | Restic | Backup repository; credentials; protected paths; application-native backups | Scheduled only | Scheduled job completes verification and records a successful snapshot | Never start at reboot; run only in the 1:20-3:20 maintenance slot. |
| 240 | Recyclarr | Radarr; Sonarr; approved version-controlled configuration | Scheduled only | Dry-run/preview gate passes and scheduled synchronization exits successfully | Never start at reboot; run only in the 5:30-6:00 maintenance slot. |
| 250 | Kometa | Native Plex; token; media and metadata mounts; approved configuration | Scheduled only | Preflight passes and scheduled run exits successfully without overlapping heavy I/O | Never start at reboot; run only in the 6:00-7:00 maintenance slot. |
SCHEDULED-JOB BOUNDARY Restic, Recyclarr, and Kometa remain stopped during an ordinary reboot. The maintenance-window scheduler starts them only in their assigned slots. Scrutiny and the host-exporter design remain conditional until their macOS and Docker Desktop feasibility gates are approved.
13.6.3 Startup Authority and Recovery¶
The macOS launchd service for the JUKEBOX startup orchestrator is the sole boot authority for orchestrated Compose projects. Before that controller is activated, every governed boot container - including Caddy and FlareSolverr - must use restart: no so Docker cannot bypass the documented order after a daemon or host restart.
Within a Compose project, health checks and depends_on with condition: service_healthy may release local dependencies. Across projects, only the startup plan may issue starts. A single-run lock prevents concurrent startup sequences.
Runtime crash recovery is separate from boot ordering. After a service has passed readiness, the orchestrator may attempt up to three restarts in fifteen minutes with exponential backoff. Exhausting the budget marks the service failed, applies its documented downstream failure effect, preserves logs, and alerts the operator. Scheduled-only containers are never restarted outside their maintenance slot.
14. Resource Capacity Planning¶
Capacity planning prevents the approved portfolio from exhausting JUKEBOX or the Docker Desktop virtual machine. Values below are initial engineering estimates for sizing and rollout order; they are not vendor guarantees or measured production values. Every deployed service must replace its estimate with observed idle, normal, and peak measurements.
| CURRENT DOCKER ALLOCATION LIMIT JUKEBOX has 32 GB physical memory, which is expected to support the approved portfolio when heavy work is scheduled. Docker Desktop is presently allocated approximately 7.75 GiB RAM and 10 CPUs; that Docker VM allocation is not sufficient for the complete 25-container target with safe headroom. |
|---|
14.1 Planning Method¶
-
Idle RAM is the expected stable working set after startup with no intensive task running.
-
Burst RAM is a planning high-water mark during scans, searches, dashboard queries, backup, unpack, browser automation, or transcoding.
-
CPU ranges indicate expected active cores, not reservations. Summing every peak is intentionally conservative because heavy tasks must be scheduled apart.
-
Media files are excluded from application storage. Plex metadata, Prometheus retention, Scrutiny time-series data, logs, images, and backup caches remain platform-capacity consumers.
-
Resource budgets are observation targets. Hard container limits are added only after stable workloads are measured and recovery behavior is tested.
14.2 Per-Container Planning Estimates¶
| KEY | APPLICATION | MODE | IDLE MiB | BURST MiB | CPU CORES | I/O | PLANNING NOTE |
|---|---|---|---|---|---|---|---|
| BAZ | Bazarr | Always-on | 200 | 500 | 0.25-1 | Moderate scan | Subtitle scans create temporary CPU and filesystem bursts. |
| CAD | Caddy | Always-on | 64 | 128 | 0.10-0.50 | Low | Traffic volume is modest; TLS and logging create brief bursts. |
| CAV | cAdvisor | Always-on | 100 | 250 | 0.10-0.50 | Moderate reads | Collection interval controls monitoring overhead. |
| CLN | Cleanuparr | Always-on | 100 | 250 | 0.10-0.50 | Low | Queue checks are light except during cleanup actions. |
| DOZ | Dozzle | Always-on | 64 | 200 | 0.10-0.50 | Log reads | Browser sessions and wide log searches raise usage. |
| FLR | FlareSolverr | On demand | 256 | 1024 | 0.25-2 | Low disk | Browser processes are bursty and can dominate memory. |
| GRA | Grafana | Always-on | 200 | 500 | 0.25-1 | Low | Dashboard queries shift work to Prometheus. |
| HOM | Homepage | Always-on | 128 | 300 | 0.10-0.50 | Low | Widget refresh frequency controls network and CPU usage. |
| KOM | Kometa | Scheduled | 64 | 1000 | 0.10-2 | High scan | Run outside backup, unpack, and library-scan windows. |
| KUM | Uptime Kuma | Always-on | 200 | 500 | 0.25-1 | Low-moderate | Monitor count, interval, and retention control growth. |
| LID | Lidarr | Always-on | 350 | 800 | 0.25-1 | Moderate scan | Large music libraries increase database and scan demand. |
| MTR | Maintainerr | Always-on | 250 | 600 | 0.25-1 | Moderate scan | Rule evaluation and collection refreshes are bursty. |
| NDE | Node Exporter | Always-on | 32 | 64 | 0.05-0.20 | Low | Containerized source is the Docker Linux VM; never label it as JUKEBOX macOS host telemetry. |
| NTF | Notifiarr | Always-on | 100 | 250 | 0.10-0.50 | Low | Mostly network-bound notification processing. |
| POR | Portainer | Always-on | 128 | 300 | 0.10-0.50 | Low | Administration activity creates short-lived increases. |
| PRM | Prometheus | Always-on | 500 | 1500 | 0.25-2 | High writes | Retention, scrape interval, and metric cardinality are decisive. |
| PRW | Prowlarr | Always-on | 300 | 700 | 0.25-1 | Low-moderate | Indexer synchronization and searches create network bursts. |
| RAD | Radarr | Always-on | 350 | 800 | 0.25-1 | Moderate scan | Large libraries and refreshes increase database activity. |
| REC | Recyclarr | Scheduled | 0 | 256 | 0-0.50 | Low | Container may remain stopped between scheduled synchronizations. |
| RES | Restic | Scheduled | 0 | 1000 | 0-2 | Very high | Backup scans are disk-intensive; never overlap media unpacking. |
| SCR | Scrutiny | Conditional | 600 | 1200 | 0.25-1 | Moderate writes | Omnibus deployment includes time-series storage; disk access is unverified. |
| SEE | Seerr | Always-on | 300 | 700 | 0.25-1 | Low | Request activity is generally light. |
| SON | Sonarr | Always-on | 350 | 800 | 0.25-1 | Moderate scan | Large libraries and refreshes increase database activity. |
| TAU | Tautulli | Always-on | 200 | 500 | 0.25-1 | Moderate writes | History retention and concurrent streams drive database growth. |
| WUD | What's Up Docker | Scheduled checks | 128 | 300 | 0.10-0.50 | Low | Registry scans are light; updates create image-download bursts. |
14.2.1 Estimate Provenance¶
Every value in Section 14.2 is an engineering planning allowance, not a measurement or vendor guarantee. The companion table records basis, verification state, and confidence without over-widening the operating table. Replace each row with observed idle, normal, and peak measurements during staged deployment.
| APP KEY | BASIS | VERIFIED DATE | CONFIDENCE |
|---|---|---|---|
| BAZ | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| CAD | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| CAV | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| CLN | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| DOZ | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| FLR | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| GRA | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| HOM | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| KOM | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| KUM | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| LID | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| MTR | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| NDE | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| NTF | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| POR | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| PRM | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| PRW | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| RAD | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| REC | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| RES | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| SCR | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| SEE | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| SON | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| TAU | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
| WUD | Engineering estimate; validate with Docker stats and application workload test | Not yet measured | Low until measured |
14.3 Aggregate Capacity Model¶
| SCENARIO | TARGET CONTAINERS | IDLE WORKING SET | CONCURRENT BURST | DOCKER MEMORY | DECISION |
|---|---|---|---|---|---|
| Current as-built | Caddy; FlareSolverr | ~0.3 GiB | ~1.2 GiB | 7.75 GiB current | Adequate for the present two containers. |
| Platform services | Caddy; Portainer; Homepage; Kuma; Dozzle; WUD | ~0.7 GiB | ~1.9 GiB | 8 GiB current | Suitable first deployment wave. |
| Media automation; Plex, Transmission, and SABnzbd native; Scrutiny held | 24 containers | ~4.26 GiB | ~12.92 GiB theoretical | 14-16 GiB | Safe with heavy-job scheduling, PIA gating, and measurement. |
| Full approved target | 25 target containers | 4.85 GiB | 14.09 GiB theoretical | 16 GiB initial target | Expected to fit on the 32 GB host; stage rollout and measure memory pressure. |
| Unscheduled all-peak stress | 25 target containers | N/A | ~16.0 GiB including VM overhead | 18 GiB+ only if measured | Not an operating mode; heavy workloads must not overlap. |
| RECOMMENDED ALLOCATION Increase Docker Desktop memory in stages: 12 GiB for the initial platform and light media wave, then 16 GiB before the complete 25-container wave. Increase toward 18 GiB only if measured Docker demand and macOS memory pressure justify it. Retain 10 CPUs initially and control contention through scheduling before increasing CPU allocation. |
|---|
14.4 Storage and Retention Budget¶
| CAPACITY AREA | INITIAL BUDGET | PRIMARY DRIVERS | CONTROL |
|---|---|---|---|
| Compose, configuration, and small databases | 20-40 GiB | Application count; backups; SQLite databases | Bind mounts; native exports; Restic retention |
| Prometheus metrics | 20-50 GiB | Scrape interval; retention; label cardinality | Begin with 15-day retention and a size ceiling |
| Scrutiny / InfluxDB | 10-25 GiB | Device count and time-series retention | Deploy only after feasibility gate; bound retention |
| Container images and build cache | 40-80 GiB | Multi-architecture images; Caddy builds; old images | WUD control; deliberate image pruning after rollback window |
| Logs and temporary working data | 20-50 GiB | Container logs; FlareSolverr browser cache; temporary application files | Log rotation; separate transcode/cache paths; alerts |
| Total new Docker platform reserve | 110-245 GiB | Excludes media and existing Plex metadata | Keep at least 20% of PlexDB free; alert before 75% utilization |
14.5 Maintenance Window and Workload Scheduling¶
OFFICIAL MAINTENANCE WINDOW Scheduled maintenance is authorized only from 12:00 a.m. through 8:00 a.m. Eastern Time. All work must finish by 8:00 a.m.; activity outside the window requires a separately documented exception.
Heavy-I/O jobs run sequentially and never overlap. Application-native exports, Restic, and Arq/B2 run before upgrades and form a mandatory go/no-go gate. If a backup fails or a task overruns its slot, upgrades and later optional work are deferred rather than compressed or run concurrently. Monitoring remains active throughout the window.
| TIME | ACTIVITY | FREQUENCY | MODE | I/O IMPACT | FAILURE / OVERRUN ACTION |
|---|---|---|---|---|---|
| 12:00-12:20 | WUD detection and pre-maintenance checks | Nightly | Automatic detection; updates remain disabled | Low | Abort the sequence if host, storage, backup, network, or application prechecks fail. |
| 12:20-1:20 | Application-native configuration and database backups | Nightly | Automatic | Moderate | Stop dependent work on failure; do not overlap Restic. |
| 1:20-3:20 | Restic local backup and repository verification | Nightly | Automatic | High | Stop cleanly at 3:20; failure closes the upgrade gate. |
| 3:20-4:20 | Arq 7 immutable incremental backup to Backblaze B2 | Nightly after commissioning | Automatic | Moderate / network | Verify current backup record and lock maintenance; failure closes the upgrade gate. |
| 4:20-4:30 | Backup verification and upgrade go/no-go gate | Nightly | Automatic checks plus operator exception control | Low | Proceed only when application-native, Restic, and Arq/B2 recovery points all pass. |
| 4:30-5:30 | Approved application and container updates with controlled restarts | As approved | Approval-triggered automation | Moderate / variable | Roll back the failed service and halt later changes until stable. |
| 5:30-6:00 | Recyclarr | Scheduled nights | Automatic after approval | Low / moderate | Defer if backup or update work consumed the slot. |
| 6:00-7:00 | Kometa or another scheduled heavy application job | Designated nights | Automatic after approval | High | Never overlap another heavy job; skip on macOS update nights. |
| 7:00-7:30 | Health checks, functional verification, and rollback if necessary | Nightly | Automatic checks plus operator review | Low | Resolve or roll back failures by 7:30; begin no new maintenance. |
| 7:30-8:00 | Manual macOS update installation, if necessary | When required | Manual | High; restart possible | Install only when safe completion and verification by 8:00 are reasonable; otherwise defer. |
MACOS UPDATE NIGHT EXCEPTION Backups and the 4:20-4:30 go/no-go gate still run first. A larger or restart-requiring macOS update replaces the 6:00-7:00 heavy-job slot and any lower-priority work needed to preserve recovery time. Begin only when installation, restart, and verification of macOS, Plex, Docker Desktop, containers, Caddy, storage, and network access can reasonably finish by 8:00; otherwise defer the update.
INITIAL-SEED EXCEPTION The first Arq upload is a commissioning activity, not a one-hour routine job. It may span multiple dedicated maintenance windows. During commissioning, suspend updates and optional heavy jobs until the immutable baseline and sample restore pass; stop or throttle the seed by 8:00 a.m. if daytime resource use would be affected.
14.6 Measurement and Acceptance Gate¶
-
Record Docker Desktop memory and CPU allocation before each deployment wave.
-
Capture 24-hour idle and seven-day normal utilization after each wave using Docker statistics and Prometheus/Grafana when available.
-
Exercise each service's heavy path: native SAB repair/unpack, native Transmission peer load behind PIA, Plex stream/transcode, Kometa scan, Restic backup, and Prometheus compaction.
-
Maintain at least 20% Docker memory headroom during normal operation and avoid sustained host memory pressure or swap growth.
-
Alert at 70% sustained Docker memory, 80% short-term memory, 75% PlexDB utilization, and 85% Docker VM disk utilization; exact thresholds may be tuned from measured behavior.
-
If a deployment wave exceeds its budget, stop the wave, reconcile NET-004, and either tune, reschedule, reduce retention, increase Docker allocation within host limits, or defer the application.
-
Replace estimates in this chapter with observed baselines and retain the prior document version before changing resource decisions.
14.7 Source Baseline¶
Compose patterns and ports were derived from current upstream documentation and repositories as of August 14, 2026. Before deployment, confirm the current stable image tag and any migration notice at the official source.
-
LinuxServer.io container documentation: https://docs.linuxserver.io/images/
-
Seerr: https://github.com/seerr-team/seerr and https://docs.seerr.dev/
-
Cleanuparr: https://github.com/Cleanuparr/Cleanuparr
-
Recyclarr: https://github.com/recyclarr/recyclarr and https://recyclarr.dev/
-
Maintainerr: https://github.com/Maintainerr/Maintainerr and https://docs.maintainerr.info/
-
Uptime Kuma: https://github.com/louislam/uptime-kuma
-
WUD: https://github.com/getwud/wud and https://getwud.github.io/wud/
-
Prometheus/cAdvisor: https://prometheus.io/docs/guides/cadvisor/
-
Grafana: https://grafana.com/docs/grafana/latest/setup-grafana/installation/docker/
-
Scrutiny: https://github.com/AnalogJ/scrutiny
Appendix A - Ports and Endpoints¶
| Component | Protocol / Port | Exposure | Purpose |
|---|---|---|---|
| Caddy | TCP 80 | WAN and LAN through JUKEBOX | Automatic redirect from HTTP to HTTPS. |
| Caddy | TCP 443 | LAN and UniFi VPN through JUKEBOX | Private HTTPS listener for all documented routes. |
| Caddy | TCP 8443 | WAN through UniFi external TCP 443 | Verified Plex-only HTTPS listener receiving UniFi WAN TCP 443. |
| Caddy | UDP 443 | WAN and LAN through JUKEBOX | HTTP/3/QUIC. |
| Caddy admin API | TCP 2019 | Container-local only | Health and administrative configuration API. |
| Plex | TCP 32400 | Native macOS backend | Caddy upstream for plex.mcguckin.net. |
| Tautulli | TCP 44444 | JUKEBOX backend | Verified Caddy upstream for plexstats.mcguckin.net on the private listener. |
| Sonarr | TCP 8989 | Native macOS backend | Caddy upstream for television.mcguckin.net. |
| Radarr | TCP 7878 | Native macOS backend | Caddy upstream for movies.mcguckin.net. |
| Lidarr | TCP 8686 | Native macOS backend | Caddy upstream for music.mcguckin.net. |
| Prowlarr | TCP 9696 | Native macOS backend | Caddy upstream for indexers.mcguckin.net. |
| SABnzbd | TCP 8888 | Native macOS backend | Caddy upstream for downloads.mcguckin.net. |
| FlareSolverr | TCP 8191 | Published to JUKEBOX host; no WAN forward | Local integration endpoint for compatible indexer workflows. |
| Home Assistant | TCP 8123 | Direct LAN endpoint | Local home.mcguckin.net access; Nabu Casa handles public access. |
| HDHomeRun | TCP 80 | Direct LAN endpoint | Local tv.mcguckin.net web interface. |
| Private Internet Access | VPN tunnel / piactl status | Native macOS outbound security boundary | Provides Transmission's Only VPN path, VPN address, and connection-state checks. |
| Transmission | Existing native service port | Native macOS backend; LAN/VPN administration only | Permanent BitTorrent client; internet traffic must pass the PIA release and disconnect tests. |
Appendix B - Recovery Checklist¶
| Check | Acceptance Condition | Status |
|---|---|---|
| Host identity | JUKEBOX has the expected hostname and static address 10.10.10.10. | Verified 2026-08-14 |
| Docker Desktop | Docker engine and Compose respond under the normal macOS user session. | Verified 2026-08-14 |
| Project files | Caddy and FlareSolverr Compose definitions are present at their documented paths. | Verified 2026-08-14 |
| Caddy state | Caddy data/, config/, and the Cloudflare token are present with correct permissions. | Verified 2026-08-14 |
| Custom module | The Caddy image lists dns.providers.cloudflare. | Verified 2026-08-14 |
| Configuration | Caddy validates successfully before production reload or recreation. | Verified 2026-08-14 |
| Container health | Caddy reaches healthy; FlareSolverr remains running without restart loops. | Verified 2026-08-14 |
| Ports | Caddy owns 80/tcp, private 443/tcp and 443/udp, and Plex-only 8443/tcp; FlareSolverr owns 8191/tcp. | Verified 2026-08-14 |
| DNS | Every documented service name resolves through its approved public or UniFi split-horizon DNS boundary. | 18 planned CNAMEs pending UniFi implementation |
| Certificates | Every documented Caddy service name presents a valid certificate without issuance errors. | Verified 2026-08-14 |
| Backends | Each service reaches its expected application or authenticated login page. | Verified 2026-08-14 |
| Logs | No persistent certificate, upstream, permission, or secret-loading errors remain. | Verified 2026-08-14 |
| Security | WAN TCP 443 reaches only the Plex listener; administrative routes remain reachable from LAN/VPN TCP 443. | LAN/WAN verified; VPN client test pending |
| Documentation | Documentation was updated before infrastructure work and reconciled after verification. | Maintenance window and planned DNS documented before infrastructure change |
Appendix C - Revision History¶
| Version | Date | Author | Description |
|---|---|---|---|
| 0.13 | August 15, 2026 | Todd McGuckin | Confirmed NET-004 Section 10.2 as the sole Arq 7 and Backblaze B2 implementation authority after removing the detailed duplicate from the NET-003 file-tree proposal; established highest-credible-price budgeting; and updated the Arq planning amounts to $59.99 for the license and $29.99 per year for optional updates. |
| 0.12 | August 15, 2026 | Todd McGuckin | Adopted Arq 7 with Backblaze B2 Object Lock as the official immutable offsite backup platform; documented implementation, dependencies, security, scope, costs, verification, and recovery; added Arq to the approved portfolio; and reordered the maintenance window so all backup layers pass before upgrades begin. |
| 0.11 | August 15, 2026 | Todd McGuckin | Retained SABnzbd as a native pre-Docker prerequisite for the initial deployment; removed it from the Docker startup, recipe, and resource models; corrected the full target to 25 containers and documented independent Usenet/torrent degraded-start branches. |
| 0.10 | August 15, 2026 | Todd McGuckin | Remediated audit Sections 1 and 2: retained native Transmission behind PIA Only VPN and failure-closed tests; removed qBittorrent and every Plex-container target; corrected the 26-container startup and capacity models; defined startup authority, health checks, deployment states, metric identity, estimate provenance, metadata cleanup, and readable table sizing. |
| 0.9 | August 15, 2026 | Todd McGuckin | Added readiness-gated startup orchestration, a non-Docker prerequisite startup table, and the ordered Docker Startup Table for the complete approved target container portfolio, including migration and scheduled-job controls. |
| 0.8 | August 15, 2026 | Todd McGuckin | Established the official 12:00 a.m.-8:00 a.m. Eastern Time maintenance window; expanded the schedule with frequency, execution mode, I/O impact, failure and overrun controls; and defined the macOS update-night exception. |
| 0.7 | August 15, 2026 | Todd McGuckin | Documented approved hostnames for all 19 planned Docker containers; defined internal UniFi CNAME and private Caddy disposition; and added populated Dependencies data to the approved application portfolio. UniFi DNS implementation remains pending validation and change approval. |
| 0.6 | August 14, 2026 | Todd McGuckin | Rebuilt from the Microsoft Word-authored v0.4 package; semantically recovered the v0.5 portfolio, Compose, and capacity-planning content; corrected the package structure; and added the DOCX delivery gate and canonical container-recipe path. |
| 0.5 | August 14, 2026 | Todd McGuckin | Added the approved portfolio, Compose patterns, and resource-capacity planning. Microsoft Word rejected the package because generated OOXML body and table-property elements were out of schema order. Retained only as forensic evidence. |
| 0.4 | August 14, 2026 | Todd McGuckin | Recorded the implemented split-listener state: private TCP 443, Plex-only TCP 8443, UniFi WAN TCP 443 forwarding to 8443, Tautulli DNS and HTTPS routing, LAN/WAN verification results, VPN-client follow-up, and rollback files. |
| 0.3 | August 14, 2026 | Todd McGuckin | Corrected the pending access-boundary design after verification showed Docker Desktop obscures client addresses. Defined private TCP 443 and Plex-only TCP 8443 listeners with UniFi WAN TCP 443 forwarding to 8443. |
| 0.2 | August 14, 2026 | Todd McGuckin | Recorded documentation-first change control, Tautulli on TCP 44444, plexstats.mcguckin.net, and the approved VPN-first/Caddy-internal access model. Infrastructure changes remain pending. |
| 0.1 | August 14, 2026 | Todd McGuckin | Initial as-built Docker implementation guide covering Docker Desktop, Caddy, FlareSolverr, persistence, networking, security, operations, recovery, and known deviations. |
Related Documentation¶
| Document | Relationship |
|---|---|
| NET-002 - McGuckin Home Network Architecture Standard | Authoritative source for hostnames, static addressing, and service DNS conventions. |
| NET-003 - Container Platform Standard, Phase 1 | Defines intended Docker storage, Compose, persistence, networking, backup, and operational standards. |
| NET-003 - Container Platform Standard, Phase 2 | Defines platform-management, logging, dashboard, observability, and update-management capabilities. |
| Caddy project-local README and docs | Provide executable commands, detailed troubleshooting, security, deployment, and disaster-recovery procedures. |
| Private Internet Access - Desktop Application Split Tunneling | Authoritative behavior for Only VPN, Bypass VPN, and All Other Apps rules on macOS. |
| Private Internet Access - Basic and Advanced Desktop Settings | Authoritative VPN Kill Switch, Advanced Kill Switch, Allow LAN Traffic, and PIA connection-state behavior. |
| Docker Desktop - Networking | Authoritative explanation that macOS container egress is presented through com.docker.backend, preventing per-container host-app split-tunnel isolation. |
| AUTHORITATIVE USE When current implementation details conflict with NET-003, NET-004 records the observed state while NET-003 remains the target standard. Resolve the discrepancy through a controlled change and update both documents accordingly. |
|---|
Related¶
- Related audit:
NET-AUD-002
Document Control¶
| Field | Value |
|---|---|
| Control ID | NET-INF-004 |
| Lifecycle | PUB |
| Status | Published |
| Version | v2.2 |
| Build | 013.20260815.180509Z |
| Canonical Filename | NET-INF-004_PUB_docker-implementation-guide_013-20260815-180509Z.md |
| Prior Identity | NET-004 |