Deploy VeScreen Server
English · 简体中文 · Documentation
VeScreen Server packages the web interface, room management and optional media forwarding in one server binary. Extract and run it; room data is stored in SQLite.
The default P2P configuration handles room management, signaling and STUN; shared video and audio travel between participants. Enabling SFU adds media-forwarding bandwidth and processing on the server. For a small server, start with the default and measure CPU, memory and network use with your intended number of rooms and viewers before enabling SFU. Lowering picture resolution primarily reduces participants' capture and encoding work.
Try it locally
These instructions support Linux x64 and ARM64.
Download the Server archive matching your machine from GitHub Releases or the Gitee mirror. Use uname -m to check the architecture:
| Architecture | Archive |
|---|---|
x86_64 (x64) | piik-<revision>-runtime.tar.gz |
aarch64 (ARM64) | piik-<revision>-linux-arm64-runtime.tar.gz |
Extract it and run the following in its directory:
./piik-serverOpen http://localhost:8787. This is a local trial; use the configuration below to let friends connect over the internet. To start a temporary room on your computer, use the VeScreen App guide.
Docker Compose
On a Linux x64 or ARM64 server with Docker Compose v2, copy the two deployment files from the VeScreen tree into an empty directory:
cp deploy/container/compose.yaml .
cp deploy/container/.env.example .envReplace share.example.com in .env with your domain, then start VeScreen:
docker compose run --rm piik --check-config
docker compose up -dThe ghcr.io/tntcrafthim/piik:latest image includes the Web UI, signaling, STUN and optional SFU. Docker selects the matching architecture automatically. Complete HTTPS and firewall configuration below. The default is P2P; the sample .env also shows how to enable SFU fallback. Keep the piik-data volume, which stores room data and optional diagnostics. See container maintenance for updates and backups.
Put it online
You need a Linux x64 or ARM64 server and a domain pointing to its public IP. The example uses share.example.com; replace it with your domain.
1. Configure and start VeScreen
Create a .env file next to the binary:
PIIK_ENV=production
LISTEN_HOST=127.0.0.1
PUBLIC_BASE_URL=https://share.example.com
STUN_URLS=stun:share.example.com:3478
MAX_VIEWERS_PER_ROOM=20
SITE_ACCESS_PASSWORD=Run these commands from that directory as a regular user:
./piik-server --check-config
./piik-serverThe server reads .env automatically and stores rooms in rooms.sqlite in the working directory. A blank SITE_ACCESS_PASSWORD allows entry without a site passphrase; enter a passphrase to require one. Room invitations and access settings still apply.
PUBLIC_BASE_URL must match the address opened in the browser, including HTTPS and any non-default port. Leave ALLOWED_ORIGINS unset or empty for this single address. An existing non-empty value overrides that default; a stale value can cause 403 when creating a room.
MAX_VIEWERS_PER_ROOM sets the room's Viewer limit, excluding the Host. Choose 1..20 and restart to apply it. More Viewers can require more network and relay resources. See room capacity for defaults and the difference from App rooms.
For a public site, optionally set ROOM_EMPTY_TIMEOUT_SECONDS=3600 and restart. Rooms with nobody connected are reclaimed after an hour; if all room codes are used, the oldest empty room can be reclaimed earlier. Occupied rooms keep working. Reclaimed rooms need new invitations. Unset or 0 keeps the default indefinite retention; see room retention.
2. Enable HTTPS
Use your existing HTTPS reverse proxy to forward to 127.0.0.1:8787 with WebSocket support. If you do not have one, install Caddy and add this to its Caddyfile:
share.example.com {
reverse_proxy 127.0.0.1:8787
}Reload Caddy. It obtains and renews the certificate automatically when DNS points to the server and TCP 80/443 are reachable. See Caddy's HTTPS proxy guide.
For nginx, see the configuration example. If you copied an older example, change its Permissions-Policy to camera=(self), microphone=(self), geolocation=() and reload nginx. Empty camera/microphone allowlists prevent Browser capture even when the user grants permission; self allows this site to request access.
3. Open the ports and verify
Allow TCP 80/443 for HTTPS and UDP 3478 for STUN in the server firewall and cloud security group. Keep TCP 8787 private. The STUN hostname must resolve directly to the server; a CDN HTTP proxy does not forward its UDP traffic. See the complete port table for optional services. Embedded SFU media shares the single UDP port set by SFU_UDP_PORT.
Open https://share.example.com/healthz; it should return {"status":"ok"}. Then open the site, share a screen and join from another device. This initial configuration uses P2P media, so participants need a usable UDP path.
Optional: media fallback
Add SFU_UDP_PORT=7882 to .env, allow UDP 7882, and restart VeScreen to enable automatic SFU fallback. When the server is behind NAT, also set SFU_PUBLIC_IP to its reachable public IPv4 address. The same binary provides the fallback. Allow server forwarding capacity and outbound bandwidth for Viewers actually using the SFU. The Host must turn off Privacy mode before sharing to allow this route. Both direct and SFU media need a usable UDP connection.
To send every room through your server, also set SFU_ONLY=true and restart. The sharing settings will show Server media. Plan server bandwidth for every Viewer; this mode does not fall back to P2P if the server route fails.
Keep it running and update
For automatic startup, use the systemd or container guide. Keep .env and rooms.sqlite across updates. Back up room data while the server is stopped, replace the executable with the new release, then restart and check health and room access. Read release notes before an upgrade that changes data formats.