# 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. ```mermaid graph TD subgraph "Nutzer & Netzwerk Edge" A[Anwender] --> B(STACKIT DNS); B --> C["STACKIT CDN
(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
Datenbank)]; G["Redis
Sessions & Locks
(Optional)"]; H[(S3 Object Storage
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:** `https://github.com/cloudfoundry/cli/releases` * **STACKIT CLI:** `https://docs.stackit.cloud/stackit/de/automatisieren/cli/cli-installieren-200720436.html` * **Terraform CLI:** Optional: Wenn IaC gewünscht ist, muss terraform installiert und im Systempfad verfügbar sein. ## 2\. Terraform / Infrastruktur as Code ### 2.1. Variablen Passen sie die Variablen in der Datei terraform.tfvars an ### 2.2. Quellcode einmalig vorbereiten: ```bash chmod +x prepare_source.sh ./prepare_source.sh ``` ### 2.3. Terraform initialisieren und ausführen: ```bash terraform init terraform apply ``` ## 3\. Installation ohne Terraform ### 3.1. Bei STACKIT Cloud Foundry anmelden ```bash cf login -a https://api.cf.eu01.stackit.cloud --sso ``` ### 3.2. Organisation und Space erstellen ```bash cf create-org cf create-space -o cf target -o -s ``` ## 3.3. Moodle-Projekt lokal vorbereiten ### 3.3.1. Moodle und Plugins herunterladen ```bash # Moodle 5.0.1 wget https://packaging.moodle.org/stable500/moodle-5.0.1.tgz tar -xzf moodle-5.0.1.tgz # Redis-Plugin 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 cd moodle git clone https://github.com/catalyst/moodle-tool_objectfs.git admin/tool/objectfs cd .. ``` ### 3.3.2. Buildpack- & System-Workarounds einrichten ```bash # 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.4. Cloud Foundry & STACKIT Services erstellen #### 3.4.1. Object Storage Bucket erstellen (STACKIT CLI) ```bash stackit object-storage bucket create --name ``` ```bash stackit object-storage credential create --project-id ``` **Notieren Sie sich den ausgegebenen `accessKey` und `secretAccessKey`.** #### 3.4.2. CDN-Distribution erstellen (STACKIT CLI, Optional) Die Erstellung und Konfiguration des CDN erfolgt in mehreren Schritten. 1. **CDN-Distribution erstellen:** ```bash stackit curl -X POST --body '{ "name": "", "origin": { "path": "/", "hostname": "", "port": 443 }, "originRequestHeaders": [ { "name": "Host", "values": [ "" ] } ], "enabled": true }' /cdn/v1beta/projects//distributions ``` **Notieren Sie sich die `id` der Distribution aus der Antwort.** 2. **Benutzerdefinierte Domain hinzufügen:** ```bash stackit curl -X POST --body '{ "domain": "" }' /cdn/v1beta/projects//distributions//domains ``` 3. **Wichtige CDN-Einstellungen per Support-Ticket anfordern:** Damit Moodle hinter dem CDN korrekt funktioniert, müssen spezielle Caching- und Cookie-Regeln gesetzt werden, die aktuell nicht als Self-Service verfügbar sind. Erstellen Sie ein Ticket im STACKIT Support-Portal. * **Support-Portal:** `https://support.stackit.cloud/servicedesk/customer/portal/3` * **Anfrage-Vorlage:** > Hallo STACKIT-Team, > für unsere CDN-Distribution mit der ID `` benötigen wir bitte die folgenden Einstellungen: > 1. **"Strip Response Cookies" muss deaktiviert sein.** Moodle benötigt dies, um Session-Cookies an den Browser zu senden. > 2. **Edge Rule zum Umgehen des Caches:** Bitte erstellen Sie eine Edge Rule, die das Caching für alle dynamischen Moodle-Inhalte deaktiviert: > * **Action:** Bypass Cache > * **Conditions (Match Any):** > * Request URL (Match Wildcard): `*/*` > * Request URL (Match Wildcard): `*/*index.php*` > * Request URL (Match Wildcard): `*/*javascript.php*` > * Request URL (Match Wildcard): `*/*styles.php*` > * Request URL (Match Wildcard): `*/*yui_combo.php*` > Vielen Dank. #### 3.4.3. DNS-Einträge konfigurieren (STACKIT CLI) 1. **Zone-ID ermitteln:** ```bash stackit dns zone list ``` 2. **CDN-Standard-Domain auslesen (nur für CDN-Setup):** ```bash stackit curl -X GET /cdn/v1beta/projects//distributions/ ``` **Notieren Sie sich den Wert des `domain`-Feldes. Dies ist Ihr CNAME-Ziel für das CDN.** 3. **CNAME-Eintrag erstellen:** ```bash # Für den Betrieb MIT CDN stackit dns record-set create --zone-id --name --type CNAME --ttl 300 --records "." # Für den Betrieb OHNE CDN (falls benötigt) stackit dns record-set create --zone-id --name --type CNAME --ttl 300 --records "console.apps.01.cf.eu01.stackit.cloud." ``` #### 3.4.4. Cloud Foundry Services erstellen (CF CLI) ```bash # Datenbank-Service cf create-service # Redis-Service (Optional) cf create-service appcloud-redis7 redis-4.16.100-replica # Autoscaler-Service cf create-service autoscaler autoscaler-free-plan # User-Provided Service für die S3-Credentials cf create-user-provided-service -p '{ "access_key": "", "secret_key": "", "bucket": "", "endpoint": "https://object.storage.eu01.onstackit.cloud/" }' ``` ## 3.5. Konfigurationsdateien erstellen #### a) Manifest-Dateien **`manifest-cdn.yml` (Produktion):** ```yaml --- applications: - name: moodle memory: 2G disk_quota: 2G buildpack: https://github.com/cloudfoundry/php-buildpack.git path: moodle routes: - route: - route: env: USE_CDN: 'true' WWW_ROOT: "https://" BP_PHP_LOG_LEVEL: WARNING services: - - - - 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):** ```yaml --- applications: - name: moodle memory: 2G disk_quota: 2G buildpack: https://github.com/cloudfoundry/php-buildpack.git path: moodle routes: - route: env: USE_CDN: 'false' WWW_ROOT: "https://" BP_PHP_LOG_LEVEL: WARNING services: - - - - 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 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, '; } 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'] === '') { $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 = ''; $CFG->cookiesecure = 1; $CFG->cookiehttponly = 1; } require_once(__DIR__ . '/lib/setup.php'); ``` ## 3.6. Deployment auf Cloud Foundry Wählen Sie das gewünschte Manifest für Ihr Deployment aus. **Mit CDN (Produktion):** ```bash cf push -f manifest-cdn.yml ``` **Ohne CDN (Test / Direkter Zugriff):** ```bash cf push -f manifest-no-cdn.yml ``` Nach Abschluss des Deployments und dem Durchlaufen der Moodle-Web-Installation ist Ihre Instanz einsatzbereit.