Get NewTon DC Tournament Manager running in Docker in under 2 minutes.
Prerequisites: Docker and Docker Compose installed. Don't have Docker? Download Docker Desktop (macOS/Windows) or install via your package manager (Linux).
mkdir newton-tournament
cd newton-tournament
curl -O https://raw.githubusercontent.com/skrodahl/NewTon/main/docker/docker-compose.yml
docker compose up -d
Open http://localhost:8080 — NewTon is running.
Port 2020 = “Double 20” — nginx runs on port 2020 internally. The default host port (8080) maps to this.
Camera / QR scanning requires HTTPS. The quick start runs HTTP only. Pick one of the three setups below to enable camera access.
Image tag: All compose files below use
skrodahl/newton:latest(Docker Hub) with GHCR as a commented alternative.
SSL enabled by default — gives you HTTPS and camera access on any platform.
services:
newton-tournament:
image: skrodahl/newton:latest
# Alternative: ghcr.io/skrodahl/newton:latest
container_name: newton
ports:
- "2020:2020" # HTTP — redirects to HTTPS
- "443:443" # HTTPS
volumes:
- ./tournaments:/var/www/html/tournaments
- ./images:/var/www/html/images:ro
- newton-ssl:/etc/nginx/ssl # Persists the auto-generated certificate
restart: unless-stopped
environment:
- TZ=Europe/Oslo
- SSL_ENABLED=true # Auto-generates a self-signed cert (30-year, SAN)
- NEWTON_API_ENABLED=true # Set false to disable tournament upload/download
- NEWTON_DEMO_MODE=false # Set true to show a privacy banner
# - NEWTON_LANDING_PAGE=true # Show landing page at root URL
# - NEWTON_BASE_URL=https://darts.example.com
volumes:
newton-ssl:
Save as docker-compose.yml in a folder of your choice, then run docker compose up -d. That’s it.
Access at https://localhost. Your browser will warn about the self-signed certificate on first visit — accept the exception once and it will not appear again.
<hostname>.localPhones, tablets, and scoring stations on the same network can reach the container by name (e.g. https://newtondarts.local) once mDNS is set up on the host. macOS has Bonjour built in; Linux needs avahi-daemon; Windows needs Bonjour installed. See Docs/MDNS.md for full setup steps.
The container joins your proxy’s Docker network. SSL termination and HTTPS are handled by the proxy — no SSL_ENABLED needed.
services:
newton-tournament:
image: skrodahl/newton:latest
# Alternative: ghcr.io/skrodahl/newton:latest
container_name: newton
# ports:
# - "8080:2020" # Remove when using a reverse proxy
networks:
- proxy_network
volumes:
- ./tournaments:/var/www/html/tournaments
- ./images:/var/www/html/images:ro
restart: unless-stopped
environment:
- TZ=Europe/Oslo
- NEWTON_API_ENABLED=true
- NEWTON_DEMO_MODE=false
# - NEWTON_LANDING_PAGE=true
# - NEWTON_BASE_URL=https://darts.example.com
networks:
proxy_network:
external: true
Save as docker-compose.yml in a folder of your choice, then run docker compose up -d. That’s it.
In Nginx Proxy Manager, point the proxy host to newton:2020.
NPM sets its own Permissions-Policy header that overrides the container’s, blocking camera access in the Chalker. Add this to the Advanced tab of your NPM proxy host:
more_set_headers "Permissions-Policy: geolocation=(), microphone=(), camera=(self), payment=(), usb=(), magnetometer=(), gyroscope=(), accelerometer=(), ambient-light-sensor=()";
more_set_headers replaces the header rather than adding a duplicate. OpenResty (which NPM runs on) includes the headers-more module, so this directive is available without any additional setup.
environment:
- NEWTON_API_ENABLED=false # Disable upload API for security
- NEWTON_DEMO_MODE=true # Show privacy banner
- NEWTON_LANDING_PAGE=true # Show landing page at root
A read-only analytical surface — browse leaderboards, match history, and brackets. Tournament data comes from shared tournament files on disk. No tournament management tabs, no deletion. Accepts tournament uploads from venue instances via the relay API.
environment:
- NEWTON_API_ENABLED=true # Required for auto-import and bracket view
- NEWTON_MODE=analytics # Analytics-only mode
Mount the ./tournaments and ./images volumes. Configure the venue instance to auto-backup to this server’s relay API, or share the same tournaments directory. See Automatic Backup for the full setup guide.
| Variable | Default | Description |
|---|---|---|
SSL_ENABLED | false | Auto-generates a self-signed certificate; enables HTTPS on HTTPS_PORT and redirects HTTP on HTTP_PORT |
HTTP_PORT | 2020 | HTTP listening port (redirects to HTTPS when SSL enabled) |
HTTPS_PORT | 443 | HTTPS listening port |
SSL_HOSTNAME | newtondarts | Hostname used in the auto-generated SSL certificate’s Subject Alternative Name. Set this to match the .local hostname you advertise via mDNS — see Docs/MDNS.md. Falls back to deprecated MDNS_HOSTNAME if unset. |
NEWTON_API_ENABLED | true | Enables REST API endpoints for tournament upload, download, and delete |
NEWTON_MODE | full | App mode. analytics hides tournament management tabs, shows only Analytics and limited Global Settings |
NEWTON_DEMO_MODE | false | Shows a privacy banner at the top of the app |
NEWTON_LANDING_PAGE | false | Shows a landing page at the root URL instead of loading the app directly |
NEWTON_BASE_URL | unset | Canonical URL for Open Graph and Twitter Card meta tags on the landing page |
NEWTON_GITHUB_URL | github.com/skrodahl/NewTon | GitHub link shown in the demo banner |
NEWTON_HOST_PORT | 8080 | Host port for the basic HTTP compose (quick start only) |
The REST API has no built-in authentication. Do not expose the container directly to the public internet without additional protection. Safe options:
0.0.0.0, meaning the container is reachable from any device on your network. To restrict access to the local machine only, specify the loopback address explicitly in your ports mapping:
ports:
- "127.0.0.1:8080:2020"
With this in place, http://localhost:8080 still works, but other devices on the network cannot reach the container.
NEWTON_API_ENABLED=falseThe Docker image includes comprehensive security headers enabled by default — no configuration needed:
NewTon DC Tournament Manager achieves an A grade on securityheaders.com out of the box.
Strict-Transport-Security is included automatically when SSL_ENABLED=true. It is not set in HTTP-only mode to avoid breaking non-SSL deployments.
When terminating HTTPS at a reverse proxy, add HSTS there instead:
# Nginx Proxy Manager — Advanced tab
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Place your own files in the images/ folder. The images/ volume is mounted read-only from the host, so changes are picked up immediately — no container restart needed.
mkdir -p images
# Custom logo — supports .png, .jpg, .jpeg, or .svg
cp /path/to/your/logo.jpg ./images/logo.jpg
# Custom payment QR code
cp /path/to/your/payment-qr.png ./images/payment.png
Default images bundled in the Docker image: images/logo.jpg (club logo placeholder) and images/payment.png (GitHub project QR code). Need a payment QR? Use the QR Code Generator — transparent background, no signup required.
NEWTON_HOST_PORT=9000 docker compose up -d
docker compose logs
docker compose ps — should show 0.0.0.0:8080->2020/tcphttp://127.0.0.1:8080 instead of localhostdocker compose logsExpected with a self-signed certificate. Accept the exception once — it will not appear again. The cert is stored in the newton-ssl named volume and persists across restarts.
<hostname>.local Not ReachablemDNS resolution is a host-side concern, not handled by the container. See Docs/MDNS.md for full setup. Quick checks:
avahi-daemon on the host, set hostname, and configure allow-interfaces to exclude Docker bridge interfacesping newtondarts.local