TAUTWEEKLY FOR PLEX NAS Portable v1.1.0 · Unraid Apps and Docker Compose guide
Guide ready
READ ME FIRST · DOCKER COMPOSE EDITION

Run TautWeekly for Plex
natively on your NAS.

A focused walkthrough for deploying the NAS Portable package with Docker Compose, connecting it to Tautulli, testing every email state, and enabling weekly delivery without modifying the Tautulli container.

tautweekly / compose
$ docker compose pull
$ docker compose up -d
$ ./tautweekly.sh setup

[OK] Tautulli API connected
[OK] Animated assets verified
[OK] Preview web server healthy
[OK] Six email states available

NEXT: ./tautweekly.sh preview-all
No Plex user receives this preview.

$ |
1
dedicated Compose service
1
persistent data mount
6
deterministic preview states
0
automatic sends enabled initially
No guide sections matched that search. Try “Tautulli,” “PUID,” “preview,” “schedule,” or “backup.”
Deployment model

What Docker Compose creates

TautWeekly for Plex remains independent from Tautulli while communicating through its HTTP API.

Tautulli

Existing native or containerized service, normally exposed on port 8181.

TautWeekly for Plex container

PowerShell 7, ImageMagick, internal scheduler, email renderer, and preview server.

Persistent data/

Configuration, state, assets, logs, previews, and the automatic-send guard.

Compose maps host port 8787 to container port 8080, mounts ./data:/data, uses restart: unless-stopped, and checks both the preview server and a served animated asset.
Preflight

Requirements

Confirm these before extracting the package.

01

Docker + Compose

docker compose version or the older docker-compose command must work.

02

64-bit host

Supported host architectures are x86_64/amd64 and aarch64/arm64.

03

Persistent folder

Use a NAS share that survives container recreation and is included in backups.

04

Tautulli API

Have the Tautulli URL, published port, and API key available.

05

SMTP

Use an authenticated STARTTLS provider, typically on port 587.

06

Test recipient

Choose a private TestEmail before any real Plex user delivery is enabled.

Step 1

Extract one archive

The ZIP and TAR.GZ contain the same application. Install only one.

ZIP

Graphical or Windows-first extraction

Use the ZIP when extracting with File Explorer or another graphical archive utility, then copy the folder to your NAS.

TautWeekly-nas-docker.zip
TGZ

Linux/NAS extraction

Use TAR.GZ when extracting directly on the NAS over SSH.

mkdir -p /srv/containers/tautweekly
tar -xzf TautWeekly-nas-docker.tar.gz \
  --strip-components=1 \
  -C /srv/containers/tautweekly
i
Recommended project folder

The folder containing compose.yaml should itself be persistent. Compose uses the relative mount ./data:/data.

Step 2

Create and edit .env

These host-specific values control permissions, timezone, and the preview address.

01

Create the file

cd /srv/containers/tautweekly
cp .env.example .env
02

Find a non-root user and group

id -u
id -g

Do not configure the container to run as UID or GID 0.

03

Edit the values

COMPOSE_PROJECT_NAME=tautweekly
TZ=America/Phoenix
PUID=1000
PGID=1000
UMASK=077
PREVIEW_BIND=0.0.0.0
PREVIEW_PORT=8787
PREVIEW_BASE_URL=http://media.example.test:8787
VariableMeaningRecommended NAS value
TZContainer and scheduler timezoneIANA zone such as America/Phoenix
PUID/PGIDOwnership used inside the containerNon-root IDs that can write the project data/ folder
UMASKPermissions for new files077
PREVIEW_BINDHost interface for the preview port0.0.0.0 for LAN access or 127.0.0.1 for host-only
PREVIEW_PORTHost preview port8787
PREVIEW_BASE_URLURL shown after preview generationhttp://NAS_LAN_IP:8787
Step 3

Pull, start, and configure

The image is built locally from the included Dockerfile.

01

Pull the published image

docker compose pull
02

Start the service

docker compose up -d
docker compose ps
03

Run the interactive setup wizard

chmod +x tautweekly.sh
./tautweekly.sh setup

After entering the Tautulli URL and API key, select numbered users or ranges to exclude from scheduled and SendAll delivery.

The Plex URL and token are optional. Pressing Enter at the token prompt safely leaves it blank.

04

Restart after configuration

docker compose restart tautweekly
Alternative QNAP workflow

On QNAP, ./qnap-install.sh creates .env, pulls the published image, starts, runs setup, restarts, and verifies. Container Station can also create an application from compose.qnap.yaml.

Step 4

Point TautWeekly for Plex at Tautulli

Choose the address according to where Tautulli runs.

LAN

Published NAS port

Use the NAS LAN address and Tautulli’s published host port.

http://media.example.test:8181
NET

Shared Docker network

When both services share one custom network, resolve Tautulli by service name.

