Bastion Setup & Deployment
Purpose: For operators, shows how to configure the bastion as local container registry and package repository.
Prerequisites
- Bastion host running Ubuntu 24.04 in Zone C (disconnected network)
- Zarf CLI installed on the bastion
- The
zarf-package-opencenter-airgap-amd64-*.tar.zstartifact transferred from Zone A - SSH access from bastion to all target cluster nodes
- Minimum 100 GB free disk on
/opt/opencenter - Ports 35000 (registry) and 80 (nginx) open to target node subnet
Steps
1. Verify the artifact
Confirm the package checksum matches what was recorded in Zone A:
sha256sum -c package.sha256
If the checksum fails, do not proceed — the artifact may be corrupted or tampered with.
2. Deploy the Zarf package
zarf package deploy zarf-package-opencenter-airgap-amd64-*.tar.zst --confirm
Zarf prompts for variables unless --confirm is passed. Key variables and their defaults:
| Variable | Default | Description |
|---|---|---|
BASTION_IP | (prompted) | IP address of this bastion host |
SSH_USER | deployer | SSH user for node access |
INSTALL_PATH | /opt/opencenter | Root directory for all artifacts |
REGISTRY_PORT | 35000 | Local OCI registry listen port |
NGINX_PORT | 80 | Nginx file server listen port |
The deploy runs five components in order: bootstrap-tools → terraform-providers (optional) → kubespray-core → k8s-images (optional) → deploy-cluster.
3. Confirm services are running
After deploy completes, the deploy-cluster component runs setup-all.sh, which starts the registry and nginx. Verify:
# Registry health check
curl -s http://localhost:35000/v2/_catalog | head
# Nginx file server
curl -s http://localhost:80/ | head
# Check container status (registry runs via podman)
podman ps --filter name=local-registry
4. Validate target node connectivity
From the bastion, confirm each target node can reach the bastion services:
for node in 192.168.1.11 192.168.1.12 192.168.1.13; do
ssh ${SSH_USER}@${node} "curl -sf http://${BASTION_IP}:35000/v2/_catalog > /dev/null && echo ${node}: registry OK || echo ${node}: registry FAIL"
ssh ${SSH_USER}@${node} "curl -sf http://${BASTION_IP}:80/ > /dev/null && echo ${node}: nginx OK || echo ${node}: nginx FAIL"
done
5. Configure target nodes to use bastion
Target nodes need their container runtime and package manager pointed at the bastion. Kubespray handles this automatically when run from the bastion, but for manual verification:
# containerd registry mirror (set by Kubespray)
cat /etc/containerd/config.toml | grep -A3 'registry.mirrors'
# APT repository (set by setup-all.sh)
cat /etc/apt/sources.list.d/opencenter-local.list
Expected APT source line:
deb [trusted=yes] http://<BASTION_IP>:80/repos/ubuntu jammy main
Verification
Run a quick pull test from any target node:
# Pull an image through the bastion registry
crictl pull ${BASTION_IP}:35000/registry:2.8.3
# Install a package from the bastion repo
apt-get update && apt-get install -y jq
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
curl: (7) Failed to connect on port 35000 | Registry container not running | podman start local-registry |
curl: (7) Failed to connect on port 80 | Nginx not started | Check setup-all.sh logs in /opt/opencenter/logs/ |
| Target node can't resolve bastion | DNS not configured | Use IP address directly or add /etc/hosts entry |
manifest unknown when pulling image | Image not loaded into registry | Re-run load-push-all-images.sh from /opt/opencenter/target-scripts/ |