From 102cbcb01a31a50aa847472e18a58acdc16f4003 Mon Sep 17 00:00:00 2001 From: "bert.hausmans" Date: Thu, 21 May 2026 10:13:31 +0200 Subject: [PATCH] chore(deploy): pull image from Gitea registry + manual buildx push flow --- DEPLOY.md | 129 ++++++++++++++++++++++++++++----------------------- compose.yaml | 58 +++++++++++------------ 2 files changed, 97 insertions(+), 90 deletions(-) diff --git a/DEPLOY.md b/DEPLOY.md index bb85237..c4d9e70 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -1,90 +1,103 @@ -# Deploy to Dockge (fastest path: build on the host) +# Deploy to Dockge via the Gitea container registry -This is the quickest way to get Flashcard running on your Proxmox + Dockge setup. -Source comes from Gitea; Dockge builds the image locally and runs it. No container -registry, no Gitea Actions, no `docker login` required. +Flashcard ships as one container (API + built frontend). You build the image once, +push it to your Gitea registry, and Dockge pulls it — same pattern as your +`questionnaire` stack. -Repo: `https://gitea.hausmans.cloud/bert.hausmans/flashcards` +- Gitea repo: `https://gitea.hausmans.cloud/bert.hausmans/flashcards` +- Registry image: `10.0.10.205:3000/bert.hausmans/flashcards:latest` -## What gets deployed +## One-time prerequisites (on this Mac) -One container (`flashcard`) serving the API **and** the built frontend. It listens -on port `3000` inside the container, mapped to **`4000` on the Dockge host** -(`4000:3000` in `compose.yaml`). A persistent named volume (`flashcard-data`) holds -the SQLite database. -Migrations run automatically on every container start. +The registry is plain HTTP on an IP, so Docker must trust it. In **Docker Desktop → +Settings → Docker Engine**, add `10.0.10.205:3000` to `insecure-registries`: -## Step 1 — push the code to Gitea (from your dev machine) - -```bash -cd /Users/berthausmans/Documents/Development/flashcard -git remote add origin https://gitea.hausmans.cloud/bert.hausmans/flashcards.git # first time only -git push -u origin master +```json +{ + "insecure-registries": ["10.0.10.205:3000"] +} ``` -## Step 2 — put the stack on the Dockge host +Apply & restart Docker. Then log in to the registry (use your Gitea username and a +Gitea access token or password — run it yourself so the prompt works): -SSH into the host running Dockge. Dockge keeps stacks in `/opt/stacks` by default. - -```bash -cd /opt/stacks -git clone https://gitea.hausmans.cloud/bert.hausmans/flashcards.git flashcard +``` +! docker login 10.0.10.205:3000 ``` -A "flashcard" stack now appears in the Dockge UI (it reads `compose.yaml`). +(The Dockge host already trusts this registry since `questionnaire` pulls from it.) -## Step 3 — configure environment in Dockge +## Step 1 — build for amd64 and push -Open the **flashcard** stack in Dockge and edit the `environment:` block: +Your Mac is arm64 but the Proxmox host is amd64, so build with `--platform +linux/amd64`. From the repo root: -- `APP_URL` → how you reach the app, e.g. `http://:4000` - (this is what verification/reset/invite e-mail links use — get it right). -- `COOKIE_SECURE` → leave `"false"` for now (plain HTTP). Flip to `"true"` only - after you put the app behind HTTPS. -- SMTP (Amazon SES) → fill in `SMTP_HOST` (e.g. `email-smtp.eu-west-1.amazonaws.com`), - `SMTP_USER`, `SMTP_PASS`, and `SMTP_FROM`. **Optional for first boot** — see Step 5. +```bash +docker buildx build --platform linux/amd64 \ + -t 10.0.10.205:3000/bert.hausmans/flashcards:latest \ + --push . +``` -## Step 4 — deploy +That builds the image and pushes it straight to the Gitea registry. -Click **Deploy** (Dockge runs `docker compose up -d --build`). First build takes a -few minutes (installs deps, builds the frontend, compiles better-sqlite3). When it's -up, open `http://:4000`. +## Step 2 — create the Dockge stack -## Step 5 — create the first account (becomes sysadmin) +In Dockge, **+ Compose** → name it `flashcard`, and paste the contents of +`compose.yaml` from this repo (or copy the file into the stack directory). Then edit +the `environment:` block: -Go to `/register` and sign up. The **first registered user is automatically the +- `APP_URL` → how users reach the app, e.g. `http://10.0.10.205:4000` + (used in verification / reset / invite e-mail links — get it right). +- `COOKIE_SECURE` → leave `false` over plain HTTP; set `true` only behind HTTPS. +- SMTP (Amazon SES) → fill in `SMTP_HOST` / `SMTP_USER` / `SMTP_PASS` / `SMTP_FROM`, + **or** leave `SMTP_HOST` empty for the first boot (see Step 4). + +The stack maps host **4000 → container 4000** and persists the SQLite DB in the +`flashcard-data` volume. + +## Step 3 — deploy + +Click **Deploy**. Dockge pulls the image and starts it. Open +`http://10.0.10.205:4000`. Migrations run automatically on container start. + +## Step 4 — create the first account (becomes sysadmin) + +Go to `/register` and sign up — the **first registered user is automatically the sysadmin**. -- If SES is configured: click the verification link in your inbox. -- If you left SMTP empty: grab the verification link from the container logs — - in Dockge open the flashcard stack → Logs, and copy the - `…/verify-email?token=…` URL printed by the stub mailer. +- SES configured → click the verification link in your inbox. +- SMTP left empty → open the stack's **Logs** in Dockge and copy the + `…/verify-email?token=…` link printed by the stub mailer. Then log in. Done. ## Updating later +Rebuild & push the new image, then redeploy in Dockge: + ```bash -cd /opt/stacks/flashcard -git pull +docker buildx build --platform linux/amd64 \ + -t 10.0.10.205:3000/bert.hausmans/flashcards:latest --push . ``` -Then in Dockge click **Deploy** again (rebuilds + restarts). The `flashcard-data` -volume — and therefore all lessons, cards and accounts — persists across redeploys. +In Dockge: open the **flashcard** stack → **Pull** (fetches the new image) → +**Deploy**. The `flashcard-data` volume — and all lessons, cards and accounts — +survives redeploys. + +> Tip: for safe rollbacks, also tag a version alongside `latest`, e.g. +> `-t 10.0.10.205:3000/bert.hausmans/flashcards:2026-05-21 -t 10.0.10.205:3000/bert.hausmans/flashcards:latest`. ## Notes & gotchas -- **Data safety:** everything lives in the `flashcard-data` Docker volume. Don't - delete it. Back it up by copying `/data/flashcard.db` out of the container/volume. -- **Secure cookies need HTTPS.** With `COOKIE_SECURE=true` over plain HTTP the - browser silently discards the login cookie. Keep it `false` until you have TLS. -- **Mailpit** (`docker-compose.yml`) is dev-only and is ignored here — Dockge uses - `compose.yaml`. -- The backend runs via `tsx` (TypeScript runtime), matching dev. Migrations are - applied automatically by `docker-entrypoint.sh` before the server starts. +- **Data lives in the `flashcard-data` volume** — don't delete it; back up + `/app/data/flashcard.db`. +- **Secure cookies need HTTPS.** Over plain HTTP keep `COOKIE_SECURE=false`, + otherwise the browser drops the login cookie and sign-in silently fails. +- **Mailpit** (`docker-compose.yml`) is dev-only and unrelated to this deploy. +- The backend runs via `tsx` and applies migrations on boot + (`docker-entrypoint.sh`). -## Next step (optional, when you have time) +## Optional: automate with Gitea Actions -Move to the Gitea container registry + Gitea Actions so Dockge pulls a pre-built -image instead of building on the host. Ask and I'll add a `.gitea/workflows/build.yml` -plus a registry-based `compose.yaml`. +If you later register a Gitea `act_runner`, I can add a `.gitea/workflows/build.yml` +that builds and pushes on every push to `master`, so you skip the manual buildx step. diff --git a/compose.yaml b/compose.yaml index b75afec..f205871 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,43 +1,37 @@ -# Production stack for Dockge — builds the image on the host from this repo. -# Dockge prefers compose.yaml, so this file is used instead of the dev -# docker-compose.yml (which only runs Mailpit for local development). +# Production stack for Dockge — pulls a pre-built image from the Gitea registry. +# (Build + push the image first; see DEPLOY.md.) services: flashcard: - build: - context: . - dockerfile: Dockerfile - image: flashcard:local + image: 10.0.10.205:3000/bert.hausmans/flashcards:latest container_name: flashcard - restart: unless-stopped - # host:container — exposed on 4000 on the Dockge host, app listens on 3000 inside. ports: - - "4000:3000" - volumes: - - flashcard-data:/data + - 4000:4000 environment: - NODE_ENV: production - PORT: "3000" - DB_PATH: /data/flashcard.db + - NODE_ENV=production + - PORT=4000 + - DB_PATH=/app/data/flashcard.db # URL where users reach the app. Used in verification / reset / invite emails. - # CHANGE THIS to your real address, e.g. http://192.168.1.50:4000 - # or https://flashcards.hausmans.cloud once behind a reverse proxy. - APP_URL: "http://CHANGE-ME:4000" + # CHANGE THIS to your real address, e.g. http://10.0.10.205:4000 + - APP_URL=http://CHANGE-ME:4000 - # Cookie security. Keep "false" when serving over plain HTTP — otherwise the - # browser drops the session cookie and login silently fails. Set to "true" - # only once the app is served over HTTPS (reverse proxy with TLS). - COOKIE_SECURE: "false" - - # SMTP (Amazon SES). Leave SMTP_HOST empty to fall back to a stub mailer that - # prints verification/reset links to the container logs — handy for the very - # first sysadmin signup before SES is wired up. - SMTP_HOST: "" - SMTP_PORT: "587" - SMTP_SECURE: "false" - SMTP_USER: "" - SMTP_PASS: "" - SMTP_FROM: "Flashcard " + # Keep "false" over plain HTTP (otherwise the browser drops the login + # cookie). Set "true" only once behind an HTTPS reverse proxy. + - COOKIE_SECURE=false + # SMTP (Amazon SES). Leave SMTP_HOST empty to fall back to a stub mailer + # that prints verification/reset links to the container logs (handy for the + # first sysadmin signup before SES is wired up). + - SMTP_HOST= + - SMTP_PORT=587 + - SMTP_SECURE=false + - SMTP_USER= + - SMTP_PASS= + - SMTP_FROM=Flashcard + volumes: + - flashcard-data:/app/data + restart: unless-stopped volumes: flashcard-data: + driver: local +networks: {}