Saturday Midday Update: Lots of Automation Work
Introduction
Today was a major milestone in the automation of CodexMCP’s infrastructure. We tackled automated OpenSearch deployments, fine-tuned Cloud-Init provisioning, and streamlined VM bootstrapping within Proxmox.
The result? A fully deployed multi-node OpenSearch cluster in under 5 minutes, all built dynamically from YAML configurations with no manual intervention. This is a blend of old-school UNIX thinking and modern infrastructure automation, ensuring full visibility into system operations while eliminating unnecessary abstraction.
Here’s a deep dive into everything we accomplished.
1. Automating OpenSearch Deployment in Proxmox
The first major challenge was getting OpenSearch installed across multiple Proxmox-deployed VMs, without relying on Ansible or any external tools. Instead, we leveraged YAML-based configurations and Go-based VM bootstrap automation.
1.1. VM Configuration in vmconfig.yaml
Instead of hardcoding anything into the Go code, we designed a clear and explicit YAML configuration that defines every step of the deployment.
Example vmconfig.yaml
proxmox_host: "https://yourproxmoxhost:port"
proxmox_node: "proxmoxnode"
api_token: "env"
ssh:
username: "codexmcp"
private_key: "/home/youruser/.ssh/id_rsa"
logging_server:
name: "logs-core-1"
ipaddress: "10.0.1.100"
global_software:
- "sudo apt update && sudo apt install -y rsyslog"
- "sudo systemctl enable rsyslog && sudo systemctl start rsyslog"
- "echo '*.* @{{LOGGING_SERVER_IP}}:514;RSYSLOG_ForwardFormat' | sudo tee /etc/rsyslog.d/50-remote.conf > /dev/null"
- "sudo systemctl restart rsyslog"
clusters:
opensearch_cluster:
multi_node: true
config_template: |
cluster.name: codexmcp-cluster
node.name: "{{NODE_NAME}}"
network.host: "0.0.0.0"
{{DYNAMIC_DISCOVERY}}
plugins.security.disabled: true
software:
- "sudo apt-get update && sudo apt-get install -y lsb-release ca-certificates curl gnupg2"
- "curl -fsSL https://artifacts.opensearch.org/publickeys/opensearch.pgp | sudo gpg --dearmor -o /usr/share/keyrings/opensearch-keyring.gpg"
- "echo 'deb [signed-by=/usr/share/keyrings/opensearch-keyring.gpg] https://artifacts.opensearch.org/releases/bundle/opensearch/2.x/apt stable main' | sudo tee /etc/apt/sources.list.d/opensearch-2.x.list > /dev/null"
- "sudo apt-get update"
- "sudo apt-get install -y opensearch"
- "sudo mkdir -p /etc/opensearch"
- "sudo chown -R opensearch:opensearch /etc/opensearch /var/log/opensearch /var/lib/opensearch"
- "sudo chmod -R 750 /etc/opensearch"
- "sudo systemctl daemon-reload"
- "sudo systemctl enable --now opensearch"
vms:
- vmid: 2019
name: "os-core-1"
ipaddress: "10.0.1.151"
gateway: "10.0.1.1"
- vmid: 2020
name: "os-core-2"
ipaddress: "10.0.1.152"
gateway: "10.0.1.1"
- vmid: 2021
name: "os-core-3"
ipaddress: "10.0.1.153"
gateway: "10.0.1.1"
This structure ensures absolute clarity on what’s happening at every step.
2. Breaking Down the Automation Code
We split the Go automation logic into modular, single-responsibility files:
.
├── APIAttachCloudInit.go
├── APICloneVM.go
├── APIConfigureNetwork.go
├── APIConfigureVM.go
├── APIProxmoxRequest.go
├── APIRemoveSSHKey.go
├── APIResizeDisk.go
├── APIStartVM.go
├── APIVmExists.go
├── bootstrapvms.go
├── BSLoadInventory.go
├── BSRunRemoteCommand.go
├── BSWaitForApt.go
├── BSWaitForSSH.go
└── OSBuildConfig.go
Each file only imports what it needs, keeping things lightweight, easy to debug, and scalable.
3. Fixing the OpenSearch Installation Issues
OpenSearch had a painful installation process that required the following fixes:
3.1. Disabling Security During Bootstrap
OpenSearch won’t install cleanly if security is enabled, so we inject this config:
plugins.security.disabled: true
via:
- "sudo sh -c 'cat <<EOF > /etc/opensearch/opensearch.yml\n{{OPENSEARCH_CONFIG}}\nEOF'"
3.2. Fixing OpenSearch Permissions
Even after installation, OpenSearch wouldn’t start due to permission errors.
We solved this by adding:
- "sudo mkdir -p /etc/opensearch /var/log/opensearch /var/lib/opensearch"
- "sudo chown -R opensearch:opensearch /etc/opensearch /var/log/opensearch /var/lib/opensearch"
- "sudo chmod -R 750 /etc/opensearch"
3.3. Ensuring OpenSearch Starts Correctly
We had to run:
- "sudo su -c 'systemctl daemon-reload && systemctl start opensearch'"
because regular sudo
wasn’t enough in some cases.
4. Proxmox Cloud-Init Image Creation
We ran into issues with Ubuntu Server freezing during install because 1GB RAM was too low.
We fixed this by installing Ubuntu with 2GB RAM, then shrinking it for Cloud-Init.
Steps for a Clean Cloud-Init Template
Convert to a Proxmox Template
qm template 9000
Install Ubuntu (Minimal) and Cloud-Init
apt update && apt install -y cloud-init
cloud-init clean
shutdown -h now
Create a new VM
qm create 9000 --name ubuntu-template --memory 2048 --cores 2 --net0 virtio,bridge=vmbr0
qm set 9000 --scsihw virtio-scsi-pci --scsi0 local-lvm:10
qm set 9000 --cdrom local:iso/ubuntu-22.04-live-server-amd64.iso
qm set 9000 --boot order=ide2
Now, we can clone any number of VMs instantly from this template.
5. Final Deployment: Full Cluster Automation
Once the template and bootstrapper were ready, we deployed a full OpenSearch cluster with a single command:
go run main.go --bootstrapvms --cluster opensearch_cluster
After 5 minutes, we had a fully working OpenSearch cluster, all configured dynamically from YAML.
Final test:
curl 10.0.1.151:9200
Result:
{
"name" : "os-core-1",
"cluster_name" : "codexmcp-cluster",
"version" : {
"distribution" : "opensearch",
"number" : "2.19.0"
}
}
Conclusion
This approach eliminates unnecessary abstraction while ensuring fully automated deployments.
It’s a fusion of old-school sysadmin knowledge and modern DevOps principles—fully automated yet fully transparent.
-Remember This is all Alpha at this point
--Bryan