Add VM host deployment scripts (cloud-init + post-install)
Recommended base: Debian 13 Trixie (matches opencode-devbox base image). - cloud-init.yml: automated VM provisioning for Proxmox/OpenStack/cloud providers - setup-host.sh: interactive post-install script for manually-created VMs - README.md: documents both paths and VM sizing recommendations Installs Docker (official repo), Compose v2, ufw firewall, mosh support, and the IPv4 DNS preference workaround for Docker Hub IPv6 issues.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# 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
|
||||
|
||||
## 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**: `openstack server create --user-data cloud-init.yml ...`
|
||||
- **AWS/DigitalOcean/etc**: paste into the "user data" field
|
||||
|
||||
The VM boots with Docker installed, firewall configured, and your SSH key authorized. Log in as the `devbox` user.
|
||||
|
||||
### 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
|
||||
- IPv4 DNS preference (works around Docker Hub IPv6 connectivity issues)
|
||||
|
||||
## 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
|
||||
```
|
||||
@@ -0,0 +1,81 @@
|
||||
#cloud-config
|
||||
# cloud-init template for opencode-devbox host VM
|
||||
# Tested on Debian 13 (Trixie) and Ubuntu 24.04
|
||||
#
|
||||
# Usage:
|
||||
# - Proxmox: attach this file as cloud-init user-data in VM config
|
||||
# - OpenStack: pass as --user-data when creating the instance
|
||||
# - Cloud providers: paste into "user data" field
|
||||
#
|
||||
# Customize the marked sections before use.
|
||||
|
||||
# ── Hostname ─────────────────────────────────────────────────────────
|
||||
hostname: devbox
|
||||
manage_etc_hosts: true
|
||||
|
||||
# ── User ─────────────────────────────────────────────────────────────
|
||||
users:
|
||||
- name: devbox
|
||||
groups: sudo, docker
|
||||
shell: /bin/bash
|
||||
sudo: ALL=(ALL) NOPASSWD:ALL
|
||||
ssh_authorized_keys:
|
||||
# CUSTOMIZE: replace with your public SSH key
|
||||
- ssh-ed25519 AAAA... your-key-here
|
||||
|
||||
# ── Locale and timezone ──────────────────────────────────────────────
|
||||
locale: en_US.UTF-8
|
||||
timezone: Europe/Stockholm
|
||||
|
||||
# ── Package installation ─────────────────────────────────────────────
|
||||
package_update: true
|
||||
package_upgrade: true
|
||||
packages:
|
||||
- ca-certificates
|
||||
- curl
|
||||
- gnupg
|
||||
- git
|
||||
- tmux
|
||||
- mosh
|
||||
- ufw
|
||||
|
||||
# ── Commands to run at first boot ────────────────────────────────────
|
||||
runcmd:
|
||||
# Install Docker from official repository
|
||||
- install -m 0755 -d /etc/apt/keyrings
|
||||
- curl -fsSL https://download.docker.com/linux/$(. /etc/os-release && echo "$ID")/gpg -o /etc/apt/keyrings/docker.asc
|
||||
- chmod a+r /etc/apt/keyrings/docker.asc
|
||||
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/$(. /etc/os-release && echo \"$ID\") $(. /etc/os-release && echo \"$VERSION_CODENAME\") stable" > /etc/apt/sources.list.d/docker.list
|
||||
- apt-get update
|
||||
- apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
- usermod -aG docker devbox
|
||||
|
||||
# Firewall — allow SSH, mosh, and optionally HTTPS if running web-accessible services
|
||||
- ufw default deny incoming
|
||||
- ufw default allow outgoing
|
||||
- ufw allow ssh
|
||||
- ufw allow 60000:61000/udp
|
||||
- ufw --force enable
|
||||
|
||||
# Disable IPv6 preference for Docker (avoids intermittent Docker Hub connectivity issues)
|
||||
- echo 'precedence ::ffff:0:0/96 100' >> /etc/gai.conf
|
||||
|
||||
# Create projects directory for the user
|
||||
- mkdir -p /home/devbox/projects
|
||||
- chown devbox:devbox /home/devbox/projects
|
||||
|
||||
# ── Final message ───────────────────────────────────────────────────
|
||||
final_message: |
|
||||
opencode-devbox host VM ready.
|
||||
|
||||
Next steps:
|
||||
1. SSH in: ssh devbox@<this-host>
|
||||
2. Clone your opencode-devbox compose config, or:
|
||||
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
|
||||
3. Edit .env with your provider and keys
|
||||
4. docker compose up -d
|
||||
5. docker compose exec -u developer devbox opencode
|
||||
|
||||
Cloud-init run completed in $UPTIME seconds.
|
||||
Executable
+135
@@ -0,0 +1,135 @@
|
||||
#!/bin/bash
|
||||
# setup-host.sh — Post-install script for opencode-devbox host VM
|
||||
#
|
||||
# Run this on a fresh Debian 13 or Ubuntu 24.04 VM to set up everything
|
||||
# needed to run opencode-devbox containers.
|
||||
#
|
||||
# Usage:
|
||||
# curl -fsSL https://gitea.jordbo.se/joakimp/opencode-devbox/raw/branch/main/deploy/setup-host.sh | bash
|
||||
#
|
||||
# Or clone and run:
|
||||
# git clone https://gitea.jordbo.se/joakimp/opencode-devbox
|
||||
# cd opencode-devbox/deploy
|
||||
# ./setup-host.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ── Colors ──────────────────────────────────────────────────────────
|
||||
BOLD="\033[1m"; GREEN="\033[32m"; YELLOW="\033[33m"; RED="\033[31m"; RESET="\033[0m"
|
||||
info() { echo -e "${BOLD}==>${RESET} $*"; }
|
||||
ok() { echo -e "${GREEN}${BOLD}✓${RESET} $*"; }
|
||||
warn() { echo -e "${YELLOW}${BOLD}!${RESET} $*"; }
|
||||
err() { echo -e "${RED}${BOLD}✗${RESET} $*" >&2; }
|
||||
|
||||
# ── Detect distro ──────────────────────────────────────────────────
|
||||
if [[ ! -f /etc/os-release ]]; then
|
||||
err "Cannot detect Linux distribution — /etc/os-release missing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
. /etc/os-release
|
||||
|
||||
case "$ID" in
|
||||
debian|ubuntu)
|
||||
info "Detected $PRETTY_NAME"
|
||||
;;
|
||||
*)
|
||||
err "Unsupported distribution: $ID — this script only supports Debian and Ubuntu"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# ── Require sudo ────────────────────────────────────────────────────
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
err "Do not run as root — use a regular user with sudo"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! sudo -n true 2>/dev/null; then
|
||||
warn "This script needs sudo access. You may be prompted for your password."
|
||||
fi
|
||||
|
||||
# ── Update packages ─────────────────────────────────────────────────
|
||||
info "Updating package index..."
|
||||
sudo apt-get update -qq
|
||||
|
||||
info "Installing base packages..."
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
ca-certificates curl gnupg git tmux mosh ufw
|
||||
|
||||
# ── Docker ──────────────────────────────────────────────────────────
|
||||
if command -v docker &>/dev/null; then
|
||||
ok "Docker already installed ($(docker --version))"
|
||||
else
|
||||
info "Installing Docker from official repository..."
|
||||
sudo install -m 0755 -d /etc/apt/keyrings
|
||||
sudo curl -fsSL "https://download.docker.com/linux/${ID}/gpg" -o /etc/apt/keyrings/docker.asc
|
||||
sudo chmod a+r /etc/apt/keyrings/docker.asc
|
||||
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/${ID} ${VERSION_CODENAME} stable" | \
|
||||
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
|
||||
ok "Docker installed: $(docker --version)"
|
||||
fi
|
||||
|
||||
# ── Add user to docker group ────────────────────────────────────────
|
||||
if groups | grep -q docker; then
|
||||
ok "User already in docker group"
|
||||
else
|
||||
info "Adding $USER to docker group..."
|
||||
sudo usermod -aG docker "$USER"
|
||||
warn "You must log out and back in for docker group to take effect"
|
||||
warn "Or run: newgrp docker"
|
||||
fi
|
||||
|
||||
# ── Firewall ────────────────────────────────────────────────────────
|
||||
info "Configuring firewall (ufw)..."
|
||||
sudo ufw default deny incoming >/dev/null
|
||||
sudo ufw default allow outgoing >/dev/null
|
||||
sudo ufw allow ssh >/dev/null
|
||||
sudo ufw allow 60000:61000/udp comment 'mosh' >/dev/null
|
||||
if ! sudo ufw status | grep -q "Status: active"; then
|
||||
sudo ufw --force enable
|
||||
fi
|
||||
ok "Firewall active — SSH and mosh allowed"
|
||||
|
||||
# ── IPv4 preference for Docker Hub ──────────────────────────────────
|
||||
if ! grep -q 'precedence ::ffff:0:0/96' /etc/gai.conf 2>/dev/null; then
|
||||
info "Setting IPv4 preference in /etc/gai.conf..."
|
||||
echo 'precedence ::ffff:0:0/96 100' | sudo tee -a /etc/gai.conf > /dev/null
|
||||
ok "IPv4 preferred for DNS resolution"
|
||||
fi
|
||||
|
||||
# ── Create projects directory ───────────────────────────────────────
|
||||
if [[ ! -d "$HOME/projects" ]]; then
|
||||
mkdir -p "$HOME/projects"
|
||||
ok "Created ~/projects"
|
||||
fi
|
||||
|
||||
# ── Done ────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
ok "Host setup complete"
|
||||
echo ""
|
||||
cat <<EOF
|
||||
${BOLD}Next steps:${RESET}
|
||||
|
||||
1. If you weren't already in the docker group, log out and back in:
|
||||
exit
|
||||
ssh <your-user>@<this-host>
|
||||
|
||||
2. Set up opencode-devbox:
|
||||
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
|
||||
|
||||
3. Edit .env with your provider and API keys:
|
||||
vim .env
|
||||
|
||||
4. Start and connect:
|
||||
docker compose up -d
|
||||
docker compose exec -u developer devbox opencode
|
||||
|
||||
EOF
|
||||
Reference in New Issue
Block a user