nginx: Mehrere URL-Varianten auf eine weiterleiten

Photon

Rear Admiral Pro
🎅Rätsel-Elite ’24
Registriert
Apr. 2006
Beiträge
5.333
Hallo Community,

ich hänge an folgendem Problem: Ich nutze nginx und habe für eine Webseite zwei Subdomains, eine neue und eine alte. Für den Moment sollten beide funktionieren, ich würde aber gerne erreichen, dass die alte URL auf die neue weitergeleitet wird. Zudem sollen http-Zugriffe auf https umgeleitet werden. Also Anfragen der Form

http://alte-subdomain
http://neue-subdomain
https://alte-subdomain

sollen auf

https://neue-subdomain

weitergeleitet werden. Bisher schaffe ich es http-Abfragen umzuleiten mittels

if ($scheme = http) {
return 301 https://neue-subdomain$request_uri;
}

wie in https://serverfault.com/a/474345 beschrieben. Nur https://alte-subdomain macht also noch Probleme.

Also dachte ich, entfernst du einfach die if-Abfrage, sodass einfach stumpf immer weitergeleitet wird. Doch dann bekomme ich leider einen Verbindungsfehler, nämlich ERR_TOO_MANY_REDIRECTS. Offenbar leitet er nach dem ersten Weiterleiten nach https://neue-subdomain fröhlich weiter immer wieder auf sich selbst weiter.

Ich würde also gerne irgendwie abfragen, ob der Anfang der URL "https://neue-subdomain" ist, und falls nicht, weiterleiten. Doch wie setze ich das konkret um? Tu mich mit der Syntax noch ein wenig schwer...

Vielen Dank im Voraus,
Photon
 
Ganz wichtig: if is evil!
In vielen Fällen arbeitet das nicht so, wie man es erwarten würde, also lass die Finger davon ;)

Für die Umleitung von http auf https baust du dir einfach einen Serverblock:
NGINX:
server {
    listen 80 default_server;
    listen listen [::]:80 default_server;
    server_name _;

    return 301 "https://${host}${request_uri}";
}

Der reagiert schlicht auf Domainnamen, für die es nicht explizit einen eigenen Serverblock gibt. Der "_" ist schlicht kein gültiger Domainname und kollidiert damit nie versehentlich mit einer anderen Config. Hier kannst du auch direkt die neue Domain, anstatt ${host} eintragen, dann ersparst du dir ggf. zwei Redirects.

Für die alte Domain baust du einen eigenen Serverblock für SSL/TLS und baust da auch einfach dieselbe return Anweisung ein, ersetzt aber ${host} durch die neue Domain.

Ein dritter Serverblock lauscht dann für SSL/TLS auf die neue Domain.

----
NGINX:
#redirect http -> https
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;

    return 301 "https://neue.subdomain.tld${request_uri}";
}

#redirect https alte.subdomain.tld -> neue.subdomain.tld
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name alte.subdomain.tld;

    ...sonstiger TLS Kram...

    return 301 "https://neue.subdomain.tld${request_uri}";
}

#config für https neue.subdomain.tld
server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    server_name neue.subdomain.tld;

    ...sonstiger TLS Kram...

    ...sonstige Config...
}

... ist bestimmt noch was krum, aber das Prinzip sollte klar werden ;)
 
Zuletzt bearbeitet: (Typo beim Port für IPv6 und https)
  • Gefällt mir
Reaktionen: Photon und Poati
Falls es aus dem Beitrag über mir nicht gänzlich klar geworden ist. Du kannst es am einfachsten über mehrere aktive Configs machen, die sich im Server-Block, dem server_name unterscheiden, sprich die selbe Umleitung vornehmen.

Im Grunde sollte es auch klar werden, wenn du schaust, wie man mehrere Domains auf einem Nginx serviert.
 
  • Gefällt mir
Reaktionen: Photon
Vielen Dank für den Tipp! Ich muss beichten, ich kenne mich mit der nginx-Konfiguration gar nicht gut aus und habe die initiale Konfiguration vor Urzeiten mittels Copy&Paste aus HowTos gemacht. Hat auch gut geklappt, weil sie sehr einfach war. Aber jetzt gibt es auf einmal zwei Domains und SSL und mein nicht vorhandenes Wissen macht sich bemerkbar. Wäre also über Links für Absolut-Anfänger sehr dankbar, die zumindest ein bisschen in die richtige Richtung gehen, also vielleicht nicht ganz so allgemein sind, wie die nginx-Doku. :)

edit: Oh, jetzt seh ich den Edit von KillerCow, Riesendank! Ich les mich mal ein! :)
 
Zuletzt bearbeitet:
nginx ist leider nicht immer ganz durchsichtig. Was lange funktioniert hat, macht auf einmal Probleme, obwohl man eigenlich garnichts geändert hat und dann geht das Dokulesen und Suchmachinewälzen los. Richtig geil ist es, wenn man eine (von Anfang an verhunzte) Config von jemandem übernimmt, der selbst keine Ahnung hatte (und hat) und viele Dinge eher zufällig das bewirken, was erreicht werden sollte.

