Self-hosting
Your Sridu, on your terms
Sridu is one folder of plain HTML, CSS and JavaScript. There is no build step, no dependency and no account. Play it on play.sridu.com, run it from a folder on your laptop, or host it with Docker for your whole house or your club. This page walks you through every way, step by step.
Choose your way
Four ways to run it
The app is the same everywhere. Each way adds a little more: https for every device, one data folder, your own lobby. Not sure? Start with the first one; you can move on any time.
- No setupJust playOpen play.sridu.com in Chrome or Edge. After the first visit it works offline too.Good for: trying it out
- 5 minutesPlay from the filesDownload the ZIP, start a small web server with one command, done. Or put the folder on any web space.Needs: Python, Node or PHP
- 15 minutesDocker at homehttps for every device in the house, one data folder for all players, an admin page and your own broker.Needs: Docker on a PC, NAS or Raspberry Pi
- One eveningYour own domainA hardened setup for your club or your friends, made for a NAS behind Cloudflare Tunnel.Needs: Docker, a domain, Cloudflare
Download
Get the files
One ZIP holds the complete app and everything for Docker: the compose files, the example settings and the setup for a public domain.
index.html,css/,js/,locales/The app itself. That is all you need for playing from the files.docker-compose.ymland.env.exampleDocker at home, and its settings.deploy/public/The hardened setup for your own domain.deploy/relay/A relay for online matches, as a project of its own.README.mdThis guide, for reading offline.
Already playing? In the app, Self-host it below the game selection packs the running app into a ZIP, right in your browser. That copy holds the app files only: enough for playing from the files, not for Docker.
Way 2 · Files
Play straight from the folder
Nothing to install, no Docker. Ideal for one PC with the cameras plugged in.
Why not just double-click index.html? The browser then opens it as file://. There it blocks the app’s modules and never hands out cameras. You need a small web server, and that is one command.
1 · Unzip
Unzip the download into a folder, for example sridu in your documents.
2 · Open a terminal in that folder
- Windows: open the folder in Explorer, click into the address bar, type
cmdand press Enter. - macOS: right-click the folder in Finder, then Services → New Terminal at Folder.
- Linux: open a terminal and
cdinto the folder.
3 · Start a web server
Use whatever is already on your computer. Python comes with macOS and Linux; on Windows get it from python.org.
# Python 3
python3 -m http.server 8080
# or Node.js
npx serve -l 8080
# or PHP
php -S localhost:8080
4 · Play
Open http://localhost:8080 in Chrome or Edge. Allow the cameras, then go to Cameras → Set up automatically. No cameras yet? Start page → Demo plays with three simulated ones.
Stop the server with Ctrl+C. What you play is stored in this browser, not in the folder, so it is still there the next time you start the server on the same port.
Put it on a web space
Because Sridu is only static files, any host works. The one rule: index.html has to sit in the root of the site, and the site has to be served over https.
- Cloudflare Pages or Netlify: create a project and drag the unzipped folder into the upload box. Free, with https.
- GitHub Pages: push the folder to a repository, then Settings → Pages → deploy from the branch.
- Your own web space or NAS web station: copy the folder into the web folder by FTP or file share.
- Plain Docker, nothing extra: one nginx container serves the folder.
docker run -d -p 8080:80 -v "$PWD":/usr/share/nginx/html:ro nginx:alpine
Phones, tablets and a second board
Another device reaches your computer by its IP address, and there the browser refuses cameras and the encryption that sessions need. Only localhost and https:// are allowed. So as soon as more than one device is involved, use a web space with https, or Docker at home, which brings https along.
Way 3 · Docker at home
One command for the whole house
Runs on anything with Docker: a Windows PC or Mac with Docker Desktop, a Linux box, a Raspberry Pi 4 or 5, a Synology or QNAP NAS. Every device at home gets https, all players share one data folder, and you get an admin page and your own broker for online play.
1 · Get Docker
- Windows and macOS: install Docker Desktop and start it once.
- Linux and Raspberry Pi: Docker Engine with the compose plugin.
- Synology: Container Manager from the Package Center. The commands below run over SSH, or use Container Manager → Project → Create with the folder of the ZIP.
2 · Tell Sridu its address
Unzip the download, open a terminal in the folder and copy the example settings:
cp .env.example .env
# on Windows (cmd):
copy .env.example .env
Open .env in any text editor and put the IP address of this machine into SRIDU_HOSTS, plus a name if it has one. They go into the certificate that every other device needs:
SRIDU_HOSTS=192.168.1.20,darts.local
Do this before the first start. The certificate is made once and then kept, so the browser exception you confirm survives every update. Everything else in the file can wait; it is all explained below.
3 · Start it
docker compose up -d --build
The first start builds the images and takes a minute or two. After that, three small containers run: the app (nginx), the admin service and the broker for online play. A fourth, the relay, only starts if you ask for it.
4 · Open it
- On this machine: http://localhost:8090
- On every other device: https://192.168.1.20:8443. The browser warns once about the self-signed certificate: Advanced → Proceed.
- Admin page: http://<this machine>:8090/admin/, see below.
Want no warning at all? Put a reverse proxy such as Caddy, Traefik or Nginx Proxy Manager in front of port 8090. It gets a certificate browsers trust, and then Sridu can also be installed as an app on every device.
5 · Everyday commands
# what is going on
docker compose logs -f
# stop
docker compose down
# start again, or after an update
docker compose up -d --build
Updating: unzip the new download over the old folder. Keep .env and the data/ folder, then run the last command. With git: git pull && docker compose up -d --build.
Admin page
Settings without a text editor
Most settings from .env can also be changed on the admin page while Sridu runs, and what you set there wins. The page only answers from your home network.
- Open ithttp://<this machine>:8090/admin/ from any device at home.
- Enter the setup codeThe first visit asks for a code. The container prints it to its log:
docker compose logs api - Choose a passwordAt least 12 characters. Forgot it?
docker compose exec api node server.mjs resetprints a new setup code and ends every admin session.
- OnlineStart language, the lobby and where your players meet, relay servers, and whether darts may be corrected in the challenges and mini games.
- LeaderboardOn or off, strict mode, how long results are kept, the players and who is blocked.
- LegalImprint and privacy policy, with templates to start from. As soon as there is text, the app links to them.
- ModerationReports from the lobby, blocked devices and the word filter.
- AccountChange your password.
The admin page keeps its settings, texts and reports in the Docker volume sridu-state, never in the code.
Your data
One folder for every device
With Docker at home, the player data of every browser that uses your server is kept in one plain folder: data/, next to docker-compose.yml.
- What is in it:
players.jsonwith every game including the dart positions, the players and their challenge progress. - Synchronised by itself: at the start, after every game and once a minute. Games are recognised by their start time, so two devices never overwrite each other.
- What stays on the device: camera assignment, calibration, sound and display settings. They belong to that board, not to the player.
- Backup: copy
data/. Moving house: copy the whole folder includingdata/to the new machine and start it again. - No login: the folder is meant for your home network. The setup for a public domain switches it off, and every player keeps their data in their own browser.
- Without Docker there is no such folder. The app notices and simply keeps everything in the browser. Statistics → export gives you a JSON file whenever you want one.
Way 4 · Your own domain
A Sridu for your club
deploy/public/ is the same app, hardened for the internet. It is made for a NAS behind Cloudflare Tunnel, so no port has to be opened on the router for the app itself.
What is different from home
- Only your domain and addresses in your home network get an answer, anything else gets none
- https comes from Cloudflare, and browsers are told to use nothing else (HSTS)
- No player data on the server: it stays in every player’s browser
- Only your own broker for online play, so nothing goes to third parties
- Your own moderated lobby: word filter, blocked devices, reports
- A leaderboard that counts only darts the cameras saw
- Security headers, rate limits, unprivileged read-only containers with memory and CPU limits
Set it up
- Copy the files to the NASFor example to
/volume1/docker/sridu. - SettingsIn
deploy/public/, copy.env.exampleto.envand set at leastSRIDU_DOMAIN, for exampledarts-club.org,www.darts-club.org. - Start
docker compose up -d --buildindeploy/public/. Or Synology Container Manager → Project → Create, with that folder as the path. - Cloudflare TunnelZero Trust → Networks → Tunnels → your tunnel → Public hostnames: your domain → HTTP →
<NAS-IP>:8090, and the same for www. Or let the project run the tunnel: put its token intoCLOUDFLARE_TUNNEL_TOKEN, start with--profile tunneland usehttp://web:8080as the service. - Admin page and legal textsFrom home, open http://<NAS-IP>:8090/admin/, choose a password and fill in the imprint and privacy policy under Legal. The templates are a starting point, not legal advice.
- CheckYour domain opens the app. /admin/ answers 404 from outside. Any other name that points at the tunnel gets no answer.
Recommended Cloudflare settings
- SSL/TLS: Always Use HTTPS on, minimum TLS 1.2.
- Network: WebSockets on (the default). The lobby and online matches need them.
- Security: Bot Fight Mode on, and a rate limit on paths starting with
/api/: block above 60 requests per 10 seconds per IP. - Admin from outside: only with
SRIDU_ADMIN_REMOTE=onand a Cloudflare Access application in front of /admin. - Router and NAS firewall: no port forwarding for the app, and allow
SRIDU_PORTonly from your local network.
Optional · Relay
When online matches won’t connect
Online matches connect the two boards directly. Mobile data, strict routers and many company or school networks don’t allow that, and then a relay (TURN) forwards the encrypted traffic. The app tells you whether you need one: Online connection → Test connection.
a) Your own relay
Part of both Docker setups. It speaks UDP, so it does not go through Cloudflare Tunnel: this is the one part that needs port forwarding, and players see the IP of your internet connection.
- SettingsIn
.env:SRIDU_TURN_HOST(a name pointing directly at your connection: a DNS-only record or a DDNS name such as yourname.synology.me),SRIDU_TURN_IP(your public IP) andSRIDU_TURN_PASS(letters and digits). - RouterForward UDP 3478, UDP 31000–31040 and TCP 3478 to this machine, and allow them in its firewall.
- Start with the profile
docker compose --profile relay up -d --build - CheckFrom a phone on mobile data: Online connection → Test connection should report the relay as working.
Safe by design: the relay login is readable by every visitor, because the browser needs it. So the relay never connects to private addresses, relays UDP only, allows few relays per user and caps the bandwidth. A board in the same network as the relay needs one exception: SRIDU_TURN_ALLOW with its LAN IP.
b) A hosted TURN service
No ports to open: put its addresses into SRIDU_TURN_URLS and its login into SRIDU_TURN_USER and SRIDU_TURN_PASS, and start without the relay profile. Playing from plain files? Enter the relay in the app’s online settings instead.
c) Only the relay
deploy/relay/ runs the relay as a project of its own, for example next to a copy on a web space. Enter it on the admin page with the user and password from that file.
Reference
Every setting explained
All settings live in .env: next to docker-compose.yml at home, in deploy/public/ for a domain. After a change, run docker compose up -d again. Settings marked Admin page can also be changed there while Sridu runs, and the admin page wins.
Basics
| Setting | Default | What it does |
|---|---|---|
SRIDU_HTTP_PORT | 8090 | Port for plain http on this machine. Change it if 8090 is taken. Home only |
SRIDU_HTTPS_PORT | 8443 | Port for https, the one every other device at home uses. Home only |
SRIDU_HOSTS | empty | IP addresses and names of this machine for the self-signed certificate, comma separated, no spaces. Empty means localhost only. Only read at the very first start. Home only |
SRIDU_LANG | auto | Language everyone starts in: auto (the browser’s language) or one of en de nl fr es it pt-BR pl hr. Every player can still switch in the app. Admin page |
Your own domain
| Setting | Default | What it does |
|---|---|---|
SRIDU_DOMAIN | required | The public names, comma separated. Only these and addresses in your home network get an answer. Public only |
SRIDU_PORT | 8090 | Port on the NAS for Cloudflare Tunnel and your home network. Never forward it on the router. Public only |
SRIDU_LOCAL_NAMES | empty | Further names the NAS has at home, e.g. nas.fritz.box. Plain IPs, nas and *.local always work. Public only |
SRIDU_INDEX | on | Search engines may list the site. AI crawlers are always refused. Public only |
SRIDU_ADMIN_REMOTE | off | The admin page from the internet as well. Only with Cloudflare Access or another login in front of it. Public only |
CLOUDFLARE_TUNNEL_TOKEN | empty | Token of your tunnel, for --profile tunnel. Public only |
Online play and lobby
| Setting | Default | What it does |
|---|---|---|
SRIDU_BROKER | on | Your own signaling broker at /mqtt. Devices on your server find each other even when the public brokers are down or blocked. Home only |
SRIDU_PUBLIC_BROKERS | on · public: off | Also use the free public brokers. off keeps everything on your server and sends nothing to third parties. |
SRIDU_LOBBY | on | The lobby: open chat, a feed of matches and finishes, finding opponents. Admin page |
SRIDU_LOBBY_MODE | local | Where your players meet. local: the lobby of this server, only people on it. online: the Sridu online lobby at play.sridu.com, where names, messages and averages are visible to everybody there. mesh: serverless, every app talks to every other one, fine for a club. Admin page |
SRIDU_LOBBY_ROOMS | one | one room for everybody, or lang for one room per language. Admin page |
SRIDU_LOBBY_ONLINE_URL | play.sridu.com | Another online lobby than wss://play.sridu.com/lobby. |
SRIDU_LOBBY_GUESTS | off | Apps of other installations (those set to online) may join your lobby. Public only |
SRIDU_LOBBY_MAX | 2000 | Players in the lobby at once. About 70 KB of memory each. Public only |
SRIDU_LOBBY_PER_IP | 10 | Connections per internet address. A family or a club shares one. Public only |
SRIDU_CHAT_HISTORY | 50 | Chat lines a newcomer sees. The chat is kept in memory only. Public only |
Fair play and leaderboard
| Setting | Default | What it does |
|---|---|---|
SRIDU_CORRECT_CHALLENGES | on | Players may correct darts in the hourly challenges: tap a dart, undo, add one. off: what the cameras saw counts. Typing darts in stays possible where no camera is set up. Admin page |
SRIDU_CORRECT_MINIS | on | The same for the mini games. Admin page |
SRIDU_BOARD | on | Shared leaderboard of the hourly challenges for everybody who plays on this server, under names they choose. Admin page |
SRIDU_BOARD_STRICT | off · public: on | Only results where every dart came from the cameras: no corrections, nothing typed in, no demo. At home anything may count; a public server wants this on. Admin page |
SRIDU_BOARD_DAYS | 90 | How many days results are kept. At least 35. Admin page |
Relay (TURN)
| Setting | Default | What it does |
|---|---|---|
SRIDU_TURN_HOST | empty | Public name or IP players reach the relay by. The relay is offered to the app as soon as this and the password are set. |
SRIDU_TURN_IP | empty | Your public IP, if the host above is a name. A changing IP: update it and start again. |
SRIDU_TURN_PORT | 3478 | Port of the relay, UDP and TCP. |
SRIDU_TURN_USER | sridu | User name of the relay login. |
SRIDU_TURN_PASS | empty | Any password, letters and digits. Readable by every visitor; it only keeps strangers’ apps out. |
SRIDU_TURN_ALLOW | nobody | LAN IP of a board in the same network as the relay, the one private address it may reach. |
SRIDU_TURN_URLS | empty | A hosted TURN service instead, comma separated, e.g. turn:relay.example.org:3478. User and password above are then its login. |
SRIDU_TURN_MIN_PORT / MAX_PORT | 31000 / 31040 | Range of relay ports, one per relayed connection. Change it together with the port forwarding. Public only |
SRIDU_TURN_QUOTA | 40 | Most relayed connections at a time. Public only |
Compare
What each setup adds
The app is the same everywhere. What a server adds is what one browser can’t do alone.
| Static files (any web space) | Docker at home | Docker on your domain | |
|---|---|---|---|
| Cameras, all 26 modes, bots, statistics | Yes | Yes | Yes |
| Works offline, installs as an app | Yes | Yes, with a trusted certificate | Yes |
| Online matches, boardcam, tournaments | Yes, over public brokers | Yes, plus your own broker | Yes, your own broker only |
| Lobby and chat | Serverless lobby | Your own lobby | Your own lobby, moderated |
| Relay for strict networks | Enter one in the settings | Optional, built in | Optional, built in |
| Leaderboard | This device | Online top 100, results checked | Online top 100, camera only |
| Admin page | No | Yes, from your home network | Yes, from your home network |
| One data folder for every device | No, each browser keeps its own | Yes | No, each player keeps their own |
| Imprint and privacy page | No | Yes | Yes |
| Start language for everyone | From the browser | Yes | Yes |
Help
When something doesn’t work
The app never asks for the cameras
Browsers only hand out cameras on https:// or on localhost. Opened as a file, or over http with an IP address, the request never appears. Use http://localhost on the machine itself, and https://…:8443 from every other device.
The browser warns about the certificate
That is expected with Docker at home: the certificate is self-signed. Confirm it once per device (Advanced → Proceed). For no warning at all, put a reverse proxy with a real certificate in front.
I changed SRIDU_HOSTS, but the warning names the old address
The certificate is only made at the very first start. Remove it and start again: docker compose down, then docker volume rm sridu_sridu-certs, then docker compose up -d. Every device has to confirm the new certificate once.
Port 8090 or 8443 is already taken
Set SRIDU_HTTP_PORT and SRIDU_HTTPS_PORT in .env to free ports and run docker compose up -d again.
An online match doesn’t connect
Open Online connection → Test connection on both devices. If a relay is needed, set one up as described under Relay, or ask your opponent to leave mobile data or a strict company network.
I forgot the admin password
Run docker compose exec api node server.mjs reset in the folder of the installation. It prints a new setup code, and every admin session ends.
Will an update delete my games?
No. Games live in the browser and, with Docker at home, in the data/ folder. Keep that folder and .env when you unzip a new version, and everything is still there.
What leaves your network
Nothing leaves on its own. The only outbound connections are the ones you start: the brokers that hand two devices each other’s address for a match, a relay if you set one up, and your system’s text-to-speech voices.
Licence
Sridu is free for yourself, your household and your guests, and for the members of a non-profit club. You can take it apart, change it and pass your changes on. It may not be used commercially, run as a service for the general public or used as training material for AI systems. That makes it source-available, not open source. For a tournament, a bigger event or a commercial idea, just ask.