← Back to overview

Global Leaderboard Deployment Guide

This guide walks through hosting the bundled leaderboard_server so the Playtime Tracker desktop clients can sync automatically. The end goal is a secure service running at playtracker.al1e.dev (or your own domain) with the URL baked into released dashboard builds.


1. Prerequisites

2. Build & Install the Server

cd /opt
sudo git clone https://github.com/Sudo-Spectral/SC-Playtime-Tracker.git
sudo chown -R $USER:$USER SC-Playtime-Tracker
cd SC-Playtime-Tracker

cargo build --release --bin leaderboard_server

sudo install -Dm755 target/release/leaderboard_server /usr/local/bin/leaderboard_server
sudo install -d -m 755 /var/lib/sc-playtime
sudo chown -R scplaytime:scplaytime /var/lib/sc-playtime  # optional service user

Optionally create a dedicated service account that owns the data directory:

sudo useradd --system --home /var/lib/sc-playtime --shell /usr/sbin/nologin scplaytime
sudo chown -R scplaytime:scplaytime /var/lib/sc-playtime

3. Systemd Service

Create /etc/systemd/system/leaderboard.service:

[Unit]
Description=Star Citizen Playtime Leaderboard API
After=network-online.target
Wants=network-online.target

[Service]
User=scplaytime
Group=scplaytime
ExecStart=/usr/local/bin/leaderboard_server
WorkingDirectory=/var/lib/sc-playtime
Environment=LEADERBOARD_ADDR=127.0.0.1:8080
Environment=LEADERBOARD_STORE=/var/lib/sc-playtime/leaderboard.json
Restart=on-failure
RestartSec=3

[Install]
WantedBy=multi-user.target

Reload systemd, enable, and launch the service:

sudo systemctl daemon-reload
sudo systemctl enable --now leaderboard.service
sudo systemctl status leaderboard.service

The API now listens on 127.0.0.1:8080.

4. Reverse Proxy & TLS

Option A: Caddy (automatic HTTPS)

sudo apt install -y caddy

# /etc/caddy/Caddyfile
playtracker.al1e.dev {
    encode gzip
    reverse_proxy 127.0.0.1:8080
}

sudo systemctl reload caddy

Option B: Nginx + Certbot

sudo apt install -y nginx certbot python3-certbot-nginx
sudo certbot --nginx -d playtracker.al1e.dev

Configure /etc/nginx/sites-available/playtracker:

server {
    listen 80;
    server_name playtracker.al1e.dev;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name playtracker.al1e.dev;

    ssl_certificate /etc/letsencrypt/live/playtracker.al1e.dev/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/playtracker.al1e.dev/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:8080;
    }
}

sudo ln -s /etc/nginx/sites-available/playtracker /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Option C: Apache (mod_proxy) + Certbot

sudo apt install -y apache2 python3-certbot-apache
sudo a2enmod proxy proxy_http ssl headers
sudo certbot --apache -d playtracker.al1e.dev

Configure /etc/apache2/sites-available/playtracker.conf:

<VirtualHost *:80>
    ServerName playtracker.al1e.dev
    RewriteEngine On
    RewriteRule ^/(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</VirtualHost>

<VirtualHost *:443>
    ServerName playtracker.al1e.dev

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/playtracker.al1e.dev/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/playtracker.al1e.dev/privkey.pem

    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/

    RequestHeader set X-Forwarded-Proto "https"
</VirtualHost>

Enable the site and reload Apache:

sudo a2ensite playtracker.conf
sudo a2dissite 000-default.conf  # optional: disable default site
sudo systemctl reload apache2

5. Embed the Endpoint in Client Builds

The desktop client checks configuration sources in this order:

  1. PLAYTIME_LEADERBOARD_URL runtime environment variable.
  2. LEADERBOARD_DEFAULT_URL compile-time constant.
  3. Local fallback file if neither is provided.

Ship releases with the compile-time value set to your domain:

LEADERBOARD_DEFAULT_URL=https://playtracker.al1e.dev cargo build --release --bin dashboard

6. Verify the API

curl -X POST https://playtracker.al1e.dev/submit \
  -H "Content-Type: application/json" \
  -d '{"username":"TestPilot","total_minutes":120}'

curl https://playtracker.al1e.dev/top

The first call should return 204 No Content; the second lists leaderboard entries.

7. Optional Hardening

Need to host multiple org leaderboards? Review centralized_leaderboards.md in the repository for templated systemd units and Apache routing tips.