Files
HealthLog/docs/self-hosting/unraid/healthlog.xml
T
Marc-André Bombeck 351e7d1fe0 fix(backup): keep a dump locally only where it survives the container
The image creates DB_BACKUP_DIR owned by the app user, so an install that
runs it without the backups volume could write there, and every nightly and
pre-migration dump landed in the container's own layer. The next update
threw them away while the admin page, the boot line and the readiness card
called them kept on this server.

A dump directory now counts as kept only when it survives the container:
inside a container (Docker, Podman, Kubernetes, a container cgroup or an
overlay root) the directory must sit on a mount of its own that is not a
tmpfs, read from /proc/self/mountinfo with a device-number fallback;
outside one, a writable directory is a disk. Otherwise no dump is written
there: the nightly run uploads off-host only and records not_persistent,
the pre-migration dump is skipped with a warning, the boot line says the
directory is inside the container, the backups page stops promising local
dumps and ignores local-only ledger rows, and readiness fails with no
bucket and notes the bucket-only setup otherwise.

The Unraid template gains a path for the dumps, the Unraid and TrueNAS
pages say why it is needed, and the restore drill first runs the stack
without the volume and checks that nothing is kept or claimed.
2026-10-25 16:00:34 +01:00

69 lines
5.7 KiB
XML

<?xml version="1.0"?>
<!--
HealthLog — Unraid Community Applications template.
CA templates describe ONE container. HealthLog needs PostgreSQL (18, or 16), so
install a PostgreSQL container FIRST (CA has community PostgreSQL templates),
create a `healthlog` database + user, then point DATABASE_URL below at it.
Full walkthrough: docs/self-hosting/unraid.md.
LAN installs serve plain HTTP (http://tower:3000). Keep SESSION_COOKIE_SECURE
set to false (the default in this template) or login will silently fail.
-->
<Container version="2">
<Name>HealthLog</Name>
<Repository>ghcr.io/mbombeck/healthlog:latest</Repository>
<Registry>https://github.com/MBombeck/HealthLog/pkgs/container/healthlog</Registry>
<Network>bridge</Network>
<MyIP/>
<Shell>sh</Shell>
<Privileged>false</Privileged>
<Support>https://github.com/MBombeck/HealthLog/issues</Support>
<Project>https://github.com/MBombeck/HealthLog</Project>
<Overview>
Self-hosted personal health tracker (PWA + native iOS client): weight, blood
pressure, pulse, blood glucose, body composition, sleep, mood, menstrual
cycle, and medications on one encrypted timeline. AES-256-GCM at rest, no
vendor cloud, no telemetry.
REQUIRES a separate PostgreSQL 18 (or 16) container — install one first (CA has
community PostgreSQL templates), create a database and user, then set
DATABASE_URL below. Step-by-step guide:
https://github.com/MBombeck/HealthLog/blob/main/docs/self-hosting/unraid.md
Generate each required secret with: openssl rand -hex 32
LAN / plain-HTTP installs MUST keep SESSION_COOKIE_SECURE set to false,
otherwise the session cookie carries the Secure flag, the browser drops it
over HTTP, and login silently fails.
</Overview>
<Category>Tools: Productivity: Other:</Category>
<WebUI>http://[IP]:[PORT:3000]/</WebUI>
<Icon>https://raw.githubusercontent.com/MBombeck/HealthLog/main/public/logo-512.png</Icon>
<ExtraParams>--security-opt no-new-privileges:true</ExtraParams>
<DonateText/>
<DonateLink/>
<Config Name="WebUI Port" Target="3000" Default="3000" Mode="tcp" Description="HTTP port HealthLog listens on." Type="Port" Display="always" Required="true" Mask="false">3000</Config>
<Config Name="DATABASE_URL" Target="DATABASE_URL" Default="postgresql://healthlog:CHANGE-ME@POSTGRES-HOST:5432/healthlog?schema=public" Mode="" Description="Connection string for your separately-installed PostgreSQL 16. Replace CHANGE-ME with the DB password and POSTGRES-HOST with the Postgres container IP or name." Type="Variable" Display="always" Required="true" Mask="true"/>
<Config Name="ENCRYPTION_KEY" Target="ENCRYPTION_KEY" Default="" Mode="" Description="AES-256-GCM key for data at rest. Generate with: openssl rand -hex 32 (64-char hex). Back this up — losing it makes encrypted data unrecoverable." Type="Variable" Display="always" Required="true" Mask="true"/>
<Config Name="API_TOKEN_HMAC_KEY" Target="API_TOKEN_HMAC_KEY" Default="" Mode="" Description="HMAC key for API token hashing. Generate with: openssl rand -hex 32 (64-char hex)." Type="Variable" Display="always" Required="true" Mask="true"/>
<Config Name="SESSION_COOKIE_SECURE" Target="SESSION_COOKIE_SECURE" Default="false" Mode="" Description="Set to false for LAN / plain-HTTP installs (http://tower:3000) or login fails. Set to true only behind an HTTPS reverse proxy." Type="Variable" Display="always" Required="true" Mask="false">false</Config>
<Config Name="HEALTHLOG_PLATFORM" Target="HEALTHLOG_PLATFORM" Default="unraid" Mode="" Description="Where this server is configured. Opens the admin's encryption key backup step on the Unraid instructions." Type="Variable" Display="advanced" Required="false" Mask="false">unraid</Config>
<Config Name="ENCRYPTION_KEY_CHECK" Target="ENCRYPTION_KEY_CHECK" Default="enforce" Mode="" Description="Start-up encryption key check. enforce refuses to serve when the key does not open the stored data. warn only logs it: a last resort for a refusal you are certain is false, and it disables a safety check." Type="Variable" Display="advanced" Required="false" Mask="false">enforce</Config>
<Config Name="NEXT_PUBLIC_APP_URL" Target="NEXT_PUBLIC_APP_URL" Default="http://tower:3000" Mode="" Description="Public URL users reach HealthLog at. Use the LAN URL (e.g. http://tower:3000) or your HTTPS domain behind a reverse proxy." Type="Variable" Display="always" Required="true" Mask="false"/>
<Config Name="APP_URL" Target="APP_URL" Default="http://tower:3000" Mode="" Description="Internal app base URL. Normally identical to NEXT_PUBLIC_APP_URL." Type="Variable" Display="always" Required="true" Mask="false"/>
<Config Name="ENCRYPTION_KEYS" Target="ENCRYPTION_KEYS" Default="" Mode="" Description="Optional. Key-rotation map, e.g. {&quot;v1&quot;:&quot;&lt;hex&gt;&quot;,&quot;v2&quot;:&quot;&lt;hex&gt;&quot;}. Leave empty unless rotating; use ENCRYPTION_KEY instead." Type="Variable" Display="advanced" Required="false" Mask="true"/>
<Config Name="ENCRYPTION_ACTIVE_KEY_ID" Target="ENCRYPTION_ACTIVE_KEY_ID" Default="" Mode="" Description="Optional. Active key id for the ENCRYPTION_KEYS map (e.g. v2). Leave empty when using ENCRYPTION_KEY." Type="Variable" Display="advanced" Required="false" Mask="false"/>
<Config Name="Database dumps" Target="/var/lib/healthlog/backups" Default="/mnt/user/appdata/healthlog/backups" Mode="rw" Description="Where HealthLog keeps its nightly database dump and the one it takes before each update that brings migrations. Without this path the dumps would sit inside the container, which an update replaces, so none is kept. Must be writable by uid 1001 (chown 1001:1001 the folder once)." Type="Path" Display="always" Required="true" Mask="false">/mnt/user/appdata/healthlog/backups</Config>
</Container>