diff --git a/docs/design.md b/docs/design.md index 5c47ebe..fb23af4 100644 --- a/docs/design.md +++ b/docs/design.md @@ -1,11 +1,15 @@ # MediaShelf — Software Design -**Status:** Draft v1.3 · **Author:** Claude (spec) for Jess · **Date:** 2026-09-07 +**Status:** v1.4 — deployed · **Author:** Claude (spec) for Jess · **Date:** 2026-09-10 *Revision 1.1 — Tautulli (192.168.1.100:8181) confirmed present and promoted to the primary watch-history source; Plex's own history demoted to fallback. Deployment path settled: image built in CI/locally and pushed to Nox's Portainer.* +*Revision 1.4 — implemented and deployed. Running on Nox as Portainer stack 113 +(`mediashelf`, host port 8086), built in place from a git stack rather than a registry +(§11.2). Not yet behind NPM.* + *Revision 1.3 — keep marks (§6.6) generalised from the earlier protected-libraries idea: one `keep` concept applied at library, show, season or movie level, keyed on content guid rather than Plex rating key so marks survive library rebuilds, kept items hidden from the @@ -1359,16 +1363,22 @@ non-root user. One volume: `/data`. One port: 8080. ### 11.2 Getting the image onto Nox -The image is built off-box and delivered to Nox's Portainer rather than built there. Two -workable routes, in order of preference: +**As deployed (2026-09-10): a Portainer git stack.** No registry exists on this network +and there is no SSH account on Nox, so Portainer clones the repo onto Nox itself and +`docker compose up` builds the image there. The compose file carries both `build: .` and a +pinned `image:` tag, so the built image is still versioned rather than an anonymous +`latest`, and a redeploy replaces it predictably. + +Redeploying is a "Pull and redeploy" in Portainer, or `POST /api/stacks/{id}/git/redeploy` +against the API. Nothing has to be pushed anywhere first. + +The two alternatives, if the build ever needs to move off Nox: 1. **Registry** — build, tag `registry.hallsworth.ca/mediashelf:` (or Forgejo's - own container registry, which this Forgejo version supports), push, and have the - Portainer stack pull it. This is the route worth setting up once: redeploys become a - version bump in the stack, and rollback is pulling the previous tag. -2. **Image upload** — `docker save mediashelf: | gzip` and load it on Nox via - Portainer's *Images → Import*. No registry needed, fine for the first deploy or two, - but it makes rollback manual and versions easy to lose track of. + own container registry, which this Forgejo version supports), push, and have the stack + pull it. Worth setting up if builds get slow or Nox gets busy. +2. **Image upload** — `docker save | gzip` and load via Portainer's *Images → Import*. + Fine once or twice; makes rollback manual and versions easy to lose track of. Either way the image is **tagged with a real version**, never deployed as bare `latest`. The Mythica stack had to be torn down and recreated because a `PUT` update kept serving @@ -1380,11 +1390,12 @@ worked around. ```yaml services: mediashelf: - image: registry.hallsworth.ca/mediashelf:0.1.0 # never bare :latest, see 11.2 + image: ${MEDIASHELF_IMAGE:-mediashelf:0.1.0} # never bare :latest, see 11.2 + build: . # built on Nox by the git stack container_name: mediashelf restart: unless-stopped ports: - - "8085:8080" + - "${MEDIASHELF_PORT:-8086}:8080" volumes: - mediashelf_data:/data environment: @@ -1412,9 +1423,10 @@ volumes: in Portainer's UI.** A variable set in Portainer that isn't declared in the compose file silently does nothing — the same trap that bit `PLAYERMAP_SHOW_GMS` on the Mythica stack. -Published through Nginx Proxy Manager at `mediashelf.hallsworth.ca`, upstream -`192.168.1.77:8085`. Note the host-port → container-port mapping is 8085 → 8080; NPM's -upstream must point at the **host** port. +Host port **8086** (8085 and most of the 808x range were already taken on Nox). Not yet +published through Nginx Proxy Manager — reachable at `http://192.168.1.77:8086` on the +LAN. If an NPM host is added later its upstream must point at the **host** port, 8086, +not the container's 8080. ### 11.4 The gunicorn / scheduler constraint