| .gitignore | ||
| readme.md | ||
Umfassende Anleitung: Moodle auf STACKIT Cloud Foundry
Diese Anleitung dokumentiert den gesamten Prozess, um eine Moodle-Instanz auf STACKIT Cloud Foundry zu deployen. Sie ist als allgemeingültige Vorlage konzipiert und verwendet Platzhalter, die an Ihre Umgebung angepasst werden müssen.
Architektur
Die folgende Abbildung zeigt die Architektur der Moodle-Umgebung. CDN und Redis sind als optionale, aber für den Produktivbetrieb empfohlene Komponenten dargestellt.
graph TD
subgraph "Nutzer & Netzwerk Edge"
A[Anwender] --> B(STACKIT DNS);
B --> C["STACKIT CDN<br/>(Optional)"];
end
subgraph "Zentrale Infrastruktur"
D{Cloud Foundry Router};
end
C -.-> D;
B --> D;
subgraph "Cloud Foundry App-Instanzen"
D --> E1[Moodle Instanz 1];
D --> E2[Moodle Instanz ...n];
end
subgraph "Backing Services"
F[(MariaDB<br/>Datenbank)];
G["Redis<br/>Sessions & Locks<br/>(Optional)"];
H[(S3 Object Storage<br/>Dateien)];
end
E1 --> F;
E1 -.-> G;
E1 --> H;
E2 --> F;
E2 -.-> G;
E2 --> H;
1. Voraussetzungen & initiales Setup
1.1. CLIs installieren
-
Cloud Foundry CLI: Das primäre Werkzeug zur Interaktion mit der Cloud Foundry Plattform.
- Download:
https://github.com/cloudfoundry/cli/releases
- Download:
-
STACKIT CLI: Wird benötigt, um STACKIT-spezifische Services wie DNS, Object Storage und CDN zu verwalten.
- Installationsanleitung:
https://docs.stackit.cloud/stackit/de/automatisieren/cli/cli-installieren-200720436.html
- Installationsanleitung:
1.2. Bei STACKIT Cloud Foundry anmelden
-
API-Endpunkt:
https://api.cf.eu01.stackit.cloud -
Login-Befehl:
cf login -a https://api.cf.eu01.stackit.cloud --sso
1.3. Organisation und Space erstellen
cf create-org <DEINE_ORGANISATION>
cf create-space <DEIN_SPACE> -o <DEINE_ORGANISATION>
cf target -o <DEINE_ORGANISATION> -s <DEIN_SPACE>
2. Moodle-Projekt lokal vorbereiten
2.1. Moodle und Plugins herunterladen
# Moodle 5.0.1 herunterladen und entpacken
wget https://packaging.moodle.org/stable500/moodle-5.0.1.tgz
tar -xzf moodle-5.0.1.tgz
# Redis-Plugin für Moodle installieren (Version passend zu Moodle 5.x)
wget https://moodle.org/plugins/download.php/30019/cachestore_redis_moodle44_2024051300.zip
unzip cachestore_redis_moodle44_2024051300.zip
mv redis moodle/cache/stores/
# S3 Object File System Plugin installieren
cd moodle
git clone https://github.com/catalyst/moodle-tool_objectfs.git admin/tool/objectfs
cd ..
2.2. Buildpack- & System-Workarounds einrichten
# Web-Verzeichnis festlegen und PHP-Version auf 8.2 erzwingen
echo '{"WEBDIR": ".", "PHP_VERSION": "{PHP_82_LATEST}"}' > moodle/.bp-config/options.json
# PHP-Erweiterungen und Moodle-Einstellungen konfigurieren
mkdir -p moodle/.bp-config/php/php.ini.d/
echo "extension=mysqli" > moodle/.bp-config/php/php.ini.d/mysqli.ini
echo "extension=redis" > moodle/.bp-config/php/php.ini.d/redis.ini
echo "max_input_vars = 5000" > moodle/.bp-config/php/php.ini.d/moodle.ini
# Symbolische Links für Log- und PID-Dateien anlegen
mkdir -p moodle/logs
ln -s /dev/stdout moodle/logs/rewrite.log
ln -s /dev/stdout moodle/logs/proc-man.log
mkdir -p moodle/httpd/logs
mkdir -p moodle/php/var/run
ln -s /tmp/httpd.pid moodle/httpd/logs/httpd.pid
ln -s /tmp/php-fpm.pid moodle/php/var/run/php-fpm.pid
3. Cloud Foundry & STACKIT Services erstellen
3.1. Object Storage Bucket erstellen (STACKIT CLI)
stackit object-storage bucket create --name <DEIN_S3_BUCKET_NAME>
stackit object-storage credential create --project-id <DEINE_PROJEKT_ID>
Notieren Sie sich den ausgegebenen accessKey und secretAccessKey.
3.2. CDN-Distribution erstellen (STACKIT CLI, Optional)
-
CDN-Distribution erstellen:
# Ersetzen Sie <DEINE_PROJEKT_ID>, <DEINE_INTERNE_CF_ROUTE> und <DEINE_MOODLE_DOMAIN>. stackit curl -X POST --body '{ "name": "<DEIN_CDN_DISTRIBUTION_NAME>", "origin": { "path": "/", "hostname": "<DEINE_INTERNE_CF_ROUTE>", "port": 443 }, "originRequestHeaders": [ { "name": "Host", "values": [ "<DEINE_MOODLE_DOMAIN>" ] }, { "name": "Cache-Control", "values": [ "no-cache, no-store, must-revalidate" ] } ], "enabled": true }' /cdn/v1beta/projects/<DEINE_PROJEKT_ID>/distributionsNotieren Sie sich die
idder Distribution aus der Antwort. -
CDN-Standard-Domain auslesen:
# Ersetzen Sie <DEINE_PROJEKT_ID> und <DISTRIBUTION_ID>. stackit curl -X GET /cdn/v1beta/projects/<DEINE_PROJEKT_ID>/distributions/<DISTRIBUTION_ID>Notieren Sie sich den Wert des
domain-Feldes aus der Antwort. Dies ist Ihr CNAME-Ziel. -
Benutzerdefinierte Domain hinzufügen:
# Ersetzen Sie <DEINE_PROJEKT_ID> und <DISTRIBUTION_ID>. stackit curl -X POST --body '{ "domain": "<DEINE_MOODLE_DOMAIN>" }' /cdn/v1beta/projects/<DEINE_PROJEKT_ID>/distributions/<DISTRIBUTION_ID>/domains
3.3. DNS-Einträge konfigurieren (STACKIT CLI)
-
Zone-ID ermitteln:
stackit dns zone listNotieren Sie sich die
IDIhrer Domain-Zone. -
CNAME-Eintrag erstellen:
# Für den Betrieb MIT CDN # <DEIN_CDN_ENDPOINT> ist die Standard-Domain, die Sie in Schritt 3.2 ausgelesen haben. stackit dns record-set create --zone-id <DEINE_ZONE_ID> --name <DEINE_MOODLE_DOMAIN> --type CNAME --ttl 300 --records "<DEIN_CDN_ENDPOINT>." # Für den Betrieb OHNE CDN (falls benötigt) stackit dns record-set create --zone-id <DEINE_ZONE_ID> --name <DEINE_INTERNE_CF_ROUTE> --type CNAME --ttl 300 --records "console.apps.01.cf.eu01.stackit.cloud."
3.4. Cloud Foundry Services erstellen (CF CLI)
# Datenbank-Service
cf create-service <dein-mariadb-service> <plan> <DEINE_MARIADB_INSTANZ>
# Redis-Service (Optional)
cf create-service appcloud-redis7 redis-4.16.100-replica <DEINE_REDIS_INSTANZ>
# Autoscaler-Service
cf create-service autoscaler autoscaler-free-plan <DEIN_AUTOSCALER_INSTANZ>
# User-Provided Service für die S3-Credentials
cf create-user-provided-service <DEINE_S3_CUPS_INSTANZ> -p '{
"access_key": "<DEIN_ZUVOR_GENERIERTER_ACCESS_KEY>",
"secret_key": "<DEIN_ZUVOR_GENERIERTER_SECRET_KEY>",
"bucket": "<DEIN_S3_BUCKET_NAME>",
"endpoint": "https://object.storage.eu01.onstackit.cloud/"
}'
4. Konfigurationsdateien erstellen
a) Manifest-Dateien
manifest-cdn.yml (Produktion):
---
applications:
- name: moodle
memory: 2G
disk_quota: 2G
buildpack: https://github.com/cloudfoundry/php-buildpack.git
path: moodle
routes:
- route: <DEINE_INTERNE_CF_ROUTE>
- route: <DEINE_MOODLE_DOMAIN>
env:
USE_CDN: 'true'
WWW_ROOT: "https://<DEINE_MOODLE_DOMAIN>"
BP_PHP_LOG_LEVEL: WARNING
services:
- <DEINE_MARIADB_INSTANZ>
- <DEINE_REDIS_INSTANZ>
- <DEIN_AUTOSCALER_INSTANZ>
- <DEINE_S3_CUPS_INSTANZ>
autoscaling:
min_instances: 2
max_instances: 4
rules:
- metric_type: cpu
threshold: 50
operator: ">"
adjustment: "+1"
breach_duration_secs: 60
cool_down_secs: 60
- metric_type: cpu
threshold: 10
operator: "<"
adjustment: "-1"
breach_duration_secs: 60
cool_down_secs: 60
manifest-no-cdn.yml (Test):
---
applications:
- name: moodle
memory: 2G
disk_quota: 2G
buildpack: https://github.com/cloudfoundry/php-buildpack.git
path: moodle
routes:
- route: <DEINE_INTERNE_CF_ROUTE>
env:
USE_CDN: 'false'
WWW_ROOT: "https://<DEINE_INTERNE_CF_ROUTE>"
BP_PHP_LOG_LEVEL: WARNING
services:
- <DEINE_MARIADB_INSTANZ>
- <DEINE_REDIS_INSTANZ>
- <DEIN_AUTOSCALER_INSTANZ>
- <DEINE_S3_CUPS_INSTANZ>
autoscaling:
min_instances: 1
max_instances: 4
# ... deine Regeln
b) Dynamische config.php
Kopieren Sie moodle/config-dist.php zu moodle/config.php und ersetzen Sie den Inhalt mit dieser Vorlage.
<?php // Moodle configuration file
$useCdn = (getenv('USE_CDN') === 'true');
$wwwRoot = getenv('WWW_ROOT');
unset($CFG);
global $CFG;
$CFG = new stdClass();
$CFG->wwwroot = $wwwRoot;
$CFG->dirroot = __DIR__;
$CFG->dataroot = '/tmp/moodledata';
$CFG->admin = 'admin';
$CFG->directorypermissions = 0777;
$CFG->sslproxy = 1;
$CFG->slasharguments = false;
if ($useCdn) {
$CFG->reverseproxy = 1;
$CFG->trustedproxies = '127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, <IP_DES_CDN_KNOTENS>';
}
if (!file_exists($CFG->dataroot)) {
@mkdir($CFG->dataroot, $CFG->directorypermissions, true);
}
$CFG->dbtype = 'mariadb';
$CFG->dblibrary = 'native';
$CFG->prefix = 'mdl_';
$CFG->dboptions = array ('dbpersist' => 0, 'dbcollation' => 'utf8mb4_unicode_ci');
$vcap_services_json = getenv('VCAP_SERVICES');
if ($vcap_services_json) {
$vcap_services = json_decode($vcap_services_json, true);
// Datenbank
$db_service_key = null;
if (isset($vcap_services['appcloud-mariadb1011'])) { $db_service_key = 'appcloud-mariadb1011'; }
if ($db_service_key && isset($vcap_services[$db_service_key][0]['credentials'])) {
$db_creds = $vcap_services[$db_service_key][0]['credentials'];
$CFG->dbhost = $db_creds['host']; $CFG->dbname = $db_creds['name'];
$CFG->dbuser = $db_creds['username']; $CFG->dbpass = $db_creds['password'];
$CFG->dboptions['dbport'] = $db_creds['port'];
if (isset($db_creds['cacrt']) && !empty($db_creds['cacrt'])) {
$ca_cert_path = '/tmp/db-ca.crt';
file_put_contents($ca_cert_path, $db_creds['cacrt']);
$CFG->dboptions['ssl_ca'] = $ca_cert_path;
$CFG->dboptions['ssl_verify_server_cert'] = true;
}
}
// Redis
$redis_service_key = null;
if (isset($vcap_services['appcloud-redis7'])) { $redis_service_key = 'appcloud-redis7'; }
if ($redis_service_key && isset($vcap_services[$redis_service_key][0]['credentials'])) {
$redis_creds = $vcap_services[$redis_service_key][0]['credentials'];
$CFG->session_handler_class = '\cachestore_redis\session_handler';
$CFG->session_redis_host = $redis_creds['host']; $CFG->session_redis_port = $redis_creds['port'];
$CFG->session_redis_password = $redis_creds['password'];
$CFG->session_redis_prefix = 'moodlesess_';
$CFG->lock_factory = '\cachestore_redis\lock_factory';
}
// S3
if (isset($vcap_services['user-provided'])) {
foreach ($vcap_services['user-provided'] as $service) {
if ($service['name'] === '<DEINE_S3_CUPS_INSTANZ>') {
$s3_creds = $service['credentials'];
$CFG->objectfs_s3_key = $s3_creds['access_key'];
$CFG->objectfs_s3_secret = $s3_creds['secret_key'];
$CFG->objectfs_s3_bucket = $s3_creds['bucket'];
$CFG->objectfs_s3_endpoint = $s3_creds['endpoint'];
break;
}
}
}
}
if (empty($CFG->session_handler_class)) {
$CFG->session_handler_class = '\core\session\database';
}
if ($useCdn) {
$CFG->cookiepath = '/';
$CFG->cookiedomain = '<DEINE_MOODLE_DOMAIN>';
$CFG->cookiesecure = 1;
$CFG->cookiehttponly = 1;
}
require_once(__DIR__ . '/lib/setup.php');
5. Deployment auf Cloud Foundry
Wählen Sie das gewünschte Manifest für Ihr Deployment aus.
Mit CDN (Produktion):
cf push -f manifest-cdn.yml
Ohne CDN (Test / Direkter Zugriff):
cf push -f manifest-no-cdn.yml
Nach Abschluss des Deployments und dem Durchlaufen der Moodle-Web-Installation ist Ihre Instanz einsatzbereit.