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.

sridu-0.0.0.zip Version 0.0.0 · 0.8 MB · the complete app, Docker files included
Download coming soon
  • index.html, css/, js/, locales/ The app itself. That is all you need for playing from the files.
  • docker-compose.yml and .env.example Docker 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.md This 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 cmd and press Enter.
  • macOS: right-click the folder in Finder, then Services → New Terminal at Folder.
  • Linux: open a terminal and cd into 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.

  1. Open ithttp://<this machine>:8090/admin/ from any device at home.
  2. Enter the setup codeThe first visit asks for a code. The container prints it to its log: docker compose logs api
  3. Choose a passwordAt least 12 characters. Forgot it? docker compose exec api node server.mjs reset prints 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.json with 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 including data/ 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

  1. Copy the files to the NASFor example to /volume1/docker/sridu.
  2. SettingsIn deploy/public/, copy .env.example to .env and set at least SRIDU_DOMAIN, for example darts-club.org,www.darts-club.org.
  3. Startdocker compose up -d --build in deploy/public/. Or Synology Container Manager → Project → Create, with that folder as the path.
  4. 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 into CLOUDFLARE_TUNNEL_TOKEN, start with --profile tunnel and use http://web:8080 as the service.
  5. 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.
  6. 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=on and a Cloudflare Access application in front of /admin.
  • Router and NAS firewall: no port forwarding for the app, and allow SRIDU_PORT only 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.

  1. 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) and SRIDU_TURN_PASS (letters and digits).
  2. RouterForward UDP 3478, UDP 31000–31040 and TCP 3478 to this machine, and allow them in its firewall.
  3. Start with the profiledocker compose --profile relay up -d --build
  4. 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

SettingDefaultWhat it does
SRIDU_HTTP_PORT8090Port for plain http on this machine. Change it if 8090 is taken. Home only
SRIDU_HTTPS_PORT8443Port for https, the one every other device at home uses. Home only
SRIDU_HOSTSemptyIP 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_LANGautoLanguage 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

SettingDefaultWhat it does
SRIDU_DOMAINrequiredThe public names, comma separated. Only these and addresses in your home network get an answer. Public only
SRIDU_PORT8090Port on the NAS for Cloudflare Tunnel and your home network. Never forward it on the router. Public only
SRIDU_LOCAL_NAMESemptyFurther names the NAS has at home, e.g. nas.fritz.box. Plain IPs, nas and *.local always work. Public only
SRIDU_INDEXonSearch engines may list the site. AI crawlers are always refused. Public only
SRIDU_ADMIN_REMOTEoffThe admin page from the internet as well. Only with Cloudflare Access or another login in front of it. Public only
CLOUDFLARE_TUNNEL_TOKENemptyToken of your tunnel, for --profile tunnel. Public only

Online play and lobby

SettingDefaultWhat it does
SRIDU_BROKERonYour 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_BROKERSon · public: offAlso use the free public brokers. off keeps everything on your server and sends nothing to third parties.
SRIDU_LOBBYonThe lobby: open chat, a feed of matches and finishes, finding opponents. Admin page
SRIDU_LOBBY_MODElocalWhere 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_ROOMSoneone room for everybody, or lang for one room per language. Admin page
SRIDU_LOBBY_ONLINE_URLplay.sridu.comAnother online lobby than wss://play.sridu.com/lobby.
SRIDU_LOBBY_GUESTSoffApps of other installations (those set to online) may join your lobby. Public only
SRIDU_LOBBY_MAX2000Players in the lobby at once. About 70 KB of memory each. Public only
SRIDU_LOBBY_PER_IP10Connections per internet address. A family or a club shares one. Public only
SRIDU_CHAT_HISTORY50Chat lines a newcomer sees. The chat is kept in memory only. Public only

Fair play and leaderboard

SettingDefaultWhat it does
SRIDU_CORRECT_CHALLENGESonPlayers 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_MINISonThe same for the mini games. Admin page
SRIDU_BOARDonShared leaderboard of the hourly challenges for everybody who plays on this server, under names they choose. Admin page
SRIDU_BOARD_STRICToff · public: onOnly 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_DAYS90How many days results are kept. At least 35. Admin page

Relay (TURN)

SettingDefaultWhat it does
SRIDU_TURN_HOSTemptyPublic 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_IPemptyYour public IP, if the host above is a name. A changing IP: update it and start again.
SRIDU_TURN_PORT3478Port of the relay, UDP and TCP.
SRIDU_TURN_USERsriduUser name of the relay login.
SRIDU_TURN_PASSemptyAny password, letters and digits. Readable by every visitor; it only keeps strangers’ apps out.
SRIDU_TURN_ALLOWnobodyLAN IP of a board in the same network as the relay, the one private address it may reach.
SRIDU_TURN_URLSemptyA 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_PORT31000 / 31040Range of relay ports, one per relayed connection. Change it together with the port forwarding. Public only
SRIDU_TURN_QUOTA40Most 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 homeDocker on your domain
Cameras, all 26 modes, bots, statisticsYesYesYes
Works offline, installs as an appYesYes, with a trusted certificateYes
Online matches, boardcam, tournamentsYes, over public brokersYes, plus your own brokerYes, your own broker only
Lobby and chatServerless lobbyYour own lobbyYour own lobby, moderated
Relay for strict networksEnter one in the settingsOptional, built inOptional, built in
LeaderboardThis deviceOnline top 100, results checkedOnline top 100, camera only
Admin pageNoYes, from your home networkYes, from your home network
One data folder for every deviceNo, each browser keeps its ownYesNo, each player keeps their own
Imprint and privacy pageNoYesYes
Start language for everyoneFrom the browserYesYes

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.