No description
  • PHP 85.5%
  • JavaScript 6.2%
  • CSS 3.3%
  • Mustache 2.6%
  • Gherkin 0.9%
  • Other 1.4%
Find a file
Johannes Moskaliuk c41b9543cb
All checks were successful
/ deploy-dev (push) Successful in 21s
/ promote-demo (push) Has been skipped
CI/CD-Pipeline und Vendor-Plugin-Mechanismus dokumentieren
2026-07-04 09:57:10 +00:00
.forgejo/workflows .forgejo/workflows/deploy.yml hinzugefügt 2026-07-04 08:29:17 +00:00
.github/workflows Suite expansion: learning path block, curriculum course generator (KG track), CI and premium consolidation (#35) 2026-07-03 09:24:34 +02:00
config Fix local Moodle router deployment 2026-06-30 13:08:13 +02:00
custom-plugins dynamic_cohorts Source entfernen, wird jetzt via vendor-plugins.txt geholt 2026-07-04 09:07:46 +00:00
docker Korrekter Branch-Name (MOODLE_404_STABLE) + Fetch-Skript bricht jetzt laut ab bei Fehlern 2026-07-04 09:16:34 +00:00
docs CI/CD-Pipeline und Vendor-Plugin-Mechanismus dokumentieren 2026-07-04 09:57:10 +00:00
plugin-screenshots ai-suite: update devflow snapshot and showcase 2026-06-23 23:00:05 +02:00
scripts Add vendor-tutor-suite.sh for the push-from-local workflow (#33) 2026-07-02 20:40:13 +02:00
site Decouple LernHive core from AI suite 2026-06-30 13:07:23 +02:00
.env.example Pin filter translations fetch to release tag 2026-07-01 12:06:30 +02:00
.env.local.example Suite expansion: learning path block, curriculum course generator (KG track), CI and premium consolidation (#35) 2026-07-03 09:24:34 +02:00
.gitignore Suite expansion: learning path block, curriculum course generator (KG track), CI and premium consolidation (#35) 2026-07-03 09:24:34 +02:00
docker-compose.local.yml Decouple LernHive core from AI suite 2026-06-30 13:07:23 +02:00
docker-compose.yml Caddy-Service aus Compose entfernen (Reverse Proxy laeuft zentral bei demo) 2026-07-04 08:43:54 +00:00
FEATURE-KONZEPTE.md Advance AI suite plugin integration (#13) 2026-06-30 18:10:16 +02:00
HANDOVER-kursgenerator.md Advance AI suite plugin integration (#13) 2026-06-30 18:10:16 +02:00
HANDOVER-lernpfad.md Advance AI suite plugin integration (#13) 2026-06-30 18:10:16 +02:00
README.md Decouple LernHive core from AI suite 2026-06-30 13:07:23 +02:00
ROADMAP.md Suite expansion: learning path block, curriculum course generator (KG track), CI and premium consolidation (#35) 2026-07-03 09:24:34 +02:00

Moodle 5.2 auf Hetzner mit lokalem Deploy-Flow

Dieses Repo richtet ein produktives Moodle 5.2 auf einem Hetzner-Server ein (Docker Compose). Der aktuelle Arbeitsmodus ist lokal-first: Push auf main führt CI aus, Production-Deploy läuft nur manuell über GitHub Actions workflow_dispatch.


Architektur

        Run workflow
             │
             ▼
   ┌──────────────────┐      SSH       ┌──────────────────────────────────────┐
   │  GitHub Actions  │ ─────────────► │  Hetzner-Server (/opt/moodle)        │
   │  (deploy.yml)    │                │                                      │
   └──────────────────┘                │   scripts/deploy.sh                  │
                                       │     git pull → docker build          │
                                       │     → upgrade.php → purge_caches.php  │
                                       │                                      │
                                       │  ┌────────┐  ┌────────┐  ┌────────┐  │
                                       │  │ caddy  │─►│ moodle │─►│  db    │  │
                                       │  │ TLS    │  │ PHP8.4 │  │MariaDB │  │
                                       │  └────────┘  │ Apache │  └────────┘  │
                                       │              └───┬────┘  ┌────────┐  │
                                       │              ┌───┴────┐  │ redis  │  │
                                       │              │  cron  │  └────────┘  │
                                       │              └────────┘              │
                                       └──────────────────────────────────────┘

Was liegt im Repo (Empfehlung): nicht der Moodle-Core, sondern nur deine eigenen Plugins/Themes plus die Infrastruktur. Der Core wird beim Build an einem festgepinnten Tag (MOODLE_GIT_REF, z. B. v5.2.1) frisch von GitHub geklont. Vorteile: kleines Repo, keine Merge-Konflikte mit dem Core, und ein Core-Update ist nur eine Zeile in der .env. Deine Plugins liegen unter custom-plugins/ (siehe custom-plugins/README.md).


Verzeichnisstruktur

moodle-hetzner/
├── docker-compose.yml          # caddy + moodle + cron + db + redis
├── .env.example                # Vorlage für Secrets/Config (→ .env auf Server)
├── config/config.php           # Moodle-Config, komplett über ENV gesteuert
├── custom-plugins/             # deine Plugins/Themes (→ public/<type>/)
├── docker/
│   ├── Dockerfile              # PHP 8.4 + Apache + Moodle-Core (gepinnt)
│   ├── php.ini                 # max_input_vars=5000, OPcache, Limits
│   ├── apache-moodle.conf      # DocumentRoot → public/
│   ├── Caddyfile               # Auto-HTTPS via Let's Encrypt
│   └── entrypoint.sh           # wartet auf DB, setzt Rechte
├── scripts/
│   ├── server-setup.sh         # einmaliger Server-Bootstrap
│   ├── install.sh              # einmalige Moodle-Erstinstallation
│   └── deploy.sh               # läuft bei jedem Deploy (von CI getriggert)
└── .github/workflows/deploy.yml

Eckdaten Moodle 5.2 (verifiziert)

Komponente Anforderung
Release 5.2.0 am 20.04.2026, aktueller Punkt-Release 5.2.1
PHP min. 8.3, 8.4 unterstützt, 64-bit, Extension sodium Pflicht
max_input_vars ≥ 5000
Datenbank MariaDB ≥ 10.11 · PostgreSQL ≥ 16 · MySQL ≥ 8.4
Web-Root das public/-Verzeichnis (Code-Restructure seit 5.1)
config.php liegt im Install-Root, CLI-Skripte unter admin/cli/ im Root

Dieses Setup nutzt PHP 8.4, MariaDB 11.4 und Redis.


Schritt 1 Hetzner-Server bestellen

  1. Bei Hetzner Cloud ein Projekt anlegen und einen Server erstellen.
    • Image: Ubuntu 26.04 LTS (Fallback 24.04 LTS, falls 26.04 noch nicht im Menü ist)
    • Typ: Demo/leicht CX23 (2 vCPU, 4 GB, 40 GB SSD, ~5,49 €/Mon); empfohlen für echten Betrieb CX33 (4 vCPU, 8 GB, 80 GB), da Moodle + MariaDB + Redis + Caddy + Cron parallel laufen. Reihe: CX23 → CX33 → CX43 → CX53.
    • Netzwerk: IPv4 aktiviert lassen (für Let's Encrypt + breite Erreichbarkeit dringend empfohlen siehe Hinweis unten).
    • SSH-Key: deinen öffentlichen Key hinterlegen (sonst Passwort per Mail).
  2. Server-IP notieren.

Schritt 2 DNS setzen

Beim Domain-Provider einen A-Record anlegen, der demo.eledia.ai auf die IPv4 des Servers zeigen lässt, z. B. demo.eledia.ai → 203.0.113.10. Hast du auch eine IPv6, zusätzlich einen AAAA-Record setzen. Wichtig: Caddy holt das TLS-Zertifikat erst, wenn der DNS-Eintrag aktiv ist.

Schritt 3 Repo auf GitHub anlegen

  1. Auf GitHub ein privates Repo erstellen (z. B. moodle-hetzner).
  2. Diesen Ordner hochladen:
    cd moodle-hetzner
    git init && git add . && git commit -m "Initial Moodle 5.2 stack"
    git branch -M main
    git remote add origin git@github.com:DEINUSER/moodle-hetzner.git
    git push -u origin main
    

Schritt 4 Server bootstrappen

Per SSH als root auf den Server, dann:

curl -fsSL https://raw.githubusercontent.com/DEINUSER/moodle-hetzner/main/scripts/server-setup.sh -o server-setup.sh
bash server-setup.sh git@github.com:DEINUSER/moodle-hetzner.git

Das installiert Docker, legt den User deploy an, konfiguriert die Firewall und klont das Repo nach /opt/moodle.

Damit GitHub Actions und der Server auf das private Repo zugreifen können, hinterlege einen Deploy-Key: erzeuge auf dem Server sudo -u deploy ssh-keygen -t ed25519 und trage den public Key in den GitHub-Repo-Einstellungen unter Deploy keys (read-only genügt) ein.

Schritt 5 .env ausfüllen & installieren

sudo -u deploy -i
cd /opt/moodle
cp .env.example .env
nano .env          # Domain, E-Mail, DB-Passwörter eintragen
ADMIN_PASS='EinStarkesPasswort!' ./scripts/install.sh

Danach ist Moodle unter deiner Domain erreichbar (Caddy holt automatisch ein Let's-Encrypt-Zertifikat). Login mit admin / deinem ADMIN_PASS.

Schritt 6 Manuellen Production-Deploy aktivieren (GitHub Secrets)

Im GitHub-Repo unter Settings → Secrets and variables → Actions anlegen:

Secret Wert
SSH_HOST Server-IP oder Hostname
SSH_USER deploy
SSH_PORT 22
SSH_KEY privater SSH-Key, mit dem sich GitHub als deploy einloggt

Den passenden Public-Key in ~deploy/.ssh/authorized_keys auf dem Server eintragen. Ab jetzt kann der Production-Deploy in GitHub Actions manuell über CI & Deploy Moodle → Run workflow gestartet werden:

Push auf main deployt nicht automatisch. Er läuft durch die CI; der Server-Deploy bleibt ein bewusster manueller Schritt.


Lokale Moodle-Instanz mit OrbStack

Für lokale Tests gibt es einen getrennten Compose-Stack ohne Caddy und ohne HTTPS-Zwang. Er nutzt dieselbe Moodle-Version, dieselben Custom-Plugins und dieselben Upgrade-/Translation-Wartungsschritte wie der Server-Deploy, läuft aber nur lokal auf http://localhost:8080.

cp .env.local.example .env.local
./scripts/local-deploy.sh

Danach:

./scripts/local-deploy.sh logs      # Moodle-Logs
./scripts/local-deploy.sh down      # Container stoppen
./scripts/local-deploy.sh up        # Container wieder starten
./scripts/local-deploy.sh reset     # lokale Volumes löschen und neu installieren

PHPUnit für lokale Plugin-Tests läuft im selben lokalen Stack mit separatem Tabellenpräfix (phpu_) und eigenem Dataroot. Nach dem ersten Deploy oder nach einem Reset initialisieren und dann die Testsuite ausführen:

./scripts/local-deploy.sh phpunit-init
./scripts/local-deploy.sh phpunit
PHPUNIT_TESTSUITE=local_ragingest_testsuite ./scripts/local-deploy.sh phpunit

Login-Defaults aus .env.local.example:

admin / Admin123!

Wenn Port 8080 belegt ist, in .env.local MOODLE_LOCAL_PORT und MOODLE_WWWROOT gemeinsam ändern, zum Beispiel auf 8081 und http://localhost:8081.

Dieser lokale Flow ist bewusst vom Produktions-Deploy getrennt. Ein Commit/Push auf GitHub kann weiterhin gemacht werden, aber der lokale Test läuft über docker-compose.local.yml und löst keinen Server-Deploy aus.


Laufender Betrieb

Moodle-Core aktualisieren

In .env MOODLE_GIT_REF auf den neuen Tag setzen (z. B. v5.2.2), committen, pushen. Die Pipeline baut das Image neu und führt upgrade.php aus.

Tipp: Da .env nicht im Repo liegt, wird MOODLE_GIT_REF auf dem Server gepflegt. Alternativ den Default-Tag im docker/Dockerfile (ARG) bzw. in der Server-.env anheben. Für ein rein git-getriebenes Core-Update den Tag in einer versionierten Datei führen siehe Hinweis unten.

Plugin/Theme aktualisieren

Code unter custom-plugins/<type>/<name>/ ändern, version.php hochzählen, committen, pushen → CI läuft. Für Production anschließend den Workflow manuell starten.

Manuelles Deploy / Logs

cd /opt/moodle
./scripts/deploy.sh                 # manuell deployen
docker compose logs -f moodle       # Logs ansehen
docker compose ps                   # Status

Backup

# Datenbank
docker compose exec -T db mariadb-dump -u root -p"$MOODLE_DB_ROOT_PASS" "$MOODLE_DB_NAME" > backup.sql
# moodledata-Volume
docker run --rm -v moodle-hetzner_moodledata:/data -v "$PWD":/backup alpine \
  tar czf /backup/moodledata.tar.gz -C /data .

Für Produktion: dieses Backup per Cron + Offsite-Storage (z. B. Hetzner Storage Box) automatisieren.


Hinweise & Designentscheidungen

  • Kein Core im Repo: sauberer, kleineres Repo, einfaches Core-Update. Wenn du Core-Patches brauchst, kannst du stattdessen einen eigenen Moodle-Fork pinnen.
  • Upgrade nur im Deploy, nicht beim Container-Start: ein Neustart löst nie versehentlich eine Schema-Migration aus. Während des Upgrades ist der Wartungsmodus aktiv.
  • config.php über ENV: keine Secrets im Image, alles kommt aus .env.
  • Sicherheit: .env niemals committen (steht in .gitignore); Deploy-Key read-only; Firewall offen nur für 22/80/443; moodledata außerhalb des Web-Roots.

Quellen