TAUTWEEKLY FOR PLEXNAS / Docker Manager Quickstart
0%
Shared NAS / container Manager

One secure core.
Host-owned lifecycle.

Run the authenticated TautWeekly Manager beside Tautulli on Debian, Ubuntu, another Linux Docker server, Unraid, QNAP Container Station, or a Linux NAS. Dedicated NAS hardware is not required. The fully headless service keeps local recovery at http://127.0.0.1:8787/; use an SSH local forward for setup/recovery and the optional verified Funnel URL for ordinary remote browsers. The image stays replaceable; configuration, credentials, schedules, output, and recovery data live in the persistent volume.

fully headlesspassword requiredamd64 + arm64persistent /data
release-archive Docker host
docker compose up -d
docker compose ps
docker compose port tautweekly 8080
./tautweekly.sh manager-bootstrap

Open http://127.0.0.1:8787/ locally or through an SSH local forward
Pair once, then create the admin password.

No default password
No token in container logs
Automatic delivery remains disabled
requiredManager authentication
8 hoursin-memory session lifetime
/health/liveminimal public liveness
30 minCompose shutdown grace
Installation

Use the adapter your host owns.

Every path runs the same image and Manager core from ghcr.io/sparkmoxie/tautweekly. Debian, Ubuntu, and other Linux Docker servers use this distribution just like NAS hosts. New definitions explicitly select server, unraid, or desktop; the host remains responsible for semver/digest pins, pulls, ports, TLS, volumes, UID/GID/UMASK, and container start/stop behavior.

Unraid Apps

Install the maintained Community Applications template, review the appdata path, host port, timezone, PUID, and PGID, then start the container.

# Docker > TautWeekly for Plex > Console /opt/tautweekly/bin/run-as-user.sh \ /opt/tautweekly/bin/tautweekly-manager \ access-bootstrap --data-dir /data/manager

Forward Unraid loopback with ssh -N -L 8787:127.0.0.1:8787 root@UNRAID_HOST, then open http://127.0.0.1:8787/. The host-side ./tautweekly.sh wrapper does not exist inside an Unraid Apps container.

QNAP Container Station

In Create Application, paste compose.qnap.yaml, set the timezone and non-root identity, and replace the example host data path before validation and creation. Or extract the release over SSH and run:

chmod +x qnap-install.sh tautweekly.sh container-update.sh package-update.sh ./qnap-install.sh ./tautweekly.sh manager-bootstrap

Open http://QNAP_IP:8787/. A native QPKG is not part of this delivery; signing, App Center submission, and hardware-specific lifecycle would require a separately tested package.

Generic Compose / Linux server

No NAS appliance is required. Use this path on a headless Debian, Ubuntu, or other Linux Docker server.

# Verify TautWeekly-compose.yaml and SHA256SUMS.txt from the same release. mv TautWeekly-compose.yaml compose.yaml mkdir -p data # Set private .env values for TZ, PUID, PGID, UMASK, bind/port, and host policy. docker compose pull tautweekly docker compose up -d tautweekly docker compose ps docker compose port tautweekly 8080 docker compose exec -T tautweekly /opt/tautweekly/bin/run-as-user.sh \ /opt/tautweekly/bin/tautweekly-manager access-bootstrap --data-dir /data/manager

The no-clone asset pins full semver and selects server. It does not install the host-side ./tautweekly.sh wrapper, so use the direct Compose command above. Append the release manifest digest for immutable automation; never promote mutable minor, latest, or edge tags unattended. The verified archive wrapper remains a recovery/local-build fallback. For an audited break-fix source build only, use docker build -f platforms/nas-docker/Dockerfile .; the published semver/digest image remains preferred.

Other Docker hosts

Compatible hosts need Linux containers, Compose-compatible service settings, amd64 or arm64, a writable persistent mount at /data, and a non-root UID/GID. Docker Desktop can use the PowerShell wrapper:

docker compose pull docker compose up -d .\tautweekly-docker.ps1 manager-bootstrap

For host-published Tautulli on Docker Desktop, use the platform's host gateway name or a shared private Docker network—not container-local localhost.

First run

Pair through loopback; configure in the Manager.

The container creates a random one-time token in private persistent storage. Startup logs say pairing is required but never print the token or a credentialed URL. Use the host loopback URL directly or an administrator-controlled SSH local forward; no broad LAN port is created.

01

Retrieve

