Uptimer v2.0.0-preview documentation — it describes the release candidate, and v1.8.0 remains the current release. Commands here pull the preview image :2.0.0-rc1. The Python SDK for this preview is a local wheel, not a PyPI release. Go to the current release (v1.8.0) →
Operating › Running Uptimer

Running Uptimer

Commands, services, ports, the operations endpoint, state on disk and settings.

This is the operator reference for the 2.0 control plane: the commands it answers to, the settings it reads, the ports it serves, the paths it keeps state in, and what it no longer does. Coming from 1.8? Start with Moving from Uptimer 1.8 to 2.0.

The binary is uptimer. It is configured by environment variables and command flags. There is no configuration file.

Commands

CommandWhat it does
uptimer serve --services …Run the control plane. With no --services, every service in one process.
uptimer migrateBring the database schema up to date, then exit. The rollout gate.
uptimer workerRun a worker daemon against a control plane.
uptimer worker-cert --uid <uid>Issue (or revoke) a worker’s client certificate.
uptimer devEverything in one process for a local run: identity, certificate, bus with no socket.
uptimer versionPrint the version, commit and build time.
uptimer --help, uptimer <command> --helpWhat each command reads and accepts.

Run the binary with no command and it serves: that is what a container does. An unknown command is refused rather than ignored.

Services

serve --services takes any of ui, api, grpc, judge, nats, cache, and eventbus as the alias for nats,cache. An unknown name is refused and the message lists the choices. A single box runs them all in one process; a fleet runs them apart against the same database, bus and cache.

Asking for grpc with UPTIMER__GRPC__PORT=0 is refused: a service that was asked for and cannot serve is not quietly dropped. An installation that runs no workers turns that port off and names no services, and the default set is then everything except the worker API.

A process that runs no database-backed service — nats, cache, eventbus — never opens the product’s database.

Ports

PortServesSetting
8080the UIUPTIMER__UI__PORT
2518the public API, when it runs as its own processUPTIMER__SERVER__API__PORT
50051the worker API (gRPC, mutual TLS)UPTIMER__GRPC__PORT
4222the event busUPTIMER__EVENTBUS__PORT
6379the cacheUPTIMER__REDIS__BIND_PORT
9090operations: /metrics, /livez, /readyz (required)UPTIMER__OPS__PORT

A port a process needs and cannot bind is a refusal to start that names the port. A process that logged the failure and carried on would look healthy while serving nothing.

Run the services apart and give each process its own operations port; that is how a fleet scrapes them separately.

Operations endpoint

Every long-running process — including worker — serves one operations listener:

PathAnswers
/metricsPrometheus text, including one uptimer_build_info series per service this process runs
/livez200 while the process is running. This is what restarts a wedged container.
/readyz200 only when every selected service is serving. Otherwise 503 and the reason.

Readiness goes non-OK when a selected service fails to start or its serving loop stops — the shell, the API, the worker API, the judge, the bus and the cache each report their own — so a process that has lost one of its jobs is taken out of a load balancer rather than left in it.

A process that serves the shell with OIDC sign-in also checks its provider’s discovery document: it must be reachable, be JSON, name exactly the configured issuer, and list the authorization, token and key endpoints. Otherwise /readyz answers 503 with oidc: …, because nobody can sign in. One answer holds for 15 seconds. /livez stays 200. The endpoint is on the operations listener and needs no sign-in.

A process asked for eventbus answers to that name as well as to nats and cache, because it is the name the deployment used.

The listener is not optional: serve and a worker daemon refuse to start without a port for it, because a process nothing can scrape or probe is one nobody can take out of a load balancer. UPTIMER__OPS__PORT moves it and UPTIMER__OPS__ADDR binds it to one interface. worker --once serves none: it asks, runs, reports and stops.

Metrics

SeriesLabels
uptimer_build_infoservice, version, commit, built
http_request_duration_secondsroute, method, status
grpc_request_duration_secondsgrpc_method, grpc_code
uptimer_judge_decisions_totalresult (ok, error)
uptimer_worker_checks_totalresult (ok, error)
uptimer_oidc_sign_ins_totalresult (ok, error)