http://tautulli:8181
PMS

Optional direct Plex metadata

Direct Plex URL and token improve clearLogo support. They are not required for normal Tautulli-based operation.

http://media.example.test:32400
!
Never use 127.0.0.1:8181 for another container.

Inside TautWeekly for Plex, localhost points back to the TautWeekly for Plex container—not the NAS host and not Tautulli.

Step 5

Run the acceptance sequence

Keep automatic delivery disabled until these checks pass.

01

Verify the installation

./tautweekly.sh verify

Checks configuration, Tautulli, assets, SMTP reachability, schedule syntax, and an actual browser-served GIF.

02

Inspect users and confirm exclusions

./tautweekly.sh list-users
./tautweekly.sh exclude-users

The exclusion command updates only stable user IDs. Press Enter to keep the list or type none to clear it.

03

Generate all six previews

./tautweekly.sh preview-all

This creates manual welcome, both new-user branches, normal, quiet, and warm-up previews.

04

Open the preview index

http://NAS_LAN_IP:8787/preview-all-00-INDEX.html
05

Send all six to TestEmail

./tautweekly.sh send-test-all

No Plex user receives these six messages.

1

Manual welcome

One-off onboarding without weekly statistics.

2–3

New-user branches

First scheduled newsletter with and without viewing history.

4–6

Established branches

Normal activity, quiet/no activity, and initial warm-up.

Step 6

Enable automatic delivery

The scheduler runs inside the container and follows the configured timezone.

OFF

Disabled initially

Starting the container does not automatically authorize real sends.

TZ

Timezone-aware

The schedule follows TZ from .env.

Same-day guard

The attempt is recorded before sending to reduce duplicate delivery after restarts.

10s

Recipient delay

Production SendAll retains the configured delay between individual recipients.

./tautweekly.sh schedule-status
./tautweekly.sh schedule-enable

# Disable later:
./tautweekly.sh schedule-disable
!
Use schedule-reset cautiously.

It clears today’s automatic-attempt guard. A later scheduler poll may allow another real SendAll on the same day.

Operations

Routine Docker Compose controls

Use the wrapper for TautWeekly for Plex actions and Compose itself for container lifecycle operations.

TaskCommandEffect
Statusdocker compose psShows container state and health.
Logs./tautweekly.sh logsFollows the last 200 container log lines.
Restart./tautweekly.sh restartRestarts only the TautWeekly for Plex service.
Stopdocker compose downRemoves the disposable container/network but preserves data/.
Startdocker compose up -dRecreates the service from the current image and configuration.
Shell./tautweekly.sh shellOpens a Bash shell inside the container for diagnostics.
Repair assets./tautweekly.sh repair-assetsRefreshes email assets and the browser-preview asset mirror.
Persistence

Back up and update safely

The container is disposable; the project folder and data/ are the durable installation.

project/ ├── compose.yaml ├── Dockerfile ├── .env ├── tautweekly.sh └── data/ ├── config.json ├── state.json ├── access-state.json ├── scheduler-state.json ├── assets/ ├── output/ └── logs/
  • config.json contains Tautulli, SMTP, branding, schedule, and exclusions.
  • state.json tracks first-run and warm-up state.
  • access-state.json tracks new users and welcome delivery.
  • scheduler-state.json protects against repeated automatic attempts.
BK

Create a dated backup

./tautweekly.sh backup

The backup includes credentials because it contains config.json. Store it privately.

UP

Pull a published update

docker compose pull
docker compose up -d
./tautweekly.sh repair-assets
./tautweekly.sh verify

Do not delete the existing data/ folder during an update.

NAS-specific paths

QNAP, Unraid, and generic Linux

The Compose service is the same; only host paths and identity defaults differ.

APP
Unraid users can install from Community Applications.

Search for TautWeekly for Plex, install the official template, then open the container Console and run Setup-First.ps1 followed by Verify-Setup.ps1. Manual Compose remains available for custom stacks.

PlatformSuggested project folderPUID / PGID guidanceNotes
QNAP/share/Container/tautweeklyUse the IDs returned by id -u and id -g; avoid root.Container Station with Docker Compose. qnap-install.sh is available.
Unraid/mnt/user/appdata/tautweeklyTemplate defaults are 99 and 100.Install from Apps; use Compose Manager only for a custom stack.
Generic Linux NAS/srv/containers/tautweekly or /opt/tautweeklyUse a dedicated non-root service account with write access.Use the manual Compose workflow in this guide.
Diagnostics

Common problems

Start with status, logs, and verification before changing configuration blindly.

