Self-Hosting in Production
This page covers what you need in week one after your initial Wayland server install. It picks up where Run Wayland on a Server leaves off. Read that page first if you have not set the server up yet: it covers requirements, the three-step install, the first-login QR code, and the Tailscale private-network option.
Once the server is running interactively, you will probably want it to survive a reboot, sit behind a proper reverse proxy, and be straightforward to upgrade. This page covers all of that.
Environment overrides
Section titled “Environment overrides”Two environment variables let you change where Wayland listens and where it stores data:
| Variable | Default | What it changes |
|---|---|---|
PORT | 3000 | The port the server binds on |
DATA_DIR | (a platform default under the user’s home) | Where Wayland stores its database, config, and provider credentials |
The wayland command is the global binary from npm install -g getwayland (done during the server install on the page linked above). Set these variables before wayland start, or put them in the systemd unit file shown below.
PORT=8080 DATA_DIR=/srv/wayland wayland startRun as a systemd service
Section titled “Run as a systemd service”Running wayland start in a terminal is fine for testing, but it stops when you log out. A systemd unit keeps the server running across sessions and reboots.
Create the file /etc/systemd/system/wayland.service:
[Unit]Description=Wayland serverAfter=network.target
[Service]Type=simpleUser=waylandWorkingDirectory=/home/waylandEnvironment=PORT=3000Environment=DATA_DIR=/home/wayland/.waylandExecStart=/usr/bin/env wayland startRestart=on-failureRestartSec=5
[Install]WantedBy=multi-user.targetReplace wayland (under User and WorkingDirectory) with the Linux user you want the server to run as. Then enable and start it:
sudo systemctl daemon-reloadsudo systemctl enable waylandsudo systemctl start waylandsudo systemctl status waylandTo see live logs:
journalctl -u wayland -fReverse proxy with TLS
Section titled “Reverse proxy with TLS”The server binds on 0.0.0.0:3000 by default. For a public-facing deployment you should put it behind a reverse proxy that handles TLS, so that traffic reaches your box over HTTPS and Wayland itself only listens on localhost.
Install nginx and certbot, then obtain a certificate:
sudo apt install nginx certbot python3-certbot-nginxsudo certbot --nginx -d your.domain.comCreate /etc/nginx/sites-available/wayland:
server { listen 443 ssl; server_name your.domain.com;
ssl_certificate /etc/letsencrypt/live/your.domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your.domain.com/privkey.pem;
location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 3600; proxy_send_timeout 3600; }}
server { listen 80; server_name your.domain.com; return 301 https://$host$request_uri;}Enable it and reload:
sudo ln -s /etc/nginx/sites-available/wayland /etc/nginx/sites-enabled/sudo nginx -tsudo systemctl reload nginxUpdate the systemd unit to bind on loopback only by adding Environment=HOST=127.0.0.1 if the server supports a HOST override, or use your firewall to block external access to port 3000 directly:
sudo ufw allow 80sudo ufw allow 443sudo ufw deny 3000Caddy handles certificate acquisition and renewal automatically. Install it, then create or edit /etc/caddy/Caddyfile:
your.domain.com { reverse_proxy localhost:3000 { header_up X-Forwarded-Proto {scheme} transport http { read_buffer 4096 } }}Start or reload Caddy:
sudo systemctl enable caddysudo systemctl start caddyCaddy obtains a certificate from Let’s Encrypt automatically on first access.
Private network with Tailscale
Section titled “Private network with Tailscale”If you do not need the server reachable from the public internet, Tailscale is the simplest option. It was introduced in Run Wayland on a Server. The one-line setup:
tailscale serve 3000This serves the Wayland server over HTTPS, reachable only from devices on your tailnet. No nginx, no certbot, no firewall rules needed. For a personal or small-team setup this is the recommended path.
Upgrading between versions
Section titled “Upgrading between versions”Wayland is installed as a global npm package. To upgrade to the latest release:
npm install -g getwayland@latestThen restart the service:
sudo systemctl restart waylandTo upgrade to a specific version, pin the version tag (otherwise @latest installs the newest published release):
npm install -g getwayland@latestsudo systemctl restart waylandYour data and config in DATA_DIR are preserved across upgrades. The server migrates its own database on startup when the schema changes.
Before upgrading in production, check the Releases page for any manual migration steps called out in the release notes.
Break-glass admin password reset
Section titled “Break-glass admin password reset”If you lose the admin password, the wayland resetpass command resets it locally without needing to log in:
wayland resetpassRun this on the server itself (not over the web UI). It prints a new temporary password to the terminal. Log in with that password and change it immediately.
This command reads from DATA_DIR, so if you set a custom data directory in your systemd unit, make sure that environment variable is also set when you run wayland resetpass:
DATA_DIR=/srv/wayland wayland resetpassTroubleshooting startup failures
Section titled “Troubleshooting startup failures”The server exits immediately after wayland start.
Check the logs:
journalctl -u wayland -n 50Common causes:
- Port already in use. Another process is on port 3000. Change the port with
PORT=<other>or stop the conflicting process. DATA_DIRdoes not exist or is not writable by the service user. Create it and set ownership:sudo mkdir -p /path/to/data && sudo chown wayland:wayland /path/to/data.- Node version too old. Wayland requires Node 18 or newer. Check with
node --version.
The server starts but the web UI is unreachable.
Check that the service is running (systemctl status wayland), that your firewall allows the port you are using, and that your reverse proxy configuration points at the right port.
The QR code does not appear on restart.
The QR code only prints on the very first boot, when the admin account is created. On subsequent starts the server just logs that it is running. Use the printed admin password from the first boot, or use wayland resetpass if you did not save it.