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:
| Daemon | Job |
|---|---|
com.walisayu.walis | the service (runs as a regular account) |
com.walisayu.walis-restarter | watches 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:11120All 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, butdeploy/install.shnarrows the service tolocalhost;127.0.0.1;walis.localhost. A request that arrives through the proxy under your public name gets400 Invalid Hostnameuntil 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 setSecurity__TrustedProxies=127.0.0.1,::1(the macOS installer does). - Sandbox paths must be resolved (macOS only).
/tmpand/var/foldersare symlinks in the middle of the path; asandbox-execrule 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.