Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions docs/Glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,23 @@ Plex moves an item's own last-viewed date on any playback and only writes a hist
- Availability: movies, shows, seasons, episodes
- Type: date

#### Newest episode view date in this or an earlier season

:::info
The newest view date across this season and every season before it. A rule on season 3 answers with the last time anyone watched anything in seasons 1, 2, or 3. Use it to keep a later season while someone is still working their way towards it.

Only offered for season rules. Specials are kept separate: a specials season counts only views of its own episodes, and a numbered season never counts views of specials.

Plex keeps history rows for episodes that have since left the library, so those views still count.

If a history row comes back without the season it belongs to, the value is treated as unknown for that run instead of reporting a date that leaves views out.

:::

- Key: Plex.sw_lastViewedAtThroughSeason
- Availability: seasons
- Type: date

---

### Jellyfin
Expand Down Expand Up @@ -1120,6 +1137,23 @@ If the play date cannot be read for every user, the value is treated as unknown
- Availability: movies, shows, seasons, episodes
- Type: date

#### Newest episode view date in this or an earlier season

:::info
The newest view date across this season and every season before it. A rule on season 3 answers with the last time anyone watched anything in seasons 1, 2, or 3. Use it to keep a later season while someone is still working their way towards it. Also available on Emby.

Only offered for season rules. Specials are kept separate: a specials season counts only views of its own episodes, and a numbered season never counts views of specials.

Jellyfin and Emby read the episodes the show holds at the time of the run, so a view of an episode that has since left the library no longer counts. Plex answers from its own history, where those views still count.

A season filed without a number, such as `Season Unknown`, has no place in the order of seasons, so the value is treated as unknown.

:::

- Key: Jellyfin.sw_lastViewedAtThroughSeason
- Availability: seasons
- Type: date

---

### Radarr
Expand Down
21 changes: 11 additions & 10 deletions docs/Installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -293,16 +293,17 @@ services:

A list of all available environment variables are below. No other env variables are officially supported by Maintainerr. These are added either into the compose file or your docker run command.

