Add control plane deploy script and fix UI healthcheck

This commit is contained in:
oskar 2026-05-18 21:34:57 +02:00
parent b7251ac416
commit 9f20dcae05
4 changed files with 98 additions and 17 deletions

View file

@ -20,19 +20,22 @@ All services adhere to **filesystem-first** semantics, using `/opt/homelab/` as
- Repository cloned to `/home/oskar/homelab-codex-ws`.
### 2. Bootstrap
Run the bootstrap script to initialize the runtime filesystem and start the stack:
```bash
./scripts/bootstrap/vps-control-plane.sh
```
### 3. Verification
Verify the stack is healthy:
Run the local deployment script on the VPS to initialize the runtime filesystem and start the stack:
```bash
cd services/control-plane
docker compose ps
curl http://localhost:8080/summary
bash deploy-local.sh
```
### 3. Verification
Verify the stack is healthy using the deployment script or check container status on the VPS:
```bash
# Check status via deploy script
./scripts/deploy/deploy-control-plane.sh --ssh
# Manual status check on VPS
docker ps --filter "name=control-plane"
```
## Operational Workflows
@ -45,14 +48,16 @@ curl http://localhost:8080/summary
### Recovery Flow
In case of control plane failure:
1. Check logs: `docker compose logs -f`.
2. Restart stack: `docker compose restart`.
3. Rebuild world state: Delete `/opt/homelab/state/observer_checkpoint.json` and restart the observer service.
1. Check logs using `docker logs`.
2. Restart stack using the local deployment script: `bash deploy-local.sh`.
3. Rebuild world state: Delete `/opt/homelab/state/observer_checkpoint.json` and redeploy.
### Upgrade Flow
1. Pull latest changes from git.
2. Run bootstrap script again: `./scripts/bootstrap/vps-control-plane.sh`.
- This will rebuild images and restart containers with new code.
To deploy updates from the SOLARIA/control host:
```bash
./scripts/deploy/deploy-control-plane.sh --ssh
```
### Rollback Semantics
Since the runtime is filesystem-first and append-only:

View file

@ -0,0 +1,23 @@
#!/bin/bash
# scripts/deploy/deploy-control-plane.sh
set -e
VPS_IP="100.95.58.48"
USER="oskar"
REMOTE_REPO_PATH="/home/oskar/homelab-codex-ws"
MODE=$1
case "$MODE" in
"--ssh")
echo "Deploying to VPS ($VPS_IP) via SSH..."
ssh "$USER@$VPS_IP" "cd $REMOTE_REPO_PATH && git pull origin master && cd services/control-plane && bash deploy-local.sh"
;;
"--print")
echo "ssh $USER@$VPS_IP \"cd $REMOTE_REPO_PATH && git pull origin master && cd services/control-plane && bash deploy-local.sh\""
;;
*)
echo "Usage: $0 [--ssh|--print]"
exit 1
;;
esac

View file

@ -0,0 +1,53 @@
#!/bin/bash
# services/control-plane/deploy-local.sh
set -e
# 1. Validate it is deploying control-plane
if [[ ! $(pwd) == *"/services/control-plane" ]]; then
echo "Error: Script must be run from services/control-plane directory"
exit 1
fi
if [[ ! -f "docker-compose.yml" ]]; then
echo "Error: docker-compose.yml not found"
exit 1
fi
echo "--- Preparing Control Plane Directories ---"
# 2. Prepare required dirs
# /opt/homelab/config
# /opt/homelab/actions/{pending,approved,rejected,running,completed,failed}
# /opt/homelab/world
# /opt/homelab/state
DIRS=(
"/opt/homelab/config"
"/opt/homelab/actions/pending"
"/opt/homelab/actions/approved"
"/opt/homelab/actions/rejected"
"/opt/homelab/actions/running"
"/opt/homelab/actions/completed"
"/opt/homelab/actions/failed"
"/opt/homelab/world"
"/opt/homelab/state"
)
for dir in "${DIRS[@]}"; do
if [ ! -d "$dir" ]; then
echo "Creating $dir"
sudo mkdir -p "$dir"
fi
done
# 3. chown/chmod for UID 1000
echo "Setting permissions for UID 1000 on /opt/homelab..."
sudo chown -R 1000:1000 /opt/homelab
sudo chmod -R 775 /opt/homelab
# 4. Run docker compose up -d --build --force-recreate
echo "--- Starting Control Plane Services ---"
docker compose up -d --build --force-recreate
# 5. Print docker ps for control-plane containers
echo "--- Deployment Status ---"
docker ps --filter "name=control-plane"

View file

@ -10,7 +10,7 @@ services:
- /opt/homelab:/opt/homelab
restart: unless-stopped
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/summary', timeout=3).read()"]
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/', timeout=3).read()"]
interval: 30s
timeout: 10s
retries: 3