route is the route pattern, not the path, so one route is one series.

The two totals exist so a quiet service can be told from a stopped one: a judge with no work and a judge that has died both report nothing otherwise.

A process running judge also removes delivery records older than 30 days, once an hour.

State that must survive a restart

Everything lives under one directory, so a deployment mounts one volume.

WhatDefaultSetting
data directory/var/lib/uptimer (the image sets /data)UPTIMER__DATA_DIR
databasesqlite3://<data>/uptimer.sqliteUPTIMER__DB__DSN
session signing key<data>/session.pemUPTIMER__KEY_FILE
worker authority<data>/worker-caUPTIMER__GRPC__CA_DIR
durable queue<data>/eventbus-storeUPTIMER__EVENTBUS__STORE_DIR
worker certificate, key, CAworker.pem, worker-key.pem, worker-ca.pemUPTIMER__WORKER__CERT_FILE, __KEY_FILE, __CA_FILE

A relative path in any of those settings is read under the data directory, and an absolute one is used as given. A path typed on worker’s own --cert, --key or --ca flag is used as typed, so a worker started by hand from a directory of its own needs no data directory at all.

Restarting against the same directory reuses the database, the signing key — so sessions survive — the worker authority, the queued announcements, and a worker’s identity. None of them is recreated.

The worker authority is made on a first run, by the process that serves the worker API. Once certificates have been issued, a missing authority is a refusal to start instead: the trust every daemon holds is gone, and a new authority would refuse all of them while looking healthy. Back the directory up or keep issuing from a mounted volume.

PostgreSQL is the other supported backend: set UPTIMER__DB__DSN to a postgres://… URL, and the data directory then holds only the key, the authority and the queue.

Other settings

SettingDefaultWhat it does
UPTIMER__SERVICESevery servicewhich services a bare binary runs
UPTIMER__AUTH__DEVfalsethe development sign-in; see Sign-in
UPTIMER__SQIDS__SALTbuilt-inseeds the encoder behind every public id
UPTIMER__GENERAL__SITE_URLemptyhow this installation is reached, so an alert can link back
UPTIMER__EVENTBUS__NATS_URLnats://localhost:4222where to reach the bus
UPTIMER__REDIS__BIND_ADDRlocalhostwhere the cache listens
UPTIMER__GRPC__HOSTSlocalhost,127.0.0.1,::1names the worker API’s own certificate is good for
UPTIMER__WORKER__EVERY30seconds between a daemon asking for its assignments

Shutdown

On SIGINT or SIGTERM an all-services process stops producers first, waits up to 15 seconds for the worker API to finish a report it is holding, and only then drains the event bus. A report in flight is not lost to a restart.

What 1.x had and this does not

These are deliberate removals, not oversights. Nothing in this reference or in any example uses them.

1.x surfaceNow
--cfg YAML configurationEnvironment and flags only. There is no configuration file.
--delayRemoved. Startup ordering belongs to the orchestrator.
Top-level grpc and server commands, availabilities serviceserve --services grpc, serve --services judge.
server init, worker initworker-cert issues identities; dev sets a local run up.
Zap log levels DEV and PRODslog levels debug, info, warn and error; see Logs and error reporting.
UPTIMER__SENTRY__PROFILES_SAMPLE_RATENot read. Sentry receives errors only; there is no tracing or profiling.
/system/healthcheck/livez and /readyz on the operations listener, for every process rather than only the UI.
Metrics named after Subjects, rules lists and availabilitiesGone with the model they described. The HTTP and gRPC duration series are kept, with their dimensions.
OIDC settings named UPTIMER__SERVER__AUTH__OIDC__*Renamed to UPTIMER__AUTH__OIDC__*; see Sign-in. 1.x OIDC account links are not read; see Moving from Uptimer 1.8 to 2.0.
The 1.x public API (/api/v1/*, /api/v2/*)Answered with one explicit 410 saying the 2.0 SDK replaced it. No legacy handler runs.
1.x’s own databaseNot read, not migrated, not converted; 2.0 refuses to start against it. Move with a fresh installation: Moving from Uptimer 1.8 to 2.0.