Smriti स्मृति
Install & configure

Docker, Podman and TrueNAS SCALE — every setting, in one place.

Written for someone who has a server (or a TrueNAS box) but has never seen Smriti. Every step below is either verified against this repository's own scripts and packaging files, or clearly marked as not yet available — nothing here is a guess dressed up as documentation.

Before you begin

Smriti does not ship pre-built container images yet — every install path on this page builds the app, worker and ML-worker images from source. That means the first install takes longer than a normal docker pull would (roughly a few minutes on a modest server), and it means you need enough free disk for a source checkout, the built image layers, and your own library on top.

You will want, regardless of path:

  • A Linux server (or TrueNAS SCALE, which is Linux underneath) with at least ~5 GB free for the build, separate from your media.
  • An existing folder of photos/files you want Smriti to manage — it reads your library in place, it does not import it into a separate store.
  • A port to publish the web UI on. 30078 is Smriti's own registered default; any free port works.

Docker (recommended today)

This is the path that works right now, on any server: a plain docker compose stack, built from a git checkout, with the same network-isolation topology the maintainer runs in production (the ML worker and the database have no route to the internet — only the web container publishes a port).

Install

The one-line installer (deploy/install.sh) does the whole thing: checks the runtime, disk space and port, asks before doing anything, clones the source, generates random database credentials, builds the images, runs migrations, activates Postgres row-level security (the Vault boundary), and starts the stack.

curl -fsSL https://get.smriti.cloud/install.sh | sh

Useful flags (all also settable as SMRITI_* environment variables — see the script's own header comment for the full list):

FlagDefaultWhat it controls
--media-root=PATHpromptedthe existing folder Smriti manages, mounted read-write
--data-dir=PATH<install-dir>/datawhere Postgres/Redis/app data persist
--port=N30078host port the web UI is published on
--install-dir=PATH$HOME/smritiwhere the source checkout and generated compose file live
--ref=NAMEmaingit branch/tag to build
--yesoffskip the confirmation prompt (for scripted installs)

Prefer to read every line first, as you should for anything piped into a shell? You will be able to — the source is not public yet, so the script is not readable online today. It is plain POSIX sh, no obfuscation, and it prints exactly what it is about to do before it does it. The Compose file it generates (<install-dir>/docker-compose.yml) is also plain text once it exists, and re-running the script is how you upgrade — it never regenerates an existing install's secrets or deletes anything.

Configuration reference

Every setting the generated stack actually uses. Most are already correct defaults; you only need to touch the ones marked otherwise.

VariableSet onPurpose
DATABASE_URLapp, arq-workerconnects as the dedicated, non-superuser smriti_app role so Postgres row-level security enforces the Vault boundary. Set for you by the installer.
MEDIA_ROOTSapp, arq-workercomma-separated list of paths Smriti indexes (the installer wires your one media root to /media/library).
ML_WORKER_URLapp, arq-workerinternal-only URL of the face/CLIP worker. Config, never user input — leave it alone.
SESSION_COOKIE_SECURE, VAULT_COOKIE_SECURE, SHARE_COOKIE_SECUREappthe installer sets these to false for a plain-HTTP LAN install. If you put a TLS-terminating reverse proxy in front, set all three to true — otherwise a Secure cookie is silently never sent back over HTTP and login breaks.
FORWARDED_ALLOW_IPSappwhich exact peer IP to trust X-Forwarded-* headers from. Pinned to the bundled nginx container's fixed address by default; never set it to *.
MAX_CONCURRENT_MEDIA_JOBS, FFMPEG_THREADS, VIPS_CONCURRENCYapp, arq-workerbound how much heavy media work (thumbnails, transcodes, face scans) can run at once. Defaults are tuned for a modest, fanless box — raise them on beefier hardware.
RECOGNITION_MODEL_ID, ORT_THREADS, CLIP_MODEL_IDml-workerwhich face/CLIP model packs to serve and how many inference threads to use. Changing the recognition model later requires re-embedding every face.
SMRITI_MEDIA_ROOT, SMRITI_DATA_DIR, SMRITI_PORTthe installer's own .envthe three values you were prompted for. Safe to hand-edit before the next upgrade run.

Storage roots & data directory

The installer wires exactly one media root today. Additional storage roots (Smriti supports one per user under the hood) are an admin-panel feature you can add once the app is running, after mounting the extra path into the containers yourself.

Under the data directory, four subfolders are created and must persist across restarts and upgrades — none of them should be deleted or excluded from your backups:

  • postgres/ — the database: people, faces, albums, tags, favourites, every manual correction.
  • redis/ — the background job queue's own storage.
  • config/ — reserved for persistent app configuration.
  • appdata/ — generated thumbnail and video-transcode caches. Regenerating either is heavily CPU-bound, so wiping this is expensive, not dangerous.

Upgrade & rollback

Upgrade: re-run the installer (same command, same --install-dir). It reuses your existing secrets and paths, fetches the chosen ref, rebuilds the images, re-runs migrations (a no-op if already at head), and restarts.

Rollback: Smriti's database migrations are forward-only — there is no automatic "undo" for a schema change, because some migrations discard data on the way down. The safe rollback is: take a Postgres backup before upgrading (the pg_dump-based scripts in this repo's deploy/ directory are the reference for doing that by hand — they are not yet wired into the one-line installer itself), then if an upgrade goes wrong, restore that backup and check the source out back to the previous ref (git -C <install-dir>/src checkout <old-ref>) before rebuilding. This is a manual process today, not a one-command rollback.

