ci: add automated Gitea Actions deployment workflow for Synology NAS
Build and Deploy to Synology NAS / test (push) Failing after 1h20m56s
Build and Deploy to Synology NAS / build (push) Failing after 11m7s
Build and Deploy to Synology NAS / deploy (push) Has been cancelled
Build and Deploy to Synology NAS / notify (push) Has been cancelled

- Add Gitea Actions workflow for automated build and deployment
- Add deployment script for Synology NAS
- Add Docker Compose configurations for production deployment
- Add Gitea runner setup
- Add comprehensive documentation for CI/CD setup
- Add health check endpoint for deployment verification
- Update .gitignore for CI/CD artifacts
This commit is contained in:
2025-12-17 13:02:38 +01:00
parent 2f7bd923df
commit 94d02736f7
12 changed files with 2114 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
# Gitea Runner Configuration
# Kopiere diese Datei zu .env.gitea-runner und passe die Werte an
# ============================================
# Gitea Instance
# ============================================
# URL deiner Gitea-Installation
# Wenn Gitea auf der gleichen NAS läuft:
GITEA_URL=http://your-synology-ip:3000
# Wenn Gitea in Docker läuft und im gleichen Netzwerk:
# GITEA_URL=http://gitea:3000
# ============================================
# Runner Configuration
# ============================================
# Runner Registration Token
# Generiere diesen Token in Gitea:
# Repository → Settings → Actions → Runners → Create new Runner
RUNNER_TOKEN=your_gitea_runner_registration_token_here
# Runner Name (wird in Gitea angezeigt)
RUNNER_NAME=synology-runner
# Maximale Anzahl gleichzeitiger Jobs
RUNNER_CAPACITY=1
# Log Level: trace, debug, info, warn, error, fatal
LOG_LEVEL=info
+75
View File
@@ -0,0 +1,75 @@
# Laravel Application Configuration für Synology NAS Deployment
# Kopiere diese Datei zu .env.synology und passe die Werte an
# ============================================
# Application Settings
# ============================================
APP_NAME=Laravel
APP_ENV=production
APP_KEY=base64:L9RVZ3pNFyAvTbMqicT1rL5GbgE+7lJerkU9wyc95H8=
APP_DEBUG=false
APP_URL=http://your-synology-ip:8080
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US
APP_MAINTENANCE_DRIVER=file
BCRYPT_ROUNDS=12
# ============================================
# Logging
# ============================================
LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=info
# ============================================
# Database - PostgreSQL (Haupt-Datenbank)
# ============================================
DB_CONNECTION2=pgsql
DB_HOST2=postgres
DB_PORT2=5432
DB_DATABASE2=ingest_db
DB_USERNAME2=ingest_user
DB_PASSWORD2=ingest_pwd
# ============================================
# Session & Cache
# ============================================
SESSION_DRIVER=file
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null
# ============================================
# Broadcasting & Queues
# ============================================
BROADCAST_CONNECTION=log
QUEUE_CONNECTION=sync
# ============================================
# Cache
# ============================================
CACHE_STORE=file
FILESYSTEM_DISK=local
# ============================================
# Mail Configuration
# ============================================
MAIL_MAILER=log
MAIL_SCHEME=null
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
# ============================================
# Vite
# ============================================
VITE_APP_NAME="${APP_NAME}"
+233
View File
@@ -0,0 +1,233 @@
name: Build and Deploy to Synology NAS
on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
env:
DOCKER_IMAGE: laravel-app
DOCKER_REGISTRY: ${{ secrets.SYNOLOGY_HOST }}:5000 # Synology Docker Registry Port
jobs:
# Job 1: Run Tests
test:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Validate Conventional Commit (subject line only)
id: validate
run: |
SUBJECT="$(git log -1 --pretty=%s)"
echo "Commit subject: $SUBJECT"
if echo "$SUBJECT" | grep -Eq '^(feat|fix|docs|style|refactor|perf|test|chore|build|ci|revert)(\(.+\))?: .+'; then
echo "valid=true" >> "$GITHUB_OUTPUT"
else
echo "valid=false" >> "$GITHUB_OUTPUT"
fi
- name: Setup PHP
if: ${{ steps.validate.outputs.valid == 'true' }}
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
extensions: mbstring, xml, ctype, json, bcmath, pdo, pdo_sqlite
coverage: none
- name: Install Composer Dependencies
if: ${{ steps.validate.outputs.valid == 'true' }}
run: composer install --prefer-dist --no-progress --no-suggest
- name: Setup Node.js
if: ${{ steps.validate.outputs.valid == 'true' }}
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install NPM Dependencies
if: ${{ steps.validate.outputs.valid == 'true' }}
run: npm ci
- name: Build Frontend Assets
if: ${{ steps.validate.outputs.valid == 'true' }}
run: npm run build
- name: Run Tests
if: ${{ steps.validate.outputs.valid == 'true' }}
run: php artisan test
# Job 2: Build and Push Docker Image
build:
runs-on: ubuntu-latest
needs: test
if: github.event_name == 'push'
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Validate Conventional Commit
id: validate
run: |
SUBJECT="$(git log -1 --pretty=%s)"
echo "Commit subject: $SUBJECT"
if echo "$SUBJECT" | grep -Eq '^(feat|fix|docs|style|refactor|perf|test|chore|build|ci|revert)(\(.+\))?: .+'; then
echo "valid=true" >> "$GITHUB_OUTPUT"
else
echo "valid=false" >> "$GITHUB_OUTPUT"
fi
- name: Stop if not a Conventional Commit
if: ${{ steps.validate.outputs.valid != 'true' }}
run: |
echo "Latest commit is not a valid Conventional Commit. Skipping build."
exit 0
- name: Set up Docker Buildx
if: ${{ steps.validate.outputs.valid == 'true' }}
uses: docker/setup-buildx-action@v3
- name: Determine Docker Tag
id: docker_tag
if: ${{ steps.validate.outputs.valid == 'true' }}
run: |
if [ "${{ github.ref_name }}" == "main" ]; then
echo "tag=latest" >> "$GITHUB_OUTPUT"
echo "env=production" >> "$GITHUB_OUTPUT"
else
echo "tag=${{ github.ref_name }}" >> "$GITHUB_OUTPUT"
echo "env=staging" >> "$GITHUB_OUTPUT"
fi
- name: Build Docker Image
if: ${{ steps.validate.outputs.valid == 'true' }}
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: false
load: true
tags: ${{ env.DOCKER_IMAGE }}:${{ steps.docker_tag.outputs.tag }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Save Docker Image
if: ${{ steps.validate.outputs.valid == 'true' }}
run: |
docker save ${{ env.DOCKER_IMAGE }}:${{ steps.docker_tag.outputs.tag }} | gzip > laravel-app.tar.gz
- name: Upload Docker Image Artifact
if: ${{ steps.validate.outputs.valid == 'true' }}
uses: actions/upload-artifact@v4
with:
name: docker-image
path: laravel-app.tar.gz
retention-days: 1
# Job 3: Deploy to Synology NAS
deploy:
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'develop')
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Download Docker Image Artifact
uses: actions/download-artifact@v4
with:
name: docker-image
- name: Determine Environment
id: env
run: |
if [ "${{ github.ref_name }}" == "main" ]; then
echo "env=production" >> "$GITHUB_OUTPUT"
else
echo "env=staging" >> "$GITHUB_OUTPUT"
fi
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SYNOLOGY_SSH_KEY }}" > ~/.ssh/synology_key
chmod 600 ~/.ssh/synology_key
ssh-keyscan -H ${{ secrets.SYNOLOGY_HOST }} >> ~/.ssh/known_hosts
- name: Copy Files to Synology
run: |
# Transfer Docker Image
scp -i ~/.ssh/synology_key laravel-app.tar.gz \
${{ secrets.SYNOLOGY_USER }}@${{ secrets.SYNOLOGY_HOST }}:/volume1/docker/laravel-app/
# Transfer Docker Compose file
scp -i ~/.ssh/synology_key docker-compose.synology.yml \
${{ secrets.SYNOLOGY_USER }}@${{ secrets.SYNOLOGY_HOST }}:/volume1/docker/laravel-app/
# Transfer deployment script
scp -i ~/.ssh/synology_key scripts/deploy-synology.sh \
${{ secrets.SYNOLOGY_USER }}@${{ secrets.SYNOLOGY_HOST }}:/volume1/docker/laravel-app/
- name: Deploy on Synology
run: |
ssh -i ~/.ssh/synology_key \
${{ secrets.SYNOLOGY_USER }}@${{ secrets.SYNOLOGY_HOST }} \
"cd /volume1/docker/laravel-app && chmod +x deploy-synology.sh && ./deploy-synology.sh"
- name: Health Check
run: |
sleep 10 # Wait for container to start
# Check if the app is responding
SYNOLOGY_IP="${{ secrets.SYNOLOGY_HOST }}"
MAX_RETRIES=30
RETRY_COUNT=0
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
if curl -f -s http://$SYNOLOGY_IP:8080/health > /dev/null 2>&1; then
echo "✅ Application is healthy!"
exit 0
fi
echo "⏳ Waiting for application to be ready... ($RETRY_COUNT/$MAX_RETRIES)"
sleep 5
RETRY_COUNT=$((RETRY_COUNT + 1))
done
echo "❌ Health check failed after $MAX_RETRIES attempts"
exit 1
- name: Cleanup
if: always()
run: |
rm -f ~/.ssh/synology_key
ssh -i ~/.ssh/synology_key \
${{ secrets.SYNOLOGY_USER }}@${{ secrets.SYNOLOGY_HOST }} \
"rm -f /volume1/docker/laravel-app/laravel-app.tar.gz" || true
# Job 4: Notify on Success/Failure (optional)
notify:
runs-on: ubuntu-latest
needs: [test, build, deploy]
if: always()
steps:
- name: Deployment Status
run: |
if [ "${{ needs.deploy.result }}" == "success" ]; then
echo "✅ Deployment to Synology NAS successful!"
echo "🌐 Application available at: http://${{ secrets.SYNOLOGY_HOST }}:8080"
else
echo "❌ Deployment failed. Check the logs for details."
exit 1
fi
+8
View File
@@ -39,6 +39,14 @@ yarn-error.log
/database/*.sqlite /database/*.sqlite
/database/*.sqlite-journal /database/*.sqlite-journal
*.sql.gz *.sql.gz
/backups
# CI/CD & Deployment
.env.synology
.env.gitea-runner
kubeconfig
*.tar.gz
laravel-app.tar.gz
# Backup & Temporary Files # Backup & Temporary Files
*.bak *.bak
+281
View File
@@ -0,0 +1,281 @@
# CI/CD Automatisierung für Synology NAS
Dieses Projekt ist vollständig für automatisches Deployment auf deiner Synology NAS mit Gitea Actions vorbereitet.
## 🚀 Schnellstart
### 1. Gitea Runner einrichten (einmalig)
```bash
# Auf der Synology NAS
cd /volume1/docker
mkdir gitea-runner
cd gitea-runner
# Environment Datei erstellen
cat > .env << 'EOF'
GITEA_URL=http://your-synology-ip:3000
RUNNER_TOKEN=your_token_from_gitea
RUNNER_NAME=synology-runner
EOF
# Runner starten
docker-compose -f /path/to/docker-compose.gitea-runner.yml up -d
```
**Runner Token generieren:**
1. Gitea öffnen
2. Repository → Settings → Actions → Runners
3. "Create new Runner" klicken
4. Token kopieren und in `.env` einfügen
📖 Detaillierte Anleitung: [GITEA_RUNNER_SETUP.md](GITEA_RUNNER_SETUP.md)
### 2. Repository Secrets konfigurieren (einmalig)
In Gitea: **Repository → Settings → Secrets**
| Secret Name | Wert | Beschreibung |
|------------|------|--------------|
| `SYNOLOGY_HOST` | `192.168.1.100` | IP deiner Synology |
| `SYNOLOGY_USER` | `admin` | SSH-Benutzername |
| `SYNOLOGY_SSH_KEY` | `-----BEGIN...` | Private SSH-Key |
| `APP_KEY` | `base64:...` | Laravel APP_KEY |
**SSH-Key erstellen:**
```bash
# Auf der Synology NAS
ssh-keygen -t ed25519 -C "gitea-deploy" -f ~/.ssh/gitea_deploy
cat ~/.ssh/gitea_deploy.pub >> ~/.ssh/authorized_keys
cat ~/.ssh/gitea_deploy # Diesen Key als Secret verwenden
```
### 3. Code pushen und automatisch deployen! 🎉
```bash
git add .
git commit -m "feat: meine neue Funktion"
git push origin main
```
Das wars! Der Rest läuft automatisch:
- ✅ Tests werden ausgeführt
- ✅ Docker Image wird gebaut
- ✅ Deployment auf NAS
- ✅ Health Check
- ✅ Benachrichtigung bei Erfolg/Fehler
## 📁 Wichtige Dateien
| Datei | Beschreibung |
|-------|--------------|
| [`.gitea/workflows/deploy-synology.yml`](.gitea/workflows/deploy-synology.yml) | Gitea Actions Workflow |
| [`docker-compose.synology.yml`](docker-compose.synology.yml) | Docker Compose für Deployment |
| [`scripts/deploy-synology.sh`](scripts/deploy-synology.sh) | Deployment-Script |
| [`.env.synology.example`](.env.synology.example) | Environment-Beispiel |
| [`SYNOLOGY_DEPLOYMENT.md`](SYNOLOGY_DEPLOYMENT.md) | Vollständige Deployment-Doku |
| [`GITEA_RUNNER_SETUP.md`](GITEA_RUNNER_SETUP.md) | Gitea Runner Setup-Anleitung |
## 🔄 Workflow-Prozess
```
1. Developer pushed Code zu Gitea
2. Gitea Actions Workflow startet
3. Tests laufen (Pest)
4. Docker Image wird gebaut
5. Image wird zur Synology NAS übertragen
6. Deployment-Script läuft auf NAS
7. Container werden aktualisiert
8. Migrationen & Cache-Optimierung
9. Health Check
10. ✅ Deployment erfolgreich!
```
## 🎯 Features
### Automatisierte Tests
- PHP-Tests mit Pest
- Frontend-Build-Validierung
- Nur erfolgreiche Builds werden deployed
### Intelligentes Deployment
- Automatisches Backup vor Deployment
- Rollback bei Fehlern
- Health Checks nach Deployment
- Zero-Downtime durch Docker
### Branch-spezifisches Deployment
- `main` → Production (Port 8080)
- `develop` → Staging (Port 8081)
- Feature-Branches → Nur Tests
### Conventional Commits
Der Workflow akzeptiert nur Conventional Commits:
- `feat:` - Neue Features
- `fix:` - Bugfixes
- `docs:` - Dokumentation
- `chore:` - Wartung
- `refactor:` - Code-Refactoring
- `test:` - Tests
- `ci:` - CI/CD Änderungen
**Beispiel:**
```bash
git commit -m "feat: add user authentication"
git commit -m "fix: resolve database connection issue"
```
## 🔍 Monitoring
### Workflow Status prüfen
**In Gitea:**
1. Repository öffnen
2. Tab "Actions" anklicken
3. Alle Runs mit Status sehen
**Logs ansehen:**
- Klicke auf einen Run
- Klicke auf einen Job (test/build/deploy)
- Sieh detaillierte Logs
### Container Logs
```bash
# Auf der Synology NAS via SSH
docker logs -f laravel_app
docker logs -f laravel_postgres
```
### Health Endpoint
```bash
curl http://your-synology-ip:8080/health
```
Response:
```json
{
"status": "healthy",
"timestamp": "2025-12-17T10:30:00Z",
"app": "Laravel",
"env": "production"
}
```
## 🛠 Manuelle Befehle
### Manuelles Deployment
```bash
# Auf der Synology NAS
cd /volume1/docker/laravel-app
./scripts/deploy-synology.sh
```
### Container verwalten
```bash
# Status prüfen
docker-compose -f docker-compose.synology.yml ps
# Logs ansehen
docker-compose -f docker-compose.synology.yml logs -f
# Neustart
docker-compose -f docker-compose.synology.yml restart
# Stoppen
docker-compose -f docker-compose.synology.yml down
```
### Laravel Artisan
```bash
# Migrationen
docker exec laravel_app php artisan migrate
# Cache leeren
docker exec laravel_app php artisan cache:clear
# Shell öffnen
docker exec -it laravel_app sh
```
## 🐛 Troubleshooting
### Workflow startet nicht
**Prüfen:**
1. Runner Status in Gitea → Settings → Actions → Runners
2. Commit-Message ist Conventional Commit Format
3. Branch ist `main` oder `develop`
**Lösung:**
```bash
# Runner neu starten
docker restart gitea-runner
# Runner Logs prüfen
docker logs gitea-runner
```
### Deployment schlägt fehl
**Prüfen:**
1. SSH-Verbindung zur NAS funktioniert
2. Alle Secrets sind korrekt gesetzt
3. Deployment-Script ist executable
**Lösung:**
```bash
# SSH-Key testen
ssh -i ~/.ssh/gitea_deploy admin@your-synology-ip
# Permissions prüfen
chmod +x scripts/deploy-synology.sh
```
### Health Check fehlschlägt
**Prüfen:**
1. Container läuft: `docker ps | grep laravel_app`
2. Logs: `docker logs laravel_app`
3. Netzwerk: `curl http://localhost:8080/health`
**Lösung:**
```bash
# Container neu starten
docker-compose -f docker-compose.synology.yml restart
# .env prüfen
docker exec laravel_app cat .env.synology
```
## 📚 Weitere Dokumentation
- **Deployment Details:** [SYNOLOGY_DEPLOYMENT.md](SYNOLOGY_DEPLOYMENT.md)
- **Gitea Runner Setup:** [GITEA_RUNNER_SETUP.md](GITEA_RUNNER_SETUP.md)
- **Workflow Konfiguration:** [.gitea/workflows/deploy-synology.yml](.gitea/workflows/deploy-synology.yml)
- **Deployment Script:** [scripts/deploy-synology.sh](scripts/deploy-synology.sh)
## 🎉 Das wars!
Nach der einmaligen Einrichtung läuft alles automatisch:
1. Code schreiben
2. Commit & Push
3. Warten bis Deployment fertig ist
4. Anwendung ist live! 🚀
**Happy Deploying!** 🎊
+210
View File
@@ -0,0 +1,210 @@
# Deployment Files Übersicht
Diese Datei gibt einen Überblick über alle Dateien, die für das automatisierte Deployment auf deiner Synology NAS erstellt wurden.
## 📋 Erstelle Dateien
### 1. CI/CD Workflow
- **`.gitea/workflows/deploy-synology.yml`**
- Gitea Actions Workflow für automatisches Build & Deployment
- Führt Tests aus, baut Docker Image, deployt auf NAS
- Triggert bei Push auf `main` oder `develop`
### 2. Docker Konfiguration
- **`docker-compose.synology.yml`**
- Docker Compose für Synology NAS Deployment
- Definiert Laravel App + PostgreSQL Datenbank
- Mit persistenten Volumes und Health Checks
- **`docker-compose.gitea-runner.yml`**
- Docker Compose für Gitea Runner
- Ermöglicht automatische Workflows
- **`Dockerfile`**
- Bereits vorhanden, wird verwendet für Image-Build
- Multi-stage Build für optimale Image-Größe
### 3. Environment Konfiguration
- **`.env.synology.example`**
- Beispiel-Environment für Synology Deployment
- Muss kopiert werden zu `.env.synology`
- Enthält alle notwendigen Variablen
- **`.env.gitea-runner.example`**
- Beispiel-Environment für Gitea Runner
- Muss kopiert werden zu `.env.gitea-runner`
### 4. Deployment Scripts
- **`scripts/deploy-synology.sh`**
- Automatisches Deployment-Script
- Läuft auf der Synology NAS
- Handhabt Backup, Deployment, Rollback, Health Checks
### 5. Dokumentation
- **`SYNOLOGY_DEPLOYMENT.md`**
- Vollständige Anleitung für manuelles Deployment
- Inklusive CI/CD Setup Abschnitt
- Troubleshooting Tipps
- **`GITEA_RUNNER_SETUP.md`**
- Detaillierte Anleitung für Gitea Runner Setup
- Secrets-Konfiguration
- Monitoring & Troubleshooting
- **`CI_CD_README.md`**
- Schnellstart-Anleitung für CI/CD
- Übersicht über alle Features
- Wichtige Befehle
- **`DEPLOYMENT_FILES_OVERVIEW.md`** (diese Datei)
- Übersicht über alle erstellten Dateien
### 6. Application Code
- **`routes/web.php`**
- Health Check Endpoint hinzugefügt (`/health`)
- Wird für automatische Health Checks verwendet
### 7. Git Konfiguration
- **`.gitignore`**
- Erweitert um CI/CD spezifische Dateien
- `.env.synology` und `.env.gitea-runner` ignoriert
- Build-Artefakte ignoriert
## 🔧 Verwendung der Dateien
### Einmalige Einrichtung
1. **Gitea Runner deployen:**
```bash
# Auf Synology NAS
cp .env.gitea-runner.example .env.gitea-runner
# Bearbeite .env.gitea-runner mit deinen Werten
docker-compose -f docker-compose.gitea-runner.yml up -d
```
2. **Repository Secrets in Gitea setzen:**
- `SYNOLOGY_HOST`
- `SYNOLOGY_USER`
- `SYNOLOGY_SSH_KEY`
- `APP_KEY`
3. **Workflow-Dateien committen:**
```bash
git add .gitea/
git commit -m "ci: add automated deployment"
git push origin main
```
### Manuelles Deployment
Falls du manuell deployen möchtest (ohne CI/CD):
```bash
# Auf Synology NAS
cd /volume1/docker/laravel-app
cp .env.synology.example .env.synology
# Bearbeite .env.synology
docker-compose -f docker-compose.synology.yml up -d --build
```
## 📊 Datei-Abhängigkeiten
```
.gitea/workflows/deploy-synology.yml
├── docker-compose.synology.yml
├── scripts/deploy-synology.sh
├── .env.synology (zu erstellen)
└── Dockerfile
docker-compose.gitea-runner.yml
└── .env.gitea-runner (zu erstellen)
```
## ✅ Checkliste für Deployment
### Vor dem ersten Deployment:
- [ ] Gitea Runner deployed (`docker-compose.gitea-runner.yml`)
- [ ] Runner in Gitea registriert
- [ ] Repository Secrets gesetzt
- [ ] `.env.synology` auf NAS erstellt und konfiguriert
- [ ] SSH-Keys für Deployment eingerichtet
- [ ] Projekt-Verzeichnis auf NAS: `/volume1/docker/laravel-app`
### Vor jedem Push:
- [ ] Tests lokal ausgeführt (`php artisan test`)
- [ ] Conventional Commit Message verwendet
- [ ] Code reviewed
### Nach dem Deployment:
- [ ] Workflow Status in Gitea Actions überprüft
- [ ] Health Check erfolgreich: `curl http://nas-ip:8080/health`
- [ ] Anwendung erreichbar: `http://nas-ip:8080`
- [ ] Logs prüfen: `docker logs laravel_app`
## 🔐 Sicherheit
### Dateien die NICHT committet werden sollten:
- `.env.synology` - Enthält Produktions-Secrets
- `.env.gitea-runner` - Enthält Runner-Token
- `kubeconfig` - Falls verwendet
- `*.tar.gz` - Build-Artefakte
- SSH Private Keys
Diese Dateien sind bereits in `.gitignore` eingetragen!
### Dateien die committet werden sollten:
- `.env.synology.example` - Template für andere Entwickler
- `.env.gitea-runner.example` - Template für Runner
- Alle `docker-compose*.yml` Dateien
- Alle Dokumentations-Dateien
- Workflow-Dateien in `.gitea/workflows/`
- Deployment-Scripts in `scripts/`
## 🚀 Nächste Schritte
1. **Lies die Dokumentation:**
- Start mit [CI_CD_README.md](CI_CD_README.md) für Schnellstart
- Dann [GITEA_RUNNER_SETUP.md](GITEA_RUNNER_SETUP.md) für Runner-Setup
- Bei Problemen: [SYNOLOGY_DEPLOYMENT.md](SYNOLOGY_DEPLOYMENT.md)
2. **Setup durchführen:**
- Folge der Anleitung in [GITEA_RUNNER_SETUP.md](GITEA_RUNNER_SETUP.md)
- Konfiguriere Secrets in Gitea
- Teste mit einem Push
3. **Deployment testen:**
- Mache eine kleine Änderung
- Committe mit Conventional Commit
- Push und beobachte Workflow in Gitea Actions
4. **Optional: Erweitere Workflow:**
- Füge Notifications hinzu (Email, Telegram, Discord)
- Konfiguriere mehrere Environments (Staging, Production)
- Füge weitere Tests hinzu
## 📝 Hinweise
- Alle Scripts sind für **Synology DSM 7.x** optimiert
- Docker und Docker Compose müssen auf der NAS installiert sein
- Gitea Actions muss in Gitea aktiviert sein
- PHP 8.4 und Laravel 12 werden verwendet
## 🆘 Support
Bei Fragen oder Problemen:
1. Prüfe die Troubleshooting-Sektionen in den Dokumentations-Dateien
2. Prüfe Logs: `docker logs gitea-runner` und `docker logs laravel_app`
3. Verifiziere alle Secrets und Environment-Variablen
4. Stelle sicher, dass alle Ports verfügbar sind
---
**Erstellt am:** 2025-12-17
**Version:** 1.0
**Für:** Synology NAS Deployment mit Gitea Actions
+411
View File
@@ -0,0 +1,411 @@
# Gitea Runner Setup auf Synology NAS
Diese Anleitung erklärt, wie du einen Gitea Actions Runner auf deiner Synology NAS einrichtest, um automatische Deployments durchzuführen.
## Voraussetzungen
- Gitea läuft auf deiner Synology NAS
- Docker ist auf der Synology NAS installiert
- SSH-Zugriff auf die Synology NAS
- Portainer läuft (optional, aber empfohlen für Container-Management)
## Option 1: Gitea Runner mit Docker Compose (empfohlen)
### 1. Runner Docker Compose Datei erstellen
Erstelle eine Datei `/volume1/docker/gitea-runner/docker-compose.yml`:
```yaml
version: "3.9"
services:
runner:
image: gitea/act_runner:latest
container_name: gitea-runner
restart: unless-stopped
environment:
- GITEA_INSTANCE_URL=http://your-gitea-url:3000
- GITEA_RUNNER_REGISTRATION_TOKEN=${RUNNER_TOKEN}
- GITEA_RUNNER_NAME=synology-runner
- GITEA_RUNNER_LABELS=ubuntu-latest:docker://node:20-bullseye
volumes:
- ./data:/data
- /var/run/docker.sock:/var/run/docker.sock
networks:
- gitea-network
networks:
gitea-network:
external: true
```
### 2. Runner Token generieren
1. Öffne deine Gitea-Instanz im Browser
2. Navigiere zu deinem Repository
3. Gehe zu **Settings****Actions** → **Runners**
4. Klicke auf **Create new Runner**
5. Kopiere den generierten Token
### 3. Environment Variables setzen
Erstelle eine `.env` Datei im selben Verzeichnis:
```env
RUNNER_TOKEN=dein_gitea_runner_token_hier
```
### 4. Runner starten
```bash
cd /volume1/docker/gitea-runner
docker-compose up -d
```
### 5. Runner verifizieren
```bash
# Logs anschauen
docker logs -f gitea-runner
# Status prüfen
docker ps | grep gitea-runner
```
In Gitea solltest du nun unter **Settings****Actions****Runners** deinen registrierten Runner sehen.
## Option 2: Runner direkt in Portainer deployen
### 1. In Portainer einloggen
Öffne Portainer: `http://your-synology-ip:9000`
### 2. Stack erstellen
1. Gehe zu **Stacks****+ Add stack**
2. Name: `gitea-runner`
3. Wähle **Web editor**
4. Füge die obige docker-compose.yml ein
### 3. Environment Variables
Füge folgende Environment Variable hinzu:
- **RUNNER_TOKEN**: Dein Gitea Runner Token
### 4. Deploy
Klicke auf **Deploy the stack**
## Runner Konfiguration
### Custom Runner Labels
Um spezifische Workflows auszuführen, kannst du Custom Labels hinzufügen:
```yaml
environment:
- GITEA_RUNNER_LABELS=ubuntu-latest:docker://node:20-bullseye,ubuntu-22.04:docker://ubuntu:22.04,php-8.4:docker://php:8.4-cli
```
### Mehrere Runner
Für parallele Builds kannst du mehrere Runner starten:
```yaml
services:
runner-1:
image: gitea/act_runner:latest
container_name: gitea-runner-1
# ... config ...
runner-2:
image: gitea/act_runner:latest
container_name: gitea-runner-2
# ... config ...
```
## Repository Secrets konfigurieren
Um das automatische Deployment zu ermöglichen, musst du Secrets in deinem Gitea-Repository hinterlegen:
### 1. In Gitea Repository Settings
1. Gehe zu deinem Repository
2. Klicke auf **Settings** → **Secrets**
3. Füge folgende Secrets hinzu:
| Secret Name | Beschreibung | Beispiel |
|------------|--------------|----------|
| `SYNOLOGY_HOST` | IP oder Hostname deiner Synology | `192.168.1.100` |
| `SYNOLOGY_USER` | SSH-Benutzername | `admin` |
| `SYNOLOGY_SSH_KEY` | Privater SSH-Key für Zugriff | `-----BEGIN OPENSSH PRIVATE KEY-----...` |
| `APP_KEY` | Laravel Application Key | `base64:xyz...` |
### 2. SSH-Key generieren (falls nicht vorhanden)
Auf deiner Synology NAS:
```bash
# SSH-Key-Pair generieren
ssh-keygen -t ed25519 -C "gitea-runner@synology" -f ~/.ssh/gitea_deploy
# Public Key zum authorized_keys hinzufügen
cat ~/.ssh/gitea_deploy.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
# Private Key anzeigen (für Secret)
cat ~/.ssh/gitea_deploy
```
Kopiere den **gesamten** Private Key (inklusive `-----BEGIN` und `-----END` Zeilen) und füge ihn als `SYNOLOGY_SSH_KEY` Secret hinzu.
### 3. Secrets verifizieren
Stelle sicher, dass alle benötigten Secrets gesetzt sind:
```bash
# In Gitea Repository Settings → Secrets
✅ SYNOLOGY_HOST
✅ SYNOLOGY_USER
✅ SYNOLOGY_SSH_KEY
✅ APP_KEY
```
## Workflow aktivieren
### 1. Workflow-Datei pushen
```bash
# Lokal im Projekt
git add .gitea/workflows/deploy-synology.yml
git commit -m "ci: add automated deployment workflow"
git push origin main
```
### 2. Workflow ausführen
Gitea Actions wird automatisch bei jedem Push auf `main` oder `develop` ausgelöst.
### 3. Workflow Status prüfen
1. Gehe zu deinem Repository in Gitea
2. Klicke auf **Actions**
3. Du siehst alle Workflow-Runs mit Status (Success/Failure)
4. Klicke auf einen Run, um Details und Logs zu sehen
## Workflow manuell auslösen
Falls du den Workflow manuell starten möchtest:
### 1. Workflow-Datei erweitern
Füge in `.gitea/workflows/deploy-synology.yml` hinzu:
```yaml
on:
push:
branches:
- main
- develop
workflow_dispatch: # Ermöglicht manuelles Auslösen
```
### 2. Manuell auslösen
1. Gehe zu **Actions** in deinem Repository
2. Wähle den Workflow aus
3. Klicke auf **Run workflow**
## Monitoring & Logs
### Runner Logs
```bash
# Live Logs
docker logs -f gitea-runner
# Letzte 100 Zeilen
docker logs --tail 100 gitea-runner
```
### Workflow Logs
In Gitea UI:
1. **Actions** Tab
2. Wähle einen Workflow Run
3. Klicke auf die einzelnen Jobs, um Logs zu sehen
### Deployment Logs auf Synology
```bash
# Laravel App Logs
docker logs -f laravel_app
# Deployment Script Logs
# Diese werden in der Workflow-Ausgabe angezeigt
```
## Troubleshooting
### Problem: Runner verbindet sich nicht
```bash
# Logs prüfen
docker logs gitea-runner
# Runner neu registrieren
docker-compose down
docker-compose up -d
```
### Problem: Workflow startet nicht
1. **Runner Status prüfen**: Gehe zu Repository → Settings → Actions → Runners
2. **Runner Labels prüfen**: Stelle sicher, dass `runs-on: ubuntu-latest` mit den Runner Labels übereinstimmt
3. **Secrets prüfen**: Alle benötigten Secrets müssen gesetzt sein
### Problem: SSH-Verbindung fehlschlägt
```bash
# SSH-Key Permissions prüfen
chmod 600 ~/.ssh/gitea_deploy
chmod 644 ~/.ssh/gitea_deploy.pub
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
# SSH-Verbindung testen (lokal auf der NAS)
ssh -i ~/.ssh/gitea_deploy admin@localhost
```
### Problem: Deployment schlägt fehl
```bash
# Prüfe deployment script permissions
cd /volume1/docker/laravel-app
ls -la deploy-synology.sh
# Mache es executable
chmod +x deploy-synology.sh
# Teste deployment script manuell
./deploy-synology.sh
```
### Problem: Health Check fehlschlägt
```bash
# Prüfe ob Container läuft
docker ps | grep laravel_app
# Prüfe Logs
docker logs laravel_app
# Teste Health Endpoint manuell
curl http://localhost:8080/health
```
## Best Practices
### 1. Separate Runner für Production und Staging
```yaml
services:
runner-production:
environment:
- GITEA_RUNNER_LABELS=production:docker://ubuntu:22.04
runner-staging:
environment:
- GITEA_RUNNER_LABELS=staging:docker://ubuntu:22.04
```
Im Workflow:
```yaml
jobs:
deploy-production:
runs-on: production
if: github.ref == 'refs/heads/main'
```
### 2. Workflow nur für Conventional Commits
Der aktuelle Workflow filtert bereits nach Conventional Commits:
- `feat:` - Neue Features
- `fix:` - Bugfixes
- `docs:` - Dokumentation
- `chore:` - Wartungsarbeiten
- etc.
### 3. Notifications
Erweitere den Workflow um Benachrichtigungen:
```yaml
- name: Send Notification
if: always()
run: |
# Telegram, Discord, Email, etc.
curl -X POST https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendMessage \
-d chat_id=${{ secrets.TELEGRAM_CHAT_ID }} \
-d text="Deployment status: ${{ job.status }}"
```
### 4. Rollback-Strategie
Im deployment script ist bereits ein Backup-Mechanismus implementiert:
- Datenbank-Backups vor jedem Deployment
- Letzte 5 Backups werden aufbewahrt
- Automatischer Rollback bei Fehlern
## Erweiterte Konfiguration
### Multi-Stage Deployments
Für staging und production environments:
```yaml
jobs:
deploy-staging:
if: github.ref == 'refs/heads/develop'
# ... deploy to staging ...
deploy-production:
if: github.ref == 'refs/heads/main'
needs: [test, deploy-staging]
# ... deploy to production ...
```
### Caching
Um Build-Zeiten zu verkürzen:
```yaml
- name: Cache Composer
uses: actions/cache@v3
with:
path: vendor
key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }}
- name: Cache NPM
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
```
## Weitere Ressourcen
- [Gitea Actions Dokumentation](https://docs.gitea.com/usage/actions/overview)
- [Act Runner Dokumentation](https://gitea.com/gitea/act_runner)
- [Docker Compose Dokumentation](https://docs.docker.com/compose/)
## Support
Bei Problemen:
1. Prüfe Runner Logs: `docker logs gitea-runner`
2. Prüfe Workflow Logs in Gitea Actions Tab
3. Verifiziere alle Secrets sind korrekt gesetzt
4. Teste SSH-Verbindung zur Synology manuell
+435
View File
@@ -0,0 +1,435 @@
# Synology NAS Deployment Anleitung
Diese Anleitung beschreibt, wie du diese Laravel-Anwendung auf deiner Synology NAS mit Portainer deployen kannst.
## 📋 Inhaltsverzeichnis
1. [Voraussetzungen](#voraussetzungen)
2. [Manuelles Deployment](#-vorbereitung)
3. [Automatisches CI/CD Deployment](#-automatisches-deployment-mit-gitea-actions)
4. [Monitoring & Wartung](#-monitoring--wartung)
5. [Troubleshooting](#-troubleshooting)
## Voraussetzungen
- Synology NAS mit Docker-Unterstützung
- Portainer läuft bereits auf deiner NAS
- SSH-Zugriff auf die Synology NAS (optional, aber empfohlen)
- Mindestens 2GB freier RAM
- Mindestens 5GB freier Speicherplatz
- (Optional) Gitea für automatisches CI/CD Deployment
## 📦 Vorbereitung
### 1. Projekt-Dateien auf die NAS übertragen
Es gibt mehrere Möglichkeiten, die Dateien auf deine Synology zu übertragen:
#### Option A: Via Git (empfohlen)
```bash
# SSH auf die Synology NAS
ssh admin@your-synology-ip
# Navigiere zu einem geeigneten Verzeichnis (z.B. /volume1/docker/laravel)
cd /volume1/docker
git clone <dein-repository-url> laravel-app
cd laravel-app
```
#### Option B: Via File Station
1. Öffne die Synology File Station
2. Erstelle einen Ordner: `/docker/laravel-app`
3. Lade alle Projekt-Dateien in diesen Ordner hoch
#### Option C: Via rsync/scp
```bash
# Vom lokalen Rechner aus
rsync -avz --exclude 'node_modules' --exclude 'vendor' \
/Users/sebastianfrohlich/Herd/frontend/ \
admin@your-synology-ip:/volume1/docker/laravel-app/
```
### 2. Umgebungsvariablen konfigurieren
```bash
# SSH auf der NAS
cd /volume1/docker/laravel-app
# Kopiere die Synology-Beispiel-Datei
cp .env.synology.example .env.synology
# Bearbeite die Datei mit deinen spezifischen Einstellungen
nano .env.synology
```
**Wichtige Anpassungen in `.env.synology`:**
```env
# Ersetze mit deiner Synology IP-Adresse
APP_URL=http://192.168.1.100:8080
# Setze APP_DEBUG auf false für Produktion
APP_DEBUG=false
# Generiere einen neuen APP_KEY (wichtig für Sicherheit!)
# Dies kann später mit: docker exec laravel_app php artisan key:generate gemacht werden
# PostgreSQL Passwort - ändere dies!
DB_PASSWORD2=dein_sicheres_passwort_hier
```
## 🚀 Deployment mit Portainer
### Methode 1: Docker Compose Stack (empfohlen)
1. **Öffne Portainer** in deinem Browser: `http://your-synology-ip:9000`
2. **Navigiere zu "Stacks"**:
- Klicke auf "Stacks" im linken Menü
- Klicke auf "+ Add stack"
3. **Stack konfigurieren**:
- **Name**: `laravel-app`
- **Build method**: Wähle "Repository"
- **Repository URL**: Gib deine Git-Repository-URL ein (falls vorhanden)
- Oder wähle "Upload" und lade `docker-compose.synology.yml` hoch
- Oder wähle "Web editor" und kopiere den Inhalt von `docker-compose.synology.yml`
4. **Umgebungsvariablen setzen**:
Klicke auf "Add an environment variable" und füge folgende Variablen hinzu:
```
APP_NAME=Laravel
APP_ENV=production
APP_KEY=base64:L9RVZ3pNFyAvTbMqicT1rL5GbgE+7lJerkU9wyc95H8=
APP_DEBUG=false
APP_URL=http://your-synology-ip:8080
DB_CONNECTION2=pgsql
DB_HOST2=postgres
DB_PORT2=5432
DB_DATABASE2=ingest_db
DB_USERNAME2=ingest_user
DB_PASSWORD2=dein_sicheres_passwort
```
5. **Stack deployen**:
- Klicke auf "Deploy the stack"
- Warte, bis der Build-Prozess abgeschlossen ist (kann 5-10 Minuten dauern)
### Methode 2: Build und Deploy manuell via SSH
```bash
# SSH auf die Synology
ssh admin@your-synology-ip
# Navigiere zum Projekt-Verzeichnis
cd /volume1/docker/laravel-app
# Baue das Docker Image
docker build -t laravel-app:latest .
# Starte die Services mit docker-compose
docker-compose -f docker-compose.synology.yml up -d
```
## 🔍 Verifikation
### 1. Überprüfe den Container-Status
In Portainer:
- Gehe zu "Containers"
- Du solltest zwei laufende Container sehen:
- `laravel_app` (Status: running, Port: 0.0.0.0:8080->80/tcp)
- `laravel_postgres` (Status: running, Port: 5432/tcp)
Via SSH:
```bash
docker ps
```
### 2. Überprüfe die Logs
In Portainer:
- Klicke auf den Container `laravel_app`
- Wähle "Logs"
- Du solltest keine Fehler sehen
Via SSH:
```bash
# Laravel App Logs
docker logs laravel_app
# PostgreSQL Logs
docker logs laravel_postgres
```
### 3. Teste die Anwendung
Öffne deinen Browser und navigiere zu:
```
http://your-synology-ip:8080
```
Du solltest die Laravel-Anwendung sehen!
## 🔧 Nützliche Befehle
### Artisan-Befehle ausführen
```bash
# Laravel Cache leeren
docker exec laravel_app php artisan cache:clear
# Neuen APP_KEY generieren
docker exec laravel_app php artisan key:generate
# Migrationen ausführen
docker exec laravel_app php artisan migrate
# Seeder ausführen
docker exec laravel_app php artisan db:seed
```
### Container neustarten
Via Portainer:
- Gehe zu "Containers"
- Wähle den Container aus
- Klicke auf "Restart"
Via SSH:
```bash
docker-compose -f docker-compose.synology.yml restart
```
### Container stoppen und entfernen
Via Portainer:
- Gehe zu "Stacks"
- Wähle den Stack "laravel-app"
- Klicke auf "Stop" oder "Delete"
Via SSH:
```bash
docker-compose -f docker-compose.synology.yml down
# Mit Volumes löschen (Achtung: Löscht die Datenbank!)
docker-compose -f docker-compose.synology.yml down -v
```
### Logs live verfolgen
```bash
# Alle Container
docker-compose -f docker-compose.synology.yml logs -f
# Nur Laravel App
docker logs -f laravel_app
# Nur PostgreSQL
docker logs -f laravel_postgres
```
## 🔐 Sicherheitshinweise
1. **APP_KEY ändern**: Generiere einen neuen APP_KEY für die Produktion:
```bash
docker exec laravel_app php artisan key:generate
```
2. **Datenbank-Passwort**: Ändere das Standard-PostgreSQL-Passwort in `.env.synology`
3. **APP_DEBUG**: Stelle sicher, dass `APP_DEBUG=false` in der Produktion
4. **Firewall**: Konfiguriere die Synology-Firewall, um nur benötigte Ports zu öffnen
5. **SSL/HTTPS**: Für den Produktionsbetrieb solltest du einen Reverse Proxy (z.B. Synology DSM Reverse Proxy) mit SSL-Zertifikat einrichten
## 🌐 Reverse Proxy einrichten (optional, aber empfohlen)
Für den Zugriff über eine Domain mit HTTPS:
1. **In Synology DSM**:
- Gehe zu "Systemsteuerung" → "Anmeldungsportal" → "Erweitert"
- Klicke auf "Reverse Proxy" → "Erstellen"
2. **Konfiguration**:
- **Protokoll**: HTTPS
- **Hostname**: your-domain.com
- **Port**: 443
- **Zielprotokoll**: HTTP
- **Zielhost**: localhost
- **Zielport**: 8080
3. **SSL-Zertifikat**:
- Gehe zu "Systemsteuerung" → "Sicherheit" → "Zertifikat"
- Füge ein Let's Encrypt-Zertifikat hinzu
## 📊 Monitoring & Wartung
### Container-Ressourcen überwachen
In Portainer:
- Gehe zu "Containers"
- Wähle einen Container
- Klicke auf "Stats" für Echtzeit-Metriken (CPU, RAM, Netzwerk)
### Backup
```bash
# PostgreSQL Datenbank sichern
docker exec laravel_postgres pg_dump -U ingest_user ingest_db > backup_$(date +%Y%m%d).sql
# Gesamten Stack sichern (inkl. Volumes)
docker run --rm \
-v laravel-app_postgres-data:/data \
-v /volume1/docker/backups:/backup \
alpine tar czf /backup/postgres-backup-$(date +%Y%m%d).tar.gz /data
```
### Updates
```bash
# Projekt-Code aktualisieren (wenn via Git)
cd /volume1/docker/laravel-app
git pull
# Neu bauen und deployen
docker-compose -f docker-compose.synology.yml up -d --build
# Migrationen ausführen
docker exec laravel_app php artisan migrate --force
```
## ❓ Troubleshooting
### Problem: Container startet nicht
```bash
# Logs prüfen
docker logs laravel_app
# Container interaktiv starten für Debugging
docker exec -it laravel_app sh
```
### Problem: Datenbank-Verbindung fehlgeschlagen
```bash
# PostgreSQL-Container prüfen
docker exec laravel_postgres pg_isready -U ingest_user
# Umgebungsvariablen prüfen
docker exec laravel_app env | grep DB_
```
### Problem: Permissions-Fehler
```bash
# Storage-Permissions korrigieren
docker exec laravel_app chmod -R 775 storage bootstrap/cache
docker exec laravel_app chown -R nginx:nginx storage bootstrap/cache
```
### Problem: Port bereits belegt
Wenn Port 8080 bereits verwendet wird:
1. Öffne `docker-compose.synology.yml`
2. Ändere die Port-Mapping: `"8081:80"` statt `"8080:80"`
3. Aktualisiere `APP_URL` in `.env.synology` entsprechend
## 🤖 Automatisches Deployment mit Gitea Actions
Wenn du Gitea auf deiner Synology NAS verwendest, kannst du den gesamten Build- und Deployment-Prozess automatisieren!
### Vorteile von CI/CD
- ✅ Automatischer Build bei jedem Git Push
- ✅ Automatische Tests vor Deployment
- ✅ Automatisches Deployment auf die NAS
- ✅ Rollback bei Fehlern
- ✅ Keine manuellen Schritte mehr nötig
### Quick Start
1. **Gitea Runner einrichten**
- Siehe detaillierte Anleitung: [GITEA_RUNNER_SETUP.md](GITEA_RUNNER_SETUP.md)
- Kurz: Runner Docker Container auf NAS deployen
- Runner in Gitea registrieren
2. **Repository Secrets konfigurieren**
Gehe in Gitea zu: **Repository → Settings → Secrets**
Füge folgende Secrets hinzu:
```
SYNOLOGY_HOST=192.168.1.100
SYNOLOGY_USER=admin
SYNOLOGY_SSH_KEY=<dein-ssh-private-key>
APP_KEY=<dein-laravel-app-key>
```
3. **Workflow pushen**
Der Workflow in [`.gitea/workflows/deploy-synology.yml`](.gitea/workflows/deploy-synology.yml) ist bereits vorkonfiguriert.
```bash
git add .gitea/workflows/deploy-synology.yml
git commit -m "ci: add automated deployment workflow"
git push origin main
```
4. **Automatisches Deployment genießen! 🎉**
Bei jedem Push auf `main` oder `develop`:
- Tests werden ausgeführt
- Docker Image wird gebaut
- Deployment auf NAS erfolgt automatisch
- Health Check verifiziert Deployment
### Workflow-Ablauf
```mermaid
graph LR
A[Git Push] --> B[Run Tests]
B --> C{Tests OK?}
C -->|Ja| D[Build Docker Image]
C -->|Nein| E[Abbruch]
D --> F[Transfer zu NAS]
F --> G[Deploy auf NAS]
G --> H[Health Check]
H --> I{Healthy?}
I -->|Ja| J[✅ Success]
I -->|Nein| K[Rollback]
```
### Workflow überwachen
1. Gehe zu deinem Repository in Gitea
2. Klicke auf **Actions**
3. Siehe alle Workflow-Runs mit Status
4. Klicke auf einen Run für Details und Logs
### Erweiterte Konfiguration
Weitere Details zur CI/CD-Konfiguration findest du in:
- [GITEA_RUNNER_SETUP.md](GITEA_RUNNER_SETUP.md) - Detaillierte Runner-Setup Anleitung
- [`.gitea/workflows/deploy-synology.yml`](.gitea/workflows/deploy-synology.yml) - Workflow-Konfiguration
- [`scripts/deploy-synology.sh`](scripts/deploy-synology.sh) - Deployment-Script
## 📝 Weitere Ressourcen
- [Laravel Dokumentation](https://laravel.com/docs)
- [Docker Dokumentation](https://docs.docker.com/)
- [Portainer Dokumentation](https://docs.portainer.io/)
- [Synology Docker Anleitung](https://www.synology.com/en-us/dsm/packages/Docker)
- [Gitea Actions Dokumentation](https://docs.gitea.com/usage/actions/overview)
## 🆘 Support
Bei Problemen:
1. Prüfe die Container-Logs
2. Überprüfe die Umgebungsvariablen
3. Stelle sicher, dass alle Ports verfügbar sind
4. Prüfe die Synology-Firewall-Einstellungen
5. Bei CI/CD: Prüfe Gitea Actions Logs und Runner Status
+74
View File
@@ -0,0 +1,74 @@
version: "3.9"
# Gitea Runner für automatische CI/CD Deployments
# Dieses Compose-File wird auf der Synology NAS deployed
services:
gitea-runner:
image: gitea/act_runner:latest
container_name: gitea-runner
restart: unless-stopped
environment:
# Gitea Instance URL - Passe dies an deine Gitea-Installation an
- GITEA_INSTANCE_URL=${GITEA_URL:-http://gitea:3000}
# Runner Registration Token - Wird aus Gitea UI generiert
- GITEA_RUNNER_REGISTRATION_TOKEN=${RUNNER_TOKEN}
# Runner Name - Wird in Gitea angezeigt
- GITEA_RUNNER_NAME=${RUNNER_NAME:-synology-runner}
# Runner Labels - Definiert welche Workflows dieser Runner ausführen kann
# Format: label:docker://image
- GITEA_RUNNER_LABELS=ubuntu-latest:docker://catthehacker/ubuntu:act-latest,ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04,ubuntu-20.04:docker://catthehacker/ubuntu:act-20.04
# Runner Capacity - Maximale Anzahl gleichzeitiger Jobs
- GITEA_RUNNER_CAPACITY=${RUNNER_CAPACITY:-1}
# Log Level
- GITEA_RUNNER_LOG_LEVEL=${LOG_LEVEL:-info}
volumes:
# Runner Daten (Config, Cache, etc.)
- runner-data:/data
# Docker Socket - Ermöglicht dem Runner Docker-Container zu starten
- /var/run/docker.sock:/var/run/docker.sock
# Optional: Workspace für Job-Artefakte
- runner-workspace:/workspace
networks:
- gitea-network
# Health Check
healthcheck:
test: ["CMD", "pgrep", "-f", "act_runner"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# Resource Limits (optional, aber empfohlen)
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '1'
memory: 512M
volumes:
runner-data:
driver: local
runner-workspace:
driver: local
networks:
gitea-network:
# Wenn Gitea in einem separaten Netzwerk läuft, verwende:
# external: true
# Ansonsten:
driver: bridge
+91
View File
@@ -0,0 +1,91 @@
version: "3.9"
services:
app:
build:
context: .
dockerfile: Dockerfile
image: laravel-app:latest
container_name: laravel_app
restart: unless-stopped
ports:
- "8080:80" # Angepasst für Synology (Port 81 oft belegt)
environment:
# Laravel Environment
- APP_NAME=${APP_NAME:-Laravel}
- APP_ENV=${APP_ENV:-production}
- APP_KEY=${APP_KEY}
- APP_DEBUG=${APP_DEBUG:-false}
- APP_URL=${APP_URL:-http://localhost:8080}
# Database - PostgreSQL
- DB_CONNECTION2=${DB_CONNECTION2:-pgsql}
- DB_HOST2=${DB_HOST2:-postgres}
- DB_PORT2=${DB_PORT2:-5432}
- DB_DATABASE2=${DB_DATABASE2:-ingest_db}
- DB_USERNAME2=${DB_USERNAME2:-ingest_user}
- DB_PASSWORD2=${DB_PASSWORD2:-ingest_pwd}
# Session & Cache
- SESSION_DRIVER=${SESSION_DRIVER:-file}
- CACHE_STORE=${CACHE_STORE:-file}
- QUEUE_CONNECTION=${QUEUE_CONNECTION:-sync}
# Logging
- LOG_CHANNEL=${LOG_CHANNEL:-stack}
- LOG_LEVEL=${LOG_LEVEL:-info}
# Mail
- MAIL_MAILER=${MAIL_MAILER:-log}
volumes:
- app-storage:/var/www/html/storage
- app-bootstrap-cache:/var/www/html/bootstrap/cache
- ./database:/var/www/html/database
networks:
- laravel-network
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:16-alpine
container_name: laravel_postgres
restart: unless-stopped
environment:
- POSTGRES_DB=${DB_DATABASE2:-ingest_db}
- POSTGRES_USER=${DB_USERNAME2:-ingest_user}
- POSTGRES_PASSWORD=${DB_PASSWORD2:-ingest_pwd}
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- postgres-data:/var/lib/postgresql/data
ports:
- "5432:5432" # Optional: Direktzugriff auf PostgreSQL
networks:
- laravel-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME2:-ingest_user}"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres-data:
driver: local
app-storage:
driver: local
app-bootstrap-cache:
driver: local
networks:
laravel-network:
driver: bridge
+9
View File
@@ -8,6 +8,15 @@ Route::get('/', function () {
return view('welcome'); return view('welcome');
})->name('home'); })->name('home');
Route::get('/health', function () {
return response()->json([
'status' => 'healthy',
'timestamp' => now()->toIso8601String(),
'app' => config('app.name'),
'env' => config('app.env'),
]);
})->name('health');
Route::view('dashboard', 'dashboard') Route::view('dashboard', 'dashboard')
->middleware(['auth', 'verified']) ->middleware(['auth', 'verified'])
->name('dashboard'); ->name('dashboard');
+258
View File
@@ -0,0 +1,258 @@
#!/bin/bash
# Deployment Script für Synology NAS
# Dieses Script wird auf der Synology NAS ausgeführt
set -e # Exit on error
# ============================================
# Configuration
# ============================================
PROJECT_DIR="/volume1/docker/laravel-app"
DOCKER_IMAGE="laravel-app"
COMPOSE_FILE="docker-compose.synology.yml"
ENV_FILE=".env.synology"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# ============================================
# Helper Functions
# ============================================
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# ============================================
# Pre-deployment Checks
# ============================================
log_info "Starting deployment process..."
# Check if running on Synology
if [ ! -d "/volume1" ]; then
log_error "This script should be run on Synology NAS"
exit 1
fi
# Navigate to project directory
cd "$PROJECT_DIR" || {
log_error "Project directory not found: $PROJECT_DIR"
exit 1
}
# Check if Docker is installed
if ! command -v docker &> /dev/null; then
log_error "Docker is not installed"
exit 1
fi
# Check if docker-compose is installed
if ! command -v docker-compose &> /dev/null; then
log_error "docker-compose is not installed"
exit 1
fi
# ============================================
# Load Docker Image
# ============================================
if [ -f "laravel-app.tar.gz" ]; then
log_info "Loading Docker image from artifact..."
gunzip -c laravel-app.tar.gz | docker load
# Tag the image appropriately
LOADED_IMAGE=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep laravel-app | head -n1)
if [ -n "$LOADED_IMAGE" ]; then
docker tag "$LOADED_IMAGE" "${DOCKER_IMAGE}:latest"
log_info "Tagged image as ${DOCKER_IMAGE}:latest"
fi
else
log_warn "No Docker image artifact found. Using existing image or building..."
# Check if Dockerfile exists and build if necessary
if [ -f "Dockerfile" ]; then
log_info "Building Docker image..."
docker build -t "${DOCKER_IMAGE}:latest" .
else
log_error "Neither Docker artifact nor Dockerfile found"
exit 1
fi
fi
# ============================================
# Environment Configuration
# ============================================
if [ ! -f "$ENV_FILE" ]; then
log_warn "Environment file not found: $ENV_FILE"
if [ -f ".env.synology.example" ]; then
log_info "Copying from .env.synology.example..."
cp .env.synology.example "$ENV_FILE"
log_warn "⚠️ Please configure $ENV_FILE with your settings!"
else
log_error "No environment configuration found"
exit 1
fi
fi
# ============================================
# Backup Current Deployment
# ============================================
log_info "Creating backup of current deployment..."
BACKUP_DIR="/volume1/docker/backups/laravel-app"
mkdir -p "$BACKUP_DIR"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/backup_${TIMESTAMP}.tar.gz"
# Backup database if container is running
if docker ps --format '{{.Names}}' | grep -q "laravel_postgres"; then
log_info "Backing up PostgreSQL database..."
docker exec laravel_postgres pg_dump -U ingest_user ingest_db > "$BACKUP_DIR/db_${TIMESTAMP}.sql"
fi
# Keep only last 5 backups
log_info "Cleaning old backups (keeping last 5)..."
ls -t "$BACKUP_DIR"/db_*.sql 2>/dev/null | tail -n +6 | xargs -r rm
# ============================================
# Stop Current Containers
# ============================================
log_info "Stopping current containers..."
if [ -f "$COMPOSE_FILE" ]; then
docker-compose -f "$COMPOSE_FILE" down || log_warn "No containers to stop"
else
log_warn "Compose file not found: $COMPOSE_FILE"
fi
# ============================================
# Clean up old images (optional)
# ============================================
log_info "Cleaning up old Docker images..."
docker image prune -f
# ============================================
# Start New Deployment
# ============================================
log_info "Starting new deployment..."
if [ ! -f "$COMPOSE_FILE" ]; then
log_error "Docker Compose file not found: $COMPOSE_FILE"
exit 1
fi
# Pull/use latest images and start services
docker-compose -f "$COMPOSE_FILE" up -d --build
# ============================================
# Wait for Services to Start
# ============================================
log_info "Waiting for services to start..."
sleep 10
# Check if containers are running
if ! docker ps --format '{{.Names}}' | grep -q "laravel_app"; then
log_error "Laravel app container failed to start"
# Show logs
log_info "Container logs:"
docker-compose -f "$COMPOSE_FILE" logs --tail=50
# Rollback
log_warn "Attempting rollback..."
docker-compose -f "$COMPOSE_FILE" down
exit 1
fi
# ============================================
# Post-deployment Tasks
# ============================================
log_info "Running post-deployment tasks..."
# Wait for database to be ready
log_info "Waiting for database to be ready..."
sleep 5
# Run migrations
log_info "Running database migrations..."
docker exec laravel_app php artisan migrate --force || log_warn "Migrations failed"
# Clear caches
log_info "Clearing caches..."
docker exec laravel_app php artisan cache:clear || log_warn "Cache clear failed"
docker exec laravel_app php artisan config:clear || log_warn "Config clear failed"
docker exec laravel_app php artisan view:clear || log_warn "View clear failed"
# Optimize
log_info "Optimizing application..."
docker exec laravel_app php artisan config:cache || log_warn "Config cache failed"
docker exec laravel_app php artisan route:cache || log_warn "Route cache failed"
docker exec laravel_app php artisan view:cache || log_warn "View cache failed"
# ============================================
# Health Check
# ============================================
log_info "Performing health check..."
MAX_RETRIES=30
RETRY_COUNT=0
HEALTH_CHECK_URL="http://localhost:8080"
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
if curl -f -s "$HEALTH_CHECK_URL" > /dev/null 2>&1; then
log_info "✅ Application is healthy!"
break
fi
log_info "⏳ Waiting for application... ($RETRY_COUNT/$MAX_RETRIES)"
sleep 5
RETRY_COUNT=$((RETRY_COUNT + 1))
done
if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
log_error "Health check failed after $MAX_RETRIES attempts"
# Show recent logs
log_info "Recent application logs:"
docker-compose -f "$COMPOSE_FILE" logs --tail=100
exit 1
fi
# ============================================
# Display Status
# ============================================
log_info "Deployment completed successfully! 🚀"
log_info "Container status:"
docker-compose -f "$COMPOSE_FILE" ps
log_info ""
log_info "==================================="
log_info "Application URL: http://$(hostname -I | awk '{print $1}'):8080"
log_info "==================================="
log_info ""
log_info "Useful commands:"
log_info " - View logs: docker-compose -f $COMPOSE_FILE logs -f"
log_info " - Restart: docker-compose -f $COMPOSE_FILE restart"
log_info " - Stop: docker-compose -f $COMPOSE_FILE down"
log_info " - Shell access: docker exec -it laravel_app sh"
# ============================================
# Cleanup
# ============================================
log_info "Cleaning up deployment artifacts..."
rm -f laravel-app.tar.gz
log_info "Deployment script completed!"
exit 0