uptime · 1404 days · 23 posts published · last deploy 1 day, 10 hours ago build:passing rss
~ / software-web / wagtail-multi-site-mehrere-seiten-aus-einer-code.md
Software & Web · 03. Juni 2026 · ~9min · ed3e48c

Wagtail Multi-Site: Mehrere Seiten aus einer Codebase

Ein Django-Projekt, ein Server, beliebig viele Auftritte – wie das Sites-Framework das möglich macht

>
devmaker.net
author · ed3e48c · 2026-06-03
x
Wagtail Multi-Site Architektur Hero.jpg 1024×1024
Wagtail Multi-Site Architektur Hero
Ein Server, ein Reverse Proxy, mehrere Domains: das Multi-Site-Routing im Überblick.
devmaker.net läuft auf einem Wagtail, das ich von Anfang an Multi-Site-fähig gebaut habe – ein Projekt, das problemlos mehrere Domains mit jeweils eigenen Inhaltstypen tragen kann. Aktuell ist nur dieser Blog online, aber ich habe das Setup mit weiteren Seiten (einem News-Ticker und einem Science-Portal) komplett durchgespielt. Dieser Artikel zeigt, wie die Technik funktioniert: vom Sites-Framework über eigene Page-Typen bis zum Reverse-Proxy-Routing. Du brauchst Wagtail-Grundlagen, am Ende verstehst du, wann sich Multi-Site lohnt und wo die Stolperfallen liegen.

Mehrere Webseiten bedeuten normalerweise mehrere Deployments, mehrere Datenbanken, mehrfache Wartung. Wagtail kann das anders: Ein Projekt, eine Datenbank, ein Deployment – und trotzdem beliebig viele Domains mit jeweils eigenem Look und eigenen Inhaltstypen. Ich habe devmaker.net von Anfang an auf diesem Fundament gebaut. Online ist aktuell nur dieser Blog, aber das Setup trägt mehr: Ich habe es mit einem News-Ticker und einem Science-Portal als zweite und dritte Site getestet.

Der Trick ist kein Hack, sondern eine Kernfunktion von Wagtail.

Das Wagtail Sites-Framework in einem Satz

Wagtail kann mehrere Sites in einer Installation verwalten. Jede Site ist im Kern nur ein Mapping: Hostname (+ Port) → Root-Page. Kommt ein Request rein, schaut Wagtail in der Site-Tabelle nach, welcher Hostname passt, und rendert den darunterliegenden Seitenbaum. Genau eine Site ist die is_default_site – sie fängt alles ab, was sonst nicht matcht.

Schematisch (mit Beispiel-Hosts für die nicht-öffentlichen Seiten):

Hostname              Root-Page          Status
-----------------------------------------------------------
devmaker.net          HomePage           live
news.example.com      HomePage           Beispiel / nicht online
papers.example.com    PaperHomePage      Beispiel / nicht online

Wichtig: Die Root-Pages sind komplett getrennte Bäume. Slugs dürfen sich über Sites hinweg wiederholen – ein /home-automation/ auf der einen Site kollidiert nicht mit einem gleichnamigen Pfad auf einer anderen, weil jeder Baum unter seiner eigenen Root hängt.

Eigene Page-Typen pro Domain

Das ist der eigentliche Hebel. Multi-Site heißt nicht „dreimal dasselbe mit anderem Logo“. Jede Site darf ihre eigenen Page-Modelle nutzen. Ein Blog und ein News-Ticker können sich HomePage/TopicPage/ArticlePage teilen, ein Science-Portal bekommt dagegen eigene Typen für Paper:

# pages/models.py
from wagtail.models import Page

class HomePage(Page):
    """Startseite für Blog- und News-Sites."""
    subpage_types = ["pages.TopicPage"]

class ArticlePage(Page):
    """Klassischer Blog-/News-Artikel (StreamField-Body)."""
    parent_page_types = ["pages.TopicPage"]

class PaperHomePage(Page):
    """Eigene Startseite für ein Science-Portal."""
    subpage_types = ["papers.PaperTopicPage"]

class PaperArticlePage(Page):
    """Wissenschaftliches Paper in Plain Language."""
    parent_page_types = ["papers.PaperTopicPage"]
    # ... DOI, Autoren, Original-Abstract, Rewrite ...

Über subpage_types und parent_page_types erzwinge ich, dass unter einer PaperHomePage nur Paper-Typen landen können – und unter einer HomePage nur Blog-Typen. So bleiben die Welten sauber getrennt, obwohl sie im selben Admin liegen.

Templates: geteilt, wo es geht – eigen, wo nötig

Wagtail leitet das Template automatisch aus dem Page-Typ ab: HomePagehome_page.html, PaperHomePagepaper_home_page.html. Gemeinsame Bausteine (Header, Footer, das Terminal-Editorial-Grundgerüst) liegen in einem base.html, das alle erben. Site-spezifische Unterschiede leben nur im jeweiligen Template.

