Files
Chris Chen a298d0ee1c
ci-cd-vm / ci-cd (push) Successful in 44s
update for signalR
2026-06-23 17:12:17 -07:00
..
2026-06-23 17:12:17 -07:00
2026-06-22 16:37:53 -07:00
2026-06-22 15:53:51 -07:00
2026-06-22 16:37:53 -07:00

Deploy to the Ubuntu VM (all-in-one) — LAN / HTTP

Everything runs on one Ubuntu VM, one Docker daemon: Gitea, the container registry, the build, and the ROLAC runtime. So a single Gitea Actions job (the ubuntu runner) does the whole pipeline — no cross-machine pull, no Windows-runner quirks.

git push main
   │
   ▼
Gitea (on the VM)  ── triggers .gitea/workflows/ci-cd-vm.yml
   │
   ▼
ubuntu runner (on the VM, same Docker daemon)
   dotnet test
   docker build ./API + ./APP      -> :latest + :<sha>
   docker push                     -> git.golife.love/chrischen/rolac-{api,app}
   docker compose up -d (TAG=<sha>)
   curl /api/health
   │
   ▼
browser  ->  http://<vm-ip>:8080
                 │ nginx edge (container, 8080->80)
                 ├── /        -> app container (Angular static)
                 └── /api/    -> api container (ASP.NET, :8080)
api  ──> existing PostgreSQL @ 192.168.68.55:49154   (not containerized)

No TLS yet — plain HTTP on port 8080. Add Let's Encrypt later (see the Azure deploy/ files) or front it with an existing reverse proxy.


One-time setup — on the VM

  1. Deploy dir + secrets:

    sudo mkdir -p /home/chris/docker/rolac/nginx/conf.d /home/chris/docker/rolac/data/api-storage
    sudo cp /path/to/repo/deploy/vm/.env.example /home/chris/docker/rolac/.env
    sudo nano /home/chris/docker/rolac/.env    # real DB user/password + JWT_SECRET + APP_ORIGIN
    

    Make sure the user the runner executes as can read/write /home/chris/docker/rolac.

  2. Registry token — in Gitea: Settings → Applications → new token with read:package + write:package. Log Docker in once on the VM:

    docker login git.golife.love -u ChrisChen   # paste the token
    
  3. Install act_runner on the VM with the label ubuntu and access to the host Docker. The runner must be able to run dotnet, docker, and docker compose, and reach /home/chris/docker/rolac:

    docker run -d --restart unless-stopped --name rolac-runner \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v /home/chris/docker/rolac:/home/chris/docker/rolac \
      -e GITEA_INSTANCE_URL=https://git.golife.love \
      -e GITEA_RUNNER_REGISTRATION_TOKEN=<token> \
      -e GITEA_RUNNER_LABELS=ubuntu \
      gitea/act_runner:latest
    

    The job calls dotnet test and docker build directly. If act_runner runs in a container, that image needs the .NET 8 SDK + docker CLI on PATH. Simplest: install act_runner as a native binary on the VM (it then uses the host's Docker + an installed .NET SDK). Either way the label must be ubuntu.

  4. Gitea repo secrets (Settings → Actions → Secrets):

    • REGISTRY_USER = ChrisChen
    • REGISTRY_TOKEN = the package token from step 2
  5. Enable Actions for the repo if needed (Settings → Advanced → Actions).


Day-to-day

git push to main.gitea/workflows/ci-cd-vm.yml: test → build both images → push to registry → sync compose/nginx → compose up -d → health check.

Open http://<vm-ip>:8080 and log in.

Deploy pins TAG=<git-sha>, so the running containers match exactly the commit that was built (the images already exist in the local Docker, so this is instant).


Manual deploy (no runner yet)

On the VM, from a checkout of the repo:

docker login git.golife.love -u ChrisChen
docker build -t git.golife.love/chrischen/rolac-api:latest ./API
docker build -t git.golife.love/chrischen/rolac-app:latest ./APP
mkdir -p /home/chris/docker/rolac/nginx/conf.d /home/chris/docker/rolac/data/api-storage
cp deploy/vm/docker-compose.yml      /home/chris/docker/rolac/docker-compose.yml
cp deploy/vm/nginx/conf.d/rolac.conf /home/chris/docker/rolac/nginx/conf.d/rolac.conf
cd /home/chris/docker/rolac && docker compose up -d
curl -fsS http://localhost:8080/api/health

Notes

  • First boot runs DB migrations against 192.168.68.55 automatically (Program.cs calls MigrateAsync() + seed). The VM must reach that host and the DB user needs DDL rights; back up before the first run.
  • Uploaded files persist under /home/chris/docker/rolac/data/api-storage.
  • Same Docker daemon for build + run means docker compose up finds the freshly built :<sha> images locally; docker compose pull is unnecessary here (but harmless if you add it).
  • To go HTTPS later: switch the edge to ports 80/443 and mount Let's Encrypt certs, or use the Azure deploy/ files which already include certbot.