100 lines
5 KiB
YAML
100 lines
5 KiB
YAML
services:
|
|
watchstate:
|
|
image: ghcr.io/arabcoders/watchstate:${WATCHSTATE_VERSION}
|
|
container_name: watchstate
|
|
restart: unless-stopped
|
|
# The image runs rootless and drops privileges to this uid:gid — it is a
|
|
# `user:` directive, not PUID/PGID env vars like the LinuxServer images
|
|
# (arr, jellyfin). It must match the owner of the appdata bind below or
|
|
# the container exits on start, unable to write /config. On Unraid that is
|
|
# 99:100 (nobody:users) — upstream's own Unraid note says the same.
|
|
#
|
|
# WatchState won't chown /config itself the way the LinuxServer images do,
|
|
# so the `appdata:` block on this stack's host_vars entry pre-creates the
|
|
# bind directory owned by 99:100 before `docker compose up` — otherwise
|
|
# Docker makes it root:root on first start and the container exits.
|
|
user: "${PUID}:${PGID}"
|
|
# Unraid's Docker page normally reads icon, WebUI link and console shell
|
|
# from the dockerMan template that created the container. A Compose stack
|
|
# has no template, so 6.10+ falls back to these labels; without them the
|
|
# container renders as a question mark with no WebUI or Console entry.
|
|
# See README.md → "Icons on the Unraid Docker page".
|
|
#
|
|
# `sh`, not `bash`: the image is Alpine-based (frankenphp on Alpine).
|
|
labels:
|
|
net.unraid.docker.icon: ${STACK_ICON}
|
|
net.unraid.docker.webui: "http://[IP]:${WATCHSTATE_HTTP_PORT}/"
|
|
net.unraid.docker.shell: sh
|
|
# Joins Caddy's network by the fixed `proxy` alias, same shape as arr and
|
|
# jellyfin; the real network it maps to is a per-host decision in vars.yml
|
|
# (WATCHSTATE_NETWORK → caddy-net). Caddy then proxies to
|
|
# `watchstate:8080` — the container name on caddy-net — rather than nas1's
|
|
# LAN IP and the published port.
|
|
#
|
|
# This also puts Jellyfin one hop away: WatchState reaches it as
|
|
# `http://jellyfin:8096` when adding it as a backend. Plex and anything
|
|
# else off caddy-net is addressed by nas1's LAN IP and its published port
|
|
# (e.g. http://192.168.50.1:32400) — a runtime concern configured in the
|
|
# WebUI, not here.
|
|
networks:
|
|
- proxy
|
|
environment:
|
|
# Image default is UTC; TZ comes from vars.yml. Both are named here
|
|
# because Compose reads .env only to interpolate `${...}` in this file —
|
|
# a var that nothing references never reaches the container.
|
|
WS_TZ: ${TZ}
|
|
TZ: ${TZ}
|
|
# The task scheduler (import every hour, export every 90 min) and the
|
|
# built-in cache server are both on by default. Uncomment to turn either
|
|
# off — e.g. DISABLE_CRON while doing the initial one-off backend sync by
|
|
# hand, before enabling the tasks on the Tasks page.
|
|
# DISABLE_CRON: "1"
|
|
# DISABLE_CACHE: "1"
|
|
# --- Reverse-proxy auth (optional) --------------------------------------
|
|
# WatchState has its own internal auth (the first-run system user). If it
|
|
# is ever fronted by Caddy + Authentik forward-auth instead, set these so
|
|
# it trusts the proxy rather than double-prompting. Setting BOTH disables
|
|
# all internal auth — only do that once the external layer is definitely
|
|
# in front of it.
|
|
# WS_TRUST_PROXY: "true"
|
|
# WS_TRUST_LOCAL: "true"
|
|
volumes:
|
|
# SQLite database (db/watchstate_v01.db), backend configs, guid.yaml and
|
|
# logs — this directory *is* the application state, same standing as
|
|
# arr's SHELFARR_DATA_PATH. Back it up accordingly.
|
|
- ${WATCHSTATE_CONFIG_PATH}:/config
|
|
ports:
|
|
- "${WATCHSTATE_HTTP_PORT}:8080"
|
|
# Restated from the image's own HEALTHCHECK. The port here is the fixed
|
|
# internal 8080, never WATCHSTATE_HTTP_PORT.
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8080/v1/api/system/healthcheck"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
|
|
networks:
|
|
# `external: true` means "attach to a network that already exists; don't
|
|
# create it, don't delete it on `down`". Without it Compose would create a
|
|
# *new* network named `watchstate_<key>` — the deploy would still succeed and
|
|
# Caddy would silently fail to resolve `watchstate`. `name:` is what stops
|
|
# the project-name prefix being applied.
|
|
#
|
|
# The local alias is a fixed `proxy` so the compose file stays static; which
|
|
# real network it maps to is a per-host decision in vars.yml
|
|
# (WATCHSTATE_NETWORK). Same shape as arr's `proxy` → `caddy-net` and
|
|
# jellyfin's.
|
|
#
|
|
# caddy-net is defined in Unraid's Docker settings on nas1 rather than by a
|
|
# stack in this repo, so nothing here has to deploy before WatchState does.
|
|
# It must exist on the target host — an absent external network fails the
|
|
# deploy outright.
|
|
proxy:
|
|
name: ${WATCHSTATE_NETWORK}
|
|
external: true
|
|
|
|
# Reaching WatchState through Caddy means proxying to `watchstate:8080` — the
|
|
# container name on caddy-net — rather than nas1's LAN IP and the published
|
|
# port. The `ports:` mapping above is kept for direct access that bypasses the
|
|
# proxy; drop it if you don't want WATCHSTATE_HTTP_PORT reachable on the LAN.
|