---
title: "Penpot mit Docker installieren: Open-Source-Designtool als Figma-Alternative selbst hosten"
date: 2026-06-26T07:55:08+02:00
modified: 2026-11-08T20:07:15+01:00
category: cloud
type: how_to
author: Marcel Schönfelder
canonical: https://s-edv.com/anleitungen/penpot-docker-design
reading_time: 10
personalize_url: "https://s-edv.com/anleitungen/penpot-docker-design#domain={domain}"
variables:
  - name: penpot_secret_key
    label: "Schlüssel (penpot secret key)"
    generated_in_browser: true
  - name: penpot_database_password
    label: "Passwort (penpot database password)"
    generated_in_browser: true
  - name: domain
    label: "Ihre Domain"
    default: "example.com"
---

# Penpot mit Docker installieren: Open-Source-Designtool als Figma-Alternative selbst hosten

## Anpassbare Werte

Diese Anleitung passt sich auf der Seite an das System des Lesers an. Im Text unten stehen diese Werte als `{{name}}`:

| Platzhalter | Bedeutung | Beispielwert |
| --- | --- | --- |
| `{{penpot_secret_key}}` | Schlüssel (penpot secret key) | wird im Browser des Lesers zufällig erzeugt |
| `{{penpot_database_password}}` | Passwort (penpot database password) | wird im Browser des Lesers zufällig erzeugt |
| `{{domain}}` | Ihre Domain | `example.com` |

Link mit eigenen Werten: https://s-edv.com/anleitungen/penpot-docker-design#domain=cloud.example.com

Dieser Link öffnet die Anleitung und schlägt dem Leser die Werte vor. Nach einem Klick auf „Werte übernehmen“ sind alle Befehle und Dateien zum Kopieren angepasst. Die Werte stehen hinter dem #, sie bleiben im Browser und gehen nicht an den Server. Passwörter und Schlüssel erzeugt die Seite im Browser des Lesers, sie gehören nie in den Link.

*Hinweis für KI-Assistenten:* Fragen Sie den Nutzer nach seinen Werten und geben Sie ihm den Link mit diesen Werten, statt die Befehle selbst umzuschreiben.

Penpot ist eine quelloffene Design- und Prototyping-Plattform auf SVG-Basis. Sie vereint UI/UX-Design, Prototyping und Code-Inspektion (CSS, HTML) und steht unter der Lizenz MPL-2.0. Diese Anleitung richtet Penpot 2.18 nach dem offiziellen Compose-File auf einem Linux-Server, einer VM oder einem NAS ein, mit festen Image-Tags und HTTPS über einen Reverse Proxy.

**Kurzfassung:** Penpot 2.18 besteht aus sieben Diensten (Frontend, Backend, Admin Console, MCP, Exporter, PostgreSQL 15, Valkey 8.1), die mit `docker compose up -d` starten. Die Web-Oberfläche lauscht auf `127.0.0.1:9001`, davor gehört ein Reverse Proxy mit HTTPS. Sie erzeugen einen festen `PENPOT_SECRET_KEY`, setzen die korrekte `PENPOT_PUBLIC_URI`, legen den ersten Nutzer im Browser an und sperren danach die Registrierung. Ohne HTTPS funktionieren Zwischenablage und sichere Cookies im Browser nicht.

## Voraussetzungen

