Markdown

Erweitert

Architektur

GitLab-Pipelines bauen Docker-Images, ein GitOps-Repository hält fest, welche Version wo läuft, und Ansible bringt diesen Stand auf Server, die MainPath mit Traefik, Firewall und HTTPS eingerichtet hat.

Auf dieser Seite

Jedes Projekt ist eine Gruppe im GitLab von MainPath unter gitlab.application-platform.com mit einem Repository pro Komponente, local-configuration für die gemeinsame Editor-Konfiguration, gitops-configuration für das Deployment und gitlab-profile mit der README.

orgs/<organisation>/<projekt>/
├── backend/                  # z. B. NestJS-API mit Dockerfile
├── <app>/                    # z. B. Flutter-App, auch mehrere
├── <homepage>/               # z. B. Hugo-Site
├── gitops-configuration/     # Deployment-Konfiguration für Dev und Prod
├── local-configuration/      # .vscode, .idea
└── gitlab-profile/           # README der Gruppe

Im geklonten Projektordner zeigen Symlinks auf local-configuration, deshalb sehen Editoren für alle Repos dieselben Einstellungen. Regeln für KI-Agenten kommen aus dem Agent-Plugin (mp agent install).

Vom Push zum laufenden Container

flowchart LR
  push["Push auf main"] -->|"Pipeline"| image["Docker-Image<br/>mit Versions-Tag"]
  image -->|"Tag eintragen"| gitops["gitops-configuration<br/>versions.yaml"]
  gitops -->|"Ansible"| dev["Dev-Server"]
  gitops -->|"Ansible, manueller Job"| prod["Prod-Server"]

Die Pipeline berechnet aus den Commit-Nachrichten die nächste Version (feat: und fix: zählen hoch), baut das Docker-Image, lädt es in die Registry und trägt den Tag in die Deployment-Konfiguration für Dev ein; das Deployment-Repository rollt ihn per Ansible auf den Dev-Server aus. Produktion bekommt denselben Tag erst über den manuellen Produktions-Job, den Git-Workflow und Deployment beschreibt.

Das GitOps-Repository

gitops-configuration/
└── configurations/
    ├── dev/
    │   ├── generated.yaml   # Plattform: Hostnamen, Registry, Secrets (SOPS)
    │   ├── custom.yaml      # du: eigene Umgebungsvariablen
    │   └── versions.yaml    # Pipeline: deployte Image-Versionen
    └── prod/                # gleiche Struktur

generated.yaml schreibt MainPath bei jeder Projektänderung mit Hostnamen, Registry-Zugang und SOPS-verschlüsselten Secrets wie Datenbank-Passwörtern und JWT-Secrets. custom.yaml gehört dir und nimmt eigene Umgebungsvariablen unter additional_env_variables auf. versions.yaml schreibt die Pipeline mit dem deployten Image-Tag. Jeder Commit auf main, ob von der Pipeline oder von dir, löst das Ansible-Deployment der betroffenen Umgebung aus. Das Zusammenspiel mit den env/-Dateien steht unter Umgebungsvariablen.

Was auf dem Server läuft

Beim ersten Deployment richtet MainPath den Server per Ansible ein: Docker, Traefik als Reverse Proxy, eine Firewall, HTTPS-Zertifikate und einen Deploy-Schlüssel in den authorized_keys des angegebenen Benutzers. Traefik verteilt Anfragen anhand der Domain an den richtigen Container, auch an Docker Apps. Let’s Encrypt prüft die Domain standardmäßig per TLS-ALPN am Server; bei Cloudflare setzt MainPath die DNS-Einträge deshalb ohne Proxy. Ist der Server von außen nicht erreichbar, kannst du in den Details einer DNS-Anbindung optional DNS-01 anhaken.

Die Daten deines Backends liegen außerhalb der Container auf dem Server: ./backend-mysql für die Datenbank, ./backend-uploads für Uploads, die im Container unter /app/upload erscheinen, und ./backend-backups für die Archive von Easy Backup. Ein Release tauscht nur die Container aus.

Reine Homepage-Projekte auf einem Webspace lädt die Pipeline per FTP oder SFTP hoch, ohne Docker, GitOps und Ansible. Projekte auf einem Kubernetes-Cluster rollt GitOps per Helm aus; Datenbanken liegen dann als Cloud-Datenbank im Konto unter Cloud-Accounts. Auf klassischen Servern laufen Anwendungen weiterhin per Docker.

Generierte Konfiguration und Sentry

MainPath erzeugt .gitlab-ci.yml, env/*.generated.env und generated.yaml und überschreibt sie bei jeder Projektänderung; eigene Werte gehören in env/*.custom.env und custom.yaml. Aktivierst du Sentry für eine Komponente unter Funktionen, legt MainPath das Sentry-Projekt in deinem unter Anbindungen verbundenen Konto an und schreibt die DSN in diese Konfiguration, für Apps zum Beispiel in env/shared.generated.env. Den Umgang damit beschreibt Betrieb.