Skip to content
LightCurve
WebsiteApp

Product

Deployment

Run LightCurve on your own server: the image, its settings, the first administrator, backups.

LightCurve is one service: a small Node.js server that handles the accounts and serves the application to signed-in users. The same image runs the hosted service and the on-premises deployments.

The server does no computation — the simulation and the analyses run in the users’ browsers — so a small machine is enough: 1 vCPU, 1 GB of memory and a few hundred MB of disk serve hundreds of users.

Prepare the server

On a fresh Ubuntu 24.04 or Debian 12 server, from app/deploy/ of the repository: sudo bash setup-vps.sh. It installs the updates, automatic security updates, a firewall (SSH, HTTP and HTTPS only), Docker, and the nightly jobs (backup, deletion of ended licences).

Configure

Fill in .env (created from .env.example): the domains, the public address and the SMTP account used for invitations and password resets.

Run
Terminal window
cd app/deploy
docker compose up -d --build

Caddy, in front, obtains and renews the HTTPS certificates. It can also serve a static website on a second domain (LC_SITE_DOMAIN, files in app/deploy/site/); without a website, remove its two blocks from the Caddyfile.

Create the first administrator
Terminal window
docker compose exec lightcurve node dist-server/cli.js init --email you@example.org --name "Your Name" --org "Your organisation"

The command prints the link that sets the password. From there, create organisations and invite users from the Administration page.

Variable Default Meaning
LC_PUBLIC_URL http://localhost:8787 Public address of the application: links in the e-mails, allowed origin of the forms. HTTPS turns on Secure cookies and HSTS
PORT 8787 Port of the server
LC_DATA_DIR /data in the image Folder of the database (lightcurve.db)
LC_TRUST_PROXY — 1 behind a reverse proxy that sets X-Forwarded-For (set by the compose file)
SMTP_URL — smtps://user:password@host:465. Without it, e-mails are printed in the server log
MAIL_FROM LightCurve <no-reply@lightcurve.space> Sender of the e-mails
LC_SUPPORT_EMAIL contact@lightcurve.space Address shown for licence questions
LC_WEBSITE_URL https://lightcurve.space Site linked from the sign-in page
LC_LICENCE_KEY — The server’s licence key (or LC_LICENCE_FILE, a file holding it). Required: without a valid key the application is not served

Every accounts server runs under a signed licence key. It sets the highest plan and add-ons the server may grant, the most active users across all its organisations, and the end date; the organisations stored in its database are capped accordingly, whatever their settings. On premises, the key is issued in the name of your organisation and renewed every year with the on-premises option. Without a valid key — missing, altered or expired — the application is not served; sign-in, accounts and administration stay available and show why. The Administration page and node dist-server/cli.js licence show the licence in force and the seats in use.

Command Does
node dist-server/cli.js init --email … [--name …] [--org …] Creates the team organisation and its first administrator
node dist-server/cli.js link --email … A new password link for an existing account
node dist-server/cli.js list Organisations, licences and users
node dist-server/cli.js ended [--days 90] [--delete] Organisations whose licence ended more than 90 days ago; --delete removes them with their users, as the privacy policy promises
node dist-server/cli.js backup --out <file> A consistent copy of the database
node dist-server/cli.js licence The server’s licence and the active users

All the state is the SQLite database in the data volume. backup.sh, run every night by setup-vps.sh, takes a consistent copy while the service runs (cli.js backup, SQLite VACUUM INTO) into app/deploy/backups/ and keeps 14 days; copy them off the server from time to time. Nothing else needs saving: users’ measurements and models never reach the server.

Every night, organisations whose licence ended more than 85 days ago are deleted with their users, and log lines older than 12 months are purged. To update the service: bash update.sh (pulls the code, rebuilds, restarts; accounts are kept).

For air-gapped sites, the image runs the same way on an isolated network — the application needs no outside resource, except the optional TLE download from CelesTrak. Without accounts at all, the single-file build (npm run build:standalone) opens in a browser from a local file and uses licence keys.