Wenn ich pro Site doch dasselbe Modell mit anderem Look brauche, hilft ein Blick auf den Hostname im Context:

class ArticlePage(Page):
    def get_template(self, request, *args, **kwargs):
        site = request.site if hasattr(request, "site") else None
        host = getattr(site, "hostname", "")
        if host.startswith("news."):
            return "pages/article_page_news.html"  # kompakter News-Look
        return "pages/article_page.html"            # ausführlicher Blog-Look

Ein Reverse Proxy, mehrere Domains

Netzwerkseitig ist es unspektakulär – und genau das ist der Punkt. Alle Domains zeigen per DNS auf dieselbe öffentliche IP. Ein Reverse Proxy im Homelab terminiert TLS für jeden Hostname und reicht sie an denselben Gunicorn-Upstream weiter. Wagtail entscheidet anhand des Host-Headers, welche Site gerendert wird:

# Ein Upstream für alle Domains
upstream wagtail { server 127.0.0.1:8000; }

server {
    listen 443 ssl;
    server_name devmaker.net news.example.com papers.example.com;

    # TLS pro Host (z. B. via Let's Encrypt / Nginx Proxy Manager)
    ssl_certificate     /etc/letsencrypt/live/multi/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/multi/privkey.pem;

    location / {
        proxy_pass http://wagtail;
        proxy_set_header Host $host;            # <- entscheidend!
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Die eine Zeile, auf die es ankommt, ist proxy_set_header Host $host;. Ohne den korrekten Host-Header sieht Django immer nur die Proxy-Adresse – und Wagtail fällt auf die Default-Site zurück. Damit Django die Hosts überhaupt akzeptiert, müssen sie in den Settings stehen:

# settings/production.py
ALLOWED_HOSTS = [
    "devmaker.net",
    "news.example.com",
    "papers.example.com",
]

# Hinter dem Reverse Proxy: HTTPS korrekt erkennen
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
USE_X_FORWARDED_HOST = True

Locales teilen sich alle Sites

devmaker.net ist zweisprachig (Deutsch als Default, Englisch dazu) – und dieselbe Mechanik gilt site-übergreifend. Die Locales sind global, nicht pro Site. Mit wagtail-localize bekommt jede Page einen Übersetzungsbaum, und der Sprachpräfix läuft über i18n_patterns. So teilt sich der komplette Übersetzungs-Workflow über alle Marken hinweg – ein Tooling, beliebig viele Auftritte.

Stolperfalle Default-Site

Genau eine Site darf is_default_site=True sein. Vergisst du das beim Anlegen einer neuen Site, beantwortet Wagtail unbekannte Hosts entweder gar nicht oder mit der falschen Seite. Symptom: Eine neue Domain zeigt plötzlich den Blog statt der erwarteten Seite.

Was geteilt wird – und was nicht

  • Geteilt: Datenbank, Media-Storage, Bilder, Snippets, User & Permissions, das Admin-Backend, Locales, Deployment.
  • Getrennt: Seitenbäume, Page-Typen, Templates, URLs/Slugs, Sitemaps pro Host.

Das gemeinsame Media-Pool ist Komfort und Risiko zugleich: Ein Bild, das ich für die eine Site hochlade, ist im Admin auch bei der anderen wählbar. Mit Collections lässt sich das pro Marke ordnen, wenn nötig.

Lessons Learned

  • Multi-Site spart real Wartung. Ein git pull, eine Migration, ein Neustart – alle Seiten sind aktuell. Das ist der größte Gewinn gegenüber getrennten Deployments.
  • Von Anfang an Multi-Site-fähig bauen lohnt sich. Auch wenn nur eine Seite online geht: Das Fundament steht, und eine zweite Site ist später eine Frage von Stunden, nicht von Tagen.
  • Eigene Page-Typen sind der Unterschied zwischen „echt verschiedene Seiten“ und „Themes“. Plane sie früh, nicht als Nachgedanke.
  • Der Host-Header ist die häufigste Fehlerquelle. Die meisten „falsche Seite wird angezeigt“-Bugs hängen am Reverse Proxy, nicht an Wagtail.

Fazit

Wagtail Multi-Site ist eine der unterschätztesten Funktionen des CMS. Wer mehrere Projekte plant – oder sich die Tür dafür offenhalten will – spart sich mit einem sauberen Sites-Setup massiv Infrastruktur, ohne die Seiten inhaltlich zu verbiegen. Bei mir trägt das Fundament aktuell devmaker.net und ist für weitere Auftritte vorbereitet: pragmatisch, nicht überengineered.

// responses (0)
> echo "your thoughts" >> wagtail-multi-site-mehrere-seiten-aus-einer-code.responses

Schreibe einen Kommentar

Wird für die Bestätigung benötigt