Skip to content

Applikations-Konfiguration

Was webhost.md für die Webserver-Schicht beschreibt, deckt dieses Dokument für die einzelne App-Instanz ab — also alles, was eine Applikations-Klasse pro Host ausrollt.

Ressourcen pro App-Instanz

Eine Applikations-Klasse (z.B. iteasapps::iscan) erzeugt pro Instanz:

RessourceBeschreibung
Linux-System-UserDedizierter Benutzer für die Isolation gegenüber anderen Apps auf demselben Host
Verzeichnis-Struktur/var/www/<system_user>/{current,shared,releases}
PHP-FPM-PoolEigener Pool, läuft unter dem System-User, eigener Unix-Socket
Nginx-VHostServer-Block-Konfiguration pro Applikation
MariaDB-DatenbankLokale Datenbank für die Applikation
MariaDB-Login (App)Lokaler App-DB-Login auf localhost
Lokale secrets.phpMaterialisierte Secrets im config/-Subdirectory (siehe Secrets-Handling)
Fail2Ban-JailPro VHost ein Jail-Set für Auth- und 4xx-Floods
Smoke-TestHealthcheck-Aufruf gegen die Domain nach erfolgreichem Rollout

Naming-Konvention

Da pro Host nur ein Kunde läuft, taucht die Kundenkennung in keinem Resource-Identifier auf — sie steckt im Hostnamen bzw. Puppet-Certname. Die Identifier setzen sich nur aus dem App-Namen zusammen.

Für eine iScan-Instanz:

RessourceWert
App-Nameiscan
System-User (Linux)f01_iscan
App-Verzeichnis/var/www/f01_iscan/current/
App-DB-Nameiscan
App-DB-Login (MariaDB)iscan
Vault-Basis-Pfadsecret/iteasapps/iscan/

Alle Werte sind als Smart-Class-Parameter überschreibbar; die Defaults werden aus dem App-Namen abgeleitet.

Datenbank-Anbindung

Lokaler App-Login

Pro App-Instanz wird eine MariaDB-Datenbank angelegt, dazu ein App-Login mit vollen Rechten auf diese Datenbank. Verbindungs-Host ist localhost.

Das Passwort liegt in Vault unter secret/iteasapps/<app>/db_password und wird vom Puppet-Agent an zwei Stellen geschrieben: beim Anlegen des MariaDB-Logins und in die lokale secrets.php, aus der die App es zur Laufzeit liest.

Fehlt das Secret in Vault, scheitert ausschließlich die Login-Resource. Der Rest des Katalogs läuft durch; beim nächsten Agent-Run wird der Schritt wiederholt.

Eingehender Remote-Login: EDBS-Server

Der MariaDB-User m01_edbs wird über die Klasse iteas_services::edbs im Schwester-Modul verwaltet, nicht über die App-Klasse (siehe Foreman → EDBS-Anbindung). Sie wird einmal pro Host klassifiziert, weil der EDBS-Server pro Host nur eine MariaDB-Identität braucht — unabhängig davon, wie viele iScan- oder iTransfer-Instanzen am gleichen Host laufen.

Die Verbindung läuft von außen in den Host hinein. Die iScan-App stellt sie nicht her und liest die Zugangsdaten nicht — m01_edbs ist nur die Identität, mit der sich der externe EDBS-Server gegen die lokale MariaDB authentifiziert. Importierte Datensätze liest die App anschließend über den lokalen App-Login.

Konsequenzen:

  • Der EDBS-Login steht nicht in den Smart-Class-Parametern der App-Klassen.
  • Das Passwort liegt unter secret/iteas_services/edbs/password, nicht unter secret/iteasapps/<app>/.
  • iteas_services::edbs wird einmal pro Host klassifiziert, unabhängig von den App-Klassen.

Namensräume

m01_edbs ist ausschließlich ein MariaDB-Login — kein gleichnamiger Linux-User. Konvention: f01_* für Linux, m01_* für MariaDB.

