Server documentation · English
Give your community its own server.
On a Linux server one command is enough: the installer asks for your domain, HTTPS and the Directory, writes the configuration with secure random values and starts everything with Docker. On a Windows machine a package does the same without Docker. Either way the bundled Caddy obtains the HTTPS certificate, PostgreSQL stores your server data, LiveKit handles voice and video. No Git, no Node.js and no source build are involved.
What you are installing: the open-source Squorli Server and its web client. Squorli Directory is a separate, non-open-source service; you connect it, you do not install it.
Choose your way. Everything below it – first login, Directory, reverse proxy, troubleshooting – applies to each of them.
Linux server with Docker
The recommended way for a rented server: one script, a few questions, done.
What you need
- A Linux server (x86_64) with root access through
sudo, such as a rented virtual server running Debian or Ubuntu, plus curl. The installer brings Docker and its Compose plugin along if they are missing. Around 1 GB of memory for the app, the database and LiveKit together, more with many simultaneous video streams. - A domain of your own, such as
chat.example.org, with DNS pointing at the server. Browsers only release microphone and camera over HTTPS; localhost is the single exception. - Inbound 80/tcp and 443/tcp for the bundled proxy and 7881/tcp and 7882/udp straight to LiveKit. Media never travels through an HTTP proxy; behind a router, forward those ports. If 7881 or 7882 is already taken, choose others in the installer.
- For video, upload bandwidth at the server: LiveKit forwards every camera to every viewer, so the upload grows with cameras times viewers. A full channel with 15 cameras and 15 viewers needs roughly 60 Mbit/s upload and 20 Mbit/s download – a projection from a measurement of about 4 Mbit/s per viewer. For large video channels, rent a server; a home connection is usually too weak.
No validated production sizing or participant guarantee is available yet. If you already run a reverse proxy, choose that in the installer; Use an existing reverse proxy has the details.
Install
Log in to the server over SSH, download the installer and run it. It is a readable Bash script: you can look through it on GitHub beforehand.
curl -fsSL https://raw.githubusercontent.com/danielklessa/squorli/main/deploy/install.sh -o install.sh
sudo bash install.shThe installer asks one question after another, in German or English. Press Enter to accept a suggestion in square brackets:
- Domain – exactly the hostname browsers use, without
https://. The installer shows which address it points to in DNS. - Server name – the initial name, changeable later in Administration.
- Who takes care of HTTPS – the bundled Caddy with a Let's Encrypt certificate, a reverse proxy on the same machine, or one on another machine (Use an existing reverse proxy).
- Ports – the installer shows which ports it needs, checks whether another service already holds them and then suggests free ones. You can also pick every port yourself. Only Caddy needs 80 and 443 fixed, because Let's Encrypt checks the domain over them.
- Squorli Directory – yes (the suggestion, gives your members a global account), no (the server works on its own, with server accounts
~nameof its own), or another directory. - Who becomes the owner – your Squorli account by its public key (with a directory only), a server account (
~name) you register with a setup code the installer makes and shows at the end, or whoever signs in first with an account (First login). - Public IP for voice and video – leave it empty and LiveKit detects it itself. Only with NAT or several network interfaces do you enter the public IP.
- Container image – the suggestion is
ghcr.io/danielklessa/squorli-server:latest. For production, enter a fixed tag or digest from the GitHub container package.
After a summary and your confirmation it does the rest. If Docker is missing, it installs Docker with the official script from get.docker.com after asking. It places the configuration in /opt/squorli, generates the database password and the LiveKit secret as random values in a .env only root can read, opens the ports in an active ufw or firewalld firewall after asking, pulls the images, starts the containers and checks /api/health and /rtc/validate through your domain. A firewall at your hosting provider and port forwardings in a router are yours to set up.
At the end the installer names your server's address. If it does not answer over HTTPS yet, DNS or the inbound ports are usually not right yet; Caddy keeps trying on its own (Troubleshooting).
You can run the installer again at any time: it recognizes the existing installation and offers to update it or to change its settings. Secrets, database and files are kept, and changed files are saved with the extension .bak. The published image exists for x86_64 (amd64) only for now; on ARM machines, build from source.
Updates and backups
The installer sets up the command squorli, which manages the installation in /opt/squorli:
# The installer's command for this installation (run as root)
sudo squorli status
sudo squorli logs server
sudo squorli backup
sudo squorli update
# Checks domain, certificate, proxy, LiveKit, media ports and the directory
sudo squorli doctor
# Replaces database and files with a backup (asks first)
sudo squorli restore /opt/squorli/backups/20260925-120000squorli backup writes a database dump, an archive of attachments and preview pictures and a copy of .env into a folder under /opt/squorli/backups. The server's identity key lives in the database; attachments alone are not a complete backup. Keep the copies off the server. squorli restore with such a folder puts it back: it stops the app, replaces the database and all files with the backup's and starts again; the .env stays as it is. To move to a new host, install there first, then copy the folder over and restore it. squorli update pulls the current images, backs up first when one of them is new, and restarts only the containers whose image changed; the others keep running. Running the installer again and choosing “Update” also renews the configuration files for Compose, Caddy and LiveKit.
squorli doctor checks what goes wrong most often in a setup and names the likely cause: whether the domain resolves and the certificate is valid, whether the proxy passes the WebSocket upgrade and /rtc to LiveKit, whether LiveKit accepts the API key, whether the TCP media port is reachable and whether the Directory reaches the server. With a Directory configured it repeats the checks from outside, because a server cannot see for itself whether its ports are open from the internet. The same check exists in the client under Verwaltung › Server › “Check the connection”; there the browser also makes a real media connection and tells whether it runs over UDP, over TCP only, or not at all.
Record the image version: latest is mutable, and migrations run at startup – rolling the image back does not undo a database change.
Automatic updates
squorli autoupdate on sets up a job that looks for new images at an interval you choose, from every hour to once a day, and installs them. When nothing is new, nothing is restarted; when something is, the job backs up first and restarts only what changed. squorli autoupdate shows the state and the last runs, squorli autoupdate off removes the job. squorli update --check only looks.
# Looks for new images every so many hours and installs them; asks for the hours (1 to 24)
sudo squorli autoupdate on
# The state and the last runs
sudo squorli autoupdate
sudo squorli autoupdate off
# Only looks: exit code 10 when something is new, 0 when not
sudo squorli update --checkRead this before you switch it on. An update restarts the app server whenever a new version appears; whoever is writing or talking at that moment is cut off briefly. With 24 hours the job runs once a day at 04:17, which is the calm choice. A version that asks for work by hand before the update is not installed automatically: the job notes it in its log and waits for your squorli update. An update that fails is not taken back on Linux: the backup from before it brings the old state back. The job follows the image tag in APP_IMAGE: stable names the newest published version, and the command offers to enter it; latest changes with every change in development; a fixed version never changes by itself.
If your squorli does not know autoupdate yet, run the installer again and choose “Update”: it writes the command anew.
Windows without Docker
For a Windows machine there is a package that needs no Docker: the app server with a Node.js of its own, plus PostgreSQL, LiveKit and Caddy, set up as Windows services. It is the same Squorli as on Linux, with the same questions during setup and the same command squorli to manage it.
New and not proven everywhere yet. So far the package was installed and run on Windows 11, with the bundled Caddy, with a reverse proxy on the same machine and on localhost: setup, services, voice, a restart of the machine, backup and restore, update, removal. The package's automatic test (setup, every command, backup, update, removal) also passes on Windows Server. Still to come: IIS in front, Windows 10, and a Windows Server in use by people.
What you need
- Windows 10 from 22H2, Windows 11 (Home too) or Windows Server 2019, 2022 or 2025, each 64 bit (x64). An account with administrator rights, 2 GB of free disk space, around 1 GB of memory. Windows PowerShell is part of Windows; if Microsoft's Visual C++ runtime is missing, the setup downloads it from Microsoft after asking.
- Domain, ports and bandwidth as for the Linux server: a domain that points at the machine, inbound 80/tcp and 443/tcp for the bundled Caddy, and 7881/tcp and 7882/udp for voice and video.
- A PC as a server has limits: Windows Update restarts it, in standby the server is unreachable (the setup offers to switch off standby on mains power), and the upload of a home connection is tight for video. Behind a router you forward the ports; if the connection's public address changes, the domain needs dynamic DNS.
- The programs in the package are not signed. Windows may therefore ask before it runs them.
Install
On the release page on GitHub, take two files from the newest release named “Squorli Server” into the same folder: squorli-server-<version>-windows-x64.zip and the file of the same name ending in .sha256. Then open a PowerShell as administrator (right-click Start › Terminal (Admin)), change into that folder and run:
# In the folder with the two downloaded files
$zip = Get-Item .\squorli-server-*-windows-x64.zip
# The next two lines must print the same value
(Get-FileHash $zip -Algorithm SHA256).Hash.ToLower()
(Get-Content "$zip.sha256").Split(' ')[0]
Unblock-File $zip
& "$env:SystemRoot\System32\tar.exe" -xf $zip
cd $zip.BaseName
powershell -ExecutionPolicy Bypass -File .\install.ps1The two lines printed must be the same: then the package is the one that was published. The setup asks the same questions as the installer for Linux, in German or English – without the one about the container image. It adds what Windows needs:
- Folders – the programs live in
C:\Program Files\Squorli, the data inC:\ProgramData\Squorli. - All five ports – besides the media ports also those of the app server, LiveKit's signaling and the database, because here they are ports of the machine itself. The setup replaces the ones in use by free ones.
- Windows firewall – after asking, the setup opens the media ports, and 80 and 443 with the bundled Caddy.
- Standby – on a PC only: whether standby and hibernation on mains power are switched off.
Then it copies the programs, writes the .env with fresh random values (readable by administrators and the app server's service only), creates the database and sets up the services SquorliPostgres, SquorliLiveKit, SquorliServer and – with the bundled Caddy – SquorliCaddy. They start with Windows without anybody signing in, run under a service account of their own each and are restarted after a crash. At the end the setup checks /api/health and /rtc/validate and names the address and, if chosen, the setup code for the first login.
Managing, updates and backups
The setup installs the command squorli. It works in newly opened windows and needs administrator rights:
# The setup's command for this installation (in a newly opened window, as administrator)
squorli status
squorli logs server
squorli backup
squorli update
# Checks domain, certificate, proxy, LiveKit, media ports and the directory
squorli doctor
# One service, or all of them, with the services that depend on it
squorli restart server
# Replaces database and files with a backup (asks first); takes a backup of a Linux installation too
squorli restore C:\ProgramData\Squorli\backups\20260928-120000squorli backup writes the database, the files and a copy of .env into a folder under C:\ProgramData\Squorli\backups that only administrators can read; keep copies off the machine. squorli restore puts such a folder back and also takes the backup of a Linux installation – that is how a server moves from Linux to Windows. squorli logs shows the last lines, with -Follow it keeps reading. squorli doctor checks the same as on Linux.
squorli update fetches the newest release from GitHub, checks its SHA-256 checksum, backs up first and then runs the setup of the new version. It stops only the services whose programs changed: with a new version of Squorli alone, PostgreSQL and LiveKit keep running. If the new version does not start, it brings the previous program files back. That does not undo migrations of the database: the backup the update wrote before is there for that.
# Change settings: the setup again, it finds the installation
powershell -ExecutionPolicy Bypass -File "C:\Program Files\Squorli\install.ps1"
# Remove services and programs; the data stays unless you type "delete"
powershell -ExecutionPolicy Bypass -File "C:\Program Files\Squorli\uninstall.ps1"Running the setup again changes the settings; secrets, database and files stay. When removing, the data folder is kept unless you explicitly type “delete”.
Automatic updates
squorli autoupdate on sets up a task in the Windows task scheduler that looks for a new version at an interval you choose, from every hour to once a day, and installs it. When there is none, nothing is stopped; when there is one, the task backs up first and stops only what changed. squorli autoupdate shows the state and the last runs, squorli autoupdate off removes the task. squorli update -Check only looks.
# Looks for a new version every so many hours and installs it; asks for the hours (1 to 24)
squorli autoupdate on
# The state and the last runs
squorli autoupdate
squorli autoupdate off
# Only looks: exit code 10 when there is a newer version, 0 when not
squorli update -CheckRead this before you switch it on. An update restarts the app server whenever a new version appears; whoever is writing or talking at that moment is cut off briefly. With 24 hours the task runs once a day at 04:17, which is the calm choice. A version that asks for work by hand before the update is not installed automatically: the job notes it in its log and waits for your squorli update. If a new version does not start, the previous program files come back; what happened is in C:\ProgramData\Squorli\logs\autoupdate.log.
The commands arrive with the first version after 0.6.0: if your squorli does not know autoupdate yet, run squorli update once.
With a web server that is there already
On many Windows Servers IIS already holds ports 80 and 443. The setup notices, names the program and suggests “A reverse proxy on this machine”: the app server and LiveKit then listen on 127.0.0.1 only, and your web server forwards to them. Templates for nginx, Caddy and IIS (URL Rewrite and Application Request Routing) are in C:\Program Files\Squorli\proxies after the installation; the one for IIS has not been checked against a real installation yet. What the proxy has to do is described under Use an existing reverse proxy.
By hand with Docker Compose
The installer for Linux only carries out the following steps. If you want to keep each of them in your own hands, install manually like this – in any folder, with Docker Engine, the Compose plugin, curl and OpenSSL. What the server needs is listed under Linux server.
Download the configuration
mkdir -p squorli/deploy/caddy squorli/deploy/livekit squorli/deploy/proxies
cd squorli
curl -fL https://raw.githubusercontent.com/danielklessa/squorli/main/.env.example -o .env
curl -fL https://raw.githubusercontent.com/danielklessa/squorli/main/deploy/compose.yml -o deploy/compose.yml
curl -fL https://raw.githubusercontent.com/danielklessa/squorli/main/deploy/caddy/Caddyfile -o deploy/caddy/Caddyfile
curl -fL https://raw.githubusercontent.com/danielklessa/squorli/main/deploy/livekit/livekit.yaml -o deploy/livekit/livekit.yaml
curl -fL https://raw.githubusercontent.com/danielklessa/squorli/main/deploy/proxies/nginx.ports.yml -o deploy/proxies/nginx.ports.ymlThese commands download five configuration files into a new squorli folder, no source code: the application and the web client come from the published container image. You only need the nginx overlay for the home setup or your own reverse proxy. Run the download once in a new directory – downloading again would overwrite the .env you filled in. Squorli Server is licensed under the Apache License 2.0; see LICENSE and NOTICE in the repository.
Fill in the .env file
Open .env in the squorli folder with a text editor and replace the hostname and the secrets. The file holds passwords: keep it private.
PUBLIC_DOMAIN=chat.example.org
SERVER_NAME=My community
APP_IMAGE=ghcr.io/danielklessa/squorli-server:latest
PROXY_MODE=bundled
POSTGRES_PASSWORD=REPLACE_WITH_RANDOM_HEX
LIVEKIT_API_KEY=squorli
LIVEKIT_API_SECRET=REPLACE_WITH_ANOTHER_RANDOM_HEX
DIRECTORY_URL=https://directory.squorli.com
LIVEKIT_NODE_IP=
# Optional: reserve initial ownership for your public key
# OWNER_PUBLIC_KEY=YOUR_64_CHARACTER_HEX_PUBLIC_KEYGenerate a separate random value for each secret. A hex value also avoids reserved characters in the database URL.
openssl rand -hex 32| Value | Meaning |
|---|---|
PUBLIC_DOMAIN | Exactly the hostname browsers use – no scheme, no path. Sign-in signatures are bound to it. |
APP_IMAGE | The published image ghcr.io/danielklessa/squorli-server:latest. Available tags and digests are listed on the GitHub container package; pin a tag or digest for production. |
PROXY_MODE | bundled for the included Caddy. The value must match the Compose profile; the template says external, so change it explicitly. |
POSTGRES_PASSWORDLIVEKIT_API_SECRET | One separate random value each, from the command above. The LiveKit secret needs at least 32 characters; never reuse a development secret. |
DIRECTORY_URL | https://directory.squorli.com is the default and gives your members a global account. Leaving it empty means the server works on its own and every account is a server account (~name and password, usable on any device). |
LOCAL_ACCOUNTS | Server accounts (~name) next to Squorli accounts: true or false fixes it, empty means Administration decides (off by default). Always on without a directory. |
LIVEKIT_NODE_IP | Leave it empty – LiveKit detects its public address itself. With NAT or several network interfaces, enter the host's public IP. |
OWNER_PUBLIC_KEY | The public key of your Squorli account (64 hex characters), so that only you become the owner; see First login. |
OWNER_SETUP_CODE | Instead or as well: a secret code (for example from openssl rand -hex 12). Whoever enters it while registering a server account becomes the owner, as long as there is none. |
Every other variable is documented in the environment template, among them SERVER_NAME (the initial name, changeable later in Administration), MAX_UPLOAD_MB (attachment limit, 25 by default), LINK_PREVIEWS (previews for linked pages, on by default; false turns them and the server's outgoing requests off) and LOG_REQUESTS (one log line per request with the IP address, for troubleshooting only; off by default).
Start and check
cd deploy
docker compose --env-file ../.env --profile bundled pull
docker compose --env-file ../.env --profile bundled up -d --no-build
docker compose --env-file ../.env --profile bundled ps
docker compose --env-file ../.env --profile bundled logs --tail=100 serverAlways pass --env-file ../.env: without it the database password and the LiveKit keys stay empty. pull fetches the published image and --no-build keeps Compose from building locally. Database migrations run automatically when the app starts.
Caddy now requests a certificate for your domain, which needs correct DNS and open inbound ports. Then check two addresses:
curl -fsS https://chat.example.org/api/health
curl -s -o /dev/null -w '%{http_code}\n' https://chat.example.org/rtc/validateThe health response names ok: true, your domain and a serverKey. HTTP 401 from /rtc/validate is correct without a token and shows that the request reaches LiveKit. It does not yet prove that media flows – the first voice channel does.
Back up, update, restore
Back up and update from squorli/deploy with these commands – with your actual profile and overlays, without git pull and without downloading your .env again:
# Run from deploy; write a logical database backup to a private location
docker compose --env-file ../.env --profile bundled exec -T postgres pg_dump -U chat -d chat > squorli-database.sql
# Attachments and link preview pictures out of the volume of the project squorli
docker run --rm -v squorli_appdata:/data:ro -v "$PWD":/backup alpine tar czf /backup/squorli-files.tar.gz -C /data .For a consistent snapshot, pause writes during the backup. The SQL dump contains server data, but neither attachments nor .env.
# Run from squorli/deploy after reviewing the update and backing up
docker compose --env-file ../.env --profile bundled pull
docker compose --env-file ../.env --profile bundled up -d --no-build
docker compose --env-file ../.env --profile bundled logs --tail=100 serverRestoring, in the folder with the two backup files:
# Run from deploy with your profile and overlays; replaces the database and all files
docker compose --env-file ../.env --profile bundled stop server
docker compose --env-file ../.env --profile bundled exec -T postgres psql -U chat -d postgres -c 'DROP DATABASE chat WITH (FORCE)' -c 'CREATE DATABASE chat OWNER chat'
docker compose --env-file ../.env --profile bundled exec -T postgres psql -q -v ON_ERROR_STOP=1 -U chat -d chat < squorli-database.sql
docker run --rm -i -v squorli_appdata:/data alpine sh -c 'find /data -mindepth 1 -delete && tar xzf - -C /data' < squorli-files.tar.gz
docker compose --env-file ../.env --profile bundled up -d --no-buildRecord the image version: latest is mutable, and migrations run at startup – rolling the image back does not undo a database change. Avoid docker compose down -v on a production server: it deletes the volumes with all their data.
Try it at home
To get to know Squorli you need neither a domain nor a certificate: the server runs on your own computer and you open it at http://localhost:3000. Because browsers treat localhost as a secure context, microphone, camera and screen sharing work there too.
On Windows it also works without Docker: install the package for Windows and answer the question about the domain with localhost. The setup then suggests a reverse proxy on this machine and points LiveKit at localhost; no proxy is needed for the test. Afterwards open the address the setup names at its end – usually http://localhost:3000 – and read on below where the server account is created.
With Docker you need Docker Desktop on Windows, on Linux Docker Engine with the Compose plugin. This home setup is done by hand, not with the installer.
Fetch the configuration – on Linux with the download command of the manual installation, on Windows with this block in a PowerShell:
mkdir squorli\deploy\caddy, squorli\deploy\livekit, squorli\deploy\proxies
cd squorli
$b = "https://raw.githubusercontent.com/danielklessa/squorli/main"
curl.exe -fL $b/.env.example -o .env
curl.exe -fL $b/deploy/compose.yml -o deploy\compose.yml
curl.exe -fL $b/deploy/caddy/Caddyfile -o deploy\caddy\Caddyfile
curl.exe -fL $b/deploy/livekit/livekit.yaml -o deploy\livekit\livekit.yaml
curl.exe -fL $b/deploy/proxies/nginx.ports.yml -o deploy\proxies\nginx.ports.ymlThen fill in .env like this – the content is the same on both systems:
PUBLIC_DOMAIN=localhost
SERVER_NAME=Test
APP_IMAGE=ghcr.io/danielklessa/squorli-server:latest
PROXY_MODE=external
POSTGRES_PASSWORD=REPLACE_WITH_RANDOM_HEX
LIVEKIT_API_KEY=squorli
LIVEKIT_API_SECRET=REPLACE_WITH_ANOTHER_RANDOM_HEX
# Local test only: the browser reaches LiveKit directly, LiveKit offers itself as 127.0.0.1
LIVEKIT_PUBLIC_URL=ws://localhost:7880
LIVEKIT_NODE_IP=127.0.0.1
# A server on localhost cannot prove its host to the Directory: sign in with a server account (~name)
DIRECTORY_URL=Generate the random values with openssl rand -hex 32 on Linux, or with the first line of the following block on Windows. notepad .env opens the file; the last line checks the running server:
# One random value per secret
-join (1..32 | ForEach-Object { '{0:x2}' -f (Get-Random -Maximum 256) })
notepad .env
# After the start: the server answers on localhost
curl.exe -fsS http://localhost:3000/api/healthBoth systems start it with the same command. The overlay nginx.ports.yml publishes the app and LiveKit on 127.0.0.1 only, so nothing is open to the outside:
cd deploy
docker compose --env-file ../.env -f compose.yml -f proxies/nginx.ports.yml --profile external pull
docker compose --env-file ../.env -f compose.yml -f proxies/nginx.ports.yml --profile external up -d --no-buildOpen http://localhost:3000 and create a server account (~name and password); the first sign-in with an account becomes the owner; a second browser window – ideally a private window or a second profile – is your second member. To let it in without an invitation, switch on open joining under Server in Administration. Text, voice channels, camera and screen sharing work fully between those windows.
The local test has two limits. A second device on your home network cannot take part, because it does not reach localhost and browsers release no microphone over a plain HTTP address. And a Directory account does not work here: the Directory verifies control over the domain by fetching /api/health – with localhost it ends up at itself. So sign in with a server account while testing. To clean up with Docker:
# From squorli/deploy: stops the test and deletes its database and files
docker compose --env-file ../.env -f compose.yml -f proxies/nginx.ports.yml --profile external down -vFrom the test to a real home server: as soon as friends should join, you need a domain – a free dynamic DNS name will do – and port forwardings in your router for 80/tcp, 443/tcp, 7881/tcp and 7882/udp to the machine that carries the server. Then install on a Linux machine or a Windows machine and choose the bundled Caddy: it obtains the certificate and Squorli runs exactly as it would on a rented server. If your line sits behind carrier-grade NAT (no public IPv4 address of your own), port forwarding cannot work – then only a server with a public address will do.
First login
- Open
https://chat.example.orgin a current browser. - Sign in with your Squorli account (
@name). Without a directory, create a server account (~nameand password) under “Create an account”. - The first sign-in with an account becomes the owner, or – with a setup code – whoever enters the code from the installation in the “Setup code” field while creating the server account. There is no access with a bare browser key any more.
- From then on the server is closed: further members need an invite link. With a directory, Administration > Server decides whether server accounts are allowed next to Squorli accounts.
Reserve the first login. Unless you set it, the first person to sign in with an account becomes the owner of the server; without a directory, whoever creates the first server account. There are two ways to set it: the public key of your Squorli account (OWNER_PUBLIC_KEY, the client shows it under Settings > Account), or a setup code (OWNER_SETUP_CODE): whoever enters that code while registering a server account becomes the owner – even where server accounts are otherwise off. Without either, sign in yourself right after the installation, before you hand the address around. Changing it later does not bring lost ownership back.
Everything else – server name and icon, categories and channels, roles, invitations, moderation, web radio and the status API – happens in Administration. The administrator guide explains it with pictures of the real interface. What your members meet day to day is in the member guide.
A global account: Squorli Directory
With DIRECTORY_URL=https://directory.squorli.com – the setup's suggestion – your members sign in with one account that works on every connected server. They get a handle such as @name, a password-encrypted backup of their key, authenticator and recovery codes, their profile picture, synchronized settings, and friends and direct messages across servers. Without an account the key lives in exactly one browser: lose it and the access is gone.
The server registers itself with a key of its own. The Directory fetches your public /api/health endpoint and compares the server key – that way only whoever runs a domain can claim it. The hostname must match PUBLIC_DOMAIN; you only need DIRECTORY_PROOF_URL when the health endpoint lives at a different address. To switch the Directory on or off later, run the installer or the setup again and choose “Change settings”; after a manual installation, recreate the app container with the same Compose command after the change.
Registration does not publish your server: public listing, description and open joining are separate switches in Administration. Direct messages between friends are end-to-end encrypted; that is not a claim about channel messages, attachments, voice or video. If the Directory is unavailable, conversations on your server continue; Directory features and new key retrievals do not.
Use an existing reverse proxy
If the machine already runs a web server or reverse proxy (nginx, Apache, Plesk, IIS), choose “A reverse proxy on this machine” during setup: the bundled Caddy stays off, and the app and LiveKit listen on 127.0.0.1 only. If the proxy sits on another machine, such as a Nginx Proxy Manager, choose the third option and give this server's LAN or VPN address and the proxy's IP.
In the proxy, forward /rtc* to port 7880 and everything else to port 3000; both routes need WebSocket upgrades. The setup names exactly these targets at the end, also when you chose other ports. Media ports 7881/tcp and 7882/udp still go straight to the chat server. After a manual installation, set PROXY_MODE=external and start with the external profile and the matching overlay:
# Run from the deploy directory
docker compose --env-file ../.env -f compose.yml -f proxies/nginx.ports.yml --profile external pull
docker compose --env-file ../.env -f compose.yml -f proxies/nginx.ports.yml --profile external up -d --no-buildThe guide for existing reverse proxies covers nginx, Nginx Proxy Manager, Plesk and Traefik including trusted proxies, firewall rules and verification steps. Sub-path hosting is not supported.
Troubleshooting
The first stop is squorli doctor on the server or Verwaltung › Server › “Check the connection” in the client: both name the likely cause.
| Symptom | Check |
|---|---|
The setup reports that https://… does not answer yet | The domain's DNS record must point at the server, and 80/tcp and 443/tcp must be reachable from outside – in a firewall at your hosting provider or in the router too. Caddy keeps trying; squorli logs caddy shows what it is stuck on. |
| The setup reports ports 80 or 443 in use | A web server already runs on the machine. Choose “A reverse proxy on this machine” (Use an existing reverse proxy); your web server then forwards to Squorli. Other ports in use the setup replaces by free ones itself. |
| Sign-in fails with 401 | PUBLIC_DOMAIN must match the hostname in the browser. Signatures are bound to it. |
| Voice connects, but no audio arrives | Check 7881/tcp and 7882/udp and the host's public IP (LIVEKIT_NODE_IP), plus microphone permissions and audio playback in the browser. |
| No audio in the home setup with Docker | A local test needs LIVEKIT_PUBLIC_URL=ws://localhost:7880 and LIVEKIT_NODE_IP=127.0.0.1, otherwise LiveKit announces an address from the Docker network. |
| The WebSocket connection fails | Check upgrade forwarding for /api/ws and /rtc. |
| Directory registration fails | The public health endpoint must be reachable by the Directory over HTTPS and return the matching server key and hostname. |
| The database password stays empty (manual installation) | --env-file ../.env is missing from the Compose command. |
Windows does not find the command squorli | The entry in the PATH applies to newly opened windows only. Open a new window as administrator. |
| A service does not start on Windows | squorli status shows the services, squorli logs server (or postgres, livekit, caddy) the last lines. The log of the setup is in C:\ProgramData\Squorli\logs. |
| A guest cannot write or share video | Assign the member role in Administration. Guest permissions are intentionally limited. |
| Joining from a restrictive network fails | TURN is off by default. Enabling it needs your own certificate, LiveKit configuration and 5349/tcp. TURN acceptance is still pending. |
Development status: video and screen sharing are implemented and have been tested with real webcams and screen shares. Tests in restrictive networks and with TURN are not finished. Do not treat this guide as a production reliability guarantee.
Alternative: build from source
Only people who want to compile their own changes or use an ARM machine need Git and a source checkout. Configure its .env before starting, leave APP_IMAGE empty and use this command. For an external proxy, the matching profile and your overlays apply again.
# Optional source build in a separate checkout
git clone https://github.com/danielklessa/squorli.git squorli-source
cd squorli-source
cp .env.example .env
# Configure .env, set PROXY_MODE=bundled and leave APP_IMAGE unset
cd deploy
docker compose --env-file ../.env --profile bundled up -d --buildBased on the checked-in server configuration of 28 September 2026. The installer for Linux was run through in a test environment on 23 September 2026 (fresh installation, update, switching the HTTPS setup), and the home setup was verified with the published image; the package for Windows ran on Windows 11 on 28 September 2026 from the installation to the removal. The server README and the environment template in the repository are the source of truth.