Zum Inhalt springen

Weiterleitungen mit nginx

Fertige nginx-Konfiguration für 301-Weiterleitungen: einzelne Seiten, Muster, ganze Domains, HTTPS und www in einem Hop und Hunderte URLs per map.

return oder rewrite?

Eine .htaccess gibt es bei nginx nicht. Alle Weiterleitungen stehen in der Serverkonfiguration, meist in /etc/nginx/nginx.conf oder in einer Datei unter /etc/nginx/conf.d/ bzw. sites-available/. Für Redirects stehen dir zwei Direktiven zur Verfügung:

DirektiveStatuscodesWann einsetzen
return 301 URL;Alle: 301, 302, 303, 307, 308Die Standardwahl. Schnell, eindeutig, beendet die Verarbeitung sofort.
rewrite regex ersetzung permanent;301 (permanent) oder 302 (redirect)Wenn du den Pfad per regulärem Ausdruck umbauen musst.

Die nginx-Dokumentation empfiehlt selbst, wo immer möglich return zu nehmen. Es muss keinen Regex auswerten und kann auch 307 und 308 senden – das kann rewrite nicht. Greif zu rewrite nur, wenn du den neuen Pfad wirklich aus Teilen des alten zusammensetzen musst.

Einzelne Seite weiterleiten

Am saubersten geht das mit einer exakten Location:

location = /alte-seite {
    return 301 https://example.com/neue-seite/;
}

Das = sorgt dafür, dass nur genau /alte-seite passt, nicht /alte-seite/ oder /alte-seiten. Ein relatives Ziel wie return 301 /neue-seite/; geht auch: nginx macht daraus mit dem angefragten Host eine absolute URL, weil absolute_redirect standardmäßig aktiv ist.

Wichtig: return mit fester URL verwirft den Query-String. Willst du ihn behalten, häng $is_args$args an:

location = /alte-seite {
    return 301 https://example.com/neue-seite/$is_args$args;
}

Ordner oder Muster weiterleiten

Mit einer Regex-Location und Captures:

location ~ ^/blog/\d{4}/(.+)$ {
    return 301 https://example.com/artikel/$1$is_args$args;
}

Dasselbe mit rewrite, das du direkt in den server-Block schreiben kannst:

rewrite ^/blog/\d{4}/(.+)$ https://example.com/artikel/$1 permanent;

rewrite hängt den ursprünglichen Query-String automatisch an. Soll er wegfallen, beende die Ersetzung mit einem Fragezeichen: ... /artikel/$1? permanent;.

Denk daran, wie nginx die Location auswählt: zuerst exakte Treffer (=), dann der längste Präfix. Ist der nicht mit ^~ markiert, prüft nginx anschließend die Regex-Locations in der Reihenfolge, in der sie in der Datei stehen – der erste Treffer gewinnt. Eine Weiterleitung in einer Regex-Location kann also von einem früheren Regex wie einem allgemeinen location ~ \.php$ verdeckt werden.

HTTP auf HTTPS und www in einem Schritt

Am saubersten klappt das mit getrennten Server-Blöcken und ganz ohne if. Jede nicht-kanonische Variante landet mit genau einer Weiterleitung auf https://example.com:

# 1. Alle HTTP-Anfragen, mit und ohne www
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

# 2. HTTPS auf www
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name www.example.com;
    ssl_certificate     /etc/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/ssl/example.com/privkey.pem;
    return 301 https://example.com$request_uri;
}

# 3. Der kanonische Host
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name example.com;
    ssl_certificate     /etc/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/ssl/example.com/privkey.pem;
    root /var/www/example.com;
}

Zwei Details sind wichtig: Das Zertifikat muss auch www.example.com abdecken, sonst zeigt der Browser einen Zertifikatsfehler, bevor die Weiterleitung überhaupt greifen kann. Und die Direktive http2 on; gibt es erst seit nginx 1.25.1 – bei älteren Versionen schreibst du stattdessen listen 443 ssl http2;. Die SEO-Seite des Themas behandeln die Ratgeber HTTP auf HTTPS und www-Weiterleitung.

$request_uri oder $uri?

Die beiden Variablen sehen ähnlich aus, verhalten sich in Weiterleitungen aber unterschiedlich:

  • $request_uri ist die ursprüngliche Anfrage: Pfad plus Query-String, genau so, wie der Client sie geschickt hat, noch URL-kodiert. Ideal für „gleicher Pfad auf anderem Host“, weil nichts verloren geht oder verändert wird.
  • $uri ist der normalisierte, dekodierte Pfad ohne Query-String und kann sich während der Verarbeitung ändern (etwa nach einem internen Rewrite oder durch index). Nimm ihn zum Vergleichen, nicht als Weiterleitungsziel.

Schreib also nicht return 301 https://example.com$uri$is_args$args;, wenn $request_uri den Job erledigt. Dekodierte Zeichen in $uri können kaputte oder sogar unsichere Location-Header erzeugen.

Ganze Domain weiterleiten

server {
    listen 80;
    listen [::]:80;
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name alte-domain.de www.alte-domain.de;
    ssl_certificate     /etc/ssl/alte-domain.de/fullchain.pem;
    ssl_certificate_key /etc/ssl/alte-domain.de/privkey.pem;
    return 301 https://example.com$request_uri;
}

Halte das Zertifikat der alten Domain gültig, solange die Weiterleitung läuft. Sonst scheitern Links und Lesezeichen mit https://alte-domain.de, bevor sie die Weiterleitung überhaupt erreichen. Alles Weitere steht in der Checkliste zum Domain-Umzug.

Viele Weiterleitungen mit map

Hunderte location-Blöcke sind schwer zu pflegen und langsam auszuwerten. Eine map ist dagegen ein Hash-Lookup und skaliert gut. Sie gehört in den http-Kontext, also außerhalb jedes server-Blocks:

