All checks were successful
Deploy to NAS / deploy (push) Successful in 44s
- README.md: rewrite with accurate setup steps including all lessons learned - CLAUDE.md: update with working CI/CD patterns and known pitfalls - gitea-actions.md: new file documenting Gitea Actions usage, expressions, act_runner config, and troubleshooting for future projects Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
197 lines
5.4 KiB
Markdown
197 lines
5.4 KiB
Markdown
# Infrastruktur & Deployment
|
|
|
|
## Architektur
|
|
|
|
```
|
|
Synology NAS (192.168.1.4)
|
|
├── Gitea :3000 — Git + CI/CD
|
|
├── act_runner — Gitea Actions Runner
|
|
├── /volume2/docker/shared/
|
|
│ ├── postgres:16-alpine :5433 — Geteilte DB (alle Projekte)
|
|
│ └── pgdata/ — Persistente Daten
|
|
└── /volume2/docker/<projekt>/
|
|
├── <app>-Container :<port> — Anwendung
|
|
├── uploads/ — Persistente Uploads
|
|
└── .env — Projekt-Secrets
|
|
```
|
|
|
|
**Datenbankverbindung aus Containern:** `host-gateway:5433`
|
|
|
|
---
|
|
|
|
## 1. Shared PostgreSQL einrichten (einmalig)
|
|
|
|
```bash
|
|
sudo mkdir -p /volume2/docker/shared/pgdata
|
|
sudo cp infra/docker-compose.yml /volume2/docker/shared/
|
|
echo "POSTGRES_PASSWORD=<sicheres-passwort>" | sudo tee /volume2/docker/shared/.env
|
|
cd /volume2/docker/shared && sudo docker compose up -d
|
|
```
|
|
|
|
Datenbank anlegen:
|
|
```bash
|
|
sudo docker exec -it shared-postgres-1 psql -U postgres
|
|
```
|
|
```sql
|
|
CREATE DATABASE <dbname>;
|
|
CREATE USER <dbuser> WITH PASSWORD '<passwort>';
|
|
GRANT ALL PRIVILEGES ON DATABASE <dbname> TO <dbuser>;
|
|
GRANT ALL ON SCHEMA public TO <dbuser>; -- wichtig für PostgreSQL 15+
|
|
\q
|
|
```
|
|
|
|
---
|
|
|
|
## 2. act_runner einrichten (einmalig)
|
|
|
|
Token holen: **Gitea → Site-Administration → Actions → Runner → Runner erstellen**
|
|
|
|
```bash
|
|
sudo docker run -d \
|
|
--name gitea-runner \
|
|
--restart unless-stopped \
|
|
--network host \
|
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
|
-v /volume2/docker/gitea-runner:/data \
|
|
-e GITEA_INSTANCE_URL=http://192.168.1.4:3000 \
|
|
-e GITEA_RUNNER_REGISTRATION_TOKEN=<token> \
|
|
-e GITEA_RUNNER_NAME=nas-runner \
|
|
-e GITEA_RUNNER_LABELS=self-hosted,linux,amd64 \
|
|
gitea/act_runner:latest
|
|
```
|
|
|
|
> **Wichtig:** `GITEA_INSTANCE_URL` muss die NAS-IP sein, nicht `localhost` —
|
|
> Job-Container können `localhost` nicht auflösen.
|
|
|
|
`/volume2/docker/gitea-runner/config.yaml` anlegen:
|
|
```yaml
|
|
runner:
|
|
name: "nas-runner"
|
|
|
|
container:
|
|
valid_volumes:
|
|
- /volume2/docker
|
|
```
|
|
|
|
Runner neu starten: `sudo docker restart gitea-runner`
|
|
|
|
---
|
|
|
|
## 3. Neues Projekt deployen
|
|
|
|
### 3.1 Verzeichnis anlegen
|
|
```bash
|
|
sudo mkdir -p /volume2/docker/<projekt>/uploads
|
|
```
|
|
|
|
### 3.2 docker-compose.yml (im Repo)
|
|
```yaml
|
|
services:
|
|
api:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
ports:
|
|
- "${APP_PORT:-8080}:8080"
|
|
extra_hosts:
|
|
- "host-gateway:host-gateway"
|
|
environment:
|
|
DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@host-gateway:5433/${DB_NAME}
|
|
volumes:
|
|
- /volume2/docker/<projekt>/uploads:/uploads
|
|
restart: unless-stopped
|
|
```
|
|
|
|
### 3.3 Gitea Secrets & Variables
|
|
|
|
**Secrets** (Repository → Einstellungen → Actions → Secrets):
|
|
| Secret | Wert |
|
|
|--------|------|
|
|
| `DB_PASSWORD` | Datenbankpasswort |
|
|
|
|
**Variables** (Repository → Einstellungen → Actions → Variables):
|
|
| Variable | Wert |
|
|
|----------|------|
|
|
| `DEPLOY_DIR` | `/volume2/docker/<projekt>` |
|
|
| `DB_USER` | `<dbuser>` |
|
|
| `DB_NAME` | `<dbname>` |
|
|
| `APP_PORT` | `<port>` |
|
|
|
|
### 3.4 Gitea Actions Workflow (`.gitea/workflows/deploy.yml`)
|
|
```yaml
|
|
name: Deploy to NAS
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
deploy:
|
|
runs-on: self-hosted
|
|
container:
|
|
image: docker:latest
|
|
options: -v /volume2/docker:/volume2/docker
|
|
|
|
steps:
|
|
- name: Pull code
|
|
run: |
|
|
if [ -d "${{ vars.DEPLOY_DIR }}/.git" ]; then
|
|
git -C ${{ vars.DEPLOY_DIR }} pull
|
|
else
|
|
git clone http://192.168.1.4:3000/<org>/<repo>.git ${{ vars.DEPLOY_DIR }}
|
|
fi
|
|
|
|
- name: Write .env
|
|
run: printf 'DB_PASSWORD=%s\n' '${{ secrets.DB_PASSWORD }}' > ${{ vars.DEPLOY_DIR }}/.env
|
|
|
|
- name: Build & Deploy
|
|
run: docker compose -f ${{ vars.DEPLOY_DIR }}/docker-compose.yml up --build -d
|
|
|
|
- name: Health check
|
|
run: |
|
|
sleep 15
|
|
wget -qO- http://192.168.1.4:${{ vars.APP_PORT }}/healthz || exit 1
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Synology-spezifische Hinweise
|
|
|
|
| Problem | Lösung |
|
|
|---------|--------|
|
|
| `permission denied` bei Docker-Befehlen | Immer `sudo docker ...` verwenden |
|
|
| Ports < 1024 nicht bindbar | Internen Port > 1024 wählen, z.B. `LISTEN_PORT: 8080` |
|
|
| Docker-Socket im Container Manager UI nicht mountbar | `docker run` via SSH ausführen |
|
|
| `act_runner` kann `localhost:3000` nicht erreichen | NAS-IP statt `localhost` in `GITEA_INSTANCE_URL` |
|
|
| Volume-Mount wird ignoriert | `valid_volumes` in `config.yaml` eintragen |
|
|
| Session-Cookies funktionieren nicht | `Secure: false` setzen bei HTTP-Deployment |
|
|
| `GRANT ALL PRIVILEGES` reicht nicht | Zusätzlich `GRANT ALL ON SCHEMA public` ausführen (PG 15+) |
|
|
|
|
---
|
|
|
|
## 5. Wartung
|
|
|
|
```bash
|
|
# Logs
|
|
sudo docker compose -f /volume2/docker/shared/docker-compose.yml logs -f postgres
|
|
sudo docker compose -f /volume2/docker/<projekt>/docker-compose.yml logs -f
|
|
|
|
# Backup
|
|
sudo docker exec shared-postgres-1 pg_dump -U postgres <dbname> \
|
|
> /volume2/docker/shared/backup_$(date +%Y%m%d)_<dbname>.sql
|
|
|
|
# Alle Container stoppen
|
|
sudo docker compose -f /volume2/docker/shared/docker-compose.yml down
|
|
sudo docker compose -f /volume2/docker/<projekt>/docker-compose.yml down
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Dienste & Ports
|
|
|
|
| Dienst | Port | Beschreibung |
|
|
|--------|------|--------------|
|
|
| Gitea | 3000 | Git-Server + CI/CD |
|
|
| PostgreSQL | 5433 | Geteilte DB (intern: 5432) |
|
|
| Pamietnik | 9050 | Tagebuch-App |
|