Update
This commit is contained in:
+66
-21
@@ -1,10 +1,18 @@
|
||||
# Deploy to Synology NAS (Container Manager) — LAN / HTTP
|
||||
|
||||
Target: run the ROLAC stack on a Synology NAS, reachable on the LAN at
|
||||
`http://<nas-ip>:8080`, with images built & pushed to the **local Gitea registry**
|
||||
(`git.golife.love`, same NAS) and auto-deployed by a **Gitea act_runner** on push to `main`.
|
||||
Target: run the ROLAC stack on a Synology **DS220+** (Celeron J4025 / 2GB RAM),
|
||||
reachable on the LAN at `http://<nas-ip>:8080`. Images are **built on the dev PC**
|
||||
(the NAS is too weak to compile — Angular's build alone can need >2GB RAM), pushed to
|
||||
the **Gitea registry** on the NAS, and the NAS only **pulls + restarts** the containers.
|
||||
|
||||
```
|
||||
push main
|
||||
dev PC ───────────────► Gitea (NAS)
|
||||
(runner: builder) │ triggers .gitea/workflows/ci-cd-nas.yml
|
||||
test + build + push ─────────┤
|
||||
▼
|
||||
NAS runner (label: nas) ── deploy only ──┐
|
||||
▼
|
||||
browser (LAN) -> http://<nas-ip>:8080
|
||||
│ nginx edge (container, 8080->80)
|
||||
├── / -> app container (Angular static)
|
||||
@@ -12,12 +20,42 @@ browser (LAN) -> http://<nas-ip>:8080
|
||||
api ──> existing PostgreSQL @ 192.168.68.55:49154 (not containerized)
|
||||
```
|
||||
|
||||
Why this split: DS220+ can comfortably **run** these lightweight containers
|
||||
(nginx + precompiled .NET + static files) but cannot **build** them. So building
|
||||
(test, `dotnet publish`, `ng build`) runs on the dev PC; the NAS just pulls.
|
||||
|
||||
Differences vs the Azure plan: no TLS/certbot, edge on **8080** (DSM owns 80/443),
|
||||
reuse the LAN database, deploy via the on-NAS runner (no SSH).
|
||||
|
||||
---
|
||||
|
||||
## One-time NAS setup
|
||||
## Two runners, two jobs
|
||||
|
||||
| Job | `runs-on` | Where | Does |
|
||||
|-----|-----------|-------|------|
|
||||
| `build-push` | `windows` | **dev PC** | test → build both images → push to registry |
|
||||
| `deploy` | `nas` | **NAS** | pull images → `docker compose up -d` → health check |
|
||||
|
||||
> The dev-PC runner is registered with the label `windows:host` — `runs-on` matches
|
||||
> the label NAME (`windows`); `:host` is the run mode (executes directly on the PC,
|
||||
> not in a container, so it uses Docker Desktop + the installed .NET SDK).
|
||||
|
||||
`deploy` has `needs: build-push`, so it only runs after the build succeeds.
|
||||
|
||||
---
|
||||
|
||||
## One-time setup — DEV PC (the `windows` runner) ✅ already done
|
||||
|
||||
The dev PC runs act_runner natively with the label `windows:host`, using its
|
||||
installed Docker Desktop + .NET 8 SDK. The workflow's `build-push` job targets
|
||||
`runs-on: windows`. Requirements (for reference):
|
||||
|
||||
- Docker Desktop running, and `docker` on PATH.
|
||||
- .NET 8 SDK on PATH (`dotnet test` runs on this machine).
|
||||
- **Git for Windows** installed — the job uses `shell: bash` (Git Bash) for the
|
||||
multi-line `docker build`/`push` steps.
|
||||
|
||||
## One-time setup — NAS (the `nas` runner)
|
||||
|
||||
1. **Deploy dir + secrets** (via SSH or File Station):
|
||||
```bash
|
||||
@@ -32,14 +70,11 @@ reuse the LAN database, deploy via the on-NAS runner (no SSH).
|
||||
docker login git.golife.love -u ChrisChen # paste the token
|
||||
```
|
||||
|
||||
3. **Install the act_runner on the NAS** (Container Manager → Registry → `gitea/act_runner`,
|
||||
3. **Install act_runner on the NAS** (Container Manager → Registry → `gitea/act_runner`,
|
||||
or `docker run`). It must:
|
||||
- mount the host Docker socket: `-v /var/run/docker.sock:/var/run/docker.sock`
|
||||
- mount the deploy dir at the same path: `-v /volume1/docker/rolac:/volume1/docker/rolac`
|
||||
- register against Gitea with the label **`nas`** (this is what `runs-on: nas` targets).
|
||||
|
||||
Get a registration token in Gitea: Site/Repo → Settings → Actions → Runners →
|
||||
"Create new runner". Example:
|
||||
- register with the label **`nas`** (this is what `runs-on: nas` targets).
|
||||
```bash
|
||||
docker run -d --restart unless-stopped --name rolac-runner \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
@@ -50,33 +85,42 @@ reuse the LAN database, deploy via the on-NAS runner (no SSH).
|
||||
gitea/act_runner:latest
|
||||
```
|
||||
|
||||
4. **Gitea repo secrets** (Settings → Actions → Secrets):
|
||||
- `REGISTRY_USER` = `ChrisChen`
|
||||
- `REGISTRY_TOKEN` = the package token from step 2
|
||||
## One-time setup — Gitea repo
|
||||
|
||||
5. **Enable Actions** for the repo if not already (Settings → Advanced → Actions).
|
||||
1. **Secrets** (Settings → Actions → Secrets):
|
||||
- `REGISTRY_USER` = `ChrisChen`
|
||||
- `REGISTRY_TOKEN` = the package token (with `write:package`)
|
||||
2. **Enable Actions** for the repo if not already (Settings → Advanced → Actions).
|
||||
|
||||
---
|
||||
|
||||
## Day-to-day
|
||||
|
||||
`git push` to `main` → `.gitea/workflows/ci-cd-nas.yml` runs:
|
||||
**test → build both images → push to registry → sync compose/nginx → `docker compose up -d` → health check.**
|
||||
`git push` to `main` → `.gitea/workflows/ci-cd-nas.yml`:
|
||||
|
||||
1. **dev PC** (`builder`): `dotnet test` → build `rolac-api` + `rolac-app`
|
||||
(tags `:latest` and `:<git-sha>`) → push to `git.golife.love/chrischen/*`.
|
||||
2. **NAS** (`nas`): sync compose/nginx → `TAG=<git-sha> docker compose pull` →
|
||||
`docker compose up -d` → `curl /api/health`.
|
||||
|
||||
Open `http://<nas-ip>:8080` and log in.
|
||||
|
||||
Deploy pins `TAG=<git-sha>` (not `latest`), so the NAS always runs exactly the image
|
||||
this commit produced and `compose pull` forces a fresh fetch.
|
||||
|
||||
---
|
||||
|
||||
## Manual deploy (no runner yet)
|
||||
## Manual fallback (no runners yet)
|
||||
|
||||
From a machine with Docker + `docker login git.golife.love`:
|
||||
From the dev PC (Docker Desktop + `docker login git.golife.love`):
|
||||
```powershell
|
||||
# repo root, build + push (uses deploy/build-push.ps1)
|
||||
# repo root — build + push both images (tags :latest and :<git-sha>)
|
||||
.\deploy\build-push.ps1
|
||||
```
|
||||
Then on the NAS:
|
||||
```bash
|
||||
cd /volume1/docker/rolac
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
curl -fsS http://localhost:8080/api/health
|
||||
```
|
||||
@@ -88,9 +132,10 @@ curl -fsS http://localhost:8080/api/health
|
||||
- **First boot runs DB migrations** against `192.168.68.55` automatically
|
||||
(`Program.cs` calls `MigrateAsync()` + seed). Make sure the DB user has DDL rights;
|
||||
back up before the first run.
|
||||
- **Bind-mount paths**: the runner deploys by running compose at `/volume1/docker/rolac`
|
||||
on the host (socket-mounted), so `./nginx/conf.d` and `./data` resolve to real NAS
|
||||
paths — that's why the runner mounts that dir at the *same* path.
|
||||
- **Bind-mount paths**: the NAS runner runs compose at `/volume1/docker/rolac` on the
|
||||
host (socket-mounted), so `./nginx/conf.d` and `./data` resolve to real NAS paths —
|
||||
that's why the runner mounts that dir at the *same* path.
|
||||
- **Uploaded files** persist under `/volume1/docker/rolac/data/api-storage`.
|
||||
- **DS220+ runs, never builds.** Keep all compilation on the dev PC / a beefier runner.
|
||||
- To expose beyond the LAN later, put it behind DSM's reverse proxy (Application Portal)
|
||||
or switch to the Azure `deploy/` files with certbot.
|
||||
|
||||
Reference in New Issue
Block a user