Repository navigation
Releases: Jake-double-one/wokearr
Release list
wokearr-v0.5.0-security-hardening
Highlights
Wokearr no longer runs as root. It now runs as user 1000:1000 (PUID/PGID). Nothing to do: on the first start, existing data in /data is handed over to that user automatically, and the container log says so once. If that isn't possible (read-only or network mount), Wokearr keeps running as root as before, and the log and a notice in the web UI say what to change. PUID=0 keeps it on root.
Security hardening: secrets no longer leak into logs, the run protocol or notifications. Cross-site requests and off-site fetches are refused.
Security
- The Plex token could leak. When a request to Plex failed, the error message quoted the full image URL, token included. That URL ended up in the container log, the run protocol and notifications. Secrets (Plex token, login password, notification tokens,
token=/password=/apikey=in URLs) are now removed everywhere, tracebacks included. A stored run protocol is cleaned on the first start. - Cross-site requests: with
AUTH_METHOD=none, any website could start a rebuild, a push or the poster cleanup. Requests that change something now always need theX-Requested-Withheader the UI sends. - Server-side request forgery: review pages are only fetched from
https://isitwokeornot.com. Sitemap entries and redirects pointing elsewhere are ignored. - Review links in the grid are only ever
https://isitwokeornot.com/...links. - Content Security Policy,
nosniffandReferrer-Policy: same-originon every response. - Dependencies: Pillow 12.3.0 (16 known vulnerabilities fixed), requests 2.34.2, plexapi 4.18.3.
- Runs as
1000:1000instead of root (see above).docker-compose.yamlsetsno-new-privileges. python app.py(local development) listens on 127.0.0.1 only. The debugger only starts withFLASK_DEBUG=1.
Added
- Test suite, lint, dependency audit and a container test (update from root, read-only mount,
PUID=0,user:) on every pull request. Dependabot handles updates. - Test images per pull request:
ghcr.io/jake-double-one/wokearr:pr-<number>. licenses.txt: licenses of all libraries and components in the image, also in the image under/usr/share/doc/wokearr/.
Changed
- Finished background jobs no longer pile up in memory (the latest 50 are kept).
- An invalid poster id answers 404 instead of an error.
- The README points to the companion userscript isitwokeornot-tampermonkey-companion.
Upgrade note
- With a bind mount, the files on the host belong to
1000:1000after the first start. SetPUID/PGIDfor a different user. - If a request to Plex ever failed while notifications were on, the Plex token may have been sent along. To renew it, sign out all devices in your Plex account settings and update
PLEX_TOKEN. - Scripts calling the API directly need the header
X-Requested-With: wokearrfor POST requests.
Full changelog: v0.4.1...v0.5.0
v0.4.1
Wokearr has a face now: an open eye, since "woke" literally means awake.
Added
-
Favicon and logo. The open eye in the UI's orange appears in:
- the browser tab (SVG plus a 16/32/48 px
favicon.ico) - the iPhone home screen (
apple-touch-icon.png) - the README title
/favicon.icois also served at the root and stays reachable while a login is active. - the browser tab (SVG plus a 16/32/48 px
-
Screenshot in the README. The titles, posters and scores in it are made up.
Changed
-
The eye replaces the "WA" mark in the header and on the login page, so the tab, header and login now look the same.
-
The README explains the difference between the two counters in the run protocol:
- "scores updated": review pages fetched again, e.g. after a text edit on isitwokeornot.com
- "scores changed": a title in your library got a new score
Only the second one triggers a notification.
Fixed
- The next autopilot run in the footer showed a two-digit hour in every language ("08:00 AM"). It now uses each language's usual short time format: "8:00 AM" in English, "08:00" in German.
Upgrade note
Nothing to do. Pull the new image. If the old icon sticks around, reload the page once with a hard refresh (Ctrl+F5); browsers cache favicons stubbornly.
Full changelog: CHANGELOG.md · Compare v0.4.0...v0.4.1
v0.4.0
Optional login, like Radarr and Sonarr. Nothing changes unless you turn it on.
Highlights
Set AUTH_METHOD to choose:
AUTH_METHOD |
What you get |
|---|---|
none (default) |
No login, as before. Also the choice behind a proxy that authenticates on its own (e.g. authentik forward auth); then the container port must not be reachable directly |
basic |
The browser's login popup. Works with authentik's Send HTTP-Basic Authentication. Radarr dropped Basic in v6, but this setup still works here |
forms |
A login page modeled on Radarr's, with "Remember me" (30 days) and a logout link in the footer |
Both methods use the same login from AUTH_USERNAME and AUTH_PASSWORD (or AUTH_PASSWORD_FILE for Docker secrets).
Security
- Fails closed. If the login is incomplete or
AUTH_METHODis misspelled, Wokearr stays locked and shows the reason. It never falls back to "no login"./healthzreports it as unhealthy, so it shows up in Portainer. - Brute-force protection: at most 5 failed logins per address within 15 minutes. Every failure is logged in a form fail2ban/CrowdSec can parse:
WARNING [auth] Failed login for user 'x' from 203.0.113.5 - CSRF protection: other websites can't trigger actions using your browser's stored login.
- The
formssession cookie is HttpOnly and SameSite=Lax, and Secure over HTTPS. Changing the password ends every session; a restart doesn't log anyone out.
Setup
environment:
AUTH_METHOD: "forms" # none | basic | forms
AUTH_USERNAME: "admin"
AUTH_PASSWORD: "a long password"-
In a compose file, write a
$in the password as$$. -
Use
basiconly behind HTTPS: the browser sends the credentials with every request. -
authentik with
basic:- Create a group with the attributes
wokearr_userandwokearr_password. - In the proxy provider, enable Send HTTP-Basic Authentication with those two attribute names.
Details are in the README.
- Create a group with the attributes
Upgrade note
Nothing to do: the login is off unless you set AUTH_METHOD. If you already had AUTH_USERNAME/AUTH_PASSWORD in your environment, they only take effect together with AUTH_METHOD=basic or forms. The startup log warns about that combination.
Full changelog: CHANGELOG.md · Compare v0.3.2...v0.4.0
v0.3.2
Important
Set TZ if your AUTO_SYNC_CRON is meant in local time. Until now the schedule was evaluated in UTC, because nothing passed a time zone into the container. Add it under environment: in your compose file or Portainer stack, e.g. TZ: "Europe/Berlin".
Failed runs now say why they failed, the container log gets timestamps and tracebacks, and the autopilot can notify you via Gotify, ntfy or a webhook.
Highlights
- Notifications for autopilot runs via
NOTIFY_URL. Supported are Gotify (gotify:///gotifys://), ntfy (ntfy:///ntfys://) and anyhttp(s)://webhook. The URL formats are the same as in Apprise.NOTIFY_ONpicks what's reported:error(a stage failed) and/orchanges(new titles badged, scores of your titles changed). Quiet runs send nothing. - Failed runs say why. The protocol names the failed stage and the reason in plain words, e.g. "Score database failed: isitwokeornot.com not responding (timeout)". The raw message is one tap away.
- Container log rebuilt. Every line has a timestamp, level and area, and errors come with their traceback. Each run gets a start and a finished line, and the effective configuration is logged at startup. Tokens and passwords are never logged.
- Sorting in the filter bar: title, score or release date, ascending or descending, remembered per browser.
- Next autopilot run shown in the footer.
- Score changes by name. The protocol lists which of your titles got a new score (
Barbie: 72 → 81) and which were badged for the first time.
Changed
- Autopilot stages fail independently. If isitwokeornot.com is down, the run continues with the scores already known, so new Plex titles still get their badge. Only a failed Plex comparison skips the push.
- The sitemap fetch retries once on timeouts and server errors. A failed fetch no longer uses up the cooldown.
- Log messages are always in English, whatever
LANGUAGEis set to, so they can be searched and shared as they are.LOG_LEVEL=DEBUGadds a line per title. - The delta in matched titles now compares against the last run that counted them.
Fixed
- A failed autopilot run looked like a quiet one. A run that died in the first stage showed "no changes", indistinguishable from a healthy run.
- Errors from the buttons weren't logged at all. They were only kept in the browser session.
- The cron schedule ran on UTC. See the note at the top.
- Possible loss of cached posters. A Plex connection error while listing the libraries was treated as "library not found". With every library skipped, the orphan cleanup would have deleted every cached poster. Connection errors now fail the stage, and the cleanup is skipped whenever Plex returns no titles.
- A library name Plex doesn't know is now logged, together with the names it does know.
- Titles and error messages are HTML-escaped in the grid and the protocol.
Setup examples
environment:
TZ: "Europe/Berlin"
NOTIFY_URL: "gotifys://gotify.example.com/APP_TOKEN"
NOTIFY_ON: "error,changes" # default
LOG_LEVEL: "INFO" # defaultSend a test notification with:
docker exec wokearr python notify.pyFull changelog: CHANGELOG.md · Compare v0.3.1...v0.3.2
v0.3.1
Merge pull request #28 from Jake-double-one/claude/wokearr-docs-updat…
v0.3.0
Three additions in this release, all visible directly in the UI.
Five score bands instead of three
Wokearr now uses the official classification from isitwokeornot.com instead of
its own coarse traffic light:
| Score | Band |
|---|---|
| 0–19 | Not woke |
| 20–39 | Slightly woke |
| 40–59 | Woke |
| 60–79 | Very woke |
| 80–100 | Super woke |
Two color palettes to choose from via BADGE_COLOR_SCHEME:
standard(default) mirrors the colors isitwokeornot.com uses themselvesmodifiedis an alternative ramp: green → yellow → orange → red → violet
The filter bar now has five chips, named by band rather than by color — the
same band is a different color depending on the palette.
Run protocol in the footer
Every run is now recorded and survives container restarts, so you can see what
actually changed: matched titles (including the delta to the previous run),
scores updated, posters fetched, rendered and pushed, orphans cleaned up, plus
duration and what triggered it — autopilot or a specific button.
The footer shows one quiet line with the last run; a click expands a table of
the recent runs, collapsed by default. How long entries are kept is set via
RUN_HISTORY_RETENTION (e.g. 3d, 4w, 6m; 0 keeps everything). Stored
as run_history.json in the /data volume.
Version visible in the UI
The footer shows which version is running. For latest images it also shows
the build date, so it's clear how current the image actually is. Also exposed
via /healthz.
⚠️ Note when upgrading
The first run after this update re-renders and re-uploads every poster,
seasons included. That is intended: the band colors changed, and Wokearr now
tracks which badge settings a poster was rendered with — otherwise existing
posters would silently keep their old three-band colors. From now on, changing
any badge setting (BADGE_COLOR_SCHEME, BADGE_POSITION, BADGE_LABEL_STYLE,
BADGE_WIDTH_PERCENT) takes effect automatically on the next sync instead of
requiring a manual forced push.
Nothing to do by hand, but expect a noticeably longer first run and
corresponding load on the Plex server — worth timing accordingly.
New environment variables
| Variable | Default | Description |
|---|---|---|
BADGE_COLOR_SCHEME |
standard |
Palette for the five bands: standard | modified |
RUN_HISTORY_RETENTION |
4w |
How long run-protocol entries are kept: <number><unit> with d/w/m. 0 keeps everything |
Both are optional — without them the defaults above apply.
Full Changelog: v0.2.5...v0.3.0
v0.2.5
What's Changed
- Add Polish and Turkish UI translations by @Jake-double-one in #23
- Also badge each season's own poster, not just the show by @Jake-double-one in #24
- Replace AUTO_SYNC_INTERVAL_MINUTES with a cron-based AUTO_SYNC_CRON by @Jake-double-one in #25
Full Changelog: v0.2.4...v0.2.5
v0.2.4
What's Changed
- Remove redundant "Eigenes Image bauen" README section by @Jake-double-one in #18
- Add UI internationalization: LANGUAGE env var, en-US default, German README split by @Jake-double-one in #19
- Translate remaining code comments/docstrings to English by @Jake-double-one in #20
- Rename docker-compose service/container from woke-score to wokearr by @Jake-double-one in #21
- Add French, Spanish, and Italian UI translations by @Jake-double-one in #22
Full Changelog: v0.2.3...v0.2.4
v0.2.3
Honor isitwokeornot.com operator's requests: lastmod-based sync, UTM …
v0.2.2
Add BADGE_WIDTH_PERCENT env var to configure badge size (#16)
Badge width relative to poster width is now configurable via
BADGE_WIDTH_PERCENT (default 20), with a hard-coded 20% minimum floor so
the badge stays readable on smaller posters. Both label styles ("percent"
circle and "woke" pill) scale consistently off the same value.
Claude-Session: https://claude.ai/code/session_01YPUrWpjD5pa8tXjrc453PC
Co-authored-by: Claude <noreply@anthropic.com>