For a release archive, run the host-side ./tautweekly.sh manager-bootstrap. For no-clone Compose or a vendor Console, use the documented direct access-bootstrap container command.

02

Pair

Open http://127.0.0.1:8787/ locally or through an SSH local forward, enter the token, and create an administrator password of 8–256 UTF-8 bytes.

03

Configure

Save Tautulli, recommended direct Plex, SMTP, branding, library scope, exclusions, the weekly window, and the optional custom text card. Its body is required when enabled.

04

Accept

Run safe checks, generate six preview states, and send only to TestEmail.

05

Enable

Explicitly enable future starts only after the recipient roster and test messages pass review.

!

Recovery is narrow by design.

On a release-archive install, ./tautweekly.sh manager-reset-access removes only Manager credentials, pairing material, and active browser sessions, then restarts the container. Vendor and no-wrapper deployments use the documented direct access-recover Console command and their host restart control. Both preserve newsletter configuration, secrets, schedules, state, output, history, and backups; retrieve the new token through the same bootstrap interface used during installation.

  • No default password
  • No secret in normal diagnostics
  • Five failed attempts in five minutes are rate-limited
Main features

Shape the newsletter in Manager Config.

These are the everyday controls. Use the full configuration reference only when you need an advanced field or renderer detail.

Connections and delivery

Add Tautulli, recommended direct Plex, SMTP, sender identity, and a controlled TestEmail. Saved secrets stay write-only in the Manager.

Library selection

Choose the movie and TV libraries that define the newsletter content scope. Unselected sections do not contribute releases, Trending, or personal statistics.

User exclusions

Review the discovered roster and save who is excluded. The saved policy blocks those users from previews, TestEmail, welcome, and production delivery while keeping them visible for policy review.

Managed-user addresses

A separate card appears only for active Tautulli users without native email. Private fallback assignments may share an inbox, never override native email, and remain subject to existing exclusions; TestEmail stays isolated.

Newsletter and custom text

Set the lookback, card limits, branding, and optional custom text card. When enabled, give the card a body; its title, six-choice local title GIF, subheading, and border are optional refinements.

Verify and preview

Use Validate, save, and verify, then inspect all six browser previews. Validation checks configuration and reachability without sending mail.

Test and schedule

Send the six controlled messages only to TestEmail. Enable the weekly schedule after content, recipients, timezone, and inbox rendering are correct.

Deleted-item cache

When the cache is enabled or its coverage changes, Validate, save, and verify starts a separate no-email refresh for every production-eligible included user and selected movie/TV library. It captures only qualifying live newsletter-window items by exact stable GUID and usable poster; it does not crawl the whole library or depend on PreviewAll. Run ./tautweekly.sh cache-refresh explicitly and ./tautweekly.sh cache-status for a share-safe aggregate summary. Unseeded means no qualifying live refresh or render has written an entry. Disabling the cache stops reads and writes but does not erase retained entries in /data.

GUI acceptance

Configure, refresh upstream metadata, then test safely.

In Manager Config, select the delivery libraries and exclusions, then choose Validate, save, and verify. Terminal setup is an expert/recovery fallback.

01

Confirm Plex ratings

For every included Plex Movie library, confirm Edit → Advanced → Ratings Source.

02

Refresh Plex

Run Manage Library → Refresh All Metadata for every included movie/TV library and wait. A full refresh can take a long time and can update metadata or artwork.

03

Refresh Tautulli

Open each same Library → Media Info tab and choose Refresh media info. The current control is per-library, so repeat it for every included section.

04

Accept in Manager

Open Verify, generate all six previews, and send only to TestEmail. Enable Schedule only after the roster and messages pass review.

i

Routine TautWeekly updates do not require a full metadata refresh.

Repeat the upstream refresh sequence after first setup, a Plex agent or Ratings Source change, or a ratings/artwork recovery update when output may be stale. For an ordinary TautWeekly image update, sign back in and rerun Manager Verify, previews, and TestEmail; refresh upstream libraries only when current output indicates it is needed.

  • Manager is the setup source
  • No production recipients during acceptance
  • Schedule stays disabled by default
Network and storage

Loopback recovery with verified public ingress.

The host mapping stays on loopback. The exact Funnel hostname is admitted only after route, public DNS, and trusted TLS verification; forwarding headers are intentionally not trusted.