Container is unhealthy
Run docker compose ps and ./tautweekly.sh logs. The healthcheck requests the preview root and /assets/movies.gif. A failed asset request can make the service unhealthy even when the process is still running.
Preview page loads but GIFs or icons are missing
Update to v1.0.7, then run ./tautweekly.sh repair-assets and ./tautweekly.sh verify. The current release maintains a real /data/output/assets mirror inside the preview web root; no manual symlink is required.
Verification says an animated GIF is unreadable
v1.0.7 fixes the ImageMagick frame-count parser by adding newline delimiters. Rebuild the container from the v1.0.7 project files and verify again.
Tautulli connection fails
Confirm the URL is reachable from inside the TautWeekly for Plex container. Use NAS_IP:8181 for a published port or tautulli:8181 on a shared Docker network. Do not use 127.0.0.1.
Permission denied under data/
Confirm PUID and PGID are non-root IDs with write access to the host project folder. Repair ownership on the host, then recreate the container with docker compose up -d.
Port 8787 is already in use
Change PREVIEW_PORT in .env, update PREVIEW_BASE_URL to the same port, and recreate the service.
SMTP authentication fails
Confirm STARTTLS, normally port 587, the SMTP username, and the app password/provider credential. The package does not support implicit SMTPS on port 465 through the current .NET mail client.
Complete reference

tautweekly.sh command map

Risk labels distinguish local inspection, TestEmail delivery, real recipients, and scheduler changes.

CommandRiskPurpose
verifySAFERuns complete setup and asset verification.
list-usersSAFELists users available through Tautulli.
exclude-usersCONFIGUpdates stable recipient exclusions without rerunning setup.
preview [user]SAFECreates one local/browser preview.
preview-all [user]SAFECreates all six deterministic HTML previews.
send-test [user]TESTEMAILSends one real MIME/CID message only to TestEmail.
send-test-all [user]TESTEMAILSends all six states only to TestEmail.
welcome [user]REAL SENDSends a one-off welcome to the selected Plex user and records state.
send-allREAL SENDSends one newsletter to every eligible user after confirmation.
rosterSAFEDisplays first-seen and welcome-state tracking.
repair-assetsSAFERefreshes source assets and the browser-preview mirror.
schedule-statusSAFEShows configured schedule and current guard state.
schedule-enableSYSTEMAuthorizes automatic weekly SendAll.
schedule-disableSYSTEMStops future automatic sends.
schedule-resetREAL RISKClears today’s automatic-attempt guard.
backupSAFECreates a dated TAR.GZ of the host data/ directory.
updateSYSTEMPulls the current published image and recreates the service.
logsSAFEFollows recent service logs.
statusSAFEDisplays Compose service status.
restartSYSTEMRestarts only the TautWeekly for Plex container.
shellADVANCEDOpens a Bash shell inside the container.
Recommended final sequence

verifylist-usersexclude-userspreview-allsend-test-allschedule-statusschedule-enable.

Current email behavior

Adaptive stats and the Binge Champion award

Light viewing weeks reveal more detail without making heavy viewing weeks excessively tall.

1–3

Itemized movies

Mini poster, movie title, Rotten Tomatoes critic score, and audience score.

1–3

Itemized episodes

Mini show poster, show title, Sxx EPxx episode title, and IMDb score.

4+

Compact counts

At four or more, the card returns to the large-number format to protect email length.

Binge Champion is a privacy-preserving server-wide award.

The user with the most qualifying watch time wins; total plays break an exact-time tie. Every scheduled weekly email shows the same anonymous movie-play, TV-play, and total-time aggregate. Only the winner’s card receives the gold border, larger trophy, and “YOU WON” treatment.

i
Trending is not duplicated.

Trending ranks a media title and displays its server-wide play count once. Binge Champion ranks a person by qualifying watch time, but never reveals that person’s name, user ID, or watched titles.

Global movie formatting

Genre now appears in watched-movie statistics

The compact 1–3 movie recap now matches the rest of the newsletter’s movie hierarchy.

1–3

Adaptive movie rows

Each row includes a mini poster, title, genre, and Rotten Tomatoes critic and audience scores.

GLOBAL

One genre rule

Show the first two genres and append “, and more” when additional genres exist.

CLEAN

No empty genre row

When metadata has no genre, the rating line moves up automatically with no blank space.

Applied everywhere the adaptive movie-stat card can render.

This includes production and portable previews, individual tests, six-state test suites, scheduled weekly newsletters, and all applicable recipient states.

PowerShell 5.1 hotfix

Single-item adaptive cards now retain array semantics

Exactly one watched movie or one streamed episode no longer becomes a scalar under strict mode.

Resolved: “The property ‘Count’ cannot be found on this object.”

MovieItems and EpisodeItems are initialized and assigned explicitly as arrays before the adaptive renderer checks their counts.

0

Empty collection

Retains a valid zero-length array.

1

Single item

Remains an array instead of being unwrapped into a scalar.

2–3

Multiple items

Continues to render the adaptive poster rows normally.

Copied