endeavour: .env-Rechte, Socket-Prüfung und HTTPS-Proxy korrigiert
- deploy.sh setzt die .env auf root:mareike-docker 0640 und prüft DB_SOCKET/Socket vor dem Build - optionale shared/deploy.conf für server-spezifische Einstellungen (z. B. MAREIKE_DB_SOCKET_DIR) - nginx: absolute_redirect off, damit keine http://-Redirects entstehen - Anleitung: Proxy per mod_rewrite nur unter HTTPS, keine KeyHelp-Weiterleitung, lv auf der Hauptdomain Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+75
-22
@@ -51,7 +51,8 @@ Browser ──HTTPS──▶ KeyHelp-Webserver (Apache/nginx, Let's Encrypt, ein
|
||||
/opt/mareike/
|
||||
├── bin/deploy.sh Kopie von docker/endeavour/deploy.sh
|
||||
├── src/ Git-Checkout (wird bei jedem Deploy aktualisiert)
|
||||
├── shared/.env Konfiguration mit Zugangsdaten (nur root lesbar)
|
||||
├── shared/.env Konfiguration mit Zugangsdaten (root, Gruppe mareike-docker lesbar, 0640)
|
||||
├── shared/deploy.conf optional: Server-Einstellungen für deploy.sh (z. B. MAREIKE_DB_SOCKET_DIR)
|
||||
└── storage/ Laravel-storage/ (Logs, Sessions, erzeugte PDFs/ZIPs) – persistent
|
||||
```
|
||||
|
||||
@@ -152,8 +153,18 @@ install -m 0750 /opt/mareike/src/docker/endeavour/deploy.sh /opt/mareike/bin/dep
|
||||
mysql -e "SELECT @@socket;" # erwartet: /run/mysqld/mysqld.sock
|
||||
```
|
||||
|
||||
Liegt der Socket woanders, in `/opt/mareike/bin/deploy.sh` die Variable `MAREIKE_DB_SOCKET_DIR` auf das Verzeichnis
|
||||
setzen und `DB_SOCKET` in der `.env` anpassen.
|
||||
Liegt der Socket woanders, z. B. unter `/var/lib/mysql/mysql.sock`, das **Verzeichnis** in
|
||||
`/opt/mareike/shared/deploy.conf` eintragen:
|
||||
|
||||
```bash
|
||||
echo 'MAREIKE_DB_SOCKET_DIR=/var/lib/mysql' > /opt/mareike/shared/deploy.conf
|
||||
```
|
||||
|
||||
In der `.env` bleibt das Verzeichnis `/run/mysqld`, denn so heißt der Mount-Punkt im Container. Nur der Dateiname
|
||||
wird übernommen, im Beispiel also `DB_SOCKET=/run/mysqld/mysql.sock`.
|
||||
|
||||
`deploy.sh` prüft vor jedem Build, ob `DB_SOCKET` gesetzt ist und der Socket auf dem Host existiert. Wenn nicht,
|
||||
bricht es mit einem Hinweis ab.
|
||||
|
||||
Weil die Datenbank von KeyHelp verwaltet wird, ist sie automatisch im **KeyHelp-Backup** enthalten.
|
||||
|
||||
@@ -162,7 +173,7 @@ Weil die Datenbank von KeyHelp verwaltet wird, ist sie automatisch im **KeyHelp-
|
||||
## 5. `.env` anlegen
|
||||
|
||||
```bash
|
||||
install -m 0600 /opt/mareike/src/docker/endeavour/env.production.example /opt/mareike/shared/.env
|
||||
install -m 0640 -o root -g mareike-docker /opt/mareike/src/docker/endeavour/env.production.example /opt/mareike/shared/.env
|
||||
echo "base64:$(openssl rand -base64 32)" # Ergebnis als APP_KEY eintragen
|
||||
nano /opt/mareike/shared/.env
|
||||
```
|
||||
@@ -225,7 +236,7 @@ angelegt wird.
|
||||
App\Models\Tenant::create([
|
||||
'slug' => 'lv',
|
||||
'name' => '<Name des Verbands>',
|
||||
'url' => '<lv-subdomain>.meine-anmeldung.digital',
|
||||
'url' => 'meine-anmeldung.digital',
|
||||
'email' => '<kontakt@…>',
|
||||
'email_finance' => '<finanzen@…>',
|
||||
'account_name' => '<Kontoinhaber>',
|
||||
@@ -249,7 +260,7 @@ global und werden für jeden aktiven Tenant ausgeführt.
|
||||
|
||||
### 6.4 Erste Administratorin / ersten Administrator
|
||||
|
||||
1. Auf `https://<lv-subdomain>.meine-anmeldung.digital` ganz normal registrieren. Voraussetzung: Abschnitt 7 ist
|
||||
1. Auf `https://meine-anmeldung.digital` ganz normal registrieren. Voraussetzung: Abschnitt 7 ist
|
||||
erledigt und der Mailversand funktioniert.
|
||||
2. Das Konto zur Administration hochstufen:
|
||||
|
||||
@@ -261,20 +272,36 @@ global und werden für jeden aktiven Tenant ausgeführt.
|
||||
|
||||
## 7. Tenant-Domain in KeyHelp einrichten (je Tenant)
|
||||
|
||||
Diesen Ablauf für den Dach-Tenant `lv` und später für jede weitere Gruppe wiederholen.
|
||||
Domain-Schema:
|
||||
|
||||
### 7.1 Einmalig: Proxy-Module aktivieren (Apache)
|
||||
- Dach-Tenant `lv`: die **Hauptdomain** `meine-anmeldung.digital`. Sie existiert in KeyHelp bereits samt
|
||||
Let's-Encrypt-Zertifikat.
|
||||
- Gruppen: `<gruppe>.meine-anmeldung.digital`, jede als eigene Domain in KeyHelp mit eigenem Zertifikat.
|
||||
|
||||
Den folgenden Ablauf für die Hauptdomain und später für jede Gruppe wiederholen.
|
||||
|
||||
> **Wichtig:** Nicht die KeyHelp-Funktion **„Weiterleitung“** benutzen. Sie schickt den *Browser* auf
|
||||
> `http://127.0.0.1:8080`, und das kann nicht funktionieren. Gebraucht wird ein **Proxy**: KeyHelp holt die Seite
|
||||
> intern vom Container ab und liefert sie selbst per HTTPS mit seinem Zertifikat aus. Das geschieht ausschließlich über
|
||||
> die Webserver-Direktiven unten.
|
||||
|
||||
### 7.1 Einmalig: Module aktivieren (Apache)
|
||||
|
||||
```bash
|
||||
a2enmod proxy proxy_http headers
|
||||
a2enmod proxy proxy_http headers rewrite
|
||||
systemctl reload apache2
|
||||
```
|
||||
|
||||
### 7.2 Domain anlegen
|
||||
### 7.2 Domain einrichten
|
||||
|
||||
1. KeyHelp → **Domains** → neue Domain für das mareike-Konto, z. B. `wilde-moehre.meine-anmeldung.digital`.
|
||||
Den DNS-Eintrag (A/AAAA) auf endeavour setzen, falls KeyHelp den DNS nicht selbst verwaltet.
|
||||
2. **SSL/TLS:** Let's Encrypt aktivieren und **HTTPS erzwingen** einschalten.
|
||||
1. **Hauptdomain:** In KeyHelp die vorhandene Domain `meine-anmeldung.digital` öffnen. Eine eventuell eingerichtete
|
||||
*Weiterleitung* entfernen.
|
||||
**Gruppe:** KeyHelp → **Domains** → neue Domain für das mareike-Konto anlegen, z. B.
|
||||
`wilde-moehre.meine-anmeldung.digital`. Den DNS-Eintrag (A/AAAA) auf endeavour setzen, falls KeyHelp den DNS nicht
|
||||
selbst verwaltet.
|
||||
2. **SSL/TLS:** Let's Encrypt aktiv und **HTTPS erzwingen** eingeschaltet. Bei der Hauptdomain muss
|
||||
`www.meine-anmeldung.digital` im Zertifikat enthalten sein, sonst gibt es beim www-Redirect eine
|
||||
Zertifikatswarnung.
|
||||
3. PHP wird für diese Domain nicht gebraucht.
|
||||
4. In den Domain-Einstellungen im Feld für **individuelle Webserver-Direktiven** (nur als Admin sichtbar, die
|
||||
Bezeichnung variiert je nach KeyHelp-Version) Folgendes eintragen:
|
||||
@@ -282,17 +309,34 @@ systemctl reload apache2
|
||||
**Apache** (KeyHelp-Standard):
|
||||
|
||||
```apache
|
||||
RewriteEngine On
|
||||
# Let's Encrypt von KeyHelp nicht anfassen
|
||||
RewriteRule ^/?\.well-known/acme-challenge/ - [L]
|
||||
# www → ohne www
|
||||
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
|
||||
RewriteRule ^/?(.*)$ https://%1/$1 [R=301,L,NE]
|
||||
# alles ohne TLS auf https umleiten
|
||||
RewriteCond %{HTTPS} !=on
|
||||
RewriteRule ^/?(.*)$ https://%{HTTP_HOST}/$1 [R=301,L,NE]
|
||||
# unter https an den Container durchreichen
|
||||
RewriteRule ^/?(.*)$ http://127.0.0.1:8080/$1 [P,L,NE]
|
||||
|
||||
ProxyPreserveHost On
|
||||
ProxyRequests Off
|
||||
RequestHeader set X-Forwarded-Proto "https"
|
||||
ProxyPass /.well-known/acme-challenge/ !
|
||||
ProxyPass / http://127.0.0.1:8080/
|
||||
ProxyPassReverse / http://127.0.0.1:8080/
|
||||
RequestHeader set X-Forwarded-Proto "https"
|
||||
Header always set Strict-Transport-Security "max-age=31536000" "expr=%{HTTPS} == 'on'"
|
||||
```
|
||||
|
||||
Die Regeln funktionieren unabhängig davon, ob KeyHelp die Direktiven in den Port-80- oder den Port-443-vHost
|
||||
schreibt. Ohne TLS wird immer auf `https://` umgeleitet, nur unter HTTPS wird an den Container weitergereicht. Das
|
||||
`http://127.0.0.1:8080` ist dabei die **interne** Verbindung zum Container, der Browser sieht sie nie.
|
||||
|
||||
**nginx** (falls KeyHelp auf nginx läuft):
|
||||
|
||||
```nginx
|
||||
if ($scheme != "https") {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8080;
|
||||
proxy_set_header Host $host;
|
||||
@@ -301,9 +345,6 @@ systemctl reload apache2
|
||||
client_max_body_size 70m;
|
||||
}
|
||||
```
|
||||
|
||||
Die Ausnahme für `/.well-known/acme-challenge/` sorgt dafür, dass KeyHelp die Zertifikate weiter selbst verlängern
|
||||
kann.
|
||||
5. Speichern und die Domain aufrufen. Solange der Tenant noch nicht existiert, zeigt mareike **404 „Tenant not
|
||||
found“**. Das ist ein gutes Zeichen, denn der Proxy funktioniert.
|
||||
|
||||
@@ -324,7 +365,7 @@ Tenants:
|
||||
|
||||
```bash
|
||||
cat > /etc/cron.d/mareike <<'EOF'
|
||||
* * * * * root curl -fsS -o /dev/null -H "Host: <lv-subdomain>.meine-anmeldung.digital" http://127.0.0.1:8080/execute-crons
|
||||
* * * * * root curl -fsS -o /dev/null -H "Host: meine-anmeldung.digital" http://127.0.0.1:8080/execute-crons
|
||||
EOF
|
||||
```
|
||||
|
||||
@@ -378,14 +419,26 @@ Enthält ein Release Datenbankänderungen, deshalb vorher ein DB-Backup ziehen.
|
||||
|
||||
| Symptom | Ursache / Lösung |
|
||||
|---|---|
|
||||
| `Database file at path […database.sqlite] does not exist` | Die `.env` wird im Container nicht gelesen, Laravel fällt dann auf SQLite zurück. Rechte prüfen (0640, Gruppe `mareike-docker`) und ob `MAREIKE_ENV_FILE` auf die richtige Datei zeigt. |
|
||||
| Browser landet auf `http://` | In KeyHelp ist eine *Weiterleitung* statt der Proxy-Direktiven eingerichtet, oder es sind noch die alten `ProxyPass`-Direktiven ohne HTTPS-Umleitung aktiv (Abschnitt 7.2). Woher die http-Umleitung kommt, zeigen die drei `curl`-Befehle darunter. |
|
||||
| 404 „Tenant not found“ | Der Host passt nicht zu `tenants.url` (Tippfehler, `https://` oder `/` im Eintrag), der Tenant ist nicht `has_active_instance`, oder der Proxy reicht den Host nicht durch (`ProxyPreserveHost On` fehlt). |
|
||||
| 502/503 vom KeyHelp-Webserver | Container laufen nicht (`deploy.sh compose ps`) oder die Firewall wurde neu geladen, dann hilft `systemctl restart docker`. |
|
||||
| Seite lädt ohne CSS, Mixed Content | `ASSET_URL` ist gesetzt oder die nginx-Config im Container wurde nicht übernommen (`fastcgi_param HTTPS on`). |
|
||||
| `SQLSTATE[HY000] [2002]` | Socket nicht erreichbar. `SELECT @@socket` prüfen, `MAREIKE_DB_SOCKET_DIR` bzw. `DB_SOCKET` anpassen, nach einem MariaDB-Neustart den Stack mit `deploy.sh compose restart app` neu starten. |
|
||||
| `SQLSTATE[HY000] [2002] No such file or directory` | Im Container liegt kein Socket unter `DB_SOCKET`. Entweder fehlt `DB_SOCKET` in der `.env`, oder der Socket liegt auf dem Host nicht in `/run/mysqld`. Pfad mit `mysql -NBe "SELECT @@socket;"` prüfen und ggf. `MAREIKE_DB_SOCKET_DIR` in `shared/deploy.conf` setzen (Abschnitt 4). Nach einem MariaDB-Neustart hilft oft `deploy.sh compose restart app`. |
|
||||
| `Permission denied` in storage/ | Besitzer von `/opt/mareike/storage` muss `mareike-docker` sein, der nächste `deploy.sh`-Lauf korrigiert das. |
|
||||
| Upload bricht ab | Grenzen prüfen: `MAX_INVOICE_FILE_SIZE` in der `.env`, 64 MB in `php.ini`, 70 MB in `nginx.conf`. |
|
||||
| Mails kommen nicht an | `MAIL_*` prüfen, Log in `storage/logs/`. Absenderadresse muss zum Postfach passen (SPF/DKIM der Domain in KeyHelp). |
|
||||
|
||||
Woher kommt eine Umleitung auf `http://`?
|
||||
|
||||
```bash
|
||||
curl -sI http://meine-anmeldung.digital/ | grep -iE '^(HTTP|Location)' # erwartet: 301 → https://meine-anmeldung.digital/
|
||||
curl -sI https://meine-anmeldung.digital/ | grep -iE '^(HTTP|Location)' # erwartet: 302 → https://meine-anmeldung.digital/login
|
||||
curl -sI -H 'Host: meine-anmeldung.digital' http://127.0.0.1:8080/ | grep -i '^Location' # Container direkt: https://…/login
|
||||
```
|
||||
|
||||
Zeigt der dritte Befehl `https://`, der zweite aber `http://`, liegt es an den KeyHelp-Einstellungen, nicht an mareike.
|
||||
|
||||
Logs:
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user