HybridOps Studio — ctrl-01 Provisioner (How to Use)¶
Demo: Watch on YouTube
Source: View Script on GitHub
This HOWTO explains how to create a Day-0 → Day-1 control plane VM on Proxmox with a single command.
It’s designed for professionals and reviewers who want to see the automation process end-to-end — reproducible, auditable, and cloud-ready.
Reference: See ADR-0012: Control node runs as a VM (cloud-init) for design rationale and constraints.
Quick Start¶
Run these commands on your Proxmox host:
# 1) Upload and execute the provisioner
scp control/provision/provision-ctrl01-proxmox-ubuntu.sh root@<proxmox-ip>:/root/
ssh root@<proxmox-ip>
chmod +x /root/provision-ctrl01-proxmox-ubuntu.sh
/root/provision-ctrl01-proxmox-ubuntu.sh
# 2) After the VM boots, connect inside and monitor Day-1 progress
ssh ubuntu@172.16.10.5
sudo journalctl -u ctrl01-bootstrap.service -f
Default values (customisable via environment variables):
Bridge: vmbr1 IP: 172.16.10.5/28 Gateway: 172.16.10.1 DNS: 8.8.8.8
User: ubuntu Password: TempPass123! Bootstrap delay: 30 s
Prerequisites¶
- A Proxmox VE host with outbound internet access
- A storage that supports snippets (
localis auto-enabled by the script) - Optional SSH public key on the Proxmox host:
~/.ssh/id_rsa.pubor~/.ssh/id_ed25519.pub
Overview of the Provisioning Process¶
Day-0 (on Proxmox)¶
- Downloads the Ubuntu 22.04 (Jammy) cloud image.
- Generates a cloud-init file supporting both key and password login.
- Creates the VM, attaches cloud-init, and expands the disk (+28 GB).
- Configures IP, DNS, and console; boots the VM.
Day-1 (inside the VM)¶
- Expands the filesystem to use the full disk.
- Installs baseline packages (
qemu-guest-agent,curl,git,jq, etc.). - Installs Terraform, Packer, kubectl, Helm, Ansible, and optionally Jenkins.
- Clones the repository (
https://github.com/jeleel-muibi/hybridops.studio→/srv/hybridops). - Produces audit evidence:
/var/log/ctrl01_bootstrap.log,/var/lib/ctrl01/status.json. - Opens minimal firewall ports (SSH 22; Jenkins 8080 if enabled).
- Applies adaptive hardening — disables password login after the grace period once an SSH key is present.
Customisation via Environment Variables¶
VMID=101 VMNAME=ctrl-01 BRIDGE=vmbr1 IPCIDR=172.16.10.5/28 \
GATEWAY=172.16.10.1 DNS1=8.8.8.8 CIUSER=ubuntu CIPASS='ChangeMe!' \
ENABLE_FULL_BOOTSTRAP=true ENABLE_JENKINS=true ENABLE_AUTO_HARDEN=true \
HARDEN_GRACE_MIN=10 BOOTSTRAP_DELAY_SEC=30 \
REPO_URL='https://github.com/jeleel-muibi/hybridops.studio' REPO_BRANCH=main \
REPO_DIR=/srv/hybridops /root/provision-ctrl01-proxmox-ubuntu.sh
Key parameters:
- ENABLE_JENKINS=false — skip Jenkins setup (port 8080 not opened).
- ENABLE_AUTO_HARDEN=false — keep password authentication active.
- HARDEN_GRACE_MIN=20 — wait 20 min before enforcing key-only SSH.
- BOOTSTRAP_DELAY_SEC=60 — start Day-1 after 60 seconds.
Verifying Success¶
Inside the VM:
sudo journalctl -u ctrl01-bootstrap.service --no-pager | tail -n 60
sudo tail -n 200 /var/log/ctrl01_bootstrap.log
cat /var/lib/ctrl01/status.json
terraform -v
packer -v
kubectl version --client --output=yaml
helm version
ansible --version
If Jenkins was enabled:
sudo systemctl status jenkins --no-pager
sudo ss -lntp | grep :8080 || true
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
Success indicators:
- Jenkins reachable (if enabled)
- All CLI tools operational
- status.json shows "phase": "bootstrap-complete"
Related Documentation¶
- ADR 0012 — Control node runs as a VM
- Runbook — ctrl-01 bootstrap / verification
- Script —
control/provision/provision-ctrl01-proxmox-ubuntu.sh
Security Notes¶
- The default password is for initial bootstrap only.
- Adaptive hardening automatically disables password login once a key is present.
- UFW allows only SSH (22/tcp); Jenkins (8080/tcp) opens only when explicitly enabled.
- Log and status artifacts are immutable for audit and evidence purposes.
Maintainer: HybridOps.Studio License: MIT-0 for code, CC-BY-4.0 for documentation unless otherwise stated.