Files
CASAN/.gitea/vps-setup-runbook.md
T
thanhnvandClaude Opus 4.8 36a4812ef3 refactor(structure): promote app to repo root + remove redundant workspace cruft
Standard production layout: the OKR app (was nested under AINative_OKR_CASAN5/) is now
the repository root. No more wrapper directory.

- Promote AINative_OKR_CASAN5/* -> repo root (backend/ frontend/ packages/ apps/
  .specify/ docs/ infra/ nginx/ scripts/ + configs). Merge tool dirs: .gitea (kept the
  active deploy ci.yml, added harness-ci.yml + runbooks), .claude (agents/commands +
  launch.json), .github moved up.
- Remove redundant: 00_SUBMISSION_PACKAGE, scattered root notes (FPT_CASAN_Full.md,
  tu-tuong-casan.md, casan-tu-sinh..., casan_harness_assessment.md, source-review...,
  README_CASAN5_REFINED.md), casan-next-plans/ and optimize-docs/ (competition/planning
  artifacts — roadmap + design history preserved in git log / commit messages).
- Update all references to the old layout:
  - .gitea/workflows/{ci,harness-ci}.yml, .github/workflows/{ci,deploy}.yml:
    working-directory .; drop AINative_OKR_CASAN5/ prefix; .specify/{tests,scripts}
    -> packages/casan-harness/... (.specify/logs state kept)
  - .claude/launch.json, .gitea/*-runbook.md: path prefixes
  - CLAUDE.md, README.md: docs/input -> apps/okr/domain/input
  - policy-bundle.yaml: 8 policy paths -> packages/casan-harness/...; manifest re-signed
- secrets-scan.sh: fixture excludes -> new package/domain paths.

Full gate from the new root: PASS=64 FAIL=0 SKIP=3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 13:26:36 +09:00

5.4 KiB

VPS CI/CD Setup Runbook

Oracle Cloud Tokyo — 161.33.139.73

Architecture

VPS (Ubuntu 24.04, 1 GB RAM)
├── /opt/gitea/
│   ├── docker-compose.yml     ← add act-runner service here
│   ├── .env                   ← add RUNNER_REGISTRATION_TOKEN here
│   ├── act-runner-config.yaml ← copy from .gitea/act-runner-config.yaml
│   └── gitea-data/

Step 1 — Enable Gitea Actions

SSH into the VPS:

ssh ubuntu@161.33.139.73

Add the Actions env variable to the Gitea service in docker-compose.yml:

# In the gitea service environment section, add:
- GITEA__actions__ENABLED=true

Restart Gitea:

cd /opt/gitea
docker compose restart gitea

Verify: Open http://161.33.139.73:3000 → Site Administration → Runners You should see "Runners" menu item (confirming Actions is enabled).


Step 2 — Get the Runner Registration Token

  1. Log into Gitea as admin: http://161.33.139.73:3000
  2. Go to: Site Administration (⚙) → Runners → "Create new runner"
  3. Copy the Registration Token shown (looks like: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)

Step 3 — Copy act_runner config to VPS

From your local machine:

scp .gitea/act-runner-config.yaml \
    ubuntu@161.33.139.73:/opt/gitea/act-runner-config.yaml

Step 4 — Add RUNNER_REGISTRATION_TOKEN to /opt/gitea/.env

On the VPS:

# Replace <TOKEN> with the token copied in Step 2
echo "RUNNER_REGISTRATION_TOKEN=<TOKEN>" >> /opt/gitea/.env

Step 5 — Add act_runner service to docker-compose.yml

Edit /opt/gitea/docker-compose.yml and add the act-runner service.

Typical Gitea docker-compose.yml after changes:

version: "3"

networks:
  gitea:
    external: false

volumes:
  gitea-data:
  act-runner-data:

services:
  gitea:
    image: gitea/gitea:latest
    container_name: gitea
    restart: always
    networks:
      - gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__actions__ENABLED=true        # ← ADD THIS LINE
    ports:
      - "3000:3000"
      - "2222:22"
    volumes:
      - ./gitea-data:/data

  act-runner:
    image: gitea/act_runner:latest
    container_name: act-runner
    restart: unless-stopped
    networks:
      - gitea                                # same network as gitea
    depends_on:
      - gitea
    environment:
      - GITEA_INSTANCE_URL=http://gitea:3000 # internal Docker hostname
      - GITEA_RUNNER_REGISTRATION_TOKEN=${RUNNER_REGISTRATION_TOKEN}
      - GITEA_RUNNER_NAME=casan-runner-oracle
      - CONFIG_FILE=/config/act-runner-config.yaml
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock   # DinD for job containers
      - ./act-runner-config.yaml:/config/act-runner-config.yaml:ro
      - act-runner-data:/data

If your current docker-compose.yml already has a networks: or volumes: section, merge them — don't add duplicate top-level keys.


Step 6 — Start act_runner

cd /opt/gitea
docker compose pull act-runner
docker compose up -d act-runner

Check registration:

docker compose logs -f act-runner
# Look for: "runner registered" or "connected to Gitea"

In Gitea Web UI: Site Administration → Runners → you should see "casan-runner-oracle" with status Online.


Step 7 — Pull the catthehacker runner image (one-time)

The first CI run will pull catthehacker/ubuntu:act-22.04 (~2 GB). Pre-pull to avoid timeout:

docker pull catthehacker/ubuntu:act-22.04

This takes ~2-5 minutes depending on internet speed.


Step 8 — Create repo in Gitea and push the project

On the VPS (or via Gitea web UI), create a new repository:

On your local machine:

cd Output_CASAN5_REFINED  # repo root (app promoted from AINative_OKR_CASAN5/)

# Add Gitea as remote
git remote add gitea ssh://git@161.33.139.73:2222/<YOUR_USER>/casan5.git

# Push
git push gitea main

Step 9 — Verify CI triggered

After push, go to: http://161.33.139.73:3000/<YOUR_USER>/casan5/actions

You should see a workflow run in progress. Click it to see live logs.

Expected final result:

✅ Frontend Tests (H3 gate)        — 16/16 PASS
✅ CASAN Security Gate (H4/H5/H2)  — PASS=7 SKIP=1 FAIL=0

SKIP=1 is expected (Ollama is not on the CI server — this is the model-router/red-team group). The gate exits 0 because FAIL=0.


Memory Monitoring

# Watch RAM usage while CI runs
watch -n 2 'free -h && docker stats --no-stream'

If OOM occurs, reduce the job container memory limit in act-runner-config.yaml or add swap:

sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Troubleshooting

Symptom Fix
Runner shows "Offline" Check docker compose logs act-runner; verify token is correct
GITEA_INSTANCE_URL unreachable Ensure gitea and act-runner are on the same Docker network
Job stuck "Waiting for runner" Runner is busy (capacity=1); wait or increase capacity
python: command not found The workflow's "Install test tools" step installs python-is-python3
OOM during npm ci Switch to npm ci -w frontend (already done in workflow) or add swap
catthehacker/ubuntu:act-22.04 pull fails Run docker pull manually on VPS first