Skip to main content Skip to navigation Skip to footer

On-Premise Installation

Running the account server and CLI distribution on your own infrastructure.

Rediacc can run entirely on your own infrastructure. The standalone Docker image includes the account server, web portal, marketing site, and CLI distribution endpoint. No external dependencies on Rediacc’s hosted services are required.

Docker Image

Pull the standalone image:

docker pull ghcr.io/rediacc/server:stable

Run with default settings:

docker run -p 80:80 -p 443:443 ghcr.io/rediacc/server:stable

The image serves:

  • Account API at /account/api/v1/
  • Web portal at /account/
  • Marketing site at /
  • CLI artifacts at /releases/
  • Renet binaries at /bin/

Installing the CLI from Your Server

Users can install the CLI directly from your on-premise server. The install script auto-detects the update channel and configures the CLI to check your server for updates.

curl -fsSL https://account.example.com/install.sh | \
  REDIACC_SERVER_URL=https://account.example.com bash

This single command:

  1. Downloads the CLI binary from your server’s /releases/ endpoint
  2. Queries /account/api/v1/.well-known/server-info to discover the update channel
  3. Writes server.json with your server URL, update channel, and encryption keys
  4. Configures rdc update to check your server for future updates

No REDIACC_CHANNEL variable is needed. The install script reads the channel from your server’s configuration automatically.

CLI Configuration with Named Configs

For users who connect to multiple servers (on-premise, production, edge), named configs keep each environment isolated:

# Create a config for your on-premise server
rdc config init --name myserver --server https://account.example.com

# Log in using that config
rdc --config myserver subscription login

# All commands with --config use the on-premise server
rdc --config myserver machine query --name prod-1

Each named config stores its own account server URL and subscription token. Switching configs switches the entire server context.

Air-Gapped Environments

For environments without internet access, set both the server URL and a custom releases URL:

curl -fsSL https://account.example.com/install.sh | \
  REDIACC_SERVER_URL=https://account.example.com \
  REDIACC_RELEASES_URL=https://account.example.com/releases \
  bash

The CLI will check account.example.com/releases/cli/stable/manifest.json for updates instead of the public releases CDN.

If the server is completely offline, install the CLI via npm from the bundled tarball:

npm install -g https://account.example.com/npm/rediacc-cli-latest.tgz

Environment Variables Reference

VariableUsed byPurpose
REDIACC_SERVER_URLInstall scriptAccount server URL. Auto-discovers channel and encryption keys.
REDIACC_RELEASES_URLInstall script, CLI updaterCustom releases endpoint for CLI binaries. Default: https://releases.rediacc.com
REDIACC_CHANNELInstall scriptOverride the update channel. Auto-detected from server if not set.
REDIACC_ACCOUNT_SERVERCLI runtimeOverride account server URL for all CLI commands.
RDC_UPDATE_CHANNELCLI runtimeOverride update channel for rdc update.

Server Configuration

The on-premise Docker image uses the same ENVIRONMENT variable as the hosted service. Set it in your Docker environment or orchestration config:

  • ENVIRONMENT=production (default): standard limits, stable update channel recommended to clients
  • ENVIRONMENT=edge: 2X Community limits, edge update channel recommended to clients

See Release Channels for details on what each environment provides.

What the Server Tells the CLI

When the CLI connects to your server, it queries /.well-known/server-info to discover:

  • E2E encryption public key: for zero-knowledge config storage
  • Minimum CLI version: blocks outdated CLIs from connecting
  • Update channel: tells the CLI which release channel to use for updates
  • Environment: whether this is a production or edge deployment

This auto-configuration means users only need the server URL. Everything else is discovered automatically.

Licensing for Air-Gapped Deployments

Air-gapped and self-hosted on-premise servers issue licenses locally using a delegation certificate signed by the upstream master key. The certificate constrains the on-premise server to its plan limits and creates a tamper-evident chain. See License Chain & Delegation for the cryptographic design (chain integrity, fork detection, audit proofs).

This section covers the operational setup: generating keys, requesting the cert, configuring auto-renew, and the offline (air-gapped) renewal flow.

One subscription, one on-premise install

A subscription may have at most one active delegation certificate at a time. Each on-premise install enforces per-month and per-machine limits against its own local issuance ledger, so multiple active certs would multiply the effective quota with no possible reconciliation.

If you need separate environments (production, staging, DR, multi-region), purchase one subscription per install. The single-active enforcement codifies this contract: an attempt to create a second active cert returns 409 DELEGATION_CERT_ALREADY_ACTIVE with the existing cert id and instructions to renew (preferred - preserves the chain) or revoke-and-create (resets the chain).