Vault-Pfade

Vault-Struktur pro Applikation:

secret/iteasapps/<app>/
├── db_password                ← App-DB-Passwort
├── cookie_validation_key      ← Yii-Cookie-Validation-Key
├── edbs_db_password           ← Passwort für outbound iScan → Remote-EDBS
├── mailer_dsn                 ← SMTP-DSN für Standard-Mails (optional)
├── sp_mailer_dsn              ← SMTP-DSN für Serviceportal-Mails (optional)
└── app_update_key             ← Update-Key für die mobile App (optional)

<app> ist der App-Name (z.B. iscan). Die Kundenzuordnung kommt aus der Hiera-Hierarchie über den Puppet-Certname — der Pfad enthält keine Kundenkennung.

PfadPflichtVerwendung
db_passwordjaLokaler App-DB-Login (DB_PASSWORD)
cookie_validation_keyjaYii-Cookie-Validation-Key (COOKIE_VALIDATION_KEY)
edbs_db_passwordjaOutbound-Verbindung zur Remote-EDBS-DB (EDBS_DB_PASSWORD)
mailer_dsnneinSMTP-DSN; ohne Eintrag greift der Code-Default
sp_mailer_dsnneindito für das Serviceportal
app_update_keyneinUpdate-Key der mobilen App; Code-Default als Fallback

Das EDBS-Passwort für die eingehende Verbindung liegt unter secret/iteas_services/edbs/password (siehe Foreman → EDBS-Anbindung).

TLS-Material liegt nicht in Vault — der Stack nutzt Certbot/ACME, siehe Webhost → TLS-Material.

Secrets-Handling

Statt die App pro Request mit Vault sprechen zu lassen, schreibt der Puppet-Agent die Werte einmal pro Run lokal nach:

/var/www/<system_user>/current/config/secrets.php

Im native-Modus ersetzt diese Datei die Container-Environment-Variablen und enthält daher die gesamte App-Konfiguration — Secrets und nicht-sensitive Smart-Class-Parameter zusammen.

php
<?php
return [
    // DB (lokal)
    'DB_HOSTNAME'               => 'localhost',
    'DB_NAME'                   => 'iscan',
    'DB_USER'                   => 'iscan',
    'DB_PASSWORD'               => '...',   // aus Vault

    // EDBS (outbound)
    'EDBS_DB_HOST'              => '...',
    'EDBS_DB_NAME'              => '...',
    'EDBS_DB_USER'              => '...',
    'EDBS_DB_PASSWORD'          => '...',   // aus Vault

    // Yii
    'YII_ENVIRONMENT'           => 'dev',
    'YII_DEBUG'                 => 'true',
    'COOKIE_VALIDATION_KEY'     => '...',   // aus Vault

    // App
    'CUSTOMER'                  => 'iteas',
    'SENDER_MAIL_ADDRESS'       => 'noreply@iscan.at',
    'SP_SENDER_MAIL_ADDRESS'    => 'noreply@opst.at',
    'SP_USER_INVITE_VALID_HOUR' => '12',
    'ENABLE_SCHEMA_CACHE'       => 'true',
    'MAILER_DSN'                => '...',   // aus Vault (oder Code-Default)
    'SP_MAILER_DSN'             => '...',   // aus Vault (oder Code-Default)
    'APP_UPDATE_KEY'            => '...',   // aus Vault (oder Code-Default)

    // Logging (Graylog & Loki)
    'ENABLE_LOGGING'            => 'false',
    'GRAYLOG_FACILITY'          => 'iscan-dev',
    'GRAYLOG_URL'               => 'gelf.log.iteas.at',
    'GRAYLOG_PORT'              => '443',
    'LOKI_ENABLE_LOGGING'       => 'false',
    'LOKI_API_URL'              => 'https://api.log.iteas.cloud/loki/api/v1/push',
    'LOKI_SERVICE_NAME'         => 'iscan-web',
];

