uptrakit

External Scheduler Deployment

External Scheduler Deployment

The uptrakit-scheduler binary runs the scheduler as a standalone service, separate from the controller. It enrolls as a service via WebSocket, receives infrastructure credentials automatically, and executes the 4 external scheduled tasks (version checks, cleanup) using direct database access and NATS messaging.

Internal tasks (CRL renewal, CA rotation check, service certificate check) run exclusively on the controller's embedded scheduler because they require in-process access to controller resources.

When to use the external scheduler

DeploymentSchedulerNotes
Single controller, simpleEmbedded (--features embedded-scheduler)Everything runs in one process
Single controller + NATSExternal binaryDecoupled scheduling, independent scaling
Multi-controller HAExternal binaryAvoids duplicate scheduling across controllers
Resilient single instanceEmbedded + externalEmbedded defers external tasks when external connects; resumes on disconnect

Prerequisites

  • A running Uptrakit controller with NATS configured (--nats-url).
  • Network connectivity from the scheduler to the controller (WebSocket) and to the NATS server.
  • Network connectivity from the scheduler to the database.
  • The controller's master encryption key must be configured (the scheduler receives it via ServiceCredentials and uses it to unwrap data encryption keys from the database).

Installation

The uptrakit-scheduler binary is built from the crates/core/scheduler/ crate:

cargo build -p uptrakit-scheduler --release

Database backend features mirror the controller:

# SQLite (default)
cargo build -p uptrakit-scheduler --release

# PostgreSQL
cargo build -p uptrakit-scheduler --release --features db-postgres

# All backends
cargo build -p uptrakit-scheduler --release --features db-all

Enrollment

The scheduler enrolls like any other Uptrakit service (agent, MQTT bridge, SSH agent):

uptrakit-scheduler --url wss://controller.example.com:8443

On first run:

  1. The scheduler connects to the controller via WebSocket.
  2. It sends an Enroll message with capabilities: scheduler, database_access, nats_access, master_key_access, graceful_shutdown.
  3. An administrator approves the service (or provides an enrollment token for auto-approval).
  4. The scheduler requests and receives a client certificate.
  5. On the next connection (mTLS), the controller sends ServiceCredentials containing the database URL, NATS URL, and master encryption key.

To auto-approve during enrollment:

uptrakit-scheduler --url wss://controller.example.com:8443 --enrollment-token <token>

CLI options

FlagDefaultDescription
--url(required)Controller WebSocket URL
--poll-interval-secs15How often the scheduler polls for due tasks (seconds)
--tofuTrust-on-first-use CA pinning
--ca-certPath to controller's CA certificate
--pki-addrPKI endpoint for CA certificate
--config-dirPlatform defaultOverride config directory
--state-dirPlatform defaultOverride state directory
--friendly-nameHostnameHuman-readable service name
--enrollment-tokenAuto-approval token
--force-enrollForce fresh enrollment
-v, --verbose0Verbosity (up to -vvv)
--versionPrint build info and exit

Credential flow

The scheduler advertises credential capabilities during enrollment. The controller automatically sends ServiceCredentials on each authenticated connection:

CapabilityCredentialDescription
database_accessdb_urlDatabase connection string
nats_accessnats_urlNATS server URL
master_key_accessmaster_key_hex256-bit master encryption key (hex)

The scheduler capability is a marker — it does not grant credentials but identifies the service type. When the controller detects a connected service with this capability, it defers external tasks from the embedded scheduler.

Security considerations

The external scheduler receives sensitive infrastructure credentials:

  • Database URL: Grants full read/write access to the application database.
  • Master encryption key: Can unwrap DEKs and decrypt all encrypted fields in the database.
  • NATS URL: Can publish messages to the NATS event stream.

When approving the scheduler service in the admin UI, security warnings are displayed for each credential capability. Approve only trusted scheduler instances.

The ServiceCredentials message is never published to NATS — it is delivered exclusively via the authenticated WebSocket connection. See Secrets and Encryption for the credential filtering rationale.

Monitoring

  • The scheduler's WebSocket connection to the controller serves as presence detection.
  • When the embedded-scheduler feature is enabled on the controller, the embedded scheduler defers external tasks when an external scheduler connects and resumes them when it disconnects. Internal tasks (CRL renewal, CA rotation check, service cert check) always run on the embedded scheduler regardless of external scheduler presence.
  • The scheduler appears in the services list with the "Scheduler" label and can be managed via the REST API and admin UI.
  • Logs use the uptrakit_scheduler tracing target. Use -v for debug, -vv for all uptrakit debug, -vvv for trace.

Graceful shutdown

On SIGTERM or SIGINT, the scheduler:

  1. Cancels the scheduler engine loop.
  2. Releases all database claims (so another instance can pick up the tasks).
  3. Sends a Disconnecting message to the controller.
  4. Closes the WebSocket connection.

On SIGHUP, the scheduler exits with a restart outcome (suitable for systemd Restart=on-failure).

Systemd service example

[Unit]
Description=Uptrakit Scheduler
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/uptrakit-scheduler --url wss://controller.example.com:8443
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target