Setting or pathPurposeBoundary
PREVIEW_BIND / PREVIEW_PORTCompatibility variable names retained for the Manager's host mapping to internal port 8080Fixed supported recovery value 127.0.0.1:8787; do not bind a LAN/all-interface address
MANAGER_ALLOWED_HOSTSBackend Host allowlistLeave empty for loopback; the independently verified active Funnel hostname is admitted automatically
Secure session boundaryVerified public HTTPS requestsThe active Funnel hostname receives Secure cookies and HSTS automatically; loopback recovery remains HTTP-only
/data/managerPassword hash, pairing state, sanitized Manager operationsPersistent, private, writable by configured PUID/PGID
/data/config.jsonTautulli/Plex/SMTP credentials and scheduleNever bake into the image, upload to issues, or expose through diagnostics
/data/output, logs, state, backupsNewsletter output and private operational historyMay reveal recipients and viewing activity; back up privately

Browser request protection

  • HttpOnly, SameSite=Strict session cookie
  • Per-session CSRF token plus same-origin mutation checks
  • Sessions live only in memory and expire after eight hours
  • Restart signs out every browser

Container hardening

  • Non-root PUID/PGID; root identities are refused
  • UMASK=077 and persistent ownership repair without following external symlinks
  • no-new-privileges, all capabilities dropped, then only ownership-transition capabilities added
  • Read-only image assumptions; mutable state belongs under /data
TLS

Reverse proxies terminate TLS; the Manager does not.

Preserve the original Host, proxy only from a trusted network, list that DNS name, and enable secure cookies. The Manager ignores X-Forwarded-For and X-Forwarded-Proto. The unauthenticated /health/live response contains only liveness; every Manager API carrying state requires a session.

  • No public HTTP exposure
  • No broad DNS wildcard
  • No credential in health checks
TS

Optional public Tailscale Funnel

Enable TAUTWEEKLY_FUNNEL_ADAPTER, recreate the container, and run the packaged interactive login command. The isolated root-only userspace adapter owns separate state and only http://127.0.0.1:8080; the non-root Manager has no Docker/Podman socket, host executable, TUN device, host network, added networking capability, auth key, token, arbitrary command, hostname, port, path, or CLI argument. Manager Settings enables and verifies the exact public route only after its password lock is active. Remote viewers need an ordinary browser, not Tailscale or a VPN.

  • Manager password remains required
  • No auth key enters Manager, Compose YAML, or the Unraid template
  • Gold Publication pending is not green public DNS/TLS Active
Delivery lifecycle

The scheduler is independent of the browser.

The GUI can only enable or disable future starts for this package. It revision-checks configuration, writes a private backup, and verifies the saved boolean.

Closing and restarting

Signing out or closing a browser changes nothing. During container shutdown the Manager listener stops first, the supervisor waits up to the configured 29-minute delivery drain, and only then stops the scheduler. Compose grants 30 minutes. A host that enforces a shorter hard-kill timeout can still interrupt a delivery.

Truthful status

The Manager reads the embedded scheduler heartbeat and persistent attempt state. A process exit is not reported as inbox delivery. Only sanitized renderer results distinguish SMTP-accepted, skipped, failed, partial, and unrecorded outcomes.

Settings status, host-owned lifecycle

Refresh the package; preserve the volume.

Settings > Updates is the primary status source. It identifies the active runtime profile, unified image repository, recommended semver reference, immutable digest policy, migration state, application/image, release package, and host-adapter versions, plus the stable release, check history, sanitized failures, and notes. Authenticated entry renders cached status first, then performs one bounded background refresh only when the last success is missing or at least 24 hours old and backoff permits. The main header Refresh reloads local status first and then starts that check only when the new typed status recommends it; it never waits for GitHub, while scoped refresh controls stay isolated. Successful results are reused for five minutes; Check now then explicitly refreshes the same endpoint. Current remains green, every non-current status gives the update card an attention glow, and the purple header SVG appears only after a successful check validates a newer running application. Normal health stays offline-capable. The non-root Manager has no Docker socket or host helper and never installs container updates.

UP

Follow the owner named in Settings.

Unraid uses Docker/Apps and the current Community Apps template. QNAP uses Container Station plus the verified wrapper over trusted SSH. Release Compose/NAS packages show ./tautweekly.sh update. Other compatible Compose hosts run docker compose pull tautweekly, then docker compose up -d --no-build --force-recreate tautweekly from their original stack; another deployment tool must use its equivalent. Preserve /data. Do not add root, privileged mode, or a Docker socket to make this a web action.

  • No one-click NAS update claim
  • No unattended update by default
  • Confirm Settings after recreation