Die Schlüssel entsprechen den Environment-Variablen aus dem docker-compose; im App-Code wird getenv('FOO') zu $config['FOO'].

Datei-Eigenschaften:

  • Owner = System-User der App (z.B. f01_iscan), Group dito, Mode 0640.
  • Wird bei jedem Puppet-Run aus den aktuellen Vault-Werten regeneriert. Eine Rotation in Vault wirkt sich beim nächsten Agent-Run aus.
  • Konsum durch die App via require/include in der Yii-Bootstrap-Phase. Kein Vault-Aufruf zur Laufzeit.
  • Vom App-Repository per .gitignore ausgeschlossen; eine secrets.php.example dient als Strukturreferenz für die lokale Entwicklung.

Folge der lokalen Materialisierung: Vault liegt nicht auf dem Request-Pfad. Bei Vault-Ausfall läuft die App weiter, bis der nächste Puppet-Run scheitert.

Sensitive-Typisierung in Puppet

Aus Vault gelesene Passwörter werden als Sensitive[String] typisiert und an Defined Types weitergereicht:

puppet
class iteasapps::iscan (
  # ...
) {
  $db_password = Sensitive(lookup('iteasapps::iscan::db_password'))

  iteasapps::sql::login { "${app_name}-app":
    login_name => $db_user,
    password   => $db_password,   # bleibt Sensitive bis zur mysql_user-Resource
    # ...
  }
}

Puppet ersetzt solche Werte beim Catalog-Render durch die Sensitive-Maske, die im Foreman-Report, in der PuppetDB und in den Agent-Logs anstelle des Klartexts erscheint.

Im EPP-Template muss $password.unwrap aufgerufen werden, sonst landet die Maske als String im Output.

App-Code-Deployment

Bisher kopierte die GitLab-CI-Pipeline das Build-Artefakt per RSync direkt auf den Zielserver. Mit der Foreman-Automation übernimmt Puppet das Verteilen.

SchrittVerantwortlichBeschreibung
TestGitLab CICodeception-Tests, statische Analyse
Compile / BuildGitLab CIComposer-Install, Asset-Build, ggf. Container-Build
Artefakt-PublikationGitLab CIBuild-Artefakt landet in einem von Foreman erreichbaren Storage (z.B. GitLab Package Registry)
Deployment auf HostForeman + PuppetApp-Klasse zieht das Artefakt, entpackt es in /var/www/<system_user>/releases/<version>/, schaltet current/ um
Smoke-TestForeman + Puppetiteasapps::healthcheck prüft die Erreichbarkeit

Puppet kann einen Deployment-Lauf jederzeit erneut anstoßen, ohne dass die CI ein neues Build produzieren muss — z.B. nach einer Smart-Class-Parameter-Änderung.

Smoke-Test

Nach dem Rollout läuft iteasapps::healthcheck: HTTPS-Aufruf gegen die Domain, erwartet Status 200. Bei Fehlschlag ist der Puppet-Run rot; Foreman zeigt das im Report.

Mehrere Applikationen pro Host

Sind mehrere App-Klassen auf demselben Host klassifiziert (z.B. iteasapps::iscan und iteasapps::itransfer):

  • iteasapps::base läuft einmal — include ist idempotent.
  • Jede App bekommt eigene System-User, FPM-Pools, VHosts und Datenbanken.
  • Resource-Titel sind über den App-Namen disjunkt.
  • Bei Domain-Kollisionen schlägt der Nginx-Reload fehl und damit der Puppet-Run.

Eine weitere App-Klasse auf einem bereits initialisierten Host erfordert kein Re-Provisioning — die Basis bleibt unangetastet (siehe Foreman → Ablauf einer Klassifizierung).

Iteas Tools Integration Platform Version v1.0.21

Version: v1.0.21 Version: v1.0.21
Commit: 7a0e1c11
Deployed at: 2026-09-24T13:56:52Z