Run it on a server
This page takes Sideporch from an installed program to a chat people can reach: a service that starts with the server, the first account, and HTTPS.
Start it as a service
With the install script, run Sideporch with systemd. Create a user for it:
sudo useradd --system --home-dir /var/lib/sideporch --shell /usr/sbin/nologin sideporch
Save this as /etc/systemd/system/sideporch.service, with your own address in --public-url:
[Unit]
Description=Sideporch team chat
After=network-online.target
Wants=network-online.target
[Service]
User=sideporch
Group=sideporch
ExecStart=/usr/local/bin/sideporch --data /var/lib/sideporch --public-url https://chat.example.com --require-setup-link
StateDirectory=sideporch
StateDirectoryMode=0700
Restart=on-failure
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Then start it, and have it start with the server:
sudo systemctl daemon-reload
sudo systemctl enable --now sideporch
journalctl -u sideporch -f # its log
Sideporch listens on 127.0.0.1:8080, so only the server itself reaches it until you add HTTPS.
Create the admin account
While no account exists, the first visitor creates the admin account. On a server others can reach before you set it up, lock setup in one of two ways:
-
A setup code you choose (new in 0.7.0), easiest where there’s no shell, like Docker, Fly.io or Kubernetes. Generate one, keep it in your password manager, and start Sideporch with it; the setup page asks for it:
openssl rand -base64 24 # a code nobody can guess docker run -d -p 8080:8080 -v sideporch:/data -e SIDEPORCH_SETUP_CODE='…' ghcr.io/niklas-heer/sideporchIt needs at least 16 characters. Wrong codes are limited per address, and the code does nothing once the first account exists, so you can leave it set.
-
A one-time link with
--require-setup-link(as in the service above), which stays out of service and container logs. Get it on the server:sudo -u sideporch sideporch setup-link --data /var/lib/sideporch docker exec sideporch /sideporch setup-link # with Docker
Behind Cloudflare Access, setup also needs Access, and without a code, whoever Access lets in first becomes the admin.
Open the link (or enter the code) and create your account, with a passkey where your browser offers one. Then invite everyone else from People. To let people join without an invite, open sign-up under Admin → Community; see Sign-up and trust.
Options
Every option can also be set with an environment variable.
| Option | Environment variable | Default | Meaning |
|---|---|---|---|
--listen | SIDEPORCH_LISTEN | 127.0.0.1:8080 | Address and port to listen on. |
--data | SIDEPORCH_DATA | sideporch-data | Directory for everything Sideporch keeps. Back it up to back up everything. |
--public-url | SIDEPORCH_PUBLIC_URL | taken from each request | The URL people use, such as https://chat.example.com, for invite and webhook links. An https:// URL also makes cookies secure. |
--setup-code | SIDEPORCH_SETUP_CODE | none | A secret of at least 16 characters that the setup page asks for before anyone can create the first account. Takes the place of --require-setup-link. New in 0.7.0. |
--require-setup-link | SIDEPORCH_REQUIRE_SETUP_LINK | off | Require the one-time link from sideporch setup-link to create the first account. |
--client-ip-header | SIDEPORCH_CLIENT_IP_HEADER | none: the connection’s address | Behind a reverse proxy, the header it puts visitors’ addresses in, such as X-Forwarded-For or Fly-Client-IP. Sign-in limits and bans use it. Only set it when every request comes through that proxy, or anyone could claim any address. New in 0.6.0. |
--cloudflare-access-team | SIDEPORCH_CLOUDFLARE_ACCESS_TEAM | none | Sign people in through Cloudflare Access: your team domain, such as myteam.cloudflareaccess.com. Set it together with the audience tag. New in 0.7.0. |
--cloudflare-access-aud | SIDEPORCH_CLOUDFLARE_ACCESS_AUD | none | The audience (AUD) tag of the Cloudflare Access application in front of the server. New in 0.7.0. |
--cloudflare-access-required | SIDEPORCH_CLOUDFLARE_ACCESS_REQUIRED | off | Refuse pages to requests that didn’t come through Cloudflare Access; webhooks, other servers, MCP and /healthz stay open. New in 0.7.0. |
--update-check | SIDEPORCH_UPDATE_CHECK | true | Ask GitHub for new releases every six hours; false keeps Sideporch from contacting GitHub. See Update. New in 0.5.0. |
SIDEPORCH_SECRET_KEY | secret.key in the data directory | A passphrase to encrypt automation secrets with, instead of the key file. | |
RUST_LOG | info | How much to log: warn, info, debug. |
Four commands besides running the server:
sideporch setup-linkprints the link for creating the first account.sideporch reset-link USERNAMEprints a one-time link for choosing a new password, for when someone, like the only admin, lost their password; with--reset-sign-init also removes their passkeys, authenticator app and MCP tokens and signs them out everywhere, for when those are lost. New in 0.7.0.sideporch restore ARCHIVEunpacks a backup. Stop the server first.sideporch updateinstalls the newest release in place of the program; see Update. New in 0.5.0.
Put it behind HTTPS
Browsers only send push notifications, install Sideporch as an app and use passkeys over HTTPS, so put a reverse proxy in front of it. Choose the name people will keep using before they make passkeys: a passkey belongs to its name, so moving to another one means signing in another way and adding new ones (an admin who has no other way in can use sideporch reset-link --reset-sign-in). Live updates use a WebSocket at /ws, which the proxy has to pass on.
With Caddy, which gets certificates by itself, this is the whole configuration:
chat.example.com {
reverse_proxy 127.0.0.1:8080
}
With nginx:
server {
listen 443 ssl;
server_name chat.example.com;
# ssl_certificate and ssl_certificate_key, for example from certbot
client_max_body_size 0; # Sideporch limits uploads itself; Slack exports can be large
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 1h;
}
}
Set --public-url to the address people use. Without it, Sideporch builds links from the Host (or X-Forwarded-Host) and X-Forwarded-Proto headers the proxy passes on.
Set --client-ip-header X-Forwarded-For too, so Sideporch sees visitors’ addresses instead of the proxy’s; otherwise sign-in limits and bans would treat everyone as one visitor. Caddy sets that header by itself; with nginx, add proxy_set_header X-Forwarded-For $remote_addr;.
Check that it runs
/healthz answers ok while Sideporch runs, for monitors and container health checks:
curl -fsS http://127.0.0.1:8080/healthz
Next: keep it up to date, and set up backups.