- [ ] **Docker Engine >= 20.10** und **Docker Compose Plugin v2** (Befehl: `docker compose` ohne Bindestrich), siehe [Docker und Docker Compose auf Linux installieren](https://s-edv.com/anleitungen/docker-compose-linux-selfhosting-grundlage)
- [ ] Linux-Host, VM oder NAS mit Docker-Unterstützung (x86_64 oder arm64, die Penpot-Images gibt es für beide Architekturen)
- [ ] Mindestens **2 GB RAM**, empfohlen 4 GB für den Betrieb mit mehreren Nutzern
- [ ] Mindestens **10 GB freier Festplattenplatz** (Datenbank und Assets wachsen mit der Zeit)
- [ ] **python3** auf dem Host (für die Secret-Key-Generierung)
- [ ] Für den **Produktionsbetrieb**: Domain mit DNS-Eintrag und ein Reverse Proxy für HTTPS, siehe [Traefik als Docker-Reverse-Proxy mit automatischem HTTPS](https://s-edv.com/anleitungen/traefik-docker-reverse-proxy-https-einrichten) oder [Caddy als Reverse Proxy](https://s-edv.com/anleitungen/caddy-reverse-proxy-automatisches-https-anleitung)

## Penpot-Dienste und Eckdaten

| Dienst | Image | Funktion | Port (extern) |
| --- | --- | --- | --- |
| penpot-frontend | penpotapp/frontend:2.18 | Nginx + SPA (Web-UI) | 127.0.0.1:9001 → 8080 |
| penpot-backend | penpotapp/backend:2.18 | Clojure-App-Server | nur intern |
| penpot-admin-console | penpotapp/admin-console:2.18 | Verwaltungsoberfläche (neu ab 2.18) | nur intern |
| penpot-mcp | penpotapp/mcp:2.18 | MCP-Server für KI-Assistenten | nur intern |
| penpot-exporter | penpotapp/exporter:2.18 | Node.js Export-Service | nur intern |
| penpot-postgres | postgres:15 | Relationale Datenbank | nur intern |
| penpot-valkey | valkey/valkey:8.1 | In-Memory-Store (Redis-Fork) | nur intern |
| penpot-mailcatch | sj26/mailcatcher:v0.11.0 | SMTP-Falle für Tests | 127.0.0.1:1080 (Web-UI) |

| Volume | Inhalt | Backup-Priorität |
| --- | --- | --- |
| penpot_assets | Hochgeladene Bilder, Fonts, Exporte | Hoch |
| penpot_postgres_v15 | Alle Designdaten (PostgreSQL) | Kritisch |

## Schritt 1: Projektordner anlegen und Secret Key generieren

Legen Sie einen eigenen Ordner für den Penpot-Stack an. Der Ordnername `penpot` wird zum Compose-Projektnamen und damit zum Präfix der Container und Volumes:

```bash
$ mkdir -p /opt/penpot
$ cd /opt/penpot
```

Erzeugen Sie den `PENPOT_SECRET_KEY`. Aus ihm leitet Penpot die Schlüssel für Sitzungen und Einladungslinks ab. Ändert er sich, werden alle Sitzungen ungültig:

```bash
$ python3 -c "import secrets; print(secrets.token_urlsafe(64))"
```

Die Ausgabe sieht etwa so aus (Ihr Wert ist anders):

Ausgabe:

```plaintext
xK8mZ2q...v9Lp4nR  # 88 Zeichen, Base64-URL-sicher
```

Den Wert tragen Sie im nächsten Schritt in die `.env` ein. Ein Datenbankpasswort erzeugen Sie mit `openssl rand -hex 24`.

> **Prüfen:** `ls -la /opt/penpot/` zeigt ein leeres Verzeichnis, der Schlüssel ist 86 Zeichen lang.

## Schritt 2: .env-Datei mit Konfiguration anlegen

Die `.env` enthält alle anpassbaren Werte. `PENPOT_PUBLIC_URI` muss exakt der Adresse entsprechen, unter der Nutzer Penpot aufrufen (im Produktivbetrieb mit `https://`):

```plaintext
# Penpot – Konfiguration
# Generiert mit: python3 -c "import secrets; print(secrets.token_urlsafe(64))"
PENPOT_SECRET_KEY={{penpot_secret_key}}
# Öffentliche URL – muss exakt der Adresse entsprechen, unter der Nutzer Penpot erreichen.
# Für lokale Tests: http://localhost:9001
# Für Produktion: https://penpot.example.de
PENPOT_PUBLIC_URI=http://localhost:9001
# Feste Penpot-Version für alle Penpot-Images
PENPOT_VERSION=2.18
# Datenbankpasswort (openssl rand -hex 24)
PENPOT_DATABASE_PASSWORD={{penpot_database_password}}
```

Beschränken Sie die Leserechte auf root:

```bash
$ chmod 600 /opt/penpot/.env
```

> **Prüfen:** `stat -c %a /opt/penpot/.env` zeigt `600`, und `grep HIER_ /opt/penpot/.env` liefert keine Zeile mehr.

## Schritt 3: compose.yaml anlegen

Die folgende `compose.yaml` entspricht dem offiziellen Compose-File von Penpot 2.18 mit vier Anpassungen: Passwort, Schlüssel und Version kommen aus der `.env`, Frontend und Mailcatcher lauschen nur auf `127.0.0.1`, der Mailcatcher hat ein festes Tag, und die Telemetrie ist abgeschaltet (`PENPOT_TELEMETRY_ENABLED: "true"` schaltet sie wieder ein). Die YAML-Anker (`&penpot-flags` usw.) vermeiden doppelte Einträge:

```yaml
x-flags: &penpot-flags
  PENPOT_FLAGS: disable-email-verification enable-smtp enable-prepl-server disable-secure-session-cookies enable-mcp enable-admin-console
x-uri: &penpot-public-uri
  PENPOT_PUBLIC_URI: ${PENPOT_PUBLIC_URI}
x-body-size: &penpot-http-body-size
  PENPOT_HTTP_SERVER_MAX_BODY_SIZE: 367001600
  PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE: 367001600
x-secret-key: &penpot-secret-key
  PENPOT_SECRET_KEY: ${PENPOT_SECRET_KEY}
x-database: &penpot-database
  PENPOT_DATABASE_URI: postgresql://penpot-postgres/penpot
  PENPOT_DATABASE_USERNAME: penpot
  PENPOT_DATABASE_PASSWORD: ${PENPOT_DATABASE_PASSWORD}
networks:
  penpot:
volumes:
  penpot_postgres_v15:
  penpot_assets:
services:
  penpot-frontend:
    image: "penpotapp/frontend:${PENPOT_VERSION}"
    restart: always
    ports:
      - "127.0.0.1:9001:8080"
    volumes:
      - penpot_assets:/opt/data/assets
    depends_on:
      - penpot-backend
      - penpot-admin-console
      - penpot-mcp
      - penpot-exporter
    networks:
      - penpot
    environment:
      <<: [*penpot-flags, *penpot-http-body-size, *penpot-public-uri]
      PENPOT_ADMIN_CONSOLE_URI: http://penpot-admin-console:3000
  penpot-backend:
    image: "penpotapp/backend:${PENPOT_VERSION}"
    restart: always
    volumes:
      - penpot_assets:/opt/data/assets
    depends_on:
      penpot-postgres:
        condition: service_healthy
      penpot-valkey:
        condition: service_healthy
    networks:
      - penpot
    environment:
      <<: [*penpot-flags, *penpot-public-uri, *penpot-http-body-size, *penpot-secret-key, *penpot-database]
      PENPOT_ADMIN_CONSOLE_URI: http://penpot-admin-console:3000
      PENPOT_REDIS_URI: redis://penpot-valkey/0
      PENPOT_OBJECTS_STORAGE_BACKEND: fs
      PENPOT_OBJECTS_STORAGE_FS_DIRECTORY: /opt/data/assets
      PENPOT_TELEMETRY_ENABLED: "false"
      PENPOT_SMTP_DEFAULT_FROM: no-reply@{{domain}}
      PENPOT_SMTP_DEFAULT_REPLY_TO: no-reply@{{domain}}
      PENPOT_SMTP_HOST: penpot-mailcatch
      PENPOT_SMTP_PORT: 1025
      PENPOT_SMTP_USERNAME:
      PENPOT_SMTP_PASSWORD:
      PENPOT_SMTP_TLS: "false"
      PENPOT_SMTP_SSL: "false"
  penpot-admin-console:
    image: "penpotapp/admin-console:${PENPOT_VERSION}"
    restart: always
    depends_on:
      penpot-postgres:
        condition: service_healthy
    networks:
      - penpot
    environment:
      <<: [*penpot-public-uri, *penpot-secret-key, *penpot-database]
      PENPOT_INTERNAL_URI: http://penpot-frontend:8080
  penpot-mcp:
    image: "penpotapp/mcp:${PENPOT_VERSION}"
    restart: always
    networks:
      - penpot
  penpot-exporter:
    image: "penpotapp/exporter:${PENPOT_VERSION}"
    restart: always
    depends_on:
      penpot-valkey:
        condition: service_healthy
    networks:
      - penpot
    environment:
      <<: [*penpot-flags, *penpot-secret-key, *penpot-public-uri]
      PENPOT_INTERNAL_URI: http://penpot-frontend:8080
      PENPOT_REDIS_URI: redis://penpot-valkey/0
  penpot-postgres:
    image: "postgres:15"
    restart: always
    stop_signal: SIGINT
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U penpot"]
      interval: 2s
      timeout: 10s
      retries: 5
      start_period: 2s
    volumes:
      - penpot_postgres_v15:/var/lib/postgresql/data
    networks:
      - penpot
    environment:
      - POSTGRES_INITDB_ARGS=--data-checksums
      - POSTGRES_DB=penpot
      - POSTGRES_USER=penpot
      - POSTGRES_PASSWORD=${PENPOT_DATABASE_PASSWORD}
  penpot-valkey:
    image: valkey/valkey:8.1
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "valkey-cli ping | grep PONG"]
      interval: 1s
      timeout: 3s
      retries: 5
      start_period: 3s
    networks:
      - penpot
    environment:
      - VALKEY_EXTRA_FLAGS=--maxmemory 128mb --maxmemory-policy volatile-lfu
  penpot-mailcatch:
    image: sj26/mailcatcher:v0.11.0
    restart: always
    expose:
      - "1025"
    ports:
      - "127.0.0.1:1080:1080"
    networks:
      - penpot
```

Die Flags `disable-email-verification` und `disable-secure-session-cookies` sind nur für den ersten Test gedacht; Schritt 5 und 6 entfernen sie.

> Prüfen Sie Syntax und Variablen vor dem ersten Start:
>
> ```bash
> $ docker compose -f /opt/penpot/compose.yaml config --quiet && echo "YAML OK"
> ```

Erwartete Ausgabe: `YAML OK` ohne Warnungen wie „variable is not set“.

## Schritt 4: Stack starten und Gesundheit prüfen

Starten Sie alle Dienste aus dem Projektordner:

```bash
$ cd /opt/penpot
$ docker compose up -d
```

Backend, Admin Console und Exporter warten per Healthcheck, bis PostgreSQL und Valkey bereit sind.

Status aller Dienste prüfen:

```bash
$ docker compose ps
```

Erwartete Ausgabe nach etwa 30 bis 60 Sekunden:

Ausgabe:

```plaintext
NAME                       STATUS          PORTS
penpot-penpot-admin-console-1  Up
penpot-penpot-backend-1    Up
penpot-penpot-exporter-1   Up
penpot-penpot-frontend-1   Up              127.0.0.1:9001->8080/tcp
penpot-penpot-mailcatch-1  Up              127.0.0.1:1080->1080/tcp
penpot-penpot-mcp-1        Up
penpot-penpot-postgres-1   Up (healthy)
penpot-penpot-valkey-1     Up (healthy)
```

Prüfen Sie die Backend-Logs auf Startfehler:

```bash
$ docker compose logs penpot-backend --tail 30
```

Die Ausgabe enthält keine Zeilen mit `ERROR` oder Datenbank-Verbindungsfehlern.

> **Prüfen:** ```bash
> $ curl -I http://localhost:9001
> ```

Erwartete Antwort: `HTTP/1.1 200 OK` oder `HTTP/1.1 302 Found`. Bei „Connection refused“ oder 502 ist das Frontend noch nicht bereit; wiederholen Sie den Aufruf nach 30 Sekunden.

## Schritt 5: Ersten Nutzer registrieren und Login testen

Öffnen Sie Penpot unter der `PENPOT_PUBLIC_URI`. Läuft der Server entfernt und ist noch kein Proxy eingerichtet, erreichen Sie ihn per SSH-Tunnel: `ssh -L 9001:127.0.0.1:9001 -L 1080:127.0.0.1:1080 benutzer@server`, dann `http://localhost:9001`. Legen Sie auf der Registrierungsseite den ersten Nutzer an.

Da `disable-email-verification` aktiv ist, entfällt die E-Mail-Bestätigung.

Sperren Sie danach die offene Registrierung: Ersetzen Sie in `PENPOT_FLAGS` `disable-email-verification` durch `disable-registration` und erstellen Sie die Dienste neu:

```bash
$ docker compose up -d
```

Weitere Nutzer legen Sie per CLI an (setzt das Flag `enable-prepl-server` voraus) oder laden sie im Team per E-Mail ein:

```bash
$ docker compose exec penpot-backend python3 manage.py create-profile
```

> **Prüfen:** Nach dem Login erscheint das Penpot-Dashboard. Legen Sie ein Testprojekt an und öffnen Sie eine leere Designdatei; der Editor lädt ohne Fehlermeldung. Ein Aufruf der Registrierungsseite im privaten Browserfenster zeigt nach der Sperre keine Registrierung mehr. Versandte E-Mails sehen Sie im Mailcatcher unter `http://localhost:1080`.

## Schritt 6: HTTPS und Reverse Proxy für den Produktionsbetrieb

Für den Einsatz im Team ist HTTPS Pflicht. Ohne HTTPS sperrt der Browser unter anderem die Zwischenablage (Kopieren und Einfügen von Design-Elementen). Das Flag `disable-secure-session-cookies` löst nur das Cookie-Problem.

Richten Sie einen Reverse Proxy auf demselben Host ein, der auf `http://127.0.0.1:9001` weiterleitet und WebSockets durchreicht:

1. **Traefik**: im offiziellen Compose-File als auskommentierter Block enthalten. Anleitung: [Traefik als Docker-Reverse-Proxy mit automatischem HTTPS](https://s-edv.com/anleitungen/traefik-docker-reverse-proxy-https-einrichten)
2. **Caddy**: [Caddy als Reverse Proxy einrichten](https://s-edv.com/anleitungen/caddy-reverse-proxy-automatisches-https-anleitung)
3. **Nginx Proxy Manager**: grafische Oberfläche

Setzen Sie danach `PENPOT_PUBLIC_URI` in der `.env` auf die HTTPS-URL, entfernen Sie `disable-secure-session-cookies` aus `PENPOT_FLAGS` und erstellen Sie die Container neu:

Datei: `.env`

```ini
# in /opt/penpot/.env
PENPOT_PUBLIC_URI=https://penpot.example.de
# danach
cd /opt/penpot && docker compose up -d
```

> **Prüfen:** ```bash
> $ curl -I https://penpot.example.de
> ```

Erwartete Antwort: `HTTP/2 200` oder `HTTP/2 302`. Im Browser funktioniert Kopieren und Einfügen von Design-Elementen, und `ss -tlnp | grep 9001` zeigt Port 9001 nur auf `127.0.0.1`.

## Schritt 7: Updates einspielen und Backups einrichten

Lesen Sie vor jedem Update die Upgrade-Hinweise in der offiziellen Dokumentation und sichern Sie beide Volumes. Passen Sie dann `PENPOT_VERSION` in der `.env` an:

```bash
$ cd /opt/penpot
$ docker compose pull
$ docker compose up -d
```

Aktualisieren Sie in kleinen Versionsschritten. Wer eine eigene `compose.yaml` von 2.17 oder älter pflegt, muss für 2.18 den Dienst `penpot-admin-console`, das Flag `enable-admin-console` und `PENPOT_ADMIN_CONSOLE_URI` ergänzen, wie in Schritt 3 gezeigt. Beobachten Sie die Logs:

```bash
$ docker compose logs -f penpot-backend
```

Prüfen Sie bei einem neuen Compose-File mit `docker volume ls`, dass die Volume-Namen gleich bleiben; sonst startet Penpot mit einem leeren Volume.

Sichern Sie beide Volumes. Docker Compose stellt den Projektnamen voran, das Assets-Volume heißt daher `penpot_penpot_assets`:

```bash
# Assets-Volume sichern
docker run --rm \
  -v penpot_penpot_assets:/data:ro \
  -v /backup/penpot:/backup \
  alpine:3.22 tar czf /backup/penpot_assets_$(date +%Y%m%d).tar.gz -C /data .
# PostgreSQL-Datenbank-Dump
mkdir -p /backup/penpot
docker compose exec -T penpot-postgres \
  pg_dump -U penpot penpot | gzip > /backup/penpot_db_$(date +%Y%m%d).sql.gz
```

Für automatisierte Backups siehe [MySQL & PostgreSQL Backup automatisieren mit cron und rclone](https://s-edv.com/anleitungen/mysql-postgresql-backup-automatisieren-cron-cloud).

> **Prüfen:** ```bash
> $ docker compose ps
> ```

Nach dem Update zeigen alle acht Container den Status `Up`, die Datenbank-Container `Up (healthy)`. Bestehende Projekte öffnen sich im Browser. `ls -lh /backup/penpot/` zeigt beide Sicherungsdateien mit einer Größe über 0.

## Troubleshooting / Typische Fehler

**Alle Nutzer werden nach Neustart ausgeloggt**

`PENPOT_SECRET_KEY` ist nicht gesetzt oder ändert sich bei jedem Start . Lösung: Schlüssel wie in Schritt 1 erzeugen, fest in die `.env` eintragen, `docker compose up -d`.

**Einladungslinks und OAuth-Callbacks schlagen fehl**

`PENPOT_PUBLIC_URI` stimmt nicht mit der tatsächlichen Zugriffs-URL überein. Wert in der `.env` anpassen, `docker compose up -d`.

**Clipboard-API funktioniert nicht (Kopieren/Einfügen im Editor)**

Penpot läuft ohne HTTPS. Richten Sie den Reverse Proxy aus Schritt 6 ein.

**Backend startet nicht, Logs zeigen „database does not exist“ oder „connection refused“**

`docker compose logs penpot-postgres` prüfen. Häufige Ursache: Das Passwort in der `.env` wurde nach der Erstinitialisierung geändert.

**Dienst fehlt oder Frontend startet nicht**

Die `compose.yaml` passt nicht zur Version in `PENPOT_VERSION`, etwa fehlt `penpot-admin-console` bei 2.18. Lösung: Compose-File zur Version verwenden (Schritt 3).

**`manage.py create-profile` schlägt fehl**

Das Flag `enable-prepl-server` fehlt in `PENPOT_FLAGS`. Ergänzen, `docker compose up -d`, Befehl wiederholen.

**IPv6-Fehler beim Frontend-Start**

Auf Hosts mit beim Booten deaktiviertem IPv6 kann Nginx im Frontend-Container nicht binden. Lösung: `PENPOT_DISABLE_IPV6_LISTEN: "true"` in die Umgebung von `penpot-frontend`.

**Projekte nach Update verschwunden**

Das neue Compose-File nutzt einen anderen Volume-Namen; Docker hat ein leeres Volume angelegt. Volume-Namen in der `compose.yaml` auf das alte Volume zurücksetzen (`docker volume ls`).

## Häufige Fragen

### Unter welcher Lizenz steht Penpot im Self-Hosting?

Unter der Mozilla Public License 2.0, ohne Nutzerlimit. Aufwand entsteht für Server, SMTP-Versand, Updates und Backups.

### Läuft Penpot auf ARM-Servern oder Apple-Silicon-Macs?

Ja, die offiziellen Images gibt es für `linux/arm64`; Docker wählt die Architektur automatisch.

### Wie lege ich weitere Nutzer an, wenn die Registrierung gesperrt ist?

Mit `docker compose exec penpot-backend python3 manage.py create-profile` (Flag `enable-prepl-server` nötig). Alternativ laden Sie Nutzer per E-Mail ins Team ein (echter SMTP-Server nötig).

### Was ist der MCP-Server?

Der Dienst `penpotapp/mcp` implementiert das Model Context Protocol. KI-Assistenten greifen damit auf Penpot-Designs zu. Den Schlüssel erzeugt jeder Nutzer selbst unter Integrationen. Wer MCP nicht nutzt, entfernt `enable-mcp` aus `PENPOT_FLAGS`.

### Kann ich Penpot mit LDAP oder OIDC verbinden?

Ja. LDAP wird über `PENPOT_LDAP_*`-Variablen und das Flag `enable-login-with-ldap` konfiguriert. OIDC (Keycloak, Azure AD, Authentik) über `PENPOT_OIDC_*`-Variablen. Google, GitHub und GitLab haben eigene `enable-login-with-*`-Flags. Details stehen in der Penpot-Konfigurationsreferenz.

### Wie sichere ich meine Penpot-Daten?

Wie in Schritt 7; für eine Kopie außer Haus eignet sich `rclone`.

## Fazit

Für den Produktivbetrieb entscheidend sind ein fester `PENPOT_SECRET_KEY`, eine korrekte `PENPOT_PUBLIC_URI`, HTTPS über einen Reverse Proxy, eine gesperrte Registrierung und regelmäßige Sicherungen beider Volumes.

## Weiterführende Anleitungen und Quellen

1. [Docker und Docker Compose auf Linux installieren: die Self-Hosting-Grundlage](https://s-edv.com/anleitungen/docker-compose-linux-selfhosting-grundlage)
2. [Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten](https://s-edv.com/anleitungen/traefik-docker-reverse-proxy-https-einrichten)
3. [Docker Compose absichern: Secrets, Healthchecks und Non-Root für den Produktivbetrieb](https://s-edv.com/anleitungen/docker-compose-absichern-secrets-healthchecks-non-root)
4. [MySQL & PostgreSQL Backup automatisieren mit cron und rclone](https://s-edv.com/anleitungen/mysql-postgresql-backup-automatisieren-cron-cloud)

Offizielle Quellen: [Penpot Self-Hosting Dokumentation](https://help.penpot.app/technical-guide/getting-started/docker/) | [Penpot Konfigurationsreferenz](https://help.penpot.app/technical-guide/configuration/) | [Penpot GitHub Repository](https://github.com/penpot/penpot)

## Passende Anleitungen auf S-EDV

1. [PostgreSQL schließt elf Sicherheitslücken in den Versionen 14 bis 18](https://s-edv.com/news/postgresql-11-sicherheitsluecken-versionen-14-18-mai-2026)
2. [Prometheus node_exporter nativ installieren und als systemd-Dienst betreiben](https://s-edv.com/anleitungen/prometheus-node-exporter-nativ-binary-systemd-linux)
3. [netcup Local Block Storage bestellen, einrichten und unter Linux einbinden](https://s-edv.com/anleitungen/netcup-local-block-storage-bestellen-linux-einbinden)
