Skip to navigation

Compile service

rivet-server is an HTTPS service that compiles catalogs for hosts. A host running rivet run in server mode sends its facts and a credential. The service verifies the credential, checks that the host may use the requested environment, compiles the environment’s release, and returns the catalog. The host then verifies the assets and applies the catalog itself. The service never changes managed hosts.

rivet-server --config /etc/rivet/server.hcl

The server configuration uses the same literal-only format as the agent configuration, shown here as plain text. Keep it outside the published source directory.

GCP instance identity

listen = "0.0.0.0:8443"
source {
uri = "gs://example-rivet-config/site"
}
tls {
cert_file = "/etc/rivet/pki/server.pem"
key_file = "/etc/rivet/pki/server-key.pem"
}
authentication {
type = "gcp"
audience = "https://rivet.example.com"
projects = ["example-project"]
}
allow "managed-nodes" {
principal = "gcp:service-account:rivet-agent@example-project.iam.gserviceaccount.com"
environments = ["production", "staging"]
}

This assumes port 443 on rivet.example.com forwards to the listener on 8443. The listener always uses TLS. The service’s own storage credentials need read access to the source; they are independent of how hosts authenticate. S3 sources work too.

The service verifies the token’s signature against Google’s keys, along with its issuer, audience, lifetime, verified service-account email, project, and full instance identity. Each request gets:

  • a principal, gcp:service-account:<email>, which allow rules match;
  • a node identity, gcp:instance:<project>:<zone>:<instance-id>.

Authorizing a service account admits every VM that runs as it. Add target_identity to a rule (see authorization) to bind it to one machine.

mTLS

Keep listen, source, and tls from above, and replace the authentication and allow rules:

authentication {
type = "mtls"
ca_file = "/etc/rivet/pki/node-ca.pem"
crl_file = "/etc/rivet/pki/node-crls.pem"
trusted_extensions {
role = "1.3.6.1.4.1.55555.1"
environment = "1.3.6.1.4.1.55555.2"
}
}
allow "web-node" {
principal = "mtls:uri:urn:rivet:node:web-01"
environments = ["production", "staging"]
}

Here ca_file is the CA for client certificates. Each client certificate must contain exactly one URI SAN starting with urn:rivet:node:. That URI is the node identity, and the principal is mtls:uri: followed by the URI. TLS must terminate at rivet-server; certificate headers forwarded by a proxy are ignored.

crl_file is optional and enables revocation checks. Certificates, CAs, and CRLs load at startup, so restart the service to pick up new ones. Issuing and renewing client certificates is up to your deployment.

trusted_extensions is optional. It names certificate extension OIDs to expose as trusted claims, such as trusted.claims.extensions.role. Replace the example OIDs with ones from your own namespace. Values must be UTF-8 strings of at most 4 KiB, and at most 64 extensions can be mapped. Your CA must control these values: if it signs whatever role a host asks for, hosts can choose their own classification.

OIDC

authentication {
type = "oidc"
issuer = "https://identity.example.com"
audience = "rivet"
jwks_url = "https://identity.example.com/.well-known/jwks.json"
}
allow "workload" {
principal = "oidc:https://identity.example.com:rivet-agent"
environments = ["production"]
}

The issuer must sign tokens with RS256 and publish keys at an HTTPS JWKS URL. Tokens must be valid for at most one hour. The principal and node identity are both oidc:<issuer>:<subject>. Keys are refreshed every five minutes. A token signed with an unknown key triggers an earlier refresh, at most once every 30 seconds. Configure the host’s token file and keep it fresh with your workload identity system.

On AWS, use mTLS or an OIDC workload token to authenticate, and IAM credentials for storage reads. Rivet doesn’t accept SigV4 requests or EC2 instance identity documents.

Authorization

Requests are denied unless an allow rule matches. Each rule has a unique name, an exact principal, and the environments it may use. Add target_identity to bind a rule to one machine’s hashed identity, copied from that host’s facts (target.identity). That is an extra check on top of credential authentication, not a replacement.

Facts submitted by a host are inventory only. Configuration sees the verified identity through the separate trusted namespace, which only the service can populate.

Source files, catalogs, and cached assets can all contain secrets in plain text. Protect the service host, its cache, and storage write access as carefully as host credentials.

Signed asset delivery

By default, hosts download assets from storage with their own credentials. To remove that requirement, add:

signed_assets = true
signed_asset_ttl_secs = 900

The service then returns signed GET URLs, valid for signed_asset_ttl_secs seconds (1 to 3600, default 900). This needs an S3 or GCS source and service credentials that can sign URLs; on GCS, a service-account key or IAM signing permission. Every external asset must belong to the release, so arbitrary cloud objects can’t be delivered this way.

If URLs expire before the host finishes downloading, the agent can ask once for fresh URLs for the same catalog. A refresh never picks up a newer release. Refresh grants last an hour and are lost when the service restarts. Signed URLs and tickets are never stored in caches, reports, or journals.

Settings and limits

Setting or limitValue
listenDefault 0.0.0.0:8443
cache_dirDefault /var/cache/rivet-server; must be private and owned by the service user
signed_assetsDefault false
Configuration fileAt most 64 KiB
Connections128 at once; 10-second TLS handshake; 90-second connection lifetime
Concurrent compiles and refreshes4; extra requests get HTTP 429
Facts per request1 MiB of inventory and 64 KiB of trusted claims
Refresh grants10,000 grants, 64 MiB total

Configuration and PEM files follow the agent’s file permission rules. Changes to configuration, TLS material, allow rules, or CRLs take effect after a restart.

Plugins

The service loads approved plugin definitions and functions from /etc/rivet/plugins.lock.json, or the file passed with --plugin-lock. A release can require plugins, but can’t install or approve them. Plugin hooks and functions run as the service user and must be pure. Hosts install their own runtime plugins separately; function-only plugins need nothing on the host, because results are compiled into the catalog.

Protocol

The service exposes POST /v1/compile and POST /v1/assets/refresh. rivet run is the supported client, and the protocol is experimental. Compile responses carry Cache-Control: no-store. Service failures never trigger source-mode or offline fallback.

The repository’s distribution checks use local fixtures, so test cloud credentials, signing, and IAM policy in your own deployment.