Skip to main content
CoreSDK
Deployment

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

ChannelDescription
stableProduction releases only. New versions ship after a 7-day bake period on edge. Default for new installs.
edgeCandidate releases. Receives new versions first. Suitable for staging environments.
manualNo 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 stable and edge channel 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:

  1. Download bundle to a temporary path.
  2. Verify JWS signature against the embedded public key.
  3. Verify the bundle manifest SHA-256 checksum against the embedded value in the JWS payload.
  4. If both pass, stage the new binary alongside the current one.
  5. Send SIGTERM to the running process and start the new binary.
  6. Run the health check endpoint (/healthz) until it returns 200 OK or the rollback timeout elapses.
  7. 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.target

After editing the unit file:

sudo systemctl daemon-reload
sudo systemctl restart coresdk-sidecar

To trigger a manual update check without waiting for the next interval:

core sidecar update --check

Docker

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-config

Update 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 coresdk

Air-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.jws

To 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-only

Bundles 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

VariableDefaultDescription
CORESDK_UPDATE_CHANNELstableUpdate channel: stable, edge, or manual
CORESDK_UPDATE_CHECK_INTERVAL_SECS3600Seconds between automatic update checks
CORESDK_UPDATE_DISABLEDfalseSet to true to disable the auto-updater entirely without changing the channel
CORESDK_UPDATE_ROLLBACK_TIMEOUT60Seconds to wait for health check before rolling back
CORESDK_UPDATE_BUNDLE_PATHPath to a local bundle for manual channel installs
CORESDK_RUNTIMEauto-detectedSet to k8s to disable built-in auto-update entirely

Next steps

On this page