Backup and upgrade

./tautweekly.sh backup ./tautweekly.sh check-update ./tautweekly.sh update # then sign in, confirm Settings > Updates, preview, and TestEmail

The updater preserves .env, data/, named volumes, and unrelated host files. For named volumes, use a temporary trusted container or NAS-native backup tool to archive the volume while preserving ownership and modes. In Manager Config, one backup can be permanently deleted only after Confirm delete; the live config is unchanged.

Rollback

Pin TAUTWEEKLY_IMAGE to the prior verified version or digest and recreate the service. Do not restore an older config over a newer one blindly; use the timestamped config.backup.*.json files and review compatibility first.

Reinstall or move

Recreate the container with the same /data bind mount or named volume. Keep PUID/GID consistent or repair ownership from the trusted host before start. Stale absolute host paths belong in the host manifest, not in container configuration.

Uninstall

docker compose down # The data directory/volume remains. # Delete it separately only after a verified backup # and only when permanent data removal is intended.

Never use a volume-removal option as part of a routine reinstall or rollback.

v23

Migrate v0.22.0 without moving private data

The NAS/generic repository name stays ghcr.io/sparkmoxie/tautweekly; add server, preserve the exact /data mount, PUID/PGID/UMASK, ports, networks, and host policy, then pull and recreate with the original host tool. Wait for health and sign in with the existing password. An unexpected pairing screen means the old data mount is missing. Rerun interrupted pulls/recreates; roll back to the recorded v0.22.0 semver/digest against the same mount; never delete a volume or appdata. See the complete migration contract.

  • Back up and record the old digest first
  • Manager never controls Docker
  • Verify profile, Config, schedule/history, six previews, and TestEmail
v14

One-time migration for an older saved host adapter

If Settings reports Legacy or Mismatched, the image may have updated while the external package did not. Retrieve the token with the documented direct container Console command, then download the current stable NAS archive and SHA256SUMS.txt, verify them, and extract the archive over the same package directory without deleting .env or data/. After that one-time refresh, the packaged update command advances host files and image together.

  • Never copy from unreleased main
  • Preserve the data path
  • Unraid refreshes its saved Apps template instead
Basic troubleshooting

Check the boundary that failed.

Start with the Manager status and the host-owned container controls; keep credentials and private logs out of public support reports.

Manager does not open

Run docker compose ps and docker compose port tautweekly 8080. Confirm the container is healthy, the mapping reports 127.0.0.1:8787, the SSH local forward is active when needed, and /data is writable by the configured PUID/PGID. Then review only recent container logs.

Verify cannot reach a service

Test the saved Tautulli or Plex URL from the container network. Container localhost means TautWeekly itself; use a shared network, NAS address, or supported host gateway.

Preview is skipped or incomplete

Confirm one unambiguous owner/admin sample, selected libraries, and the metadata readiness sequence. Save and verify again before regenerating previews.

TestEmail or schedule fails

Keep production disabled. Recheck SMTP, sender permission, TestEmail, timezone, recipient exclusions, and the saved configuration revision; then inspect the sanitized operation result.

Validation and gaps

Automated confidence, explicit hardware limits.

The repository exercises shared Manager unit/security/accessibility tests, shell and package contracts, a virtual health service, isolated persistent data, amd64 boot smoke, and multi-architecture image builds in CI.

Covered without real services

  • No real Tautulli, Plex, SMTP, or user configuration
  • Private Manager bootstrap and log-redaction checks
  • Host-header, CSRF, cookie, recovery, and scheduler contracts
  • Container health, non-root ownership, and root-refusal smoke tests
  • amd64 and arm64 Buildx targets

Irreducible acceptance gaps

  • QNAP firmware/Container Station behavior on physical hardware
  • Unraid Community Applications moderation and live WebUI behavior
  • NAS-vendor reverse proxies, firewalls, storage ACLs, and hard-stop timeouts
  • Real SMTP providers, Plex/Tautulli datasets, and mail clients
  • Native QPKG signing or App Center submission, which is not in scope
QA

Complete environment acceptance before enabling delivery.

Confirm the Manager URL, authentication recovery, volume backup, direct Plex and Tautulli checks, six browser previews, all six TestEmail messages, restart persistence, scheduler timezone, update/rollback, and non-destructive uninstall behavior on the actual NAS.

  • Keep production disabled
  • Use synthetic data for support
  • Never share private diagnostics