Closing the command-center security queue #70/#71/#72/#73/#74: rolling tags let a rebuild move under a running service with nobody approving it, and make a CVE audit ungradeable. 36 quadlet units across dankclaw, dankserver and frankbook-pro now carry tag@sha256; localhost/* builds stay exempt (their build is the pin). The pihole and copyparty pins pull the fixed builds; valkey 9.1.2 (already running) and redis 7.4.11 are pinned in place, vendor fixes TBD. New gate tests/quadlet_image_pins.bats: no unpinned registry image, no generator-rejected key anywhere. Three seams that pinned the old exact-tag law (frankbook readarr, open_webui, seerr) now require tag AND digest - strictly stronger. Quadlet Lifecycle docs: batch-abort law, entrypoint flags-only law, pin law.
64 lines
2.9 KiB
INI
64 lines
2.9 KiB
INI
# Quadlet unit: Calibre Content Server (rootless, boot-persistent).
|
|
#
|
|
# Install path on dankserver:
|
|
# ~/.config/containers/systemd/calibre-server.container
|
|
# Unit name: calibre-server.service (podman 5.x drops the container- prefix)
|
|
#
|
|
# The image is the CURRENT linuxserver/calibre (9.15.0), which is a desktop
|
|
# image (Selkies web-streamed GUI on 8080/8181) with the headless
|
|
# calibre-server available inside. The compose-era snippet in
|
|
# serverAppConfigs-docs/Dankserver/Calibre.md predates the desktop revamp;
|
|
# the dedicated headless images (ta264/docker-calibre, agentgreen) are
|
|
# dormant (calibre 6.10 / 2017), so this unit runs calibre-server as the
|
|
# image's s6-overlay main service via Exec=; the desktop also runs but its
|
|
# ports are internal-only (see the port map below).
|
|
#
|
|
# Port map: Network=pasta is port-FORWARD mode on this host (the container
|
|
# keeps its own netns; only PublishPort'd ports reach the host — verified
|
|
# 2026-09-21: 8080/8090/8182 inside the container are not visible on the
|
|
# host, only the 8084 forward). So the ONLY exposed surface is:
|
|
# 8090 -> host 8084 calibre-server (the content server; 8080 inside the
|
|
# container is the image's own nginx, 8083 on the host
|
|
# is calibre-web)
|
|
# The desktop GUI (nginx 8080/8181 + WS 8082, inside the container) runs but
|
|
# is internal-only: no PublishPort. Exposing it is one PublishPort line away
|
|
# if the browser GUI is ever wanted (the basic-auth credential is already in
|
|
# the env file).
|
|
# Auth: calibre-server 9.x keeps its users in a SQLite userdb (the pw column
|
|
# is PLAINTEXT, so the file is mode 600). The single admin account is
|
|
# bootstrapped once by the deploy handler (deploy_calibre_server) via
|
|
# `calibre-server --manage-users -- add`, password piped on stdin with
|
|
# printf (a trailing newline from echo lands in the stored password and
|
|
# breaks every login). The desktop's basic auth (CUSTOM_USER/CUSTOM_PASSWORD)
|
|
# reuses the same credential pair. Both live in the machine-local env file;
|
|
# this unit holds no secrets.
|
|
#
|
|
# --auth-mode=basic is required: on a non-SSL port the server defaults to
|
|
# Digest auth, which rejects plain Basic clients with 400 "Unsupported
|
|
# authentication method".
|
|
|
|
[Unit]
|
|
Description=Calibre content server container
|
|
After=network.target
|
|
|
|
[Container]
|
|
ContainerName=calibre-server
|
|
Image=lscr.io/linuxserver/calibre:9.15.0@sha256:59e4b0e036e62f228f8bcfae1ade42f47047719885fe454ddbad38e4597b987b
|
|
Network=pasta
|
|
EnvironmentFile=/home/dank/Containers/calibre-server/env
|
|
Environment=PUID=1000
|
|
Environment=PGID=1000
|
|
Environment=TZ=America/Vancouver
|
|
Volume=/home/dank/Containers/calibre-web/books:/books
|
|
Volume=/home/dank/Containers/calibre-server/userdb.sqlite:/userdb.sqlite
|
|
Exec=calibre-server --port 8090 --enable-auth --auth-mode=basic --userdb /userdb.sqlite /books
|
|
PublishPort=8084:8090
|
|
|
|
[Service]
|
|
TimeoutStartSec=300
|
|
Restart=always
|
|
RestartSec=5
|
|
|
|
[Install]
|
|
WantedBy=default.target
|