Skip to content

Deployment ​

This page describes a macOS deployment — LaunchDaemons, cloudflared and Caddy. Walis itself runs on Windows and Linux too (see Getting started); the self-update mechanism below applies anywhere, only the service manager differs.

Self-updating ​

Walis ships a job that updates Walis. The catch is that a build is a child process of the service, so a script that restarts the service kills itself before the result is written — the build would hang in Running forever.

The fix is to split the work in two:

DaemonJob
com.walisayu.walisthe service (runs as a regular account)
com.walisayu.walis-restarterwatches var/restart.request, validates the staged release, promotes it into the root-owned releases/, switches current and restarts the service 8 seconds later

releases/ and current are owned by root (755), so ordinary builds cannot replace the binary the service restarts into. The update job (registered as an administrator-only trusted job) only does three things — pull, build into var/staging/<timestamp>, touch the trigger file — and then exits normally. The restarter lives outside the service's process tree, validates and promotes the staged release, and restarts the service without affecting the build result. A failed build or failed validation never swaps the symlink, so the service stays on the previous release.

Reverse proxy and tunnel ​

<host>.example.com
  → cloudflared  (LaunchDaemon)
  → Caddy on 127.0.0.1:8080  (LaunchDaemon)
  → the service on 127.0.0.1:11120

All three are LaunchDaemons so they come back after a reboot without anyone logging in. Note that brew services is not used: those are user LaunchAgents that only run once someone logs in.

Two things that will bite you:

  • AllowedHosts. Walis itself answers to any host name, but deploy/install.sh narrows the service to localhost;127.0.0.1;walis.localhost. A request that arrives through the proxy under your public name gets 400 Invalid Hostname until you add it — pass, for example, WALIS_ALLOWED_HOSTS='localhost;127.0.0.1;walis.localhost;walis.example.com' to the installer.
  • The first administrator. The setup screen asks for the setup code, through the proxy and on the machine itself. See First connection.
  • List the proxy. Forwarded headers are only accepted from Security__TrustedProxies; for a proxy on the same machine set Security__TrustedProxies=127.0.0.1,::1 (the macOS installer does).
  • Sandbox paths must be resolved (macOS only). /tmp and /var/folders are symlinks in the middle of the path; a sandbox-exec rule written with the unresolved path silently does nothing.

Backups ​

Walis can back up its own database (VACUUM INTO on SQLite, safe while running; the same archive format for PostgreSQL, MySQL and SQL Server), artifacts, extra paths you list, and a separate application PostgreSQL via pg_dump. The database goes into the archive in an engine-independent form, so the same backup restores into SQLite, PostgreSQL, MySQL or SQL Server. Archives are encrypted with Walis' own authenticated format — PBKDF2-SHA256 and AES-256-GCM chunks — and are restored through Walis (the backup page or POST /api/backup/restore), which rejects anything modified or truncated; see Backup and restore.

Targets: a local or mounted path, S3-compatible storage (R2 or AWS, signed in-process), Dropbox, Google Drive and OneDrive. A passphrase is mandatory as soon as backups are enabled or any target exists — a backup contains password hashes and cloud keys.

Released under the MIT License.