Skip to main content

Air-gapped Installation

This guide covers installing the PatchCTL agent in environments without direct internet access.

Limited Functionality

Air-gapped installations require a proxy or bastion host for the agent to communicate with the PatchCTL API. Fully offline operation is not supported.

Architecture Options

Option 1: HTTPS Proxy

Route agent traffic through an HTTPS proxy with internet access:

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│ Air-gapped │ │ HTTPS Proxy │ │ PatchCTL API │
│ Server │────►│ (Squid, etc) │────►│ │
│ │ │ │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘

Option 2: Bastion Host

Use a bastion host with internet access to relay traffic:

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│ Air-gapped │ │ Bastion Host │ │ PatchCTL API │
│ Server │────►│ (SSH tunnel) │────►│ │
│ │ │ │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘

Prerequisites

  1. A method to transfer files to the air-gapped network
  2. Either a proxy server or bastion host with internet access
  3. Firewall rules allowing the required connectivity

Step 1: Download Files Externally

On a machine with internet access, download the required files:

# Create a transfer directory
mkdir patchctl-transfer && cd patchctl-transfer

# Download the appropriate binary for your distro
# For Ubuntu/Debian:
curl -fsSLO https://downloads.patchctl.com/latest/patchctl-agent-linux-amd64

# For RHEL/Rocky:
curl -fsSLO https://downloads.patchctl.com/latest/patchctl-agent-linux-amd64-rhel

# For SUSE:
curl -fsSLO https://downloads.patchctl.com/latest/patchctl-agent-linux-amd64-suse

# Verify checksums (recommended)
sha256sum patchctl-agent-*

Step 2: Transfer to Air-gapped Network

Transfer the downloaded binary using your approved method:

  • USB drive
  • Secure file transfer
  • Network share
  • CD/DVD

Step 3: Install on Target Server

# Create directories
sudo mkdir -p /opt/patchctl/bin /etc/patchctl

# Copy binary
sudo cp patchctl-agent-linux-amd64 /opt/patchctl/bin/patchctl-agent
sudo chmod +x /opt/patchctl/bin/patchctl-agent

# Create configuration (see below for proxy settings)
sudo nano /etc/patchctl/config.json

Step 4: Configure Proxy

Environment Variables

Set proxy environment variables in the systemd service:

sudo tee /etc/systemd/system/patchctl.service > /dev/null << 'EOF'
[Unit]
Description=PatchCTL Agent
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/opt/patchctl/bin/patchctl-agent
Restart=always
RestartSec=10
User=root
WorkingDirectory=/opt/patchctl

# Proxy configuration
Environment="HTTPS_PROXY=http://proxy.internal:8080"
Environment="NO_PROXY=localhost,127.0.0.1,.internal"

[Install]
WantedBy=multi-user.target
EOF

Configuration File

Create the agent configuration:

{
"license_key": "YOUR_LICENSE_KEY",
"api_endpoint": "https://api.patchctl.com",
"heartbeat_interval": 300,
"log_level": "info"
}

Step 5: Start the Service

sudo systemctl daemon-reload
sudo systemctl enable patchctl
sudo systemctl start patchctl

SSH Tunnel Method

If using an SSH tunnel through a bastion:

On the Air-gapped Server

Create a persistent SSH tunnel:

# Create tunnel (runs in background)
ssh -f -N -L 8443:api.patchctl.com:443 user@bastion.example.com

Configure the agent to use localhost:

{
"license_key": "YOUR_LICENSE_KEY",
"api_endpoint": "https://localhost:8443",
"heartbeat_interval": 300,
"log_level": "info"
}

Persistent Tunnel with autossh

For production, use autossh to maintain the tunnel:

# Install autossh
sudo apt install autossh # or dnf/zypper

# Create systemd service for tunnel
sudo tee /etc/systemd/system/patchctl-tunnel.service > /dev/null << 'EOF'
[Unit]
Description=PatchCTL API Tunnel
Before=patchctl.service

[Service]
ExecStart=/usr/bin/autossh -M 0 -N -L 8443:api.patchctl.com:443 user@bastion.example.com
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable patchctl-tunnel
sudo systemctl start patchctl-tunnel

Verification

# Check agent status
sudo systemctl status patchctl

# Test API connectivity through proxy/tunnel
curl -x http://proxy.internal:8080 -I https://api.patchctl.com/health
# or for tunnel:
curl -I https://localhost:8443/health

Troubleshooting

Proxy Authentication

If your proxy requires authentication:

Environment="HTTPS_PROXY=http://username:password@proxy.internal:8080"

Certificate Issues

If using an SSL-inspecting proxy, add the proxy's CA certificate:

# Ubuntu/Debian
sudo cp proxy-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

# RHEL/Rocky
sudo cp proxy-ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust

# SUSE
sudo cp proxy-ca.crt /etc/pki/trust/anchors/
sudo update-ca-certificates

Connection Timeouts

Increase timeout if network is slow:

{
"license_key": "YOUR_LICENSE_KEY",
"api_endpoint": "https://api.patchctl.com",
"heartbeat_interval": 300,
"connection_timeout": 60,
"log_level": "info"
}

Security Considerations

  • Use authenticated proxies where possible
  • Rotate SSH keys for tunnel access
  • Monitor tunnel/proxy logs for anomalies
  • Consider network segmentation between proxy and internal servers