Die server_name-Direktive ist in Nginx der Punkt, an dem aus einem generischen Webserver ein sauber getrenntes Mehrdomain-Setup wird. Hinter dem Stichwort nginx server name steckt genau diese Zuordnung von Hostnamen zu Serverblöcken, und in der Praxis entscheidet sie darüber, welche Website, welches Zertifikat und welche Weiterleitung greifen. Ich zeige hier, wie die Auswahl funktioniert, wann Wildcards oder reguläre Ausdrücke sinnvoll sind und welche Fehler ich in echten Konfigurationen am häufigsten sehe.
Die wichtigsten Punkte zu server_name in Nginx
-
server_nameordnet Hostnamen einem bestimmtenserver-Block zu. - Der Default-Server kommt aus der
listen-Direktive, nicht ausserver_name. - Exakte Namen sind am klarsten und am schnellsten, Wildcards und Regex nur bei echtem Bedarf.
- Bei HTTPS spielt SNI eine Rolle, weil das Zertifikat oft vor dem HTTP-
Hostausgewählt wird. - Umlaute und IDNs gehören als Punycode in die Konfiguration.
- Bei vielen Namen können
server_names_hash_max_sizeundserver_names_hash_bucket_sizerelevant werden.
Wie Nginx den passenden Serverblock auswählt
Ich trenne die Logik immer in zwei Schritte: listen wählt den Socket, server_name den Hostnamen. Zuerst schaut Nginx, auf welcher IP und auf welchem Port die Anfrage ankommt. Erst danach wird geprüft, welcher server-Block den passenden Namen trägt. Wenn nichts passt, greift der Default-Server für diesen Port, nicht irgendeine magische Fallback-Regel in server_name selbst.
| Situation | Was Nginx zuerst prüft | Ergebnis |
|---|---|---|
| Mehrere Websites auf demselben Port |
Host-Header |
Der passende Name bestimmt den server-Block |
| Mehrere IPs oder Ports |
listen-Adresse und Port |
Erst danach wird der Hostname verglichen |
| Kein passender Hostname | Default-Server des Ports | Der erste Block oder der explizit markierte Default antwortet |
| Request direkt per IP | IP im Host-Header |
Nur wenn die IP als Name konfiguriert ist, passt der Block |
Request ohne Host
|
Leerer Name ""
|
Kann gezielt mit einem separaten Block abgefangen werden |
Für einen Port mit nur einem Serverblock spart Nginx die Namenssuche sogar komplett ein. Erst wenn mehrere Blöcke oder Regex-Muster ins Spiel kommen, wird die Auswahl überhaupt interessant. Damit ist die wichtigste Fehlannahme ausgeräumt: Der Default gehört zu listen, nicht zu server_name. Als Nächstes lohnt sich der Blick auf die Namensformen selbst, weil sie sehr unterschiedliche Kosten und Nebenwirkungen haben.
Welche Namensformen sich wirklich lohnen
Für echte Projekte reicht ein einzelner Mechanismus selten aus. Nginx kennt exakte Namen, Wildcards und reguläre Ausdrücke, und die Reihenfolge ist fest: erst exakt, dann die stärkste Wildcard, zuletzt der erste passende Ausdruck. Genau dort entscheidet sich, ob die Konfiguration klar bleibt oder unnötig schwer wartbar wird.
| Form | Beispiel | Wofür ich sie nutze | Worauf ich aufpasse |
|---|---|---|---|
| Exakter Name |
example.org, www.example.org
|
Feste Domains mit klarer Zuordnung | Am schnellsten und am lesbarsten |
| Wildcard am Anfang | *.example.org |
Beliebige Subdomains | Trifft auch tiefere Ebenen wie www.sub.example.org
|
| Wildcard am Ende | mail.* |
Seltene Spezialfälle, etwa wechselnde Endungen | Für öffentliche Websites eher selten sinnvoll |
| Punktnotation | .example.org |
Root-Domain und alle Subdomains | Praktisch, aber weniger explizit als einzelne Namen |
| Regulärer Ausdruck | ~^www\d+\.example\.net$ |
Muster, Capture-Gruppen oder dynamische Zuordnung | Langsamer, fehleranfälliger und schwerer zu warten |
Wildcards funktionieren nur am Anfang oder Ende eines Namens. *.example.org ist erlaubt, w*.example.org nicht. Wenn ich den Basisnamen und alle Subdomains abdecken will, schreibe ich oft lieber explizit example.org, www.example.org und *.example.org statt nur die Kurzform .example.org. Das ist etwas länger, aber später deutlich transparenter.
Reguläre Ausdrücke setze ich sparsam ein. Sie brauchen ein führendes ~, sollten mit ^ und $ begrenzt sein und Punkte im Domainnamen müssen mit einem Backslash escaped werden. Wenn Capture-Gruppen wirklich weiterhelfen, etwa bei einem gemeinsamen root oder proxy_pass, ist das sinnvoll. Für bloßes Domain-Matching sind sie meist zu teuer und zu fehleranfällig.
server {
server_name ~^(www\.)?(?.+)$;
location / {
root /sites/$domain;
}
} Wenn die Namensform stimmt, lässt sich die Konfiguration im Alltag deutlich geradliniger schreiben. Genau das sieht man an den typischen Setups.

Praktische Konfigurationen für typische Setups
Eine kanonische Domain mit Weiterleitung
Ich lege in solchen Fällen meist fest, welche URL die kanonische ist. Das hält Analytics, Cookies und Redirect-Ketten sauber.
server {
listen 80;
server_name example.org www.example.org;
return 301 https://example.org$request_uri;
}Hier ist wichtig, dass beide Hostnamen in denselben Block fallen. Die Umleitung passiert dann kontrolliert auf die bevorzugte Adresse, statt zufällig über den Default-Server zu laufen.
Eine Anwendung für viele Subdomains
server {
listen 80;
server_name .example.org;
root /var/www/example;
}Die Punktnotation spart Tipparbeit, wenn sowohl die Root-Domain als auch beliebige Subdomains dieselbe Anwendung nutzen. Ich verwende sie nur, wenn das fachlich wirklich stimmt, weil sie in größeren Setups schnell zu breit wird.
Lesen Sie auch: Rate Limit Exceeded - 429 Fehler in NGINX & Apache beheben
Unbekannte Hosts sauber abfangen
server {
listen 80 default_server;
server_name _;
return 444;
}Der Unterstrich ist kein Sonderwort, sondern einfach ein absichtlich ungültiger Name. Genau deshalb eignet er sich für den Auffangblock, der alles abweist, was nirgends hingehört.
Wenn ich Requests ohne Host gezielt blockieren will, nutze ich den leeren Namen "" oder denselben Auffangblock, statt mich auf implizite Defaults zu verlassen. Sobald HTTPS dazukommt, verschiebt sich der Fokus von der Domain auf das Zertifikat. Das ist der Punkt, an dem viele Setups unnötig kompliziert werden.
Warum HTTPS den Namen zur Zertifikatsfrage macht
Bei HTTPS wird der Zusammenhang etwas unangenehmer, weil die TLS-Verbindung vor dem eigentlichen HTTP-Request aufgebaut wird. Nginx kennt den gewünschten Hostnamen in diesem Moment nur dann, wenn der Client SNI sendet. Ohne SNI bekommt der Browser in der Regel das Zertifikat des Default-Servers, selbst wenn server_name später eigentlich etwas anderes vorgesehen hätte.
Für die Praxis heißt das: Der Name im Serverblock und die Namen im Zertifikat müssen zusammenpassen. Sonst ist die Routing-Ebene korrekt, aber der Browser meldet trotzdem ein Zertifikatsproblem. Ich halte mich dann an vier robuste Optionen:
- Separate IPs für voneinander getrennte HTTPS-Sites, wenn maximale Trennung nötig ist.
- Ein Zertifikat mit mehreren SAN-Einträgen, wenn mehrere feste Domains zusammengehören.
- Ein Wildcard-Zertifikat, wenn nur eine Subdomain-Ebene abgedeckt werden muss.
- Gemeinsame Zertifikatsdateien auf
http-Ebene, wenn mehrere Server denselben Satz an Namen nutzen.
server {
listen 443 ssl;
server_name example.org www.example.org;
ssl_certificate example.org.chained.crt;
ssl_certificate_key example.org.key;
}Ein Wildcard-Zertifikat deckt nur eine Ebene ab. *.example.org passt also zu www.example.org, nicht zu example.org und nicht zu www.sub.example.org. Wenn Name und Zertifikat nicht zusammenpassen, sieht die Konfiguration auf dem Papier gut aus, scheitert aber im Browser. Deshalb prüfe ich die Fehlerbilder als Nächstes sehr bewusst.
Typische Fehler, die ich regelmäßig sehe
| Fehler | Typisches Symptom | Was ich ändere |
|---|---|---|
default_server wird bei server_name erwartet |
Unbekannte Hosts landen im falschen Block |
default_server gehört in listen
|
Root-Domain wird nur mit *.example.org abgedeckt |
example.org selbst passt nicht |
Root-Domain explizit ergänzen oder .example.org nutzen |
Regex ohne ~ oder ohne Anker |
Unerwartete Teiltreffer oder Startfehler |
~, ^ und $ ergänzen |
| Regulärer Ausdruck mit ungesicherten Klammern | Nginx meldet einen Syntaxfehler | Regex in Anführungszeichen setzen |
| Unicode-Domain direkt eingetragen | Der Name wird nicht so erkannt wie erwartet | IDN als Punycode notieren |
| Zu viele oder zu lange Namen | could not build the server_names_hash |
Hash-Parameter anpassen |
_ wird als magischer Catch-all verstanden |
Der Block fängt nicht automatisch alles ab |
_ nur als absichtlich ungültigen Namen verwenden |
Bei Hash-Fehlern gehe ich zuerst an server_names_hash_max_size, meist nahe an die Anzahl der konfigurierten Namen. Erst wenn das nicht reicht oder der Start von Nginx unnötig lange dauert, erhöhe ich server_names_hash_bucket_size auf die nächste Zweierpotenz. Das ist robuster, als pauschal an beiden Werten zu drehen.
Zum Debuggen nutze ich zwei Prüfungen: nginx -t für die Syntax und einen gezielten Request mit gesetztem Host-Header, etwa curl -H 'Host: example.org' http://127.0.0.1. So sehe ich schnell, ob Routing und Default-Server wirklich so greifen, wie ich es gedacht habe. Wenn diese Fehlerquellen im Blick sind, bleibt noch die Frage, wie ich neue Setups von Anfang an sauber aufbaue.
Welche Regel ich für neue Setups befolge
Meine Grundregel ist simpel: erst präzise, dann flexibel. Ich baue eine Nginx-Konfiguration immer so, dass sie mit exakten Namen funktioniert und erst an den Stellen erweitert wird, an denen eine echte fachliche Anforderung besteht.
- Ich beginne mit exakten Hostnamen und ergänze Wildcards nur, wenn sie wirklich nötig sind.
- Ich setze
default_serverbewusst pro Port und verlasse mich nicht auf implizite Defaults. - Ich behandle HTTPS immer als Zertifikats- und SNI-Thema, nicht nur als Routing-Thema.
- Ich schreibe IDNs in Punycode und prüfe die Schreibweise lieber einmal mehr.
- Ich vermeide Regex, solange ein klarer Name oder eine saubere Wildcard die Aufgabe genauso gut löst.
- Wenn mehrere hundert Namen im Spiel sind, prüfe ich früh die Hash-Werte statt erst beim Startfehler.
Wer server_name so behandelt, hat weniger Überraschungen bei Redirects, Zertifikaten und Mehrdomain-Setups. Genau dort liegt der eigentliche Nutzen der Direktive: Sie macht Hostnamen zu einer kontrollierbaren Routing-Entscheidung, statt sie dem Zufall zu überlassen.