Also sei froh, wenn du die Config selber von Grundauf aufbaust ;)

Hier noch eine Anregung als Grundlage für eine sichere TLS Konfiguration: https://ssl-config.mozilla.org/
 
  • Gefällt mir
Reaktionen: Photon
Das Ding ist, da sind jetzt auch einige Zeilen für die SSL-Konfiguration drin, die von certbot (Let's Encrypt) generiert wurden, die fasse ich wahrscheinlich besser nicht an und versuche sie unverändert einzupflanzen. Die Konfig sieht (bitte nicht schlagen) genau genommen so aus:

NGINX:
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##

# Default server configuration
#
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # SSL configuration
    #
    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;
    #
    # Note: You should disable gzip for SSL traffic.
    # See: https://bugs.debian.org/773332
    #
    # Read up on ssl_ciphers to ensure a secure configuration.
    # See: https://bugs.debian.org/765782
    #
    # Self signed certs generated by the ssl-cert package
    # Don't use them in a production server!
    #
    # include snippets/snakeoil.conf;

    root /var/www/html;

    # Add index.php to the list if you are using PHP
    index index.html index.php index.htm index.nginx-debian.html;

    server_name photon.serverpit.com tpiq.lmu.serverpit.com;
        auth_basic "Restricted"; # Ausgabe-Meldung bei Zugriff
        auth_basic_user_file /etc/nginx/.htpasswd; # Pfad zur .htpasswd-Datei

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }

    # pass PHP scripts to FastCGI server

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;

        # With php-fpm (or other unix sockets):
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        # With php-cgi (or other tcp sockets):
    #    fastcgi_pass 127.0.0.1:9000;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one

    location ~ /\.ht {
        deny all;
    }

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/tpiq.lmu.serverpit.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/tpiq.lmu.serverpit.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    if ($scheme = http) {
        return 301 https://tpiq.lmu.serverpit.com$request_uri;
    }
}


# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
#    listen 80;
#    listen [::]:80;
#
#    server_name example.com;
#
#    root /var/www/example.com;
#    index index.html;
#
#    location / {
#        try_files $uri $uri/ =404;
#    }
#}

Aber jetzt schau ich in deinen Vorschlag rein und versuche die zwei einigermaßen sinnvoll zu verheiraten. Melde mich dann nochmal mit dem Resultat!

Nachtrag:

So, nach ein wenig Copy&Paste sieht es so aus:

NGINX:
#redirect http -> https
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;

    return 301 "https://tpiq.lmu.serverpit.com${request_uri}";
}

#redirect https photon.serverpit.com -> tpiq.lmu.serverpit.com
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name photon.serverpit.com;

   #  ...sonstiger TLS Kram... <<<<< Nicht ganz sicher, ob hier noch was rein soll?

    return 301 "https://tpiq.lmu.serverpit.com${request_uri}";
}

#config für https tpiq.lmu.serverpit.com
server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    server_name tpiq.lmu.serverpit.com;

    root /var/www/html;
 
    # Add index.php to the list if you are using PHP
    index index.html index.php index.htm index.nginx-debian.html;

    server_name photon.serverpit.com tpiq.lmu.serverpit.com;
        auth_basic "Restricted"; # Ausgabe-Meldung bei Zugriff
        auth_basic_user_file /etc/nginx/.htpasswd; # Pfad zur .htpasswd-Datei
   
    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }

    # pass PHP scripts to FastCGI server
 
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
 
        # With php-fpm (or other unix sockets):
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        # With php-cgi (or other tcp sockets):
    #    fastcgi_pass 127.0.0.1:9000;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
 
    location ~ /\.ht {
        deny all;
    }

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/tpiq.lmu.serverpit.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/tpiq.lmu.serverpit.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

@KillerCow: Macht das einigermaßen Sinn? :)
 
Zuletzt bearbeitet:
Hmm, leider startet nginx mit dieser Konfiguration nicht und sagt

Code:
nginx: [emerg] a duplicate listen [::]:443 in /etc/nginx/sites-enabled/default:60

Nachtrag:

Ok, ich bin doof und es war spät am Abend. Die listen-Anweisung war tatsächlich doppelt, in Zeilen 23, 24 und 60, 61.

Aber wenn ich die aus Zeilen 23, 24 entferne, dann meldet mir der Browser, dass die Verbindung mit dem Server fehlschlug.

Nachtrag 2: Die server_name Zeile im letzten Server-Block war auch doppelt... Jetzt läuft wieder alles gut! Danke für die Hilfe! :)
 
Zuletzt bearbeitet:
Oh sorry, hab deine Antworten total übersehen @Photon
Gibt es noch Probleme oder offene Fragen? Kannst mich notfalls auch per PM anschreiben.
 
  • Gefällt mir
Reaktionen: Photon
Zurück
Oben