Skip to content

deployment

Greg Wilkins edited this page Oct 7, 2026 · 3 revisions

Signing in, and installing on the Pi

Who signs in

Authenticate authority, trust data. Officers sign in; boats never do (dialog §7.1).

Needs a sign-in editor.html, race.html, and every non-GET on /api/programmes, /api/lifecycle and /api/conduct
Open to everybody every GET, POST /api/join, POST /api/records, and the whole of /api/dialog

The open row matters as much as the closed one: a login in front of the dialog would look like a working login until race day, when every boat met a sign-in page where it expected its messages. Reads stay open because a club publishes its racing. server.configWrites: false turns all configuration writes off regardless.

With no data/config/auth.yaml, nothing is behind a login — right for a laptop, wrong for anything else.

Configuring the login

auth.yaml configures OpenID Connect (Google, typically); auth.yaml.example shows the shape, which is the same as sail-jinx's so a club running both registers one OAuth client. Signing in is automatic — opening the editor signed out goes through the provider and back — and every sign-in shows the provider's account chooser, so a browser holding two accounts is asked which.

  • allowedDomain restricts sign-in to accounts of one domain, checked against the provider's hd claim. Blank allows any account the provider vouches for.

  • allowIP lists addresses treated as an administrator without signing in, and allowLoopback adds this machine's own. Never list the address of a reverse proxy or router in front of the server: every request through it arrives from that address, so listing it opens the editor to everyone. The address is read off the connection, never off X-Forwarded-For, which a client can forge. The sign-in itself is never bypassed, so someone at a listed address can still sign in under their own name.

  • Officers are named club by club. superAdmins may change every club; each club's admins may change that club's courses and run its races, and nothing of any other club's. A write to a club the account is not an admin of is refused with a sentence saying so, and the editor and race screen offer only the clubs the account may change. Until auth.yaml names any of them, every account it admits may change every club. Addresses let past the login count as super-admins.

    superAdmins: [owner@example.org]
    clubs:
      myc.org.au:
        admins: [officer@myc.org.au, someone@gmail.com]

Sessions live in memory, so a server restart signs officers out; it affects no boat. Discovery is the one outbound call the server makes, at start-up, so with a login configured the server needs the network to start.

Adding a club

A club is a directory named after its domain under the live config, /var/lib/sail-unmarked/config/clubs/<club domain>/, holding one YAML file per series. Make the directory and a first series file — a copy of another club's, or just name: "Summer 2026" with empty points: {}, lines: {} and courses: {} — owned by the sail-unmarked user, name the club's admins in auth.yaml, and restart the service. Everything else, further series included, is done in the editor.

Installing

etc/install.sh installs the server as the sail-unmarked systemd service, matching sail-jinx's layout: code in /opt/sail-unmarked, data in /var/lib/sail-unmarked, run by a sail-unmarked system user. Upgrading is git pull && sudo etc/install.sh.

  • Configuration is seeded on first install and never overwritten. auth.yaml.example is seeded; auth.yaml never is, and it is set to mode 600 on every run because it holds a client secret.
  • With no auth.yaml, the script ends by saying the editor and race screen are open to anyone who can reach the Pi, and how to fix it.
  • The service starts after the network is up, and may only write to /var/lib/sail-unmarked.

The server listens on 8083. Behind a reverse proxy, set server.forwardedHeaders: true so it rebuilds its external URL from the proxy's headers; never set it on a server reached directly.

Clone this wiki locally