| Variable | Default Value | Description |
| -------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| TZ | _host timezone_ | Controls date formatting in logs. |
| UI_HOSTNAME | 0.0.0.0 | The listen host of the web server. Can be set to :: for IPv6. |
| UI_PORT | 6246 | The listen port of the web server. |
| BASE_PATH | | If reverse proxying with a subfolder you'll want to set this. Must be in the format of `/subfolder`. See [Reverse Proxy](./ReverseProxy.md). |
| LOG_LEVEL | info | Overrides the persisted log level for the current container process only. Accepted values are `debug`, `verbose`, `info`, `warn`, `error`, and `fatal`. |
| GITHUB_TOKEN | | GitHub Personal Access Token for higher API rate limits |
| CORS_ALLOWED_ORIGINS | | Comma-separated list of origins allowed to call the API cross-origin, e.g. `https://maintainerr.example.com`. Same-origin access (the bundled UI, including via localhost) always works and never needs this; only set it if a separate front end on a different origin calls the API. |
| TELEMETRY | | Set to `off` to disable the anonymous weekly usage report, whatever the stored setting says. See [Security](./Security.md#how-maintainerr-handles-your-data). |
| Variable | Default Value | Description |
| -------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| TZ | _host timezone_ | Controls date formatting in logs. |
| UI_HOSTNAME | 0.0.0.0 | The listen host of the web server. Can be set to :: for IPv6. |
| UI_PORT | 6246 | The listen port of the web server. |
| BASE_PATH | | If reverse proxying with a subfolder you'll want to set this. Must be in the format of `/subfolder`. See [Reverse Proxy](./ReverseProxy.md). |
| LOG_LEVEL | info | Overrides the persisted log level for the current container process only. Accepted values are `debug`, `verbose`, `info`, `warn`, `error`, and `fatal`. |
| GITHUB_TOKEN | | GitHub Personal Access Token for higher API rate limits |
| CORS_ALLOWED_ORIGINS | | Comma-separated list of origins allowed to call the API cross-origin, e.g. `https://maintainerr.example.com`. Same-origin access (the bundled UI, including via localhost) always works and never needs this; only set it if a separate front end on a different origin calls the API. |
| TELEMETRY | | Set to `off` to disable the anonymous weekly usage report, whatever the stored setting says. See [Security](./Security.md#how-maintainerr-handles-your-data). |
| SPORTARR_NET | | Set to `on` to read artwork and descriptions from sportarr.net for a Sportarr league none of your Sportarr connections tracks. Nothing is asked of sportarr.net unless it is set, though Sportarr hosts the artwork files there, so a browser still loads images from sportarr.net either way. See [Configuration](./Configuration.md#sportarr). |

:::tip
If `BASE_PATH` is set, remember to prefix health-check probe paths accordingly (for example `/maintainerr/api/health/ready`).
Expand Down
2 changes: 2 additions & 0 deletions docs/MediaServerSwitching.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ Rule groups are **deactivated** after switching and libraries must be re-assigne

Property remapping is derived at runtime by matching each property's name between the source and target application definitions, with an explicit mapping used only when no name matches. The ID pairs below illustrate the mappings resolved by that behavior and are not a stable contract. The switch preview reports exactly which of your rules will be migrated or deleted and is authoritative where this illustrative list is not.

A property that migrates can still answer differently on the new server. `Newest episode view date in this or an earlier season` is one: Plex counts views of episodes that have since left the library, while Jellyfin and Emby count only the episodes the show holds at the time of the run. The [Glossary](./Glossary.md) describes each property per server.

**Plex -> Jellyfin / Emby incompatible (rule deleted):**

- Watchlisted by (username) (ID 28)
Expand Down
2 changes: 2 additions & 0 deletions docs/Rules.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ The watch-history getters keep these cases separate: a confirmed empty history r

`Last play date (including unfinished)` (`lastPlayedAt`) is the played counterpart of `Last view date`. It answers with the last time an item was played at all, including a play someone stopped early, while `lastViewedAt` only counts a play that got far enough to be a view. It is offered for Plex, Jellyfin, Emby, Tautulli, Tracearr, and Streamystats, and it treats a failed lookup as unknown in the same way. On Plex both properties report the same date, because Plex already moves an item's last-viewed date on any playback.

`Newest episode view date in this or an earlier season` (`sw_lastViewedAtThroughSeason`) answers for a run of seasons rather than one. A rule on season 3 sees the last time anyone watched anything in seasons 1 to 3, so you can clear watched seasons without getting ahead of someone still working through the show. It is offered for Plex, Jellyfin, and Emby season rules. Plex counts views of episodes that have since left the library, while Jellyfin and Emby count only the episodes the show holds at the time of the run.

:::

:::warning Plex Watchlist Rules
Expand Down
2 changes: 1 addition & 1 deletion docs/Security.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Security is expected at the boundary you already control - your LAN, a VPN, or a
Maintainerr is built to keep your data on your own hardware and to be careful with it internally:

- **Your data stays on your hardware.** All configuration and state lives in a single SQLite database in your data directory (`/opt/data`). There is no cloud component holding any of it. Outbound traffic goes to the services you configure (your media server, the \*arrs, Seerr, and so on), to the metadata providers (TMDB/TVDB) used to match your library, and to `telemetry.maintainerr.info` for the weekly usage report below.
- **The weekly usage report is on unless you turn it off.** Once a week Maintainerr reports how it is running: its version, the platform it runs on, and which media server type is configured. Some weeks it also reports which rule properties, integrations, features, and notification agents are in use, with counts given as ranges rather than exact numbers. The report carries no identifier of any kind and nothing from your library: no account, hostname, URL, API key, library name, or media title, and no IP address is read or stored. New installs are not asked, the report is on from the start. If you are upgrading from a version without the report, Maintainerr asks you in the web interface once your media server is set up. `Keep it on` saves the answer and the prompt does not return. `Turn it off in settings` only opens the settings page, and until you save the toggle there the prompt appears again on the next visit. Either way you can change it at any time under **Settings > About > Help us improve it**. Setting the `TELEMETRY` environment variable to `off` disables it whatever that setting says. The [telemetry collector](https://github.com/Maintainerr/telemetry-collector) is a public repository, and its README lists every field the report can contain.
- **The weekly usage report is on unless you turn it off.** Once a week Maintainerr reports how it is running: its version, the platform it runs on, and which media server type is configured. Some weeks it also reports which rule properties, integrations, features, and notification agents are in use, with counts given as ranges rather than exact numbers. The report carries no identifier of any kind and nothing from your library: no account, hostname, URL, API key, library name, or media title, and no IP address is read or stored. New installs are not asked, the report is on from the start. If you are upgrading from a version without the report, Maintainerr asks you in the web interface once your media server is set up. `Keep it on` saves the answer and the prompt does not return. `Turn it off in settings` only opens the settings page, and until you save the toggle there the prompt appears again on the next visit. Either way you can change it at any time under **Settings > About > Help us improve it**. Setting the `TELEMETRY` environment variable to `off` disables it whatever that setting says, and no prompt is shown while it is set. The [telemetry collector](https://github.com/Maintainerr/telemetry-collector) is a public repository, and its README lists every field the report can contain.
- **Outbound connections use verified TLS.** Calls to your services and to metadata providers use HTTPS with normal certificate verification, which the app never disables on its own. Notification email can use TLS and can optionally be PGP-encrypted.
- **Secrets are kept out of the logs.** Every log line passes through a sanitizer that masks API keys, tokens, `Authorization` headers, and credential-bearing URLs, so secrets do not leak into log files or error dumps.
- **The rules engine cannot run code or shell out.** Rules are evaluated by a typed comparator, never `eval`-ed. Database access is fully parameterized, so there is no SQL-injection surface, and the server runs no shell commands. Settings you submit are schema-validated before they are saved.
Expand Down