# Deploy — Host VM setup Scripts for setting up a fresh Linux VM to host opencode-devbox. ## Files - **`cloud-init.yml`** — cloud-init user-data template for automated VM provisioning on OpenStack, Proxmox, or any cloud with cloud-init support - **`setup-host.sh`** — interactive post-install script for VMs that weren't provisioned with cloud-init - **`setup-openstack-secgroup.sh`** — creates an OpenStack security group with the right rules (SSH, mosh, ICMP) ## Supported distributions - **Debian 13 (Trixie)** — recommended (matches opencode-devbox base image) - **Ubuntu 24.04 LTS** — also works Other distributions will need manual adaptation. ## Quick start ### Option 1: Cloud-init (automated) Customize `cloud-init.yml` — replace the SSH public key and optionally the hostname/timezone. Then use it during VM creation: - **Proxmox**: attach as cloud-init user-data - **OpenStack**: pass via `--user-data` flag (see full example below) - **AWS/DigitalOcean/etc**: paste into the "user data" field #### Full OpenStack example Cloud-init only handles guest configuration — flavor, image, network, and security group must be specified explicitly at creation time. > **Note:** Do not use `--key-name` — the SSH key is configured in `cloud-init.yml` under `ssh_authorized_keys` for the `devbox` user. The `--key-name` flag injects into the image's default user (e.g. `debian`), not the `devbox` user created by cloud-init. ```bash # List available flavors to choose appropriate sizing openstack flavor list # Create the security group first (one-time, see below) ./setup-openstack-secgroup.sh # Basic — boot from default storage openstack server create \ --flavor c4m8 \ --image Debian-13-Trixie \ --network my-network \ --security-group opencode-devbox \ --user-data cloud-init.yml \ devbox-vm ``` If your cloud offers NVMe-backed (performance) volumes, boot from one for faster Docker and build I/O: ```bash # Performance — boot from NVMe volume (40GB, preserved on instance deletion) openstack server create \ --flavor c4m8 \ --network my-network \ --security-group opencode-devbox \ --user-data cloud-init.yml \ --block-device source_type=image,uuid=$(openstack image show Debian-13-Trixie -f value -c id),destination_type=volume,volume_size=40,delete_on_termination=false,boot_index=0,volume_type=performance \ devbox-vm ``` > **Note:** The inline `volume_type` parameter requires API microversion 2.67+. If the server goes to ERROR state, check your volume quota (`openstack quota show`) and try creating the volume separately: > ```bash > openstack volume create --image Debian-13-Trixie --size 40 --type performance --bootable devbox-boot-volume > openstack server create --flavor c4m8 --volume devbox-boot-volume --network my-network --security-group opencode-devbox --user-data cloud-init.yml devbox-vm > ``` #### Floating IP OpenStack doesn't support assigning a floating IP at instance creation time — it's a separate step after the VM is active: ```bash # Allocate a new floating IP from the external network openstack floating ip create # Assign it to the VM openstack server add floating ip devbox-vm ``` To find your external network name: `openstack network list --external`. If you already have an unassigned floating IP, skip the create step. The VM boots with Docker installed, firewall configured (or skipped on OpenStack), and your SSH key authorized. Log in as the `devbox` user. ### Console password (optional) The cloud-init template uses SSH key authentication only — no password is set by default. This is sufficient for normal use since the `devbox` user has passwordless `sudo`. A password is only needed for: - **Emergency console access** — logging in via OpenStack Horizon console (noVNC) or Proxmox VNC when SSH is unreachable - **`su - devbox`** — switching to the devbox user from another account To enable console access, uncomment the `chpasswd` block in `cloud-init.yml` before deploying: ```yaml chpasswd: expire: false users: - name: devbox password: your-password-here type: text ``` For an already-running VM, set a password via SSH: ```bash sudo passwd devbox ``` ### Option 2: Post-install script (manual) On a fresh Debian/Ubuntu VM: ```bash curl -fsSL https://gitea.jordbo.se/joakimp/opencode-devbox/raw/branch/main/deploy/setup-host.sh | bash ``` Or clone and run: ```bash git clone https://gitea.jordbo.se/joakimp/opencode-devbox cd opencode-devbox/deploy ./setup-host.sh ``` ## What gets installed - Docker Engine (from Docker's official apt repo, not distro's `docker.io`) - Docker Compose plugin (v2) - `tmux`, `mosh`, `git` - `ufw` firewall with SSH (22) and mosh (UDP 60000-61000) allowed — **skipped on OpenStack** (detected automatically; use security groups instead) - IPv4 DNS preference (works around Docker Hub IPv6 connectivity issues) ## OpenStack security groups On OpenStack, firewalling is handled by security groups rather than ufw. The `setup-host.sh` script detects OpenStack automatically and skips ufw configuration. To create the required security group: ```bash ./setup-openstack-secgroup.sh ``` This creates a security group named `opencode-devbox` with rules for SSH (TCP 22), mosh (UDP 60000-61000), and ICMP. Apply it to your instance: ```bash # New instance openstack server create --security-group opencode-devbox ... # Existing instance openstack server add security group opencode-devbox ``` ## VM sizing recommendations | Use case | vCPU | RAM | Disk | |---|---|---|---| | Minimum | 2 | 4 GB | 20 GB | | Recommended | 4 | 8 GB | 40 GB | | Heavy use (Rust/Python builds, multi-project) | 8 | 16 GB | 80 GB | ## After VM setup ```bash mkdir -p ~/opencode-devbox && cd ~/opencode-devbox curl -sL https://gitea.jordbo.se/joakimp/opencode-devbox/raw/branch/main/docker-compose.yml -o docker-compose.yml curl -sL https://gitea.jordbo.se/joakimp/opencode-devbox/raw/branch/main/.env.example -o .env vim .env # configure provider and keys docker compose up -d docker compose exec -u developer devbox opencode ```