Sidecar Auto-Update
Signed JWS update bundles, automatic rollback on failed health checks, and update channels for the CoreSDK sidecar daemon.
Sidecar Auto-Update
The CoreSDK sidecar daemon can update itself in-place without requiring manual intervention. Update bundles are signed with RS256 or ES256 and the signature is verified before any binary is applied. If the post-update health check fails, the sidecar rolls back automatically to the previous version.
This feature targets non-Kubernetes environments. On Kubernetes, use a rolling update via your
Deployment spec instead — the sidecar has no built-in auto-update logic when CORESDK_RUNTIME=k8s
is detected.
UpdateChannel enum
The UpdateChannel type is the Rust representation of the channel setting, used when embedding the sidecar updater in custom tooling:
use coresdk_server::update::UpdateChannel;
let channel = UpdateChannel::from_env(); // reads CORESDK_UPDATE_CHANNEL
match channel {
UpdateChannel::Stable => { /* production releases only */ }
UpdateChannel::Edge => { /* candidate releases */ }
UpdateChannel::Manual => { /* no automatic updates; air-gapped safe */ }
}Update channels
| Channel | Description |
|---|---|
stable | Production releases only. New versions ship after a 7-day bake period on edge. Default for new installs. |
edge | Candidate releases. Receives new versions first. Suitable for staging environments. |
manual | No automatic updates. The sidecar only applies an update when instructed explicitly via the CLI or API. Required for air-gapped deployments. |
Set the channel via the CORESDK_UPDATE_CHANNEL environment variable or in the sidecar YAML:
# coresdk-sidecar.yaml
update:
channel: stable # stable | edge | manual
check_interval: 3600 # seconds between update checks (default: 3600)
rollback_timeout: 60 # seconds to wait for health check before rollback (default: 60)Signature verification
Update bundles are distributed as JWS compact serialisation. The sidecar verifies the signature against the CoreSDK update public key before writing anything to disk.
- RS256 is used for
stableandedgechannel bundles. - ES256 (ECDSA P-256) is used for bundles targeted at air-gapped environments.
- The public key is embedded in the sidecar binary at build time and cannot be overridden at runtime.
- A bundle with an invalid or missing signature is rejected and the running binary is left untouched.
Verification happens in the following order:
- Download bundle to a temporary path.
- Verify JWS signature against the embedded public key.
- Verify the bundle manifest SHA-256 checksum against the embedded value in the JWS payload.
- If both pass, stage the new binary alongside the current one.
- Send
SIGTERMto the running process and start the new binary. - Run the health check endpoint (
/healthz) until it returns200 OKor the rollback timeout elapses. - On timeout or non-200 response, kill the new binary and restart the previous one.
systemd
# /etc/systemd/system/coresdk-sidecar.service
[Unit]
Description=CoreSDK Sidecar
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/coresdk-sidecar --config /etc/coresdk/sidecar.yaml
Restart=on-failure
RestartSec=5s
# Update channel and health check configuration
Environment=CORESDK_UPDATE_CHANNEL=stable
Environment=CORESDK_UPDATE_CHECK_INTERVAL=3600
Environment=CORESDK_UPDATE_ROLLBACK_TIMEOUT=60
# Run as a dedicated non-root user
User=coresdk
Group=coresdk
# Allow the sidecar to write the staged binary alongside itself
ReadWritePaths=/usr/local/bin
ReadWritePaths=/var/lib/coresdk
[Install]
WantedBy=multi-user.targetAfter editing the unit file:
sudo systemctl daemon-reload
sudo systemctl restart coresdk-sidecarTo trigger a manual update check without waiting for the next interval:
core sidecar update --checkDocker
When running the sidecar as a container, set the channel via an environment variable. Mount a
writable volume at /var/lib/coresdk so the sidecar can stage updated binaries.
# docker-compose.yaml
services:
coresdk-sidecar:
image: coresdk/sidecar:latest
restart: unless-stopped
environment:
CORESDK_UPDATE_CHANNEL: stable
CORESDK_UPDATE_CHECK_INTERVAL: "3600"
CORESDK_UPDATE_ROLLBACK_TIMEOUT: "60"
CORESDK_TENANT: acme
volumes:
- ./coresdk-sidecar.yaml:/etc/coresdk/sidecar.yaml:ro
- coresdk-data:/var/lib/coresdk
ports:
- "7700:7700" # gRPC
- "7701:7701" # HTTP / health
volumes:
coresdk-data:The container image is rebuilt on the stable or edge cadence and pushed to Docker Hub. If you
prefer to control image versions yourself and not use the built-in updater, pin the image tag and
set CORESDK_UPDATE_CHANNEL=manual.
Kubernetes
On Kubernetes, disable the built-in auto-update and manage sidecar versions through your standard image promotion pipeline.
# k8s/coresdk-sidecar-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: coresdk-sidecar
namespace: coresdk
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: coresdk-sidecar
template:
metadata:
labels:
app: coresdk-sidecar
spec:
containers:
- name: sidecar
image: coresdk/sidecar:1.2.0 # pin to a specific release
env:
- name: CORESDK_UPDATE_CHANNEL
value: manual # disable built-in updater on K8s
- name: CORESDK_TENANT
value: acme
ports:
- containerPort: 7700 # gRPC
- containerPort: 7701 # HTTP / health
readinessProbe:
httpGet:
path: /healthz
port: 7701
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: 7701
initialDelaySeconds: 15
periodSeconds: 30
volumeMounts:
- name: config
mountPath: /etc/coresdk
readOnly: true
volumes:
- name: config
configMap:
name: coresdk-sidecar-configUpdate the sidecar on Kubernetes by changing the image tag and applying the manifest:
kubectl set image deployment/coresdk-sidecar sidecar=coresdk/sidecar:1.3.0 -n coresdk
kubectl rollout status deployment/coresdk-sidecar -n coresdkAir-gapped deployments
Air-gapped environments cannot reach the CoreSDK update server. Use manual channel and distribute
bundles through your internal artifact store.
# coresdk-sidecar.yaml (air-gapped)
update:
channel: manual
bundle_path: /mnt/artifact-store/coresdk-sidecar-1.3.0.jwsTo apply a pre-downloaded bundle:
# Verify and apply a locally staged bundle
core sidecar update --bundle /mnt/artifact-store/coresdk-sidecar-1.3.0.jws
# Verify the bundle signature without applying
core sidecar update --bundle /mnt/artifact-store/coresdk-sidecar-1.3.0.jws --verify-onlyBundles for air-gapped distribution are signed with ES256 (ECDSA P-256) and published alongside
each stable release on the CoreSDK GitHub releases page. Download the .jws file, transfer it
through your internal pipeline, and apply with the CLI command above.
Environment variables
| Variable | Default | Description |
|---|---|---|
CORESDK_UPDATE_CHANNEL | stable | Update channel: stable, edge, or manual |
CORESDK_UPDATE_CHECK_INTERVAL_SECS | 3600 | Seconds between automatic update checks |
CORESDK_UPDATE_DISABLED | false | Set to true to disable the auto-updater entirely without changing the channel |
CORESDK_UPDATE_ROLLBACK_TIMEOUT | 60 | Seconds to wait for health check before rolling back |
CORESDK_UPDATE_BUNDLE_PATH | — | Path to a local bundle for manual channel installs |
CORESDK_RUNTIME | auto-detected | Set to k8s to disable built-in auto-update entirely |
Next steps
- Deployment overview — Docker and systemd setup
- Air-gapped deployment — offline environments and bundle distribution
- Configuration reference — full sidecar configuration options
Air-Gapped Deployments
Run CoreSDK with zero outbound connections — offline policy evaluation, local JWT validation, and manual artifact delivery for air-gapped and disconnected environments.
Data Residency
Region-specific data routing, per-tenant region pinning, and on-premise isolation for GDPR, UAE PDPL, and data sovereignty requirements.