CT-OpsCT-Ops
Home
Getting Started
Architecture
Features
Deployment
GitHub
GitHub
Home
Getting Started
Architecture
Features
Deployment
GitHub
GitHub
  • Introduction
  • Getting Started

    • Installation
    • Configuration
    • Offline Agent Install Bundle
  • Architecture

    • Architecture Overview
    • Agent Architecture
    • Ingest Service
    • Deployment Profiles
  • Features

    • Hosts & Inventory
    • Host Groups
    • Networks
    • Monitoring
    • Certificate Management
    • SSL Certificate Checker
    • Alerts
    • Notifications
    • Reports
    • Terminal
    • Service Accounts & Identity
    • Directory User Lookup
    • Tasks & Runbooks
    • Scheduled Tasks
    • Tags
    • Notes
  • Deployment

    • Docker Compose Deployment
    • Air-Gap Deployment
    • Load Testing
  • Development

    • End-to-end testing
  • Licensing
  • Security

Air-Gap Deployment

CT-Ops is designed to work in fully air-gapped environments — no internet access is required for any core feature, including agent registration, metrics collection, alerting, and agent binary distribution.


What "Air-Gapped" Means Here

  • All Docker images are bundled into a single tarball for transfer
  • The web app serves agent binaries from internal storage — agents never download from the internet
  • Licence validation uses a bundled public key (no phone-home)
  • All TLS certificates are self-signed or from your internal CA
  • No external CDN dependencies — all static assets are self-hosted

Bundling the Images

On a machine with internet access, run the bundle script to pull all images and save them to a tarball:

# Clone the repo (or download just the scripts)
git clone https://github.com/carrtech-dev/ct-ops
cd ct-ops

# Bundle all images into a single tarball
bash deploy/scripts/airgap-bundle.sh

# Output: ct-ops-bundle-<version>.tar.gz

The tarball contains:

  • web image
  • ingest image
  • timescale/timescaledb image
  • docker-compose.single.yml
  • start.sh
  • .env.example

Transferring the Bundle

# Copy to the target server (adjust as appropriate)
scp ct-ops-bundle-*.tar.gz ops@air-gapped-server:/opt/ct-ops/

Or use a USB drive, secure FTP, or any other approved transfer mechanism.


Loading Images on the Target Server

cd /opt/ct-ops
tar -xzf ct-ops-bundle-*.tar.gz
docker load < images.tar

Starting the Stack

# First run: creates .env
./start.sh
nano .env     # configure BETTER_AUTH_URL, passwords, etc.

# Second run: starts everything
./start.sh

No internet access is used during startup. The web container runs migrations from the bundled Drizzle schema — no external migration service is contacted.


Agent Distribution

Agent binaries are hosted by the web app, not downloaded from GitHub. The ingest service serves a manifest of available agent versions, and the web app serves the binaries from its AGENT_DIST_DIR volume.

To add a new agent binary to an air-gapped deployment:

  1. Build the agent on a machine with internet access:

    make agent-all   # builds for linux/amd64, linux/arm64, darwin/amd64
    
  2. Transfer the binary to the server:

    scp dist/agent-linux-amd64 ops@server:/var/lib/ct-ops/agent-dist/
    
  3. Update the agent version manifest in the web UI: Settings → Agents → Update Manifest

Agents poll the ingest service for the minimum required version. When a newer binary is available, they download it from the web app — entirely within your network.


Installing Agents on Isolated Hosts

Hosts that cannot reach the CT-Ops server at install time (jump-host-only networks, change-controlled servers, or hosts behind a one-way data diode) can be enrolled using a portable install bundle generated by the CT-Ops UI.

From Settings → Agent Enrolment, an org_admin or super_admin clicks Download Install Bundle, picks the target OS / arch, and downloads a zip containing:

  • The agent binary for that platform
  • install.sh (Linux / macOS) or install.ps1 (Windows)
  • agent.toml pre-populated with this server's ingest address
  • SHA256SUMS and a README.md

The bundle can be transferred by any approved mechanism (USB, jump host, managed file share) and installed with a single command — no outbound connectivity to the CT-Ops server is required during install. A single-use, short-expiry enrolment token can be embedded in the bundle, or left out so the operator supplies it via CT_OPS_ORG_TOKEN at install time.

See Offline Agent Install Bundle for the full walkthrough.


Updates

To update CT-Ops in an air-gapped environment, repeat the bundle and transfer process with the new version:

# On internet-connected machine
CT_OPS_VERSION=v0.4.0 bash deploy/scripts/airgap-bundle.sh

# Transfer the new tarball
scp ct-ops-bundle-v0.4.0.tar.gz ops@server:/opt/ct-ops/

# On the target server
docker load < images.tar
docker compose -f docker-compose.single.yml pull   # no-op: images already loaded
docker compose -f docker-compose.single.yml up -d  # restarts with new images

Licence Validation

CT-Ops validates enterprise licences offline using a signed JWT verified against a public key that is bundled with the binary. No network request is made. To update a licence, paste the new licence key into Settings → Licence.

Edit this page on GitHub
Last Updated: 4/18/26, 10:33 PM
Contributors: Simon Carr, Claude Sonnet 4.6, Claude, Claude Opus 4.7
Prev
Docker Compose Deployment
Next
Load Testing