--- # --------------------------------------------------------------------------- # Rootless Podman / Quadlet # --------------------------------------------------------------------------- # Duplicated on purpose from caddy/vars/default.yml: a play cannot include that # file wholesale, because it also sets `host_directory` — to the Caddy data # directory — and every playbook defines that for itself. Keep these three in # sync with caddy/vars/default.yml. (Its fourth, podman_unprivileged_port_start, # belongs to the podman tasks, which this play does not run: Trilium publishes # nothing host-side.) # # podman_user is derived from the connection: this play carries no become, so # the Quadlet units belong to whoever Ansible connects as. Requires gather_facts # (set in playbook.yml). podman_user: "{{ ansible_facts['user_id'] }}" podman_data_dir: "{{ ansible_facts['user_dir'] }}/podman-data" quadlet_dir: "{{ ansible_facts['user_dir'] }}/.config/containers/systemd" # --------------------------------------------------------------------------- # TriliumNext Notes # --------------------------------------------------------------------------- # The site is unchanged from the Docker era. The *service* name is not: this # directory and the Docker-era playbook call it `trilium`, while the live # container on monoco — which nobody deployed from here — is `trillium`, with # the extra `l`. Everything on emily is `trilium`, following the app's real name # and this playbook's own history; the only place the misspelling survives is # the source path /var/lib/trillium in the copy commands in readme.md. host: notes.tanshu.com container_name: trilium unit_name: "{{ container_name }}.service" # Fully qualified on purpose: rootless Podman resolves short names against # unqualified-search-registries, and there is no TTY to answer a prompt when # the systemd unit starts. # # This is the *TriliumNext* image, not the retired `zadam/trilium` the old # playbook pulled: monoco has been running TriliumNext since June 2025, and its # document.db carries the schema migrations that came with it. Pulling the old # image against that database would not work. # # `latest` has floated, and by more than a patch: monoco runs v0.95.0 (built # 2025-06-15) and the pull on emily is v0.106.0 (2026-09-25). TriliumNext # migrates document.db forward on first start, so the cutover is also an app # upgrade -- one-way for the copy on emily, which is why the readme says to # compare digests before the first start and to leave monoco's own tree alone. # Pin a digest or a version tag here if the migration should move the runtime # only and leave the app version to a separate, deliberate step. image: docker.io/triliumnext/notes:latest # The Quadlet file is .network. caddy/roles/register pins the # Podman network name to _net (so: trilium.network, # trilium_net). network_name: "{{ container_name }}" # The image's data directory, and the whole of this service's state. Unlike # audiobookshelf/ there is one mount target rather than four, because Trilium # keeps document.db, config.ini and its own subdirectories together. data_dir: "{{ podman_data_dir }}/{{ container_name }}" container_data_dir: /home/node/trilium-data # Subdirectories the app creates and owns itself, at mode 0700 — that is exactly # what they are on monoco. Created by the role so a fresh host and a migrated one # look the same, and so the copy target in readme.md exists: # # log/ one file per day, 91 MB of the 106 MB tree on monoco. Regenerable. # tmp/ scratch, empty at rest. # backup/ Trilium's own zipped document.db backups, 12 MB. Worth keeping. log_dir: "{{ data_dir }}/log" tmp_dir: "{{ data_dir }}/tmp" backup_dir: "{{ data_dir }}/backup" # The port the app listens on inside the container, from config.ini's # `port = 8080`, which the Docker-era container used unchanged. Caddy proxies to # it; nothing is published on the host. container_port: 8080 # The unit's own HEALTHCHECK, because the image does not ship one: v0.106.0 # dropped the docker_healthcheck.cjs that v0.95.0 had, so `podman healthcheck # run` otherwise fails with "no defined healthcheck". /api/health-check is the # endpoint the app advertises itself, writing it to `healthcheck-url` in the data # directory at startup. `curl` is in the image; `wget` is not. health_cmd: "curl -fsS -o /dev/null http://127.0.0.1:{{ container_port }}/api/health-check" # The shared Caddy unit and its Caddyfile, both owned by caddy/playbook.yml. caddy_name: caddy caddyfile_path: "{{ podman_data_dir }}/{{ caddy_name }}/conf/Caddyfile" # Caddy handles the WebSocket upgrade Trilium's live-updating editor needs, and # imposes no request-body limit, so there is nothing to carry over from the old # nginx front end. snippet_block: | {{ host }} { reverse_proxy {{ container_name }}:{{ container_port }} }