Vibed Google Timeline alternative (VIBED)
README.md

Deployment #

Rootless Podman Quadlet units for the host:

  • timeline.container: the service from localhost/timeline:latest, published on 127.0.0.1:8470, restarted on failure or when its healthcheck fails.
  • timeline.volume: named volume timeline-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.