Verify it worked

  • curl http://<host>:<port>/api/health should return a healthy response.
  • Open http://<host>:<port>/ in a browser — the first visit walks you through first-run setup, creating the super-admin account.
  • cd <install-dir> && docker compose logs -f shows all six services starting; the ML worker's healthcheck has a generous 60-second start period, so give it a minute.

Podman

Not decided yet. Podman support is under active discussion and is tracked as ADR-019, currently Proposed and unapproved — this section will be filled in once that decision lands, not before. Until then: deploy/install.sh actively detects a Podman-only host (including distros where the docker command itself is a Podman compatibility shim) and refuses cleanly with an explanation, rather than half-installing something that cannot yet reproduce Smriti's network-isolation guarantees.

TrueNAS SCALE

Not installable yet. Smriti is packaged as a TrueNAS SCALE community catalogue app in this repository (truenas-app/ix-dev/community/smriti/), and everything below is verified against that packaging's real questions.yaml — but the install itself cannot complete today, because Smriti has no published container images for TrueNAS's app system to pull (it only knows how to run named images, unlike Docker Compose it cannot build from source). This is a tracked, known gap, not an oversight. The sections below describe the form as it exists now, so it is accurate the day images ship. TrueNAS users who want to run Smriti today should use the Docker path above on any Linux host.

Adding the catalogue

Once images are published, Smriti's catalogue entry is added the same way any custom TrueNAS SCALE catalogue is: Apps → Discover Apps → the settings (gear) icon → Manage Catalogs → Add Catalog, pointing at this repository's URL with the community train. If Smriti is later accepted into TrueNAS's own official apps catalogue, it will simply appear under Discover Apps with no separate step.

The install form, setting by setting

The form is organised into six groups. Everything below matches the packaging's questions.yaml exactly.

Smriti Configuration

SettingRecommendation
Timezoneyour server's real timezone — used for schedules and timestamps.
Database Owner Password / Application Database Passwordtwo different strong, random passwords (16+ characters). The owner runs migrations; the app connects as the separate, non-superuser role so row-level security actually enforces the Vault boundary. Save both — the owner password is needed to restore a backup.
Redis Passworda strong, random password for the bundled job queue.
Take a database backup before every deploymentleave ON. alembic downgrade is not a safe undo for Smriti; this dump is the real rollback path, and a failed dump stops the deployment before it touches anything.
Face Recognition Modelbuffalo_l (the recommended default). Changing it later re-embeds every face.
ML Inference Threads / Concurrent Media Jobs / FFmpeg Threadsleave the defaults (2 / 1 / 1) on a fanless or passively-cooled NAS; raise only on hardware with real sustained cooling.
Maximum Disk/CPU Temperaturedefaults (55°C / 85°C) are conservative and match the reference hardware; lower them if your box runs hotter than expected.

User and Group Configuration

Leave both at 568 (TrueNAS SCALE's built-in apps account) unless your media datasets are owned by a different uid/gid — Smriti's containers need to run as whichever account already owns those files.

Network Configuration

WebUI Port: 30078 is Smriti's own registered default; change it only if it collides with something else already using that port.

Storage Configuration

SettingRecommendation
Media Rootsat least one is required. Point each at an existing dataset on a data pool (never the boot pool), mounted read-write — the file manager, trash and deduplicator all need to write.
Derived Data, Application Config, Postgres Data, Pre-upgrade Backupsleave as ixVolume (TrueNAS creates and manages the dataset) unless you specifically need a hand-picked path. Postgres Data and Backups are the two that matter most for disaster recovery — put them where your snapshot schedule already covers them.

Datasets & NFSv4 ACLs

TrueNAS SCALE pools commonly use NFSv4 ACLs in restricted mode, where a plain chmod fails outright. You do not need to fight this by hand: every storage entry on the install form has an Enable ACL toggle, and when it is on, TrueNAS sets the correct NFSv4 ACL for the container's uid/gid itself through its own filesystem API — the same mechanism an administrator would otherwise drive manually (TrueNAS's midclt filesystem.setacl). Turn it on for any dataset you are creating fresh for Smriti; leave it off only for a path whose permissions you have already set up correctly outside the form.

First run & verifying it worked

  • The Apps page shows the app as Running once every container passes its healthcheck — the ML worker's can take up to a minute on first start.
  • Open http://<truenas-ip>:<chosen-port>/ — the first visit walks you through first-run setup, creating the super-admin account.
  • The app's own logs (Apps → Smriti → Logs, per container) are the first place to look if a container never reaches Running.