chore(ci): setup Gitea Actions + Portainer auto-deploy pipeline
Some checks failed
Build and Push Docker Image / build-and-push (push) Has been cancelled
Some checks failed
Build and Push Docker Image / build-and-push (push) Has been cancelled
This commit is contained in:
13
.env.docker
Normal file
13
.env.docker
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Dummy environment for Docker build stage
|
||||||
|
# These values are only needed so Next.js can compile during docker build
|
||||||
|
# Runtime values are injected via docker-compose environment
|
||||||
|
DATABASE_URL=postgresql://lageplan:lageplan_secret@db:5432/lageplan
|
||||||
|
NEXTAUTH_URL=http://localhost:3000
|
||||||
|
NEXTAUTH_SECRET=build-time-secret-not-used-at-runtime
|
||||||
|
MINIO_ENDPOINT=minio
|
||||||
|
MINIO_PORT=9000
|
||||||
|
MINIO_ACCESS_KEY=minioadmin
|
||||||
|
MINIO_SECRET_KEY=minioadmin123
|
||||||
|
MINIO_BUCKET=lageplan-icons
|
||||||
|
MINIO_USE_SSL=false
|
||||||
|
MINIO_PUBLIC_URL=http://localhost:9000
|
||||||
@@ -27,3 +27,8 @@ MINIO_PUBLIC_URL=http://localhost:9002
|
|||||||
# Web App
|
# Web App
|
||||||
WEB_PORT=3000
|
WEB_PORT=3000
|
||||||
NODE_ENV=development
|
NODE_ENV=development
|
||||||
|
|
||||||
|
# --- CI/CD / Registry (nur für Portainer Deployment) ---
|
||||||
|
# Gitea Registry Login für Watchtower (automatische Image-Updates)
|
||||||
|
GITEA_REGISTRY_USER=adminpepe
|
||||||
|
GITEA_REGISTRY_PASS=dein_gitea_token_oder_passwort
|
||||||
|
|||||||
@@ -1,7 +1,48 @@
|
|||||||
# Deployment wird von Portainer erledigt (nicht Gitea Actions).
|
name: Build and Push Docker Image
|
||||||
# Portainer Stack zeigt auf dieses Repo und baut bei Push automatisch neu.
|
|
||||||
# Siehe docker-compose.portainer.yml für Details.
|
on:
|
||||||
#
|
push:
|
||||||
# Dieses File ist leer damit keine pending Jobs mehr entstehen.
|
branches:
|
||||||
name: disabled
|
- main
|
||||||
on: workflow_dispatch
|
- master
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: git.purepixel.ch
|
||||||
|
IMAGE: git.purepixel.ch/adminpepe/lageplan
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Log in to Gitea Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ env.IMAGE }}
|
||||||
|
tags: |
|
||||||
|
type=raw,value=latest
|
||||||
|
type=sha,prefix=,suffix=,format=short
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -58,4 +58,3 @@ Reglement_*/
|
|||||||
|
|
||||||
# Stack env (contains secrets)
|
# Stack env (contains secrets)
|
||||||
stack.env
|
stack.env
|
||||||
.env.docker
|
|
||||||
|
|||||||
186
deploy/README.md
186
deploy/README.md
@@ -1,102 +1,168 @@
|
|||||||
# Lageplan — Portainer Deployment
|
# Lageplan — CI/CD & Portainer Deployment
|
||||||
|
|
||||||
## Architektur
|
## Übersicht
|
||||||
|
|
||||||
```
|
```
|
||||||
Browser → :3000 (Web App) → intern: db:5432, minio:9000
|
┌─────────────┐ Push ┌─────────────────┐ Build + Push ┌─────────────────┐
|
||||||
|
│ Dein PC │ ────────────► │ Gitea (git) │ ──────────────────► │ Gitea Registry │
|
||||||
|
│ (VS Code) │ │ git.purepixel │ │ (Docker Image) │
|
||||||
|
└─────────────┘ └─────────────────┘ └────────┬────────┘
|
||||||
|
│
|
||||||
|
│ Pull
|
||||||
|
▼
|
||||||
|
┌─────────────────┐
|
||||||
|
│ Portainer │
|
||||||
|
│ (Stack Deploy) │
|
||||||
|
└─────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
Nur **ein Port (3000)** muss exponiert werden. DB und MinIO laufen rein intern im Docker-Netzwerk. Icons werden über die Web-App gestreamt — kein direkter MinIO-Zugriff nötig.
|
1. **Push auf `main`** → Gitea Actions baut Docker Image
|
||||||
|
2. **Image wird gepusht** → Gitea Container Registry (`git.purepixel.ch`)
|
||||||
|
3. **Watchtower (in Portainer)** → prüft alle 60s auf neue Images und startet Container neu
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Dateien
|
## Voraussetzungen
|
||||||
|
|
||||||
| Datei | Beschreibung |
|
- Gitea läuft mit Container Registry aktiviert
|
||||||
|-------|-------------|
|
- Gitea Actions Runner ist registriert (`deploy/docker-compose.runner.yml`)
|
||||||
| `lageplan-web-v1.0.0.tar` | Docker Image (~92 MB) |
|
- Portainer Stack ist deployed mit korrekten Environment-Variablen
|
||||||
| `portainer-stack.yml` | Stack YAML für Portainer |
|
|
||||||
| `.env.example` | Environment Variables Vorlage |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Schritt 1: Image auf Server laden
|
## Schritt 1: Gitea Container Registry aktivieren
|
||||||
|
|
||||||
```bash
|
In Gitea:
|
||||||
# Kopieren
|
1. **Admin-Konsole** → **Konfiguration** → **Pakete**
|
||||||
scp lageplan-web-v1.0.0.tar user@server:/tmp/
|
2. **Container Registry** auf `Aktiviert` setzen
|
||||||
|
3. Speichern
|
||||||
|
|
||||||
# Auf dem Server laden
|
Oder direkt in der `app.ini`:
|
||||||
docker load -i /tmp/lageplan-web-v1.0.0.tar
|
```ini
|
||||||
|
[packages]
|
||||||
|
ENABLED = true
|
||||||
|
|
||||||
# Prüfen
|
[package.container_registry]
|
||||||
docker images | grep lageplan
|
ENABLED = true
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Schritt 2: Stack in Portainer erstellen
|
## Schritt 2: Gitea Actions Runner registrieren
|
||||||
|
|
||||||
|
1. In Gitea: **Admin** → **Actions** → **Runners** → **Neuen Runner erstellen**
|
||||||
|
2. Token kopieren
|
||||||
|
3. In Portainer: Stack `gitea-runner` deployen mit [`deploy/docker-compose.runner.yml`](docker-compose.runner.yml)
|
||||||
|
4. Environment Variable `RUNNER_TOKEN` = das kopierte Token
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Schritt 3: Gitea Access Token erstellen
|
||||||
|
|
||||||
|
Das CI/CD Workflow braucht einen Token um Images in die Registry zu pushen:
|
||||||
|
|
||||||
|
1. Gitea → **Einstellungen** → **Anwendungen** → **Token erstellen**
|
||||||
|
2. Name: `registry-push`
|
||||||
|
3. Berechtigungen: `package:write` (mindestens)
|
||||||
|
4. Token kopieren und als **Repository Secret** hinterlegen:
|
||||||
|
- Repo → **Einstellungen** → **Secrets** → **Neues Secret**
|
||||||
|
- Name: `GITEA_TOKEN`
|
||||||
|
- Wert: das kopierte Token
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Schritt 4: Portainer Stack deployen
|
||||||
|
|
||||||
1. **Portainer** → `Stacks` → `+ Add stack`
|
1. **Portainer** → `Stacks` → `+ Add stack`
|
||||||
2. **Name**: `lageplan`
|
2. **Name**: `lageplan`
|
||||||
3. **Web editor**: Inhalt von `portainer-stack.yml` einfügen
|
3. **Build method**: `Repository`
|
||||||
4. **Environment variables** setzen:
|
4. **Git-URL**: `https://git.purepixel.ch/adminpepe/Lageplan.git`
|
||||||
|
5. **Compose path**: `docker-compose.portainer.yml`
|
||||||
|
6. **GitOps updates**: ✅ Aktivieren
|
||||||
|
7. **Mechanism**: `Webhook`
|
||||||
|
8. **Webhook URL kopieren** (für später)
|
||||||
|
|
||||||
| Variable | Wert |
|
### Environment Variables setzen:
|
||||||
|----------|------|
|
|
||||||
| `POSTGRES_USER` | `lageplan` |
|
|
||||||
| `POSTGRES_PASSWORD` | *(sicheres Passwort)* |
|
|
||||||
| `POSTGRES_DB` | `lageplan` |
|
|
||||||
| `MINIO_ROOT_USER` | `minioadmin` |
|
|
||||||
| `MINIO_ROOT_PASSWORD` | *(sicheres Passwort)* |
|
|
||||||
| `MINIO_BUCKET` | `lageplan-icons` |
|
|
||||||
| `WEB_PORT` | `3000` |
|
|
||||||
| `NEXTAUTH_URL` | `http://SERVER_IP:3000` |
|
|
||||||
| `NEXTAUTH_SECRET` | *(langer zufälliger String)* |
|
|
||||||
|
|
||||||
> **Tipp**: Secret generieren: `openssl rand -base64 32`
|
| Variable | Wert | Beschreibung |
|
||||||
|
|----------|------|-------------|
|
||||||
|
| `POSTGRES_USER` | `lageplan` | DB User |
|
||||||
|
| `POSTGRES_PASSWORD` | *(sicheres Passwort)* | DB Passwort |
|
||||||
|
| `POSTGRES_DB` | `lageplan` | DB Name |
|
||||||
|
| `NEXTAUTH_URL` | `https://lageplan.ch` | Deine Domain |
|
||||||
|
| `NEXTAUTH_SECRET` | *(openssl rand -base64 32)* | Auth Secret |
|
||||||
|
| `MINIO_ROOT_USER` | `minioadmin` | MinIO User |
|
||||||
|
| `MINIO_ROOT_PASSWORD` | *(sicheres Passwort)* | MinIO Passwort |
|
||||||
|
| `MINIO_BUCKET` | `lageplan-icons` | Bucket Name |
|
||||||
|
| `MINIO_PUBLIC_URL` | `https://s3.deinedomain.ch` | MinIO externe URL |
|
||||||
|
| `GITEA_REGISTRY_USER` | `adminpepe` | Gitea User für Watchtower |
|
||||||
|
| `GITEA_REGISTRY_PASS` | *(Token oder Passwort)* | Gitea Passwort/Token |
|
||||||
|
|
||||||
5. **Deploy the stack**
|
9. **Deploy the stack**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Schritt 3: Datenbank initialisieren (einmalig)
|
## Schritt 5: Webhook in Gitea eintragen
|
||||||
|
|
||||||
In Portainer: Container `web` → Console → `/bin/sh`:
|
Damit Portainer bei jedem Push automatisch neu deployed:
|
||||||
|
|
||||||
```bash
|
1. Gitea Repo → **Einstellungen** → **Webhooks** → **Neuer Webhook** → `Gitea`
|
||||||
npx prisma db push
|
2. **Ziel-URL**: Die kopierte Portainer Webhook URL
|
||||||
npx prisma db seed
|
3. **HTTP-Methode**: `POST`
|
||||||
```
|
4. **Trigger**: Nur `Push events` (oder auch `Branch filter: main`)
|
||||||
|
5. **Webhook aktivieren** → Hinzufügen
|
||||||
Oder per SSH:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec -it lageplan-web-1 npx prisma db push
|
|
||||||
docker exec -it lageplan-web-1 npx prisma db seed
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Schritt 4: Zugriff
|
## Schritt 6: Erstes Deployment testen
|
||||||
|
|
||||||
- **Web App**: `http://SERVER_IP:3000`
|
1. Lokal einen Push auf `main` machen:
|
||||||
- **Login**: `admin@lageplan.local` / `admin123`
|
```bash
|
||||||
|
git add .
|
||||||
|
git commit -m "Test CI/CD"
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
2. In Gitea: **Actions** Tab → Build-Job sollte laufen
|
||||||
|
3. Wenn grün → Image wurde in Registry gepusht
|
||||||
|
4. Watchtower (in Portainer) holt neues Image innerhalb von 60s
|
||||||
|
5. App ist unter `NEXTAUTH_URL` erreichbar
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Update
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Gitea Actions startet nicht
|
||||||
|
- Prüfen ob Runner registriert ist: Gitea → Admin → Actions → Runners
|
||||||
|
- Runner muss `Idle` oder `Active` zeigen
|
||||||
|
|
||||||
|
### Image Push schlägt fehl (401 Unauthorized)
|
||||||
|
- `GITEA_TOKEN` Secret im Repo korrekt hinterlegt?
|
||||||
|
- Token hat Berechtigung `package:write`?
|
||||||
|
- Registry in Gitea aktiviert?
|
||||||
|
|
||||||
|
### Watchtower zieht kein neues Image
|
||||||
|
- `GITEA_REGISTRY_USER` und `GITEA_REGISTRY_PASS` in Portainer gesetzt?
|
||||||
|
- Image-Name in `docker-compose.portainer.yml` korrekt?
|
||||||
|
- Watchtower Logs prüfen: Portainer → Container `watchtower` → Logs
|
||||||
|
|
||||||
|
### App startet nicht / DB-Fehler
|
||||||
|
- Environment Variables in Portainer korrekt?
|
||||||
|
- `DATABASE_URL` wird automatisch gebaut, nur `POSTGRES_*` muss gesetzt werden
|
||||||
|
- Bei erstem Start: Prisma Migrations/Seed im Web-Container ausführen:
|
||||||
|
```bash
|
||||||
|
docker exec -it lageplan-web-1 npx prisma db push
|
||||||
|
docker exec -it lageplan-web-1 npx prisma db seed
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Manuelles Update (falls nötig)
|
||||||
|
|
||||||
|
Wenn Watchtower mal nicht greift:
|
||||||
```bash
|
```bash
|
||||||
# Lokal: neues Image bauen + exportieren
|
# Auf dem Portainer-Host
|
||||||
docker compose build web
|
docker pull git.purepixel.ch/adminpepe/lageplan:latest
|
||||||
docker tag lageplan-web:latest lageplan-web:v1.1.0
|
docker compose -f docker-compose.portainer.yml up -d web
|
||||||
docker save lageplan-web:v1.1.0 -o deploy/lageplan-web-v1.1.0.tar
|
|
||||||
|
|
||||||
# Server: laden
|
|
||||||
docker load -i lageplan-web-v1.1.0.tar
|
|
||||||
|
|
||||||
# Portainer: Stack → Editor → Image-Tag ändern → Update the stack
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -7,3 +7,8 @@ MINIO_BUCKET=lageplan-icons
|
|||||||
WEB_PORT=3000
|
WEB_PORT=3000
|
||||||
NEXTAUTH_URL=http://SERVER_IP:3000
|
NEXTAUTH_URL=http://SERVER_IP:3000
|
||||||
NEXTAUTH_SECRET=HIER_LANGEN_ZUFAELLIGEN_STRING_GENERIEREN
|
NEXTAUTH_SECRET=HIER_LANGEN_ZUFAELLIGEN_STRING_GENERIEREN
|
||||||
|
MINIO_PUBLIC_URL=http://SERVER_IP:9000
|
||||||
|
|
||||||
|
# Gitea Registry Auth für Watchtower (automatische Image-Updates)
|
||||||
|
GITEA_REGISTRY_USER=adminpepe
|
||||||
|
GITEA_REGISTRY_PASS=HIER_GITEA_TOKEN_ODER_PASSWORT_SETZEN
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
##############################################
|
##############################################
|
||||||
# Gitea — Lightweight Git Server
|
# Gitea — Lightweight Git Server + Container Registry
|
||||||
#
|
#
|
||||||
# Verwendung in Portainer:
|
# Verwendung in Portainer:
|
||||||
# 1. Stacks → Add Stack → "Gitea"
|
# 1. Stacks → Add Stack → "Gitea"
|
||||||
@@ -12,6 +12,10 @@
|
|||||||
# 3. Repository "lageplan" erstellen
|
# 3. Repository "lageplan" erstellen
|
||||||
# 4. Vom PC aus: git init → git remote add origin → git push
|
# 4. Vom PC aus: git init → git remote add origin → git push
|
||||||
#
|
#
|
||||||
|
# Container Registry aktivieren:
|
||||||
|
# 1. Gitea Admin → Konfiguration → Pakete → Container Registry aktivieren
|
||||||
|
# 2. Oder app.ini: [packages] ENABLED = true
|
||||||
|
#
|
||||||
# Daten werden in gitea_data persistiert.
|
# Daten werden in gitea_data persistiert.
|
||||||
##############################################
|
##############################################
|
||||||
|
|
||||||
@@ -27,6 +31,9 @@ services:
|
|||||||
- GITEA__server__ROOT_URL=https://git.purepixel.ch
|
- GITEA__server__ROOT_URL=https://git.purepixel.ch
|
||||||
- GITEA__server__HTTP_PORT=3000
|
- GITEA__server__HTTP_PORT=3000
|
||||||
- GITEA__server__LFS_START_SERVER=true
|
- GITEA__server__LFS_START_SERVER=true
|
||||||
|
# Container Registry aktivieren
|
||||||
|
- GITEA__packages__ENABLED=true
|
||||||
|
- GITEA__package__container_registry__ENABLED=true
|
||||||
volumes:
|
volumes:
|
||||||
- gitea_data:/data
|
- gitea_data:/data
|
||||||
- /etc/timezone:/etc/timezone:ro
|
- /etc/timezone:/etc/timezone:ro
|
||||||
@@ -43,4 +50,3 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
lageplan_lageplan-net:
|
lageplan_lageplan-net:
|
||||||
external: true
|
external: true
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
# 6. Environment-Variablen setzen (siehe unten)
|
# 6. Environment-Variablen setzen (siehe unten)
|
||||||
# 7. Deploy
|
# 7. Deploy
|
||||||
#
|
#
|
||||||
# Danach: Push auf main → Portainer baut automatisch neu
|
# Danach: Push auf main → Gitea Actions baut Image →
|
||||||
|
# Portainer Webhook/Watchtower holt neues Image
|
||||||
#
|
#
|
||||||
# Benötigte Environment-Variablen:
|
# Benötigte Environment-Variablen:
|
||||||
# POSTGRES_USER (default: lageplan)
|
# POSTGRES_USER (default: lageplan)
|
||||||
@@ -21,6 +22,8 @@
|
|||||||
# MINIO_ROOT_USER (default: minioadmin)
|
# MINIO_ROOT_USER (default: minioadmin)
|
||||||
# MINIO_ROOT_PASSWORD (ÄNDERN!)
|
# MINIO_ROOT_PASSWORD (ÄNDERN!)
|
||||||
# MINIO_PUBLIC_URL (z.B. https://s3.example.com)
|
# MINIO_PUBLIC_URL (z.B. https://s3.example.com)
|
||||||
|
# GITEA_REGISTRY_USER (für Watchtower Registry-Auth)
|
||||||
|
# GITEA_REGISTRY_PASS (für Watchtower Registry-Auth)
|
||||||
##############################################
|
##############################################
|
||||||
|
|
||||||
services:
|
services:
|
||||||
@@ -81,10 +84,8 @@ services:
|
|||||||
- lageplan
|
- lageplan
|
||||||
|
|
||||||
# ─── Lageplan Web App ──────────────────────
|
# ─── Lageplan Web App ──────────────────────
|
||||||
|
# Image kommt aus Gitea Container Registry (gebaut via Gitea Actions)
|
||||||
web:
|
web:
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
image: git.purepixel.ch/adminpepe/lageplan:latest
|
image: git.purepixel.ch/adminpepe/lageplan:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
@@ -118,6 +119,9 @@ services:
|
|||||||
WATCHTOWER_POLL_INTERVAL: 60
|
WATCHTOWER_POLL_INTERVAL: 60
|
||||||
WATCHTOWER_CLEANUP: "true"
|
WATCHTOWER_CLEANUP: "true"
|
||||||
WATCHTOWER_LABEL_ENABLE: "false"
|
WATCHTOWER_LABEL_ENABLE: "false"
|
||||||
|
# Gitea Registry Auth
|
||||||
|
REPO_USER: ${GITEA_REGISTRY_USER}
|
||||||
|
REPO_PASS: ${GITEA_REGISTRY_PASS}
|
||||||
networks:
|
networks:
|
||||||
- lageplan
|
- lageplan
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user