# Warum ich camiler.org auf einem einzigen VPS betreibe

> Wie ich Docker, Redis und Cloudflare einsetze, um camiler.org auf einem kleinen VPS zu betreiben, welche Probleme das löst und welche Risiken bei mir bleiben.

> 💡 **Kurzfassung:**
> - Statt für jede Aufgabe einen eigenen verwalteten Dienst zu kaufen, habe ich die Dienste mit Docker getrennt und auf einem kleinen VPS gehalten.
> - Redis reduziert wiederholtes Rendern von Seiten und Datenbankarbeit. Cloudflare bedient einen großen Teil der statischen Inhalte und Bilder, bevor der Ursprung erreicht wird.
> - Die direkte Infrastrukturrechnung bleibt niedrig, aber Wartungsarbeit und das Ausfallrisiko einer einzelnen Maschine bleiben bei mir.

Ich entwickle und betreibe [camiler.org](https://camiler.org){.dofollow} selbst. Als ich das Projekt begann, kostete der VPS ungefähr fünf US-Dollar im Monat.

Bei diesem Budget ergab ein separater verwalteter Dienst für jedes Thema wenig Sinn. Es ging aber nicht nur um die Rechnung. Jeder zusätzliche Dienst bringt ein weiteres Dashboard, eine weitere Abhängigkeit und einen weiteren Ort, an dem man bei einem Fehler suchen muss.

Die Infrastruktur sollte für eine einzelne Person verständlich bleiben: Wo beginne ich bei einem Ausfall, wo liegen dauerhafte Daten und wie verhält sich die Website ohne Cache? Diese Grenzen prägten die Architektur. Die Such- und Inhaltsseite des Projekts behandle ich in [camiler.org aufbauen: Ein programmatisches SEO-Experiment mit Google Maps und OpenAI](/de/camiler-org-ein-programmatisches-seo-experiment-mit-google-maps-und-openai). Hier geht es darum, wie die Website online bleibt und welche Verantwortung eine geringe Infrastrukturrechnung mit sich bringt.

## Das System in Kürze

Das gesamte System läuft auf einem VPS; jeder Dienst hat seinen eigenen Docker-Container.

```text
Seitenanfrage: User -> Cloudflare -> Traefik -> Nuxt -> Redis
API-Anfrage:    User -> Cloudflare -> Traefik -> Fastify -> Redis / MariaDB
Bildanfrage:    User -> Cloudflare-Cache -> imgproxy -> Cloudflare R2
Bereitstellung: GitHub Actions -> privates Registry -> Bereitstellungs-Webhook -> Container
```

Traefik empfängt die Anfragen, die den Server erreichen. Es liest Docker-Labels, um Hostnamen Containern zuzuordnen, erneuert Let's-Encrypt-Zertifikate und beschränkt den IP-Zugriff auf interne Werkzeuge wie Portainer und phpMyAdmin.

Diese Docker-Integration war der praktische Grund für Traefik: Beim Hinzufügen eines Dienstes kann ich das Routing neben dem Container definieren, statt eine separate Reverse-Proxy-Konfiguration zu pflegen und neu zu laden. Ein wiederkehrender Schritt entfällt. Vor einem falschen Label schützt Traefik jedoch nicht; ich muss weiterhin prüfen, welche Dienste im Internet sichtbar sind und welche Netzwerke jeder Container erreichen kann.

## Auf einem kleinen Server reduzierte ich zuerst Wiederholungen

Das Frontend läuft auf Nuxt 3 mit serverseitigem Rendering. Dieselbe Moscheeseite bei jeder Anfrage neu zu erzeugen, würde begrenzte CPU- und Speicherressourcen für bereits geleistete Arbeit verbrauchen.

Eine Middleware legt gerendertes HTML komprimiert in Redis ab; ETags vermeiden zusätzlich das Senden unveränderter Inhalte. Ein einfacher Zeit-Cache genügt nicht: Ändert sich ein Moschee-Datensatz, müssen auch zusammenhängende Seiten wie „Moscheen in der Nähe“ ungültig werden. Deshalb unterstützt der Cache tagbasierte Invalidierung.

Bei einem Redis-Ausfall rendert die Website ohne Cache. Der Server leistet dann mehr Arbeit, aber dauerhafte Daten gehen nicht verloren. Redis ist ein Beschleuniger, keine maßgebliche Datenquelle.

Das Backend nutzt Fastify, Prisma und MariaDB. Redis hält außerdem häufig verwendete Abfrageergebnisse und Zähler für Ratenbegrenzungen vor. Die verfügbaren Pakete deckten nicht die gewünschte Kombination aus Routen-, Nutzer-, Gruppen- und globalen Limits ab; dafür schrieb ich eine kleine Middleware. Sie gibt Kontrolle, macht aber auch die Wartung zu meiner Verantwortung.

## Bildverkehr vom VPS fernhalten

Moscheebilder müssen in verschiedenen Größen und Formaten ausgeliefert werden. Die Originale liegen in Cloudflare R2; imgproxy erzeugt bei Bedarf Größe und Format. Cloudflare kann das Ergebnis am Netzwerkrand zwischenspeichern. Wiederholte Anfragen erreichen damit oft weder VPS noch imgproxy oder R2.

Das senkt Rechen- und Netzwerklast auf dem kleinen Server. Die S3-kompatible Schnittstelle von R2 eröffnet zudem einen Weg zu einem anderen S3-Anbieter oder MinIO. Kompatibilität macht den Umzug aber nicht mühelos: Dateien zu kopieren wäre womöglich der einfache Teil; Zugangsdaten, Cache-Regeln und der Dateifluss der Anwendung müssten sich weiterhin ändern.

## Bereitstellung bewusst klein halten

Bei einem Push in den Hauptbranch erstellt GitHub Actions das relevante Docker-Image und lädt es in eine private Registry. Anschließend ruft es einen kleinen Webhook auf dem Server auf, der den betreffenden Container mit dem neuen Image neu startet.

Diese Pipeline ist nicht ambitioniert. Sie erspart mir, mich auf dem Server anzumelden und Bereitstellungsbefehle von Hand auszuführen, lässt jeden Schritt aber sichtbar. Für ein Ein-Personen-Projekt genügt das. Portainer nutze ich für Containerstatus und Protokolle, phpMyAdmin für gelegentliche Datenbankprüfungen. Beide sind per IP eingeschränkt und liegen nicht im normalen Anfragepfad.

## Niedrige Monatsrechnung, aber keine einfache Gesamtkostenrechnung

Ein einzelner kleiner VPS hält die direkte Rechnung niedrig. Es wäre verführerisch, den Unterschied zu verwalteten Diensten vollständig als Ersparnis zu bezeichnen. Ich aktualisiere aber auch den Server, beobachte Container, behebe fehlgeschlagene Bereitstellungen und kontrolliere die Cache-Invalidierung. Einen Teil der Ersparnis bezahle ich mit meiner Zeit.

Das größere Risiko ist Ausfallzeit. Docker trennt Dienste, aber Nuxt, Fastify, Redis und MariaDB laufen trotzdem auf derselben Maschine. Fällt der Host aus, halten getrennte Container die Website nicht online.

Dieses Risiko akzeptiere ich heute: camiler.org erzielt keinen Umsatz, und ich betreibe es allein. Unter diesen Bedingungen gibt es keinen wirtschaftlichen Grund für eine teurere Hochverfügbarkeitsarchitektur. Ändern sich die Bedingungen, gibt es keinen Grund, der jetzigen Architektur treu zu bleiben.

## Wann ich den einzelnen VPS verlassen würde

Ich würde die Entscheidung überdenken, bevor der Server schlicht keine Kapazität mehr hat. Klare Auslöser wären:

- wenn die Kosten eines Ausfalls höher werden als ein zweiter Host und automatisierte Wiederherstellung;
- wenn Datenbank-, Bildverarbeitungs- oder SSR-Last andere Dienste stört;
- wenn mehr als eine Person oder ein Team unabhängige Kontrolle über die Infrastruktur braucht;
- wenn Anforderungen an Sicherung, Wiederherstellung, Audit oder Compliance die aktuelle Lösung übersteigen;
- wenn meine Wartungszeit teurer wird als die verwalteten Dienste, die sie ersetzt.

Dann müsste nicht alles neu geschrieben werden. Datenbank, Anwendung oder Bildverarbeitung könnten auf getrennte Kapazität umziehen; Cloudflare und R2 könnten bleiben oder ersetzt werden. Genau hier ist Docker für mich nützlich: Die Dienste können heute eine Maschine teilen, ohne einen praktischen Weg zur späteren Trennung zu schließen.

camiler.org auf einem VPS zu betreiben ist kein technischer Kunstgriff. So erfülle ich die heutigen Anforderungen ohne unnötige Rechnungen und Wartungsarbeit. Der Preis ist niedrig, die Grenzen sind bekannt, und ich weiß, wo ich bei einem Fehler suchen muss. Die Entscheidung ändert sich, wenn Ausfallrisiko, Verkehrslast oder Wartungskosten ein Niveau erreichen, das ich nicht mehr akzeptieren kann.

---

Language: German
License: CC BY 4.0
License URL: https://creativecommons.org/licenses/by/4.0/
Scope: Evren Bal-authored text, unless this article expressly states otherwise.
Excluded: Third-party material, quoted excerpts, logos, and separately marked images retain their own rights.
Attribution: Credit Evren Bal, link to the canonical source and license, and indicate changes.
Source: https://evrenbal.com/de/warum-ich-camiler-org-auf-einem-einzigen-vps-betreibe
