Skip to content
Draft
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ Every stack starts from the same [standard setup](documentation/standard-setup.m
| **Configarr** | Tool that applies YAML settings and TRaSH Guides profiles to Radarr and Sonarr, then exits. | [Details](services/configarr) |
| **FreshRSS** | Feed reader for RSS and Atom, with themes, extensions, and no separate database server. | [Details](services/freshrss) |
| **Hytale** | Hytale game server in a community image, for players on your Tailnet. | [Details](services/hytale) |
| **ImageMaid** | Cleaner that removes unused poster and background images from the Plex metadata folder. | [Details](services/imagemaid) |
| **Immich** | Photo and video library that backs up mobile media, with search and sharing. | [Details](services/immich) |
| **Jellyfin** | Media server that organizes and streams your movies, series, and music. | [Details](services/jellyfin) |
| **Kavita** | Digital library for comics, manga, and books, with progress synced across devices. | [Details](services/kavita) |
Expand Down
33 changes: 33 additions & 0 deletions services/imagemaid/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#URL=https://github.com/tailscale-dev/ScaleTail
# To run a second copy, copy the folder under another name and change SERVICE.

# Service Configuration
# Service name (e.g., adguard). Used as hostname in Tailscale and for container naming.
SERVICE=imagemaid
# Docker image URL from container registry (e.g., adguard/adguardhome:latest).
IMAGE_URL=kometateam/imagemaid:latest

# Network Configuration
# Preferred DNS server for Tailscale. Uncomment the "dns:" section in compose.yaml to enable.
DNS_SERVER=9.9.9.9

# Tailscale Configuration
# Auth key from https://console.tailscale.com/admin/settings/keys. See: https://tailscale.com/kb/1085/auth-keys#generate-an-auth-key for instructions.
TS_AUTHKEY=

# Time Zone setting for containers. See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
TZ=Europe/Amsterdam

# Any Container environment variables are declared below. See https://docs.docker.com/compose/how-tos/environment-variables/

# Folder of your Plex server data on this host, the one that contains the Cache, Metadata, and Plug-in Support folders.
# The default is the folder of the Plex stack of this repository. Change it when Plex runs elsewhere.
PLEX_DATA_DIR=../plex/plex-data/config/Library/Application Support/Plex Media Server
# What ImageMaid does with unused images: report (only list them), move (move them to a restore folder), or remove (delete them).
MODE=report
# When ImageMaid runs, as time|frequency, for example 05:00|weekly(sunday). Keep it set: ImageMaid runs once and exits when it is empty.
SCHEDULE=05:00|weekly(sunday)
# Address of your Plex server, for example http://100.64.0.1:32400. Leave empty, together with PLEX_TOKEN, to read the Plex database from PLEX_DATA_DIR.
PLEX_URL=
# Plex token. Leave empty to read the Plex database from PLEX_DATA_DIR. See: https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/
PLEX_TOKEN=
57 changes: 57 additions & 0 deletions services/imagemaid/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# ImageMaid

[ImageMaid](https://github.com/Kometa-Team/ImageMaid) removes unused poster and background images from the metadata folder of a Plex server, for example after you stop using Kometa overlays. It can also clean the photo transcoder cache, empty the trash, clean bundles, and optimize the database.

This stack runs ImageMaid with a Tailscale sidecar, as described in [the standard setup](../../documentation/standard-setup.md).

## At a glance

| Item | Value |
| ------------- | ------------------------------------------------------------------------- |
| Web interface | None |
| Image | `kometateam/imagemaid:latest` |
| Data | `./imagemaid-data/config` (logs and the copy of the Plex database) |
| | `PLEX_DATA_DIR` in `.env` (the Plex data folder, mounted at `/plex`) |

## Before you start

ImageMaid changes files in the Plex data folder, so it must run on the host that holds that folder.

- **Plex data folder.** `PLEX_DATA_DIR` in `.env` must point to the folder of your Plex server that contains `Cache`, `Metadata`, and `Plug-in Support`. The default is the folder of the [Plex stack](../plex/README.md) in this repository. Change it when Plex runs elsewhere. Compose stops with an error when the folder does not exist.
- **Schedule.** Keep `SCHEDULE` set in `.env`. When it is empty, ImageMaid runs once and exits, and `restart: always` then starts it again at once, over and over.
- **Mode.** `MODE=report` only lists the images that ImageMaid would remove. Check the list in the log, then set `MODE=move` to move them to an `ImageMaid Restore` folder, which you can restore. `MODE=remove` deletes them for good.
- **Plex access.** ImageMaid needs the Plex database to know which images are in use. Set `PLEX_URL` and `PLEX_TOKEN` to download it through the Plex API, or leave both empty to copy it from `PLEX_DATA_DIR`. Upstream recommends restarting Plex and keeping it idle before a copy.

## Deviations from the standard setup

- **No web interface.** The stack has no Tailscale Serve configuration, no `./config` folder, and no `ports` block. ImageMaid only makes outgoing connections: to Plex, and to Discord or Gotify when you set them up.
- **Plex data folder outside the stack.** The Plex data folder is mounted from `PLEX_DATA_DIR` instead of from `./imagemaid-data`, because ImageMaid works on the files of Plex. The mount fails when the folder is missing, so Docker does not create an empty one.
- **Runs as root.** The image has no `user` setting and runs as root, as upstream documents. Files that ImageMaid creates in `./imagemaid-data/config` belong to root.
- **Health check.** The image has no health check and no `pgrep`, so the check looks for the `python3` process, which is ImageMaid.

## First run

1. Start the stack. ImageMaid does not run at once. The log shows the schedule:

```bash
docker compose logs application
```

2. To reach Plex over your Tailnet, for example the Plex stack of this repository, set `PLEX_URL` to the Tailscale IP address of the Plex device, such as `http://100.64.0.1:32400`. To use its MagicDNS name instead, uncomment `TS_ACCEPT_DNS=true` in `compose.yaml`, as described in the [DNS section of the standard setup](../../documentation/standard-setup.md#dns).
3. To run ImageMaid right away, in the mode set in `.env`:

```bash
docker exec -e SCHEDULE= app-imagemaid /tini -s python3 /imagemaid.py
```

Stop Kometa and TitleCardMaker first, and run ImageMaid after the Plex scheduled tasks, as upstream advises.

## Configuration

`MODE`, `SCHEDULE`, `PLEX_URL`, and `PLEX_TOKEN` are the only options that `compose.yaml` passes on. ImageMaid reads every other option, such as `PHOTO_TRANSCODER`, `EMPTY_TRASH`, `CLEAN_BUNDLES`, `OPTIMIZE_DB`, `OVERLAYS_ONLY`, `DISCORD`, and the Gotify settings, from a file `.env` in `./imagemaid-data/config`. Environment variables take priority over that file. The [options](https://kometa.wiki/en/latest/kometa/scripts/imagemaid/) are described upstream.

## Links

- [ImageMaid documentation](https://kometa.wiki/en/latest/kometa/scripts/imagemaid/)
- [ImageMaid source code](https://github.com/Kometa-Team/ImageMaid)
- [ImageMaid on Docker Hub](https://hub.docker.com/r/kometateam/imagemaid)
63 changes: 63 additions & 0 deletions services/imagemaid/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
services:
# Make sure you have updated/checked the .env file with the correct variables.
# Every variable used in this file must be defined there, unless it has a default such as ${VAR:-value}.
# Tailscale Sidecar Configuration
tailscale:
image: tailscale/tailscale:latest # Image to be used
container_name: tailscale-${SERVICE} # Name for local container management
hostname: ${SERVICE} # Name used within your Tailscale environment
environment:
- TS_AUTHKEY=${TS_AUTHKEY}
- TS_STATE_DIR=/var/lib/tailscale
- TS_USERSPACE=false
- TS_ENABLE_HEALTH_CHECK=true # Enable healthcheck endpoint: "/healthz"
- TS_LOCAL_ADDR_PORT=127.0.0.1:41234 # The <addr>:<port> for the healthz endpoint
#- TS_ACCEPT_DNS=true # Uncomment only if the service must resolve MagicDNS names - this replaces Docker DNS, so Compose service names no longer resolve
- TS_AUTH_ONCE=true
volumes:
- ./ts/state:/var/lib/tailscale # Tailscale requirement - you may need to change the path
devices:
- /dev/net/tun:/dev/net/tun # Network configuration for Tailscale to work
cap_add:
- net_admin # Tailscale requirement
# If any DNS issues arise, use your preferred DNS provider by uncommenting the config below
#dns:
# - ${DNS_SERVER}
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:41234/healthz"] # Check Tailscale has a Tailnet IP and is operational
interval: 1m # How often to perform the check
timeout: 10s # Time to wait for the check to succeed
retries: 3 # Number of retries before marking as unhealthy
start_period: 10s # Time to wait before starting health checks
restart: always

# Application
application:
image: ${IMAGE_URL} # Image to be used
network_mode: service:tailscale # Sidecar configuration to route the service through Tailscale
container_name: app-${SERVICE} # Name for local container management
environment: # Variables are declared in .env file.
- TZ=${TZ}
- MODE=${MODE}
- SCHEDULE=${SCHEDULE}
- PLEX_URL=${PLEX_URL}
- PLEX_TOKEN=${PLEX_TOKEN}
volumes:
- ./${SERVICE}-data/config:/config
- type: bind # Plex data folder with the Cache, Metadata, and Plug-in Support folders
source: ${PLEX_DATA_DIR}
target: /plex
bind:
create_host_path: false # Fail when the folder is missing, so Docker does not create an empty one
depends_on:
tailscale:
condition: service_healthy
# Healthcheck: the image has no HEALTHCHECK, no endpoint, and no pgrep. ImageMaid is the only python3 process
# in the container, so check for python3 with pidof.
healthcheck:
test: ["CMD", "pidof", "python3"] # Check if ImageMaid is running and waiting for its schedule
interval: 1m # How often to perform the check
timeout: 10s # Time to wait for the check to succeed
retries: 3 # Number of retries before marking as unhealthy
start_period: 30s # Time to wait before starting health checks
restart: always # Without SCHEDULE, ImageMaid runs once and exits, and Docker would start it again at once.
Loading