Document development-first workflow with weekly prod releases.
Default all day-to-day work to gallery_dev and devgallery; add Cursor rule and update docs, env examples, and deploy guide for scheduled prod promotion.
This commit is contained in:
+150
-148
@@ -1,149 +1,151 @@
|
||||
# Deploy Gallery on TrueNAS Scale
|
||||
|
||||
|
||||
|
||||
Production deployment for the **Express API + built Vite SPA** container. PostgreSQL stays on the host at `192.168.10.122:5432`. Public URL: **https://gallery.mysuperlab.netcraze.pro** (Keenetic → TrueNAS `:5173`, protocol to device **http**).
|
||||
|
||||
|
||||
|
||||
See also [Documentation/environments.md](../../Documentation/environments.md).
|
||||
|
||||
|
||||
|
||||
## Architecture
|
||||
|
||||
|
||||
|
||||
```text
|
||||
|
||||
Browser (HTTPS)
|
||||
|
||||
→ Keenetic (KeenDNS, SSL termination)
|
||||
|
||||
→ gallery-web container on TrueNAS (:5173, HTTP)
|
||||
|
||||
→ PostgreSQL (192.168.10.122:5432) → gallery_prod
|
||||
|
||||
→ /mnt/BasePool/Applications/Gallery/data/images (volume)
|
||||
|
||||
→ SMB share Gallery → \\192.168.10.122\Gallery (image sync from dev PC)
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
||||
|
||||
| Item | Notes |
|
||||
|
||||
|------|-------|
|
||||
|
||||
| TrueNAS Scale 25.04+ | Apps → Custom App support |
|
||||
|
||||
| PostgreSQL | `gallery_prod` (dev: `gallery_dev` on same host) — split via [pgAdmin script](../../db/split-dev-prod-pgadmin.sql) |
|
||||
|
||||
| Gitea registry | `gitea.mysuperlab.netcraze.pro` — image **`danilka/gallery-web:latest`** pushed before deploy |
|
||||
|
||||
| SMB share | **`Gallery`** at `/mnt/BasePool/Applications/Gallery` for `images:sync-to-prod` |
|
||||
|
||||
| Keenetic | `gallery.mysuperlab.netcraze.pro` → `192.168.10.122:5173`, protocol **`http`**, Preserve Host ON |
|
||||
|
||||
|
||||
|
||||
If deploy fails with **`manifest unknown`**, the image is not in Gitea yet — complete [§1 Build and push](#1-build-and-push-image-dev-machine) first.
|
||||
|
||||
|
||||
|
||||
## 1. Build and push image (dev machine)
|
||||
|
||||
|
||||
|
||||
**Where:** Dev PC — **PowerShell as Administrator** (LAN push hosts entry), **Docker Desktop running**
|
||||
|
||||
|
||||
|
||||
```powershell
|
||||
|
||||
cd C:\Users\SNAP\Nextcloud\Personal\Repo\Gallery
|
||||
|
||||
docker login gitea.mysuperlab.netcraze.pro
|
||||
|
||||
npm run docker:publish
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
Push only (already built): `npm run docker:publish:push-only`
|
||||
|
||||
|
||||
|
||||
Image: `gitea.mysuperlab.netcraze.pro/danilka/gallery-web:latest`
|
||||
|
||||
|
||||
|
||||
### Gitea registry tokens
|
||||
|
||||
|
||||
|
||||
| Machine | Token scope |
|
||||
|
||||
|---------|-------------|
|
||||
|
||||
| Build PC | `write:package` |
|
||||
|
||||
| TrueNAS pull | `read:package` |
|
||||
|
||||
|
||||
|
||||
Register on TrueNAS: **Apps → Configuration → Sign in to a Docker registry** — URL `https://gitea.mysuperlab.netcraze.pro`, username `danilka` (lowercase for registry).
|
||||
|
||||
|
||||
|
||||
### Registry token URL fix
|
||||
|
||||
|
||||
|
||||
If `docker push` fails with internal HTTP token URL, set Gitea `ROOT_URL` to `https://gitea.mysuperlab.netcraze.pro/` and restart Gitea. Full walkthrough: [Drunkmeyou gitea-https-keenetic-npm-setup.md](../../../Drunkmeyou/Documentation/gitea-https-keenetic-npm-setup.md).
|
||||
|
||||
|
||||
|
||||
### Offline fallback (no registry)
|
||||
|
||||
|
||||
|
||||
On **dev PC**: `.\infra\docker\save-for-truenas.ps1` → copy `gallery-web.tar` via SMB `Gallery` share.
|
||||
|
||||
|
||||
|
||||
On **TrueNAS shell**: `sudo bash truenas-load-image.sh /path/to/gallery-web.tar`
|
||||
|
||||
|
||||
|
||||
In Custom App YAML: `pull_policy: if_not_present`, then redeploy.
|
||||
|
||||
|
||||
|
||||
## 2. Prepare TrueNAS storage
|
||||
|
||||
|
||||
|
||||
**Where:** TrueNAS — **Shell**, as **root**
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
|
||||
mkdir -p /mnt/BasePool/Applications/Gallery/data/images/portraits
|
||||
|
||||
mkdir -p /mnt/BasePool/Applications/Gallery/data/images/paintings/thumbs
|
||||
|
||||
chown -R 1001:1001 /mnt/BasePool/Applications/Gallery
|
||||
|
||||
chmod -R u+rwX,g+rwX /mnt/BasePool/Applications/Gallery
|
||||
|
||||
```
|
||||
|
||||
# Deploy Gallery on TrueNAS Scale
|
||||
|
||||
Production deployment for the **Express API + built Vite SPA** container. PostgreSQL stays on the host at `192.168.10.122:5432`. Public URL: **https://gallery.mysuperlab.netcraze.pro** (Keenetic → TrueNAS `:5173`, protocol to device **http**).
|
||||
|
||||
**Not for daily work.** Develop on dev (`gallery_dev`, https://devgallery.mysuperlab.netcraze.pro). Use this guide when **releasing** to prod (~weekly): build/push image, sync data/images if needed, restart the TrueNAS app.
|
||||
|
||||
See also [Documentation/environments.md](../../Documentation/environments.md#development-first-workflow-default).
|
||||
|
||||
## Architecture
|
||||
|
||||
```text
|
||||
Browser (HTTPS)
|
||||
→ Keenetic (KeenDNS, SSL termination)
|
||||
→ gallery-web container on TrueNAS (:5173, HTTP)
|
||||
→ PostgreSQL (192.168.10.122:5432) → gallery_prod
|
||||
→ /mnt/BasePool/Applications/Gallery/data/images (volume)
|
||||
→ SMB share Gallery → \\192.168.10.122\Gallery (image sync from dev PC)
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
| Item | Notes |
|
||||
|------|-------|
|
||||
| TrueNAS Scale 25.04+ | Apps → Custom App support |
|
||||
| PostgreSQL | `gallery_prod` (dev: `gallery_dev` on same host) — split via [pgAdmin script](../../db/split-dev-prod-pgadmin.sql) |
|
||||
| Gitea registry | `gitea.mysuperlab.netcraze.pro` — image **`danilka/gallery-web:latest`** pushed before deploy |
|
||||
| SMB share | **`Gallery`** at `/mnt/BasePool/Applications/Gallery` for `images:sync-to-prod` |
|
||||
| Keenetic | `gallery.mysuperlab.netcraze.pro` → `192.168.10.122:5173`, protocol **`http`**, Preserve Host ON |
|
||||
|
||||
If deploy fails with **`manifest unknown`**, the image is not in Gitea yet — complete [§1 Build and push](#1-build-and-push-image-dev-machine) first.
|
||||
|
||||
## 1. Build and push image (dev machine)
|
||||
|
||||
**Where:** Dev PC — **PowerShell as Administrator** (LAN push hosts entry), **Docker Desktop running**
|
||||
|
||||
```powershell
|
||||
cd C:\Users\SNAP\Nextcloud\Personal\Repo\Gallery
|
||||
docker login gitea.mysuperlab.netcraze.pro
|
||||
npm run docker:publish
|
||||
```
|
||||
|
||||
Push only (already built): `npm run docker:publish:push-only`
|
||||
|
||||
Image: `gitea.mysuperlab.netcraze.pro/danilka/gallery-web:latest`
|
||||
|
||||
### Gitea registry tokens
|
||||
|
||||
| Machine | Token scope |
|
||||
|---------|-------------|
|
||||
| Build PC | `write:package` |
|
||||
| TrueNAS pull | `read:package` |
|
||||
|
||||
Register on TrueNAS: **Apps → Configuration → Sign in to a Docker registry** — URL `https://gitea.mysuperlab.netcraze.pro`, username `danilka` (lowercase for registry).
|
||||
|
||||
### Registry token URL fix
|
||||
|
||||
If `docker push` fails with internal HTTP token URL, set Gitea `ROOT_URL` to `https://gitea.mysuperlab.netcraze.pro/` and restart Gitea. Full walkthrough: [Drunkmeyou gitea-https-keenetic-npm-setup.md](../../../Drunkmeyou/Documentation/gitea-https-keenetic-npm-setup.md).
|
||||
|
||||
### Offline fallback (no registry)
|
||||
|
||||
On **dev PC**: `.\infra\docker\save-for-truenas.ps1` → copy `gallery-web.tar` via SMB `Gallery` share.
|
||||
|
||||
On **TrueNAS shell**: `sudo bash truenas-load-image.sh /path/to/gallery-web.tar`
|
||||
|
||||
In Custom App YAML: `pull_policy: if_not_present`, then redeploy.
|
||||
|
||||
## 2. Prepare TrueNAS storage
|
||||
|
||||
**Where:** TrueNAS — **Shell**, as **root**
|
||||
|
||||
```bash
|
||||
mkdir -p /mnt/BasePool/Applications/Gallery/data/images/portraits
|
||||
mkdir -p /mnt/BasePool/Applications/Gallery/data/images/paintings/thumbs
|
||||
chown -R 1001:1001 /mnt/BasePool/Applications/Gallery
|
||||
chmod -R u+rwX,g+rwX /mnt/BasePool/Applications/Gallery
|
||||
```
|
||||
|
||||
Enable SMB share **`Gallery`** → `/mnt/BasePool/Applications/Gallery` (for image sync from dev PC).
|
||||
|
||||
## 3. Sync images (first deploy)
|
||||
|
||||
**Where:** Dev PC — PowerShell (normal), repo root
|
||||
|
||||
```powershell
|
||||
net use \\192.168.10.122\Gallery /user:YOUR_TRUENAS_USER
|
||||
cd C:\Users\SNAP\Nextcloud\Personal\Repo\Gallery
|
||||
npm run images:sync-to-prod
|
||||
```
|
||||
|
||||
UNC destination: `\\192.168.10.122\Gallery\data\images`
|
||||
|
||||
## 4. Install Custom App
|
||||
|
||||
**Where:** TrueNAS — **Web UI**
|
||||
|
||||
1. **Apps → Discover Apps → Custom App**
|
||||
2. Paste [`compose.truenas.yaml`](compose.truenas.yaml)
|
||||
3. Set `DB_PASSWORD` (replace `YOUR_POSTGRES_PASSWORD`)
|
||||
4. Deploy → wait for **gallery-web** **Running**
|
||||
|
||||
## 5. Keenetic (production)
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Domain | `gallery.mysuperlab.netcraze.pro` |
|
||||
| Upstream | `192.168.10.122:5173` |
|
||||
| Protocol to device | **`http`** |
|
||||
| Preserve Host | ON |
|
||||
|
||||
Wrong IP or `https` to device → **502 / 504** from Keenetic (`Server: Web server`).
|
||||
|
||||
## 6. Verify
|
||||
|
||||
**Bypass Keenetic** (should be instant JSON):
|
||||
|
||||
```powershell
|
||||
curl.exe -s http://192.168.10.122:5173/api/bounds
|
||||
```
|
||||
|
||||
**Public URL:**
|
||||
|
||||
```powershell
|
||||
curl.exe -sk https://gallery.mysuperlab.netcraze.pro/api/bounds
|
||||
```
|
||||
|
||||
Open **https://gallery.mysuperlab.netcraze.pro/** — timeline and `/images/paintings/...` should load.
|
||||
|
||||
On TrueNAS shell: `bash infra/docker/truenas-verify.sh`
|
||||
|
||||
## 7. Update production
|
||||
|
||||
After code changes on dev PC:
|
||||
|
||||
```powershell
|
||||
npm run docker:publish
|
||||
```
|
||||
|
||||
Restart **gallery-web** on TrueNAS (or rely on `pull_policy: always`).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Fix |
|
||||
|-------|-----|
|
||||
| **`manifest unknown`** | Run `npm run docker:publish` first; or offline `truenas-load-image.sh` |
|
||||
| **502 / 504 public URL** | Keenetic → `192.168.10.122:5173`, protocol **`http`**; verify LAN curl above |
|
||||
| Container cannot reach Postgres | `DB_HOST=192.168.10.122`; `extra_hosts` in compose |
|
||||
| Empty timeline | `DB_NAME=gallery_prod`; run pgAdmin split if still on legacy `Gallery` |
|
||||
| Missing images | `npm run images:sync-to-prod`; check volume mount and `chown 1001:1001` |
|
||||
| Pull 401 | Gitea registry credentials on TrueNAS; `read:package` token |
|
||||
| Push fails on dev PC | Gitea `ROOT_URL` HTTPS fix; use Admin PowerShell for LAN push |
|
||||
|
||||
Reference in New Issue
Block a user