1. Generate the on-premise Ed25519 key pair

The on-premise server uses a separate Ed25519 key pair to sign licenses. The upstream’s delegation cert authorizes this specific public key.

# Generate a fresh keypair
openssl genpkey -algorithm Ed25519 -out onprem-private.pem
openssl pkey -in onprem-private.pem -pubout -out onprem-public.pem

# Convert to base64 (the format the on-premise expects in env vars)
ON_PREMISE_PRIVATE_KEY=$(openssl pkey -in onprem-private.pem -outform DER | base64 -w 0)
ON_PREMISE_PUBLIC_KEY=$(openssl pkey -in onprem-private.pem -pubout -outform DER | base64 -w 0)

Store the private key alongside your other secrets (for example, a Docker secret or Kubernetes Secret). It never leaves the on-premise box.

2. Request a delegation cert from the upstream

You can request the cert from the upstream account portal in three ways:

Option A - Customer self-service (recommended). Log into the upstream portal as an org owner or admin and navigate to /account/delegation-certs. Click Create New, paste the on-premise public key (base64 SPKI), choose a validity (or accept the per-plan default), and download the resulting .json file.

Option B - Admin (cross-customer). Rediacc support or the upstream system admin can use POST /admin/delegation-certs with the same parameters.

Option C - rdc CLI (planned). A future CLI command will wrap the portal flow.

The returned .json looks like:

{
  "payload": "eyJ2ZXJzaW9uIjoxLCJzdWJzY3JpcHRpb25JZCI6...",
  "signature": "...",
  "publicKeyId": "..."
}

The cert’s validity is governed by the validity policy (per-plan defaults and ceilings, per-subscription override, capped at subscription end + 3 day grace). The response also includes effectiveDays and reason so you can see why it picked that value. See License Chain - Validity Policy for the full rules.

3. Install the cert on the on-premise server

Save the downloaded .json to a known path and point the on-premise to it:

DELEGATION_CERT_PATH=/etc/rediacc/delegation-cert.json

Or, for ephemeral / Docker-secrets workflows, embed the cert as base64 in an env var:

DELEGATION_CERT_BASE64=$(base64 -w 0 < delegation-cert.json)

If your on-premise has outbound HTTPS access to the upstream, set up automatic renewal so the cert refreshes before expiry without manual intervention:

# Required for /onprem/cert-upload to verify uploaded certs against the upstream master key.
# Fails-fast at boot if UPSTREAM_API_KEY is set without this.
UPSTREAM_PUBLIC_KEY="<upstream master Ed25519 SPKI public key, base64>"

# Required for the auto-renew loop. Mint via the portal:
#   Org owner/admin → /account/delegation-certs → "Get auto-renew token"
# This is the ONLY way to obtain a delegation:renew-scoped api token.
UPSTREAM_URL="https://www.rediacc.com"
UPSTREAM_API_KEY="rdt_..."

# Optional tuning (defaults shown).
AUTO_RENEW_INTERVAL_HOURS=24
RENEW_THRESHOLD_DAYS=14

The on-premise auto-renew loop runs once at boot and then on the configured interval. It uses an adaptive threshold (min(env.RENEW_THRESHOLD_DAYS, ceil(certValidityDays / 3))) so a 15-day COMMUNITY cert renews at 5 days remaining instead of triggering renewal on day 1. A 90-day BUSINESS cert renews at 14 days remaining (the env-configured ceiling).

If renewal fails, the cert stays in use until natural expiry. The failure backs off for 1 hour and is recorded in ${DELEGATION_CERT_PATH}.status.json plus exposed via GET /onprem/cert-status.

5. Air-gapped renewal (no outbound HTTPS)

If your on-premise cannot reach the upstream, use the manual transfer flow:

  1. Download a renewal request from the on-premise admin portal. As the on-premise system root, hit GET /onprem/renewal-request. This returns a JSON manifest containing the local chain head, the delegated public key, and a tamper-evident Ed25519 signature from your on-premise private key.
  2. Transfer the manifest to the upstream via USB, encrypted email, or any out-of-band channel. The manifest is small (a few KB) and contains no secrets.
  3. Process the manifest at the upstream. Org owner/admin opens /account/delegation-certsUpload renewal request → selects the manifest file. The upstream verifies the manifest signature against the active cert’s delegatedPublicKey (proves it came from a holder of the on-premise private key), checks anti-replay (manifests older than 7 days are rejected), then issues a fresh cert.
  4. Download the new cert from the upstream portal as a .json file.
  5. Transfer the cert back to the on-premise.
  6. Upload to the on-premise via the local admin portal (POST /onprem/cert-upload). The on-premise verifies the new cert against UPSTREAM_PUBLIC_KEY and validates that the cert’s genesisSequence still links to a chain entry in the local issuance ledger (sequence advancement during transit is supported - the chain extends naturally).

This entire loop never requires network egress from the on-premise.

Manifest failure modes

CodeCauseFix
NO_ACTIVE_CERTUpstream has no active cert for this subscriptionIssue a new cert via the create flow instead of renewing
DELEGATED_KEY_MISMATCHManifest’s delegatedPublicKey differs from the active certThe manifest may be a replay from a different on-prem install
MANIFEST_SIGNATURE_INVALIDSignature doesn’t verify against the delegated public keyManifest was tampered in transit, or you generated it on a different on-prem
MANIFEST_EXPIREDManifest is more than 7 days oldGenerate a fresh renewal request from the on-premise

Cert upload failure modes

CodeCauseFix
CHAIN_HEAD_BEHINDNew cert’s genesisSequence is ahead of local chain headUpstream is on a forked chain - investigate
CHAIN_FORK_ON_UPLOADChain hash at the cert’s genesisSequence doesn’t match local ledgerLocal chain has diverged from upstream - investigate
Signature verification failedCert isn’t signed by the configured UPSTREAM_PUBLIC_KEYCheck that UPSTREAM_PUBLIC_KEY matches the upstream master public key

6. Status and monitoring

Query the on-premise local cert state at any time:

curl https://onprem.example.com/account/api/v1/onprem/cert-status \
  -H "Cookie: <admin session>"

Returns the loaded cert’s subscriptionId, planCode, validUntil, daysUntilExpiry, plus the autoRenew block (enabled, lastSuccessAt, lastErrorAt, lastError). Wire this into your monitoring stack to alert on stale lastSuccessAt or non-null lastError.

For backup and audit, the on-premise admin can also download the currently loaded signed cert via GET /onprem/cert-current (requires elevated session).

Delegation cert env var reference

VariableRequired?Purpose
ON_PREMISE_MODEYesSet to true to enable the on-premise route subset
ON_PREMISE_PRIVATE_KEYYesBase64 PKCS8 Ed25519 private key for delegated signing
ON_PREMISE_PUBLIC_KEYYesBase64 SPKI Ed25519 public key (must match the cert’s delegatedPublicKey)
DELEGATION_CERT_PATHOne of theseFilesystem path to the signed cert JSON
DELEGATION_CERT_BASE64One of theseBase64-encoded cert JSON (alternative to file path)
UPSTREAM_PUBLIC_KEYRequired if UPSTREAM_API_KEY is set, or for /onprem/cert-upload to workBase64 SPKI of the upstream master public key. Fail-fast at boot if missing.
UPSTREAM_URLFor auto-renewUpstream account server base URL, e.g. https://www.rediacc.com
UPSTREAM_API_KEYFor auto-renewA delegation:renew-scoped api token. Mint via the portal - see Step 4.
AUTO_RENEW_INTERVAL_HOURSOptionalDefault 24. How often to check whether the cert needs renewal.
RENEW_THRESHOLD_DAYSOptionalDefault 14. Acts as a ceiling on the adaptive 1/3-of-validity threshold.

Threat model summary

The delegation cert model defends against:

  • Forged licenses: the on-premise can only sign within its plan limits; renet rejects anything outside the cert’s bounds.
  • Cert sharing across deployments: chain divergence is detected at renewal (returns CHAIN_FORK_DETECTED).
  • Quota bypass via multi-install: enforced at the upstream by single-active (one cert per subscription).
  • Chain rollback: renet stores the highest-sequence-seen per subscription and rejects any blob with a lower sequence.
  • Compromised upstream credentials: the bootstrap delegation:renew token is mintable only via the dedicated portal endpoint and is admin-gated. The token grants only renewal - it cannot read or modify any other resource.
  • Replay attacks on manifests: manifests older than 7 days are rejected.

What it does not defend against:

  • Compromised on-premise private key: a leaked private key lets an attacker sign licenses up to the cert’s validUntil. Mitigation: rotate the keypair (revoke old cert + create new with new key) and treat all licenses signed by the old key as suspect.
  • Compromised upstream master key: this is the trust root. Rotation procedures are out of scope here.