Deployment #
Rootless Podman Quadlet units for the host:
timeline.container: the service fromlocalhost/timeline:latest, published on127.0.0.1:8470, restarted on failure or when its healthcheck fails.timeline.volume: named volumetimeline-data, mounted at/data(the SQLite database).
Install #
Build the image from the repo root with mise run image. To offer the app for download, put the
APK in dist/ first (mise run apk).
mkdir -p ~/.config/containers/systemd
cp deploy/timeline.container deploy/timeline.volume ~/.config/containers/systemd/
loginctl enable-linger "$USER" # start user services at boot without a login
systemctl --user daemon-reload
systemctl --user start timeline.service
Check the generated units with /usr/libexec/podman/quadlet -dryrun -user. Quadlet units can't be
systemctl enabled: WantedBy=default.target in timeline.container starts the service at boot.
Updating #
Rebuild the image, then systemctl --user restart timeline.service. Old images pile up as
<none>; remove them with podman image prune.
When the unit files change, copy them again and run systemctl --user daemon-reload.
Status and logs #
systemctl --user status timeline.service
journalctl --user -u timeline
podman healthcheck run timeline # exit 0 when healthy
Reverse proxy #
The service has no auth; expose it only on a private network, e.g. a Caddy site on a tailnet name (or any HTTPS name):
timeline.example.ts.net {
reverse_proxy 127.0.0.1:8470
}
Caddy must reach the host's loopback (host networking if Caddy runs in a container).
Changing the port #
Edit the host side of PublishPort= in timeline.container and the proxy upstream, copy the unit,
then systemctl --user daemon-reload && systemctl --user restart timeline.service. The container
port stays 8080; if TIMELINE_ADDR is changed, pass the matching -url to the health command in
HealthCmd=.
Data #
The database lives in the timeline-data volume (podman volume inspect timeline-data shows the
host path). Removing the container or image keeps it; podman volume rm deletes it.