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.
All devices on your LAN can reach the container at https://newtondarts.local without any DNS configuration. Requires network_mode: host — Linux only (not supported on Docker Desktop for Mac/Windows).
services:
newton-tournament:
image: skrodahl/newton:latest
# Alternative: ghcr.io/skrodahl/newton:latest
container_name: newton
network_mode: host # Required for mDNS multicast to reach the LAN
volumes:
- ./tournaments:/var/www/html/tournaments
- ./images:/var/www/html/images:ro
- newton-ssl:/etc/nginx/ssl
restart: unless-stopped
environment:
- TZ=Europe/Oslo
- SSL_ENABLED=true
- MDNS_HOSTNAME=newtondarts # Reachable as newtondarts.local on the LAN
- NEWTON_API_ENABLED=true
- NEWTON_DEMO_MODE=false
# - NEWTON_LANDING_PAGE=true
# - 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://newtondarts.local. Phones, tablets, and scoring stations on the same network can all reach it by name.
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 port 443 and redirects HTTP on port 2020 |
HTTPS_PORT | 443 | HTTPS listening port |
MDNS_HOSTNAME | newtondarts | mDNS hostname — container reachable as <value>.local on the LAN (Linux only) |
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.
network_mode: host does not work on Docker Desktop for Mac or WindowsMDNS_HOSTNAME=newtondarts is setdocker compose logs — should show [newtondarts] nginx: HTTPS modeping newtondarts.local