mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
Merge origin/release/v1.46.0 into feat/v146-ai
This commit is contained in:
commit
96eeec6080
47 files changed
+2588
-1122
No files matched your search
+29
-15
@@ -19662,19 +19662,25 @@ paths:
|
||||
capability envelope when it is closed), then rate / budget gated. With no provider configured this returns 422
|
||||
(`documents.inbound.providerUnsupported`, with `meta.capability` and `meta.reason = \"no_provider\"`) — the
|
||||
stored document is untouched, only the enhancement fails. Three modes: VISION (empty body) decrypts and scans
|
||||
the stored original (PDF needs an Anthropic vision provider); TEXT (`application/json`, opt-in local OCR) `{
|
||||
mode: \"text\", text }` structures browser-OCR'd text; STORED (`application/json`) `{ mode: \"stored\" }`
|
||||
structures the document's own stored extracted text (its content index) — the manual recovery for a
|
||||
skipped/failed automatic staging run, 422 `documents.inbound.notIndexed` when no stored text exists. Extraction
|
||||
reproduces what the document states — it never interprets. Nothing reaches the structured stores here; the
|
||||
confirm route is the only write path. With `Prefer: respond-async` (v1.40) the extraction runs in the
|
||||
background: after the same quick refusals the route answers 202 with a run id, a second request while an
|
||||
extraction of this document from the same input is queued or running answers with that run, and `GET
|
||||
/api/ai-runs/{id}` serves `DocumentExtractRunResult` (`{ documentId, factsStaged, status }`, not the document
|
||||
detail) as the run's `result`. Staging re-checks the document under a row lock, so a review finished while the
|
||||
read ran fails the run with `documents.inbound.alreadyPartlyConfirmed` (409) or
|
||||
`documents.inbound.alreadyConfirmed` (422) and leaves the review untouched; the synchronous form answers the
|
||||
same in that race."
|
||||
the stored original (a PDF is rendered and read a page at a time; one that cannot be rendered needs a provider
|
||||
that reads PDFs natively, else 422 `documents.inbound.pdfNeedsAnthropic`); TEXT (`application/json`, opt-in
|
||||
local OCR) `{ mode: \"text\", text }` structures browser-OCR'd text; STORED (`application/json`) `{ mode:
|
||||
\"stored\" }` structures the document's own stored extracted text (its content index) — the manual recovery for
|
||||
a skipped/failed automatic staging run, 422 `documents.inbound.notIndexed` when no stored text exists. A long
|
||||
document is read a page or a part at a time under the same per-read limits as the lab scan (`LABS_OCR_EXTRACT`),
|
||||
each read after the first reserved against the day's budget on its own; an extraction in which no read produced
|
||||
a complete fact fails with 422 `documents.inbound.outputLimit` when the reads stopped at the provider's output
|
||||
limit, 429 `documents.inbound.budgetExceeded` when the budget refused the reads, and 422
|
||||
`documents.inbound.extractFailed` only when the provider's answers were not the schema. Extraction reproduces
|
||||
what the document states — it never interprets. Nothing reaches the structured stores here; the confirm route is
|
||||
the only write path. With `Prefer: respond-async` (v1.40) the extraction runs in the background: after the same
|
||||
quick refusals the route answers 202 with a run id, a second request while an extraction of this document from
|
||||
the same input is queued or running answers with that run, and `GET /api/ai-runs/{id}` serves
|
||||
`DocumentExtractRunResult` (`{ documentId, factsStaged, status }`, plus `incomplete` when part of the document
|
||||
may be missing from the staged facts; not the document detail) as the run's `result`. Staging re-checks the
|
||||
document under a row lock, so a review finished while the read ran fails the run with
|
||||
`documents.inbound.alreadyPartlyConfirmed` (409) or `documents.inbound.alreadyConfirmed` (422) and leaves the
|
||||
review untouched; the synchronous form answers the same in that race."
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
@@ -35482,7 +35488,7 @@ components:
|
||||
properties:
|
||||
decisions:
|
||||
minItems: 1
|
||||
maxItems: 120
|
||||
maxItems: 400
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
@@ -38381,7 +38387,7 @@ components:
|
||||
documents.inbound.factNotPending, documents.inbound.factTypeMismatch, documents.inbound.fileTooLarge,
|
||||
documents.inbound.fileType, documents.inbound.invalidMetadata, documents.inbound.invalidQuery,
|
||||
documents.inbound.invalidUpdate, documents.inbound.localOcrDisabled, documents.inbound.notFound,
|
||||
documents.inbound.notIndexed, documents.inbound.pdfNeedsAnthropic,
|
||||
documents.inbound.notIndexed, documents.inbound.outputLimit, documents.inbound.pdfNeedsAnthropic,
|
||||
documents.inbound.providerUnsupported, documents.inbound.quotaExceeded, documents.inbound.rateLimited,
|
||||
documents.inbound.restoreDuplicate, documents.inbound.restoreGone, documents.inbound.sourceAliasLimit,
|
||||
documents.inbound.uploadBusy, documents.inbound.uploadTimeout, documents.inbound.vaccinationNotFound,
|
||||
@@ -75913,6 +75919,14 @@ components:
|
||||
- FAILED
|
||||
- CONFIRMED
|
||||
- DISCARDED
|
||||
incomplete:
|
||||
description: "Present when part of the document's facts may be missing from the staged ones: a long document is read a
|
||||
page or a part at a time, and a read stopped at the provider's output limit (its complete facts kept), a
|
||||
part could not be read or was not reached (the day's budget, the run's deadline, AI turned off meanwhile),
|
||||
or the document holds more facts than one review takes. The staged facts are still worth reviewing; the
|
||||
person should check them against the document."
|
||||
type: boolean
|
||||
const: true
|
||||
required:
|
||||
- documentId
|
||||
- factsStaged
|
||||
|
||||
+20
-5
@@ -199,11 +199,26 @@ dev --create-only --name vX_Y_Z_rollback_<col>`), edit the SQL,
|
||||
|
||||
## Catalog templates
|
||||
|
||||
A new required environment variable, or a change to the compose shape, needs a
|
||||
matching pull request to the TrueNAS apps catalog in the same release cycle
|
||||
(and an update to `docs/self-hosting/unraid/healthlog.xml` and
|
||||
`docs/self-hosting/portainer/templates.json`). See
|
||||
`docs/self-hosting/truenas.md` for what the catalog template carries.
|
||||
The TrueNAS catalog bot follows new image tags on its own, so a routine
|
||||
release needs nothing there. These changes do need a matching pull request to
|
||||
`truenas/apps` (`ix-dev/community/healthlog/`) in the same release cycle, and
|
||||
an update to `docs/self-hosting/unraid/healthlog.xml` and
|
||||
`docs/self-hosting/portainer/templates.json`:
|
||||
|
||||
- a new required environment variable, or a new format or minimum for an
|
||||
existing one (the form validates the secrets);
|
||||
- a changed listening port, health check path or health semantics, or start
|
||||
time beyond the template's five-minute start period;
|
||||
- a required PostgreSQL major version, or an extension the stock `postgres`
|
||||
image does not ship;
|
||||
- any other change to the compose shape: a new container, a volume the app
|
||||
must write to, a different user.
|
||||
|
||||
The catalog app sets `HEALTHLOG_PLATFORM=truenas`, `PORT`, `HOSTNAME`,
|
||||
`DATABASE_URL`, `ENCRYPTION_KEY`, `API_TOKEN_HMAC_KEY`, `APP_URL`,
|
||||
`NEXT_PUBLIC_APP_URL` and `SESSION_COOKIE_SECURE`; everything else reaches it
|
||||
through the form's additional environment variables. See
|
||||
`docs/self-hosting/truenas.md` for the operator side.
|
||||
|
||||
## Verify the served version
|
||||
|
||||
|
||||
@@ -274,13 +274,13 @@ Encryption: the step shows the key id and a fingerprint (the first 12 hex
|
||||
characters of SHA-256 over the key) and can check a pasted copy without
|
||||
storing it. Admins see a dashboard reminder until the active key is confirmed.
|
||||
|
||||
| Platform | Where the key is set |
|
||||
| --------- | --------------------------------------------------------------- |
|
||||
| Compose | `.env` next to `docker-compose.yml` |
|
||||
| TrueNAS | Apps, HealthLog, Edit, Environment |
|
||||
| Coolify | the application's Environment Variables |
|
||||
| Unraid | the container template (Docker tab, Edit) or the Compose `.env` |
|
||||
| Portainer | the stack's Environment variables |
|
||||
| Platform | Where the key is set |
|
||||
| --------- | -------------------------------------------------------------------------------------------------- |
|
||||
| Compose | `.env` next to `docker-compose.yml` |
|
||||
| TrueNAS | Apps, HealthLog, Edit: the Encryption Key field (`ENCRYPTION_KEY` in a YAML install's environment) |
|
||||
| Coolify | the application's Environment Variables |
|
||||
| Unraid | the container template (Docker tab, Edit) or the Compose `.env` |
|
||||
| Portainer | the stack's Environment variables |
|
||||
|
||||
Set `HEALTHLOG_PLATFORM` (`compose`, `truenas`, `coolify`, `unraid`,
|
||||
`portainer`) to open the step on your platform's instructions.
|
||||
|
||||
+171
-59
@@ -1,82 +1,152 @@
|
||||
# HealthLog on TrueNAS SCALE
|
||||
# HealthLog on TrueNAS
|
||||
|
||||
HealthLog runs on TrueNAS SCALE as a Docker app: one `app` container from
|
||||
`ghcr.io/mbombeck/healthlog` and one PostgreSQL 16 database. The app container
|
||||
is stateless; everything you care about lives in the database dataset and in
|
||||
one value you must keep yourself: the encryption key.
|
||||
HealthLog runs on TrueNAS Community Edition (formerly SCALE) as a Docker app:
|
||||
one container from `ghcr.io/mbombeck/healthlog` and one PostgreSQL database.
|
||||
The app container is stateless. Everything you care about lives in the
|
||||
database dataset and in one value you must keep yourself: the encryption key.
|
||||
|
||||
## What the app needs
|
||||
> **Status: pending catalog review.** A HealthLog app for the TrueNAS
|
||||
> Community train has been prepared but is not listed yet. Until it is, use
|
||||
> [Install via YAML](#before-the-listing-install-via-yaml) at the end of this
|
||||
> page. This note goes away once the app appears under Apps, Discover Apps.
|
||||
|
||||
| Setting | Value |
|
||||
| ------------ | ---------------------------------------------------------------------------------------- |
|
||||
| Image | `ghcr.io/mbombeck/healthlog`, tag `X.Y.Z` (amd64 and arm64) |
|
||||
| Port | `3000` (HTTP) |
|
||||
| User | runs as uid `1001`; no extra capabilities, `no-new-privileges` is fine |
|
||||
| Health check | `GET /api/health`, `200` when ready |
|
||||
| Start period | at least 60 s, with more retries than the image's 5 × 30 s: migrations run at every boot |
|
||||
| Database | PostgreSQL 16 (17 and later are not a drop-in), no extensions |
|
||||
| Volumes | none for the app; the database gets its own dataset |
|
||||
## Install from the Community train
|
||||
|
||||
## Environment
|
||||
1. Generate two secrets. Open the TrueNAS shell (System, Shell) and run the
|
||||
command twice, once for each field:
|
||||
|
||||
| Variable | Required | Notes |
|
||||
| ----------------------- | -------- | ------------------------------------------------------------------------------------------- |
|
||||
| `DATABASE_URL` | yes | `postgresql://<user>:<password>@<host>:5432/<db>` |
|
||||
| `ENCRYPTION_KEY` | yes | 64 hex characters: `openssl rand -hex 32`. Keep a copy outside the NAS (see below). |
|
||||
| `API_TOKEN_HMAC_KEY` | yes | 64 hex characters, generated the same way. Changing it signs everyone out. |
|
||||
| `NEXT_PUBLIC_APP_URL` | yes | the address people open, for example `http://truenas.local:30180` |
|
||||
| `APP_URL` | yes | the same address |
|
||||
| `SESSION_COOKIE_SECURE` | no | `false` for a LAN install served over plain `http://`; leave unset behind an HTTPS proxy |
|
||||
| `HEALTHLOG_PLATFORM` | no | `truenas`: the admin's key backup step opens on the TrueNAS instructions |
|
||||
| `GEOLITE2_DIR` | no | a mounted directory of GeoLite2 `.mmdb` files, so sign-in locations are resolved on the NAS |
|
||||
```bash
|
||||
openssl rand -hex 32
|
||||
```
|
||||
|
||||
`HEALTHLOG_PROCESS_TYPE` stays unset (`all`): one container serves the web app
|
||||
and runs the background jobs.
|
||||
Each run prints 64 hex characters. Put both in your password manager
|
||||
before you continue; see [Back up your encryption key](#back-up-your-encryption-key).
|
||||
|
||||
2. Open Apps, Discover Apps, search for **HealthLog** and choose Install.
|
||||
3. Fill in the form:
|
||||
|
||||
| Field | What to enter |
|
||||
| --------------------- | -------------------------------------------------------------------------------------------------------------- |
|
||||
| Timezone | your timezone |
|
||||
| Database Password | any strong password; only the two containers use it |
|
||||
| Encryption Key | the first `openssl rand -hex 32` output |
|
||||
| Token Signing Key | the second output. Changing it later signs everyone out |
|
||||
| App URL | the address you open HealthLog at, with scheme and port, for example `http://192.168.1.10:30536` |
|
||||
| Secure Cookies | leave off when you open HealthLog over `http://` on the LAN; turn on behind an HTTPS reverse proxy (see below) |
|
||||
| WebUI Port | `30536` unless that port is taken |
|
||||
| Postgres Data Storage | the default ixVolume, or a host path on a dataset you snapshot |
|
||||
| Resources | keep memory at 1536 MB or more; the default of 4096 MB is fine |
|
||||
|
||||
4. Install. The first start applies the database migrations before the web
|
||||
server listens, so give it a minute. The app shows as running once
|
||||
`/api/health` answers.
|
||||
5. Open the App URL. The first account you register becomes the admin.
|
||||
|
||||
The App URL has to match the address in the browser: passkeys, sign-in
|
||||
redirects and the links in notifications are built from it. If you later put
|
||||
HealthLog behind a reverse proxy with its own domain, change App URL to that
|
||||
`https://` address.
|
||||
|
||||
Settings the form does not show go under Additional Environment Variables, for
|
||||
example `UPDATE_CHECK_DISABLED=1`. The full list is in
|
||||
[environment.md](environment.md). To use your own GeoLite2 databases, add the
|
||||
directory under Additional Storage and point `GEOLITE2_DIR` at its mount path
|
||||
([geolite2.md](geolite2.md)).
|
||||
|
||||
## Plain HTTP on the LAN
|
||||
|
||||
Most NAS installs are reached over `http://`. Set `SESSION_COOKIE_SECURE=false`
|
||||
for that. If it is left at its default, the browser drops the sign-in cookie
|
||||
and the login page says so before you type a password: "This server only sets
|
||||
its sign-in cookie over https://".
|
||||
Most NAS installs are reached over `http://`. Leave **Secure Cookies** off for
|
||||
that. With it on, the browser drops the sign-in cookie on a plain-HTTP page,
|
||||
and the login page says so before you type a password: "Signing in cannot
|
||||
complete on this page". Turn it on only when HealthLog is served over
|
||||
`https://`, and set App URL to that `https://` address.
|
||||
|
||||
## Back up your encryption key
|
||||
|
||||
HealthLog encrypts tokens, notes, documents and in-database backups with
|
||||
`ENCRYPTION_KEY`. The key is not stored in the database. If the app is deleted
|
||||
and reinstalled with a new key over the old database dataset, the data is
|
||||
HealthLog encrypts tokens, notes, documents and in-database backups with the
|
||||
Encryption Key. The key is not stored in the database. If the app is deleted
|
||||
and installed again with a new key over the old database dataset, the data is
|
||||
still there but cannot be read.
|
||||
|
||||
1. Copy `ENCRYPTION_KEY` from the app's settings (Apps, HealthLog, Edit,
|
||||
Environment) into your password manager.
|
||||
2. Sign in as the admin and open Admin, Encryption. The step shows the key id
|
||||
and a fingerprint, the first 12 hex characters of SHA-256 over the key.
|
||||
Compare it with your copy:
|
||||
TrueNAS keeps the values you typed into the form with the app's configuration
|
||||
on the apps pool. Treat that as a convenience, not as your copy: deleting the
|
||||
app removes it, and a reinstall starts with empty fields. Keep the key in a
|
||||
password manager or another place outside the NAS.
|
||||
|
||||
1. Open Apps, select HealthLog and choose Edit. The key is the Encryption Key
|
||||
field under HealthLog Configuration.
|
||||
2. Sign in as the admin and open Admin, Encryption. The **Back up your
|
||||
encryption key** step shows the active key id and a fingerprint, the first
|
||||
12 hex characters of SHA-256 over the key. Compare it with your copy:
|
||||
|
||||
```bash
|
||||
echo -n "<your key>" | xxd -r -p | sha256sum | cut -c1-12
|
||||
```
|
||||
|
||||
or paste the copy into "Check my copy" (it is compared and dropped, never
|
||||
stored or logged).
|
||||
or paste the copy into **Check my copy**. It is compared and dropped, never
|
||||
stored or logged.
|
||||
|
||||
3. Confirm the backup. Until you do, admins see a reminder on the dashboard.
|
||||
After a key rotation the step comes back for the new key.
|
||||
3. Press **I have backed up this key**. Until you do, admins see a reminder on
|
||||
the dashboard. After a key rotation the step comes back for the new key.
|
||||
|
||||
The catalog app sets `HEALTHLOG_PLATFORM=truenas`, so the step opens on these
|
||||
instructions.
|
||||
|
||||
## Backups and restore
|
||||
|
||||
A restore needs two things: a backup of the database **and** the Encryption
|
||||
Key that was active when it was taken. One without the other gets you nothing
|
||||
back.
|
||||
|
||||
- **Snapshots.** Snapshot the Postgres Data Storage dataset (the ixVolume
|
||||
lives under the apps pool, a host path wherever you put it). Stop the app
|
||||
first, or the snapshot holds a database that was mid-write.
|
||||
- **A dump.** Open a shell on the `postgres` container (Apps, HealthLog,
|
||||
the container's Shell) and run:
|
||||
|
||||
```bash
|
||||
pg_dump -U healthlog healthlog > /var/lib/postgresql/healthlog-$(date +%F).sql
|
||||
```
|
||||
|
||||
The file lands in the Postgres Data Storage dataset, next to the database
|
||||
files, so copy it off the NAS as well.
|
||||
|
||||
- **Off-host.** HealthLog can push encrypted nightly backups to any
|
||||
S3-compatible bucket; see [backup-restore.md](../ops/backup-restore.md).
|
||||
|
||||
To restore a dump, run the app with the Encryption Key the dump was taken
|
||||
under, put the dump file in the Postgres Data Storage dataset, and from the
|
||||
`postgres` container shell replace the database with it:
|
||||
|
||||
```bash
|
||||
psql -U healthlog -d postgres \
|
||||
-c "DROP DATABASE healthlog WITH (FORCE);" \
|
||||
-c "CREATE DATABASE healthlog OWNER healthlog;"
|
||||
psql -v ON_ERROR_STOP=1 -U healthlog healthlog < /var/lib/postgresql/healthlog-YYYY-MM-DD.sql
|
||||
```
|
||||
|
||||
Then restart the app. Restoring over the existing database without dropping
|
||||
it first does not work: the tables the background queue creates on its own
|
||||
refuse a plain overwrite.
|
||||
|
||||
## When the key does not match the database
|
||||
|
||||
At every start HealthLog checks that its key opens the data already in the
|
||||
database. If it does not, it refuses to serve instead of failing on every
|
||||
encrypted value: pages show "HealthLog cannot open its data", API requests
|
||||
answer `503` with `meta.errorCode` `encryption.key_mismatch`, `/api/health`
|
||||
answers `503` with `reason: "encryption_key_mismatch"`, and no background jobs
|
||||
run. TrueNAS shows the app as unhealthy rather than crashed, so the reason
|
||||
stays visible.
|
||||
database. A missing or malformed key stops the container at once with
|
||||
`HealthLog: ERROR — encryption configuration is invalid.` in its log. A
|
||||
well-formed key that does not open the stored data is different: HealthLog
|
||||
refuses to serve instead of failing on every encrypted value. Pages show
|
||||
"HealthLog cannot open its data", API requests answer `503` with
|
||||
`meta.errorCode` `encryption.key_mismatch`, `/api/health` answers `503` with
|
||||
`reason: "encryption_key_mismatch"`, and no background jobs run. TrueNAS
|
||||
shows the app as unhealthy rather than crashed, so the reason stays visible in
|
||||
the app's logs.
|
||||
|
||||
Fix it one of three ways, then restart the app:
|
||||
|
||||
1. Put the original `ENCRYPTION_KEY` back.
|
||||
2. Point `DATABASE_URL` at the database that belongs to this key.
|
||||
1. Put the original Encryption Key back (Apps, HealthLog, Edit).
|
||||
2. Point the app at the database that belongs to this key, for example by
|
||||
restoring that dataset.
|
||||
3. Start fresh with an empty database. The old data and its backups need the
|
||||
old key.
|
||||
|
||||
@@ -91,9 +161,8 @@ checks again at the next start.
|
||||
|
||||
If you are certain the configured key is the one the data was written with,
|
||||
and the app still refuses because the check recorded a different key earlier,
|
||||
remove that record and restart. Open a shell on the database container (Apps,
|
||||
HealthLog, the database container's Shell) and run, with the key id the log
|
||||
names (`v1` unless you use `ENCRYPTION_KEYS`):
|
||||
remove that record and restart. Open a shell on the `postgres` container and
|
||||
run, with the key id the log names (`v1` unless you use `ENCRYPTION_KEYS`):
|
||||
|
||||
```bash
|
||||
psql -U healthlog healthlog \
|
||||
@@ -108,7 +177,7 @@ id: the rotation script removes its record once no values remain under it.
|
||||
|
||||
On a first start there is no record to remove. If the check refuses there and
|
||||
you are certain the key is right, add `ENCRYPTION_KEY_CHECK` = `warn` under
|
||||
Apps, HealthLog, Edit, Environment as a last resort. The check still runs and
|
||||
Additional Environment Variables as a last resort. The check still runs and
|
||||
logs, `/api/health` reports `warning: "encryption_key_mismatch"` without
|
||||
failing, the app serves, and no key is recorded until the check passes. This
|
||||
switches off a safety check: with a wrong key every encrypted value fails and
|
||||
@@ -117,6 +186,49 @@ confirmed.
|
||||
|
||||
## Updates
|
||||
|
||||
Pick the new tag, take a snapshot of the database dataset first, and update.
|
||||
Migrations run on start; the first start of a new install applies all of them,
|
||||
which is why the start period above is generous.
|
||||
The catalog follows HealthLog releases on its own: when a new image is
|
||||
published, the TrueNAS catalog picks it up and the app shows an update. Take a
|
||||
snapshot or a dump first, then update.
|
||||
|
||||
Database migrations run at every start, before the web server listens, and
|
||||
only go forward. The start log says how many are pending. Going back to an
|
||||
older version with Roll Back does not undo them, and an older version may not
|
||||
start against a database a newer one has migrated. The way back is the
|
||||
database backup you took before the update, restored together with the older
|
||||
version.
|
||||
|
||||
The Postgres Image field offers the Postgres major versions the catalog
|
||||
supports. Changing it runs a one-way upgrade of the database files, so back up
|
||||
before you touch it.
|
||||
|
||||
## Before the listing: install via YAML
|
||||
|
||||
Until the catalog app is listed, install HealthLog with Apps, Discover Apps,
|
||||
the menu next to Custom App, Install via YAML, using these values:
|
||||
|
||||
| Setting | Value |
|
||||
| ------------ | ---------------------------------------------------------------------------------------- |
|
||||
| Image | `ghcr.io/mbombeck/healthlog`, tag `X.Y.Z` (amd64 and arm64) |
|
||||
| Port | `3000` (HTTP) |
|
||||
| User | runs as uid `1001` by default; no extra capabilities, `no-new-privileges` is fine |
|
||||
| Health check | `GET /api/health`, `200` when ready |
|
||||
| Start period | at least 60 s, with more retries than the image's 5 × 30 s: migrations run at every boot |
|
||||
| Database | PostgreSQL 16 or 18, no extensions, in its own container with its own dataset |
|
||||
| Volumes | none for the app; the database gets its own dataset |
|
||||
|
||||
| Variable | Required | Notes |
|
||||
| ----------------------- | -------- | ---------------------------------------------------------------------------------------- |
|
||||
| `DATABASE_URL` | yes | `postgresql://<user>:<password>@<host>:5432/<db>` |
|
||||
| `ENCRYPTION_KEY` | yes | 64 hex characters: `openssl rand -hex 32`. Keep a copy outside the NAS. |
|
||||
| `API_TOKEN_HMAC_KEY` | yes | 64 hex characters, generated the same way. Changing it signs everyone out. |
|
||||
| `NEXT_PUBLIC_APP_URL` | yes | the address people open, for example `http://truenas.local:30180` |
|
||||
| `APP_URL` | yes | the same address |
|
||||
| `SESSION_COOKIE_SECURE` | no | `false` for a LAN install served over plain `http://`; leave unset behind an HTTPS proxy |
|
||||
| `HEALTHLOG_PLATFORM` | no | `truenas`: the admin's key backup step opens on the TrueNAS instructions |
|
||||
|
||||
`HEALTHLOG_PROCESS_TYPE` stays unset (`all`): one container serves the web app
|
||||
and runs the background jobs. In a YAML install the key sits in the
|
||||
environment block, so the place to copy it from is `ENCRYPTION_KEY` there.
|
||||
To move from a YAML install to the catalog app later, take a dump, install the
|
||||
catalog app with the same key, and restore the dump as described under
|
||||
[Backups and restore](#backups-and-restore).
|
||||
Reference in new issue
Block a user