map $uri $redirect_target {
    default                "";
    /alte-seite            /neue-seite/;
    /preise.html           /preise/;
    /team/max-mustermann   /ueber-uns/;
    ~^/shop/(?<slug>.+)$   /store/$slug;
}

Im Server-Block nutzt du sie dann so:

server {
    # ...
    if ($redirect_target) {
        return 301 $redirect_target$is_args$args;
    }
}

return innerhalb von if gehört zu den wenigen Verwendungen von if, die immer unbedenklich sind. nginx prüft zuerst die exakten Einträge, danach die Regex-Einträge (mit ~) in ihrer Reihenfolge. Bei langen Listen lagerst du die Einträge in eine eigene Datei aus und schreibst include /etc/nginx/redirects.map; in den map-Block. Meldet nginx, dass es den Map-Hash nicht bauen kann, erhöhst du map_hash_max_size oder map_hash_bucket_size im http-Block.

Diese Einträge (und die anderen Snippets auf dieser Seite) erzeugst du aus einer URL-Liste mit dem nginx-Redirect-Generator.

Trailing Slash

Den Slash am Ende überall außer auf der Startseite entfernen:

rewrite ^/(.+)/$ /$1 permanent;

Mach das nur, wenn deine Anwendung die URLs ohne Slash auch wirklich ausliefert. nginx selbst hängt bei echten Verzeichnissen per 301 einen Slash an – ihn wieder zu entfernen, führt direkt in die Schleife.

Sicher testen und neu laden

Prüf die Syntax immer, bevor du neu lädst. Eine kaputte Konfiguration verhindert, dass nginx startet:

sudo nginx -t
sudo systemctl reload nginx

nginx -t liest alle eingebundenen Dateien und nennt dir Datei und Zeile jedes Fehlers. reload (oder nginx -s reload) übernimmt die neue Konfiguration, ohne offene Verbindungen zu kappen – anders als ein Restart.

Danach testest du das Ergebnis. Browser cachen 301-Weiterleitungen, ein Test im Browser nach einer Änderung führt daher oft in die Irre. Nimm curl -I http://www.example.com/alte-seite oder gib die URL in den Redirect-Checker ein – der zeigt dir jeden Hop mit Statuscode und Ziel. Prüf jede Variante (HTTP, www, mit Query-String) und achte darauf, dass es genau ein Hop ist. Siehst du zwei oder mehr, erfährst du im Artikel über Redirect-Ketten, wie du sie zusammenfasst.

Häufige Fragen

Was ist der Unterschied zwischen return 301 und rewrite permanent?

Beide senden einen 301. return antwortet sofort mit einer URL, die du festlegst, unterstützt jeden Statuscode und braucht keinen Regex. rewrite ... permanent baut das Ziel aus einem Regex-Treffer und behält den Query-String automatisch. Nimm return, solange du den Pfad nicht umbauen musst.

Wie sende ich mit nginx eine 308-Weiterleitung?

Mit return 308 https://example.com/neu/;. rewrite kennt nur 301 und 302. Ein 308 behält Methode und Body der Anfrage bei, was bei APIs und Formularen wichtig ist – mehr dazu unter 307 vs. 308.

Muss ich nginx nach Änderungen an Weiterleitungen neu starten?

Nein, ein Reload reicht: erst sudo nginx -t für die Syntaxprüfung, dann sudo systemctl reload nginx. Laufende Verbindungen bleiben dabei bestehen.

Kann nginx meine .htaccess-Weiterleitungen lesen?

Nein, nginx ignoriert .htaccess-Dateien komplett. Jede Regel muss als nginx-Konfiguration neu geschrieben werden. Der Ratgeber zur .htaccess-Weiterleitung hilft dir zu verstehen, was die alten Regeln tun, und der nginx-Generator erzeugt die neuen.

  • .htaccess-Weiterleitung auf Apache

    So leitest du einzelne Seiten und ganze Domains per .htaccess weiter: mod_alias oder mod_rewrite, fertige Regeln für die typischen Fälle und wie du Schleifen und Ketten vermeidest.

  • Weiterleitungen mit Cloudflare

    Cloudflare kann Weiterleitungen direkt am Edge beantworten, bevor eine Anfrage deinen Server erreicht. So funktionieren Single Redirects, Bulk Redirects und Always Use HTTPS – und so verhinderst du, dass sie sich mit deinem Server in die Quere kommen.

  • Weiterleitungen in WordPress

    In WordPress kannst du URLs auf mehreren Wegen weiterleiten: per Plugin, per Regel in der .htaccess oder mit ein paar Zeilen PHP. Hier erfährst du, welcher Weg wann passt und wie du die typischen Stolperfallen mit Caching und HTTPS umgehst.

  • Weiterleitungen in Next.js

    In Next.js kannst du an vier Stellen weiterleiten: in der Konfiguration, in der Middleware, im Servercode des App Routers und über die Option trailingSlash. Jede davon sendet standardmäßig andere Statuscodes – es lohnt sich also, die Unterschiede zu kennen.

  • Weiterleitungen bei Vercel und Netlify

    Bei Vercel und Netlify fasst du keine Webserver-Konfiguration an. Weiterleitungen stehen in einer Datei in deinem Repository oder im Dashboard, und das Edge-Netzwerk der Plattform liefert sie aus. So funktionieren beide – und hier unterscheiden sie sich.

  • Weiterleitungen mit Microsoft IIS

    IIS bietet dir zwei Wege für Weiterleitungen: die eingebaute HTTP-Umleitung und das URL-Rewrite-Modul. Hier erfährst du, wann du welches nimmst – mit web.config-Beispielen zum Kopieren.