spusteni jen pres WG
This commit is contained in:
@@ -4,6 +4,14 @@
|
|||||||
# NIKDY necommitovat .env do gitu!
|
# NIKDY necommitovat .env do gitu!
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
|
# ---- Deploy / přístup k UI (produkce, deploy/docker-compose.yml) ----
|
||||||
|
# Lokálně na serveru jen přes SSH: nech výchozí (127.0.0.1) – EMS_PUBLIC_BASE může zůstat prázdné (default v compose).
|
||||||
|
#
|
||||||
|
# Přístup jen přes WireGuard: na serveru zjisti IP wg0, např. ip -4 addr show wg0
|
||||||
|
EMS_FRONTEND_BIND=10.200.200.1 # IP WireGuard rozhraní serveru (ne veřejná IP)
|
||||||
|
# EMS_PUBLIC_BASE=http://10.0.0.1:8080 # stejná báze jako v prohlížeči (bez koncového /)
|
||||||
|
# Volitelně Caddy na wg0: pak EMS_PUBLIC_BASE=https://ems.internal a frontend bind nechat 127.0.0.1 + reverse_proxy v Caddy.
|
||||||
|
|
||||||
# ---- PostgreSQL ----
|
# ---- PostgreSQL ----
|
||||||
DB_USER=ems_user
|
DB_USER=ems_user
|
||||||
DB_PASSWORD=change_me_strong_password
|
DB_PASSWORD=change_me_strong_password
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# Deploy na single server: build a compose běží na hostu přes /opt/ems-deploy/deploy.sh (bez DinD).
|
# Deploy na single server: deploy.sh volá hostovský Docker přes /var/run/docker.sock (bez DinD).
|
||||||
#
|
#
|
||||||
# Vyžaduje act_runner na stejném stroji jako Docker s host executorem, nebo upravit job na SSH.
|
# Job běží v kontejneru — /opt/ems-deploy a sock musí být přimountované (viz container.volumes).
|
||||||
# Sladit `runs-on` s labely registrace runneru (např. self-hosted + ems-deploy).
|
# V /opt/gitea-stack/runner/config.yaml nastav container.valid_volumes na stejné cesty.
|
||||||
|
# Sladit `runs-on` s labely registrace runneru (výchozí: self-hosted).
|
||||||
|
|
||||||
name: deploy
|
name: deploy
|
||||||
|
|
||||||
@@ -14,9 +15,16 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
runs-on: self-hosted
|
runs-on: self-hosted
|
||||||
|
container:
|
||||||
|
image: docker.io/library/alpine:3.20
|
||||||
|
volumes:
|
||||||
|
- /opt/ems-deploy:/opt/ems-deploy
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
steps:
|
steps:
|
||||||
- name: Run deploy script on host
|
- name: Install git, bash, Docker CLI + Compose v2
|
||||||
run: /opt/ems-deploy/deploy.sh
|
run: apk add --no-cache git bash docker-cli docker-cli-compose
|
||||||
|
- name: Run deploy script (host Docker + /opt/ems-deploy checkout)
|
||||||
|
run: bash /opt/ems-deploy/deploy.sh
|
||||||
|
|
||||||
# Alternativa: runner v Dockeru bez přístupu k hostu — odkomentovat a upravit SERVER + secrets.
|
# Alternativa: runner v Dockeru bez přístupu k hostu — odkomentovat a upravit SERVER + secrets.
|
||||||
# deploy-ssh:
|
# deploy-ssh:
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ Specifikace z `docs/02-architecture.md`, modulových docs a komentářů v `plan
|
|||||||
| Rolling plán, forecast log | `db/migration/V007__rolling_replanning.sql` |
|
| Rolling plán, forecast log | `db/migration/V007__rolling_replanning.sql` |
|
||||||
| Audit 15min | `db/routines/R__fn_fill_audit_interval.sql`, `docs/04-modules/telemetry.md` |
|
| Audit 15min | `db/routines/R__fn_fill_audit_interval.sql`, `docs/04-modules/telemetry.md` |
|
||||||
| Nové sloupce / tabulky | nový `db/migration/V00x__*.sql` + případně `db/routines` / `db/views` |
|
| Nové sloupce / tabulky | nový `db/migration/V00x__*.sql` + případně `db/routines` / `db/views` |
|
||||||
|
| Self-hosted deploy (Gitea, Caddy, `/opt/ems-deploy`) | `docs/deployment-self-hosted.md`, `deploy/deploy.sh` |
|
||||||
| Nespecifikované chování | `docs/06-open-questions.md` (přidat otázku, neimpl. naslepo) |
|
| Nespecifikované chování | `docs/06-open-questions.md` (přidat otázku, neimpl. naslepo) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
# Produkční stack pro single-server deploy.
|
# Produkční stack pro single-server deploy.
|
||||||
# Na serveru: kopíruje se do /opt/ems-deploy/docker-compose.yml (viz deploy/deploy.sh).
|
# Na serveru: kopíruje se do /opt/ems-deploy/docker-compose.yml (viz deploy/deploy.sh).
|
||||||
# Cesty ./app/* jsou relativní k adresáři, kde leží tento soubor po zkopírování (/opt/ems-deploy).
|
# Cesty ./app/* jsou relativní k adresáři, kde leží tento soubor po zkopírování (/opt/ems-deploy).
|
||||||
|
#
|
||||||
|
# Jen přes WireGuard: v .env nastav EMS_FRONTEND_BIND na IP wg0 serveru (viz .env.example) a EMS_PUBLIC_BASE
|
||||||
|
# na stejnou bázi URL, kterou otevřeš v prohlížeči (např. http://10.0.0.1:8080).
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
@@ -54,10 +57,10 @@ services:
|
|||||||
PGRST_DB_ANON_ROLE: ${POSTGREST_ANON_ROLE:-ems_anon}
|
PGRST_DB_ANON_ROLE: ${POSTGREST_ANON_ROLE:-ems_anon}
|
||||||
PGRST_JWT_SECRET: ${POSTGREST_JWT_SECRET}
|
PGRST_JWT_SECRET: ${POSTGREST_JWT_SECRET}
|
||||||
PGRST_SERVER_PORT: 3000
|
PGRST_SERVER_PORT: 3000
|
||||||
# Za Caddy změň na veřejnou bázi URL API (např. https://ems.example.com/rest).
|
# Musí odpovídat URL, ze které klient volá /rest/ (typicky EMS_PUBLIC_BASE + /rest).
|
||||||
PGRST_OPENAPI_SERVER_PROXY_URI: http://localhost/rest
|
PGRST_OPENAPI_SERVER_PROXY_URI: ${EMS_PUBLIC_BASE:-http://127.0.0.1:8080}/rest
|
||||||
ports:
|
# Bez ports: PostgREST jen uvnitř sítě (frontend nginx → postgrest:3000). Host :3000 často koliduje.
|
||||||
- "127.0.0.1:3000:3000"
|
# Přímý přístup z hostu: odkomentuj např. "127.0.0.1:3001:3000"
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
build:
|
build:
|
||||||
@@ -98,7 +101,7 @@ services:
|
|||||||
context: ./app/frontend
|
context: ./app/frontend
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:8080:80"
|
- "${EMS_FRONTEND_BIND:-127.0.0.1}:8080:80"
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- backend
|
||||||
- postgrest
|
- postgrest
|
||||||
|
|||||||
160
docs/deployment-self-hosted.md
Normal file
160
docs/deployment-self-hosted.md
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
# Self-hosted deploy: Gitea + Caddy + EMS (`/opt/ems-deploy`)
|
||||||
|
|
||||||
|
Runbook pro **single-node Debian**, **Docker Compose**, **Gitea Actions** bez Kubernetes. Doplňuje konkrétní stav serveru (ZFS, `zfs` storage driver, Caddy na hostu, Gitea v `/opt/gitea-stack`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Co kde běží
|
||||||
|
|
||||||
|
| Oblast | Cesta / adresa | Poznámka |
|
||||||
|
|--------|----------------|----------|
|
||||||
|
| Gitea (HTTP) | `https://git.vojacek.eu` → Caddy → `127.0.0.1:3000` | Gitea publikuje HTTP jen na loopback. |
|
||||||
|
| Gitea (Git SSH) | `git.vojacek.eu:2222` → kontejner `:22` | Host SSH zůstává na `:22`. V `app.ini`: `START_SSH_SERVER = false` (kvůli SSH v base image). |
|
||||||
|
| Gitea stack | `/opt/gitea-stack` | `postgres`, `gitea`, `gitea-runner`; vlastní `docker-compose` + `.env`. |
|
||||||
|
| Gitea runner | stejný stack | `act_runner` s přepsaným `entrypoint`/`command`; registrace ručně → `runner/runner.json`. |
|
||||||
|
| EMS deploy | `/opt/ems-deploy` | Oddělený Compose projekt od Gitea. |
|
||||||
|
| EMS checkout | `/opt/ems-deploy/app` | Git clone stejného repa jako v Gitea. |
|
||||||
|
| EMS Compose (runtime) | `/opt/ems-deploy/docker-compose.yml` | Kopíruje se ze `app/deploy/docker-compose.yml` při každém deployi (`deploy.sh`). |
|
||||||
|
| EMS secrets | `/opt/ems-deploy/.env` | **Není v gitu**; vzor `.env.example` v repu. |
|
||||||
|
|
||||||
|
**PostgREST v produkčním `deploy/docker-compose.yml`:** služba naslouchá v **Docker síti** na `:3000`, **bez** mapování na host — frontend v kontejneru volá `postgrest:3000`. Tím se vyhne kolizi s Gitea na hostovém `127.0.0.1:3000`. Pokud někdy přidáš `ports` pro ladění, použij jiný host port než 3000.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Architektonický verdikt
|
||||||
|
|
||||||
|
**Směr (push → Actions → skript na hostu → `docker compose build && up`) je správný** pro cíl „jeden server, žádný registry, žádný DinD“.
|
||||||
|
|
||||||
|
**Tvrdá fakta / rizika**
|
||||||
|
|
||||||
|
1. **Job Gitea Actions neběží na hostu**, ale ve **job kontejneru** (Docker executor). Kroky typu `run: /opt/ems-deploy/deploy.sh` tedy **neuvidí** hostovské cesty, dokud je nepřimountuješ do job kontejneru a nepřidáš je do `valid_volumes` u runneru.
|
||||||
|
2. **Mount Docker socketu do jobu = plná moc nad hostovským Dockerem** (ekvivalent root pro kontejnery). Je to běžný pattern u self-hosted runnerů; bezpečnost = důvěra k přístupu do repa a k labelům runneru, ne veřejný runner.
|
||||||
|
3. **`docker: command not found` v jobu** je očekávané u defaultního image — buď použij image s `docker` + `docker compose`, nebo vůbec nevolaj docker uvnitř jobu (u tebe stačí spustit `deploy.sh`, který mluví s hostovským daemonem přes socket).
|
||||||
|
4. **ZFS + Docker `zfs` driver:** snapshoty a `zfs list` rostou s image vrstvami; `deploy.sh` už dělá `docker image prune -f` (dangling). Hlídej místo na poolu a případně periodický `docker system prune` (opatrně — nesmí mazat věci, co potřebuješ).
|
||||||
|
5. **`git reset --hard origin/main`:** rychlé a deterministické; jakýkoli lokální drift v `/opt/ems-deploy/app` na serveru se **ztratí**. Na produkční app adresář nesahat ručně — vždy přes git + deploy.
|
||||||
|
6. **Dvě síťě:** `ems_net` vs `gitea_net` — služby se defaultně nevidí; pro EMS to obvykle nevadí. Integrovat Gitea DB s EMS nechceš.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Tok deploye (cílový)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
dev[Dev laptop] -->|git push| gitea[Gitea main]
|
||||||
|
gitea --> act[Gitea Actions]
|
||||||
|
act --> runner[act_runner + Docker]
|
||||||
|
runner --> job[Job container Alpine + sock + /opt mount]
|
||||||
|
job --> sh[deploy.sh]
|
||||||
|
sh --> git[git fetch / reset main]
|
||||||
|
sh --> sync[install compose.yml]
|
||||||
|
sh --> dc["docker compose build && up -d"]
|
||||||
|
dc --> hostd[Host Docker Engine]
|
||||||
|
hostd --> ems[EMS stack]
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Vývoj lokálně, merge do `main`, push na `git.vojacek.eu:2222`.
|
||||||
|
2. Workflow `.gitea/workflows/deploy.yml` (label `self-hosted`) spustí job.
|
||||||
|
3. Job kontejner má `docker.sock` a rw mount `/opt/ems-deploy`; nainstaluje `git`, `bash`, `docker-cli`, `docker-cli-compose` (Alpine).
|
||||||
|
4. `/opt/ems-deploy/deploy.sh`: `flock`, `git` v `app/`, sync `docker-compose.yml`, `docker compose config`, `build`, `up -d`, `image prune -f`.
|
||||||
|
|
||||||
|
Build probíhá na **hostovském** Dockeru (stejný daemon jako Gitea stack), bez DinD.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Bootstrap serveru (jednorázově)
|
||||||
|
|
||||||
|
Přesně podle hlavičky v `deploy/deploy.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /opt/ems-deploy/app
|
||||||
|
sudo chown -R "$USER:$USER" /opt/ems-deploy
|
||||||
|
git clone ssh://git@git.vojacek.eu:2222/vojacekd/ems.git /opt/ems-deploy/app
|
||||||
|
cp /opt/ems-deploy/app/.env.example /opt/ems-deploy/.env
|
||||||
|
chmod 600 /opt/ems-deploy/.env
|
||||||
|
# doplnit secrets / DB / JWT / …
|
||||||
|
install -m 755 /opt/ems-deploy/app/deploy/deploy.sh /opt/ems-deploy/deploy.sh
|
||||||
|
/opt/ems-deploy/deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Uživatel, pod kterým běží runnerův job (root v Alpine job image), musí mít právo číst `.env`, psát do `app/.git` a volat Docker. Typicky runner běží jako root → ověř oprávnění na `/opt/ems-deploy`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Gitea runner — nutná úprava `config.yaml`
|
||||||
|
|
||||||
|
Aby job směl přimountovat hostové cesty, v `runner/config.yaml` (na serveru v `/opt/gitea-stack/runner/config.yaml`) **musí** být v `container.valid_volumes` povolené alespoň:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
container:
|
||||||
|
network: host
|
||||||
|
privileged: false
|
||||||
|
valid_volumes:
|
||||||
|
- /opt/ems-deploy
|
||||||
|
- /var/run/docker.sock
|
||||||
|
```
|
||||||
|
|
||||||
|
Bez toho Actions mounty odmítnou / job spadne. Po změně restart runner kontejneru.
|
||||||
|
|
||||||
|
`labels` při registraci runneru musí odpovídat `runs-on` ve workflow (např. výchozí `self-hosted`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Caddy a EMS (až bude veřejná doména)
|
||||||
|
|
||||||
|
Gitea blok v Caddyfile zůstává. Pro EMS přidej **samostatný** site blok, např.:
|
||||||
|
|
||||||
|
```caddy
|
||||||
|
ems.vojacek.eu {
|
||||||
|
encode gzip
|
||||||
|
@api path /rest*
|
||||||
|
handle @api {
|
||||||
|
uri strip_prefix /rest
|
||||||
|
reverse_proxy 127.0.0.1:8080
|
||||||
|
}
|
||||||
|
handle {
|
||||||
|
reverse_proxy 127.0.0.1:8080
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Upřesnění podle skutečného nginx ve frontend image:** pokud API jde přes stejný origin a path `/rest`, výše může stačit jeden `reverse_proxy` na `127.0.0.1:8080` bez stripu — ověř v `frontend` konfiguraci. Pro PostgREST OpenAPI nastav v `.env` / `PGRST_OPENAPI_SERVER_PROXY_URI` veřejnou bázi URL.
|
||||||
|
|
||||||
|
Produkční compose mapuje frontend na **`127.0.0.1:8080`**, backend na **`127.0.0.1:8000`**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. CI: test vs deploy
|
||||||
|
|
||||||
|
| Workflow | Účel | Poznámka |
|
||||||
|
|----------|------|----------|
|
||||||
|
| `.gitea/workflows/test.yml` | Smoke (soubory, layout) | `runs-on: ubuntu-latest` stáhne image; nepotřebuje Docker. |
|
||||||
|
| `.gitea/workflows/deploy.yml` | Deploy po pushi na `main` | Job kontejner + mounty + viz sekce 5. |
|
||||||
|
|
||||||
|
`workflow_dispatch` na deploy umožňuje ruční opakování bez prázdného commitu.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Co záměrně neděláme (zatím)
|
||||||
|
|
||||||
|
- Privátní Docker registry na stejném stroji.
|
||||||
|
- Buildkit cache export / remote cache.
|
||||||
|
- k3s/Kubernetes.
|
||||||
|
- Spouštění `docker compose` uvnitř jobu bez přístupu k **jednomu** hostovskému daemonu (tj. bez soku bys musel do DinD nebo remote docker).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Rychlá kontrola po deployi
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f /opt/ems-deploy/docker-compose.yml --env-file /opt/ems-deploy/.env ps
|
||||||
|
curl -sf http://127.0.0.1:8000/docs >/dev/null && echo backend OK
|
||||||
|
curl -sf http://127.0.0.1:8080/ >/dev/null && echo frontend OK
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Odkazy v repu
|
||||||
|
|
||||||
|
- `deploy/deploy.sh` — jediný produkční vstup „co se na serveru spouští“.
|
||||||
|
- `deploy/docker-compose.yml` — šablona runtime Compose (kopíruje se do `/opt/ems-deploy`).
|
||||||
|
- `.gitea/workflows/deploy.yml` — napojení na runner + job kontejner.
|
||||||
Reference in New Issue
Block a user