NGINX einrichten und SSL mit Certbot

Als ich während der Weihnachtszeit einen VServer bei meinem Hoster mietete, wollte ich mehrere Webseiten auf diesem Server hosten und über NGINX bereitstellen. Dabei ist mir aufgefallen, wie sehr die einzelnen Informationen im Internet zerstreut sind. Nach vielen Stunden Recherche habe ich mich dazu entschieden, alle Schritte bis zur fertigen Konfiguration von NGINX zu sammeln und hier auf meinem Blog zu veröffentlichen. Zum Zeitpunkt der Veröffentlichung dieses Beitrages verwende ich Ubuntu Version 20.04, NGINX 1.18.0 und Certbot 1.10.1. Sollten einige Schritte nicht mehr funktionieren, schreib mir eine Mail und ich aktualisiere meinen Beitrag gerne.

Bevor ich jetzt aber mit NGINX beginne, möchte ich noch eine kleine Übersicht und Einführung in IP-Adressen und Ports geben:

Wie werden Webseiten aufgerufen?

Jeder Server hat eine IP-Adresse, zum Beispiel "216.58.223.5". Durch diese eindeutige Zahlenfolge kann sich jeder mit genau diesem Server verbinden. Hinter Internetadressen wie google.com oder astrogd.eu steckt eigentlich auch nur eine IP-Adresse.

Ein weiterer wichtiger Bestandteil einer Verbindung ist der sogenannte Port eines Servers. Einen Port kann man sich ein bisschen Vorstellen wie eine Abteilung einer Firma. Die Firma selber kann viele verschiedene Abteilungen haben, aber nur eine ist z.B. für IT zuständig. Analog funktioniert das bei Servern: Ein Server kann viele verschiedene Dienste über verschiedene Ports anbieten, aber Web-Services findet man immer über Port 80 oder 443.

Dabei ist Port 80 reserviert für ungesicherte Verbindungen und Port 443 für verschlüsselte. Mehr zu Verschlüsselung später.

Möchte man also eine Webseite aufrufen, wird die Internetadresse (google.com) in eine IP-Adresse umgewandelt (216.58.223.5) und anschließend wird Port 80 aufgerufen: 216.58.223.5:80


Nun gibt es allerdings ein Problem: Üblicherweise werden mehrere Webseiten von einem Server bedient, aber alle benötigen Port 80 um unterschiedliche Seiten anzuzeigen.

Und genau da kommt NGINX ins Spiel:

Was ist NGINX?

NGINX ist ein sogenannter Reverse-Proxy. Das bedeutet, dass NGINX auf die Anfragen eines bestimmten Ports hört und sie an die richtigen Stellen auf einem Server weiterleitet. So können zum Beispiel mehrere Internetadressen auf einen Server zeigen und trotzdem werden verschiedene Ergebnisse angezeigt.

Um alles einzustellen, werden Konfigurationsdateien verwendet. In diesen kann jede Weiterleitung genau auf die Anforderungen der Webseite eingestellt werden.


Installation und Überblick

Mit NGINX starten geht ganz schnell. Auf meinem Server (Ubuntu) reicht ein einfaches sudo apt install nginx und schon ist NGINX installiert und einsatzbereit. Die Konfiguation gestaltet sich allerdings für Beginner deutlich schwieriger.

Zuerst ein paar nützliche Informationen:

NGINX wird üblicherweise in /etc/nginx/ installiert.
Dort gibt es auch eine Haupt-Konfigurationsdatei: /etc/nginx/nginx.conf
Um einzelne Webseiten zu konfigurieren, sollte aber ein neuer Ordner /etc/nginx/conf.d/ erstellt werden. Dieser wird bereits von NGINX unterstützt und enthält für jede Webseite eine eigene Datei mit der Endung ".conf".

Tipp:

Wenn die Konfigurationsdateien nach den entsprechenden Webseiten benannt werden, ist es einfacher eine bestimmte Konfiguration später zu finden. Meine Konfigurationsdatei für diese Webseite heißt zum Beispiel "blog.astrogd.eu.conf"

Änderungen testen und anwenden

Bevor Änderungen an einer Konfiguration angewendet werden, sollten sie von NGINX geprüft werden. Dabei verwendet man den folgenden Befehl:

nginx -t -c PFAD-ZUR-KONFIGURATION

Der Vorteil bei diesem Befehl ist, dass genaue Fehlerbeschreibungen bereitgestellt werden und währenddessen der Zugriff auf alle Webseiten die über NGINX laufen nicht gestört wird.

Ist eine Änderung der Konfiguration ohne Fehler getestet, muss sie nur noch angewendet werden. Dazu verwendet man den folgenden Befehl:

sudo service nginx reload

Fallback-Webseite

Bevor ich zeige wie eine Webseite hinzugefügt wird, möchte ich hier über Fallback-Seiten schreiben.

Auch Webseiten können Fehler haben und plötzlich nicht mehr erreichbar sein - das habe ich schon einige Male festgestellt. Doch wenn eine Webseite nicht mehr funktioniert wird eine nicht sehr schöne Fehlermeldung von NGINX angezeigt.

Um eine eigene Seite mit Kontaktmöglichkeiten und schönerem Aussehen anzuzeigen, habe ich meine NGINX Konfigurationen angepasst. Aber damit diese Änderungen funktionieren, muss eine Fallback-Webseite erstellt werden.

Ich habe meine Fallback-Webseite unter /var/www/servererror/ aber das ist natürlich egal und muss nur entsprechend in der Konfiguration angepasst werden.

In meinem "servererror"-Ordner habe ich eine index.html-Datei und entsprechend eine style.css-Datei.

Wer auf Fehler besonders schnell reagieren möchte oder diese an einem zentralen Ort sammelt, kann natürlich auch entsprechende Skripte in die Webseite einbinden, um automatisch den Fehler zu melden.

Eine Webseite konfigurieren

Jetzt geht's endlich ans Eingemachte: Wie konfiguriere ich eine neue Webseite mit NGINX?

Für alle die nur schnell eine Webseite hinzufügen wollen, habe ich hier die Fertige Konfiguration. Einfach Daten anpassen und es kann losgehen. Ich möchte aber dennoch die Einstellungen für alle Interessierten erklären.

# Server, an welchen die Anfrage weitergeleitet werden soll
upstream server {
    server IP-ADRESSE:PORT;
    keepalive 8;
}

# Konfiguration für NGINX
server {
    server_name INTERNET-ADRESSE;
    access_log PFAD-ZUR-LOG-DATEI;
    listen 80; # Diese Webseite wird auf Port 80 erreicht

    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-NginX-Proxy true;
      proxy_set_header X-Forwarded-Proto $scheme;

      proxy_intercept_errors on;

      proxy_pass http://server/;
      proxy_redirect off;

      error_page 500 502 503 504 = @fallback;
    }

    # Fallback Server, falls die Verbindung nicht weitergeleitet werden kann
    location @fallback {
        root PFAD-ZUM-ORDNER-DER-FEHLERWEBSEITE;

        if (!-f $request_filename) {
            rewrite ^ /index.html break;
        }
    }

}

Beginnen wir mit dem Anfang der Konfiguration:

# Server, an welchen die Anfrage weitergeleitet werden soll
upstream server {
    server IP-ADRESSE:PORT;
    keepalive 8;
}

Ein Upstream ist eine Beschreibung eines Servers. Wenn die Webseite auf dem gleichen Server wie NGINX läuft, ist die IP-Adresse 127.0.0.1.

Wichtig!: Der Port darf nicht 80 oder 443 sein, wenn NGINX auf dem gleichen Server läuft. Diese Ports werden von NGINX genutzt. NGINX leitet die Verbindung im Anschluss weiter an z.B. Port 5000

Wir können den Upstream später in der Konfiguration angeben, um die Verbindung weiterzuleiten.


Der nächste große Block der Konfiguration enthält die eigentlichen Einstellungen:

server_name INTERNET-ADRESSE; ist eine Anweisung für NGINX, auf Aufrufe von der entsprechenden Adresse zu achten. server_name www.astrogd.eu; achtet also auf alle Aufrufe zu www.astrogd.eu.

access_log PFAD-ZUR-LOG-DATEI; gibt eine Datei an, in welche Zugriffe auf die entsprechende Webseite protokolliert werden. access_log /var/log/nginx/seite.log; speichert also alle Logs in der Datei seite.log im Ordner /var/log/nginx/.

listen 80; ist eine Angabe, auf welchem Port Anfragen ankommen werden. NGINX hört also in diesem Fall auf alle Anfragen von Port 80.

Nun kommen wir zum location Block. Hier werden alle Optionen für die Weiterleitung auf den Upstream gesetzt.

proxy_set_header setzt einen sogenannten Header. In diesem sind informationen für den Upstream Server gespeichert wie zum Beispiel ob die Verbindung verschlüsselt war oder nicht und die IP-Adresse der Anfrage.

proxy_intercept_errors on; Hier sagen wir NGINX, dass Fehler über NGINX verarbeitet werden sollen.

proxy_pass http://server/; Hier wird die eigentliche Anfrage an den Upstream Server gesendet

error_page 500 502 503 504 = @fallback; Dies ist die Konfiguration für den Fallback Server. Die angegebenen Fehlercodes leiten nun an den Fallback server weiter und zeigen die konfigurierte Seite an, sollte es einen Fehler geben.

Zuletzt findet sich in der Konfiguration die Referenz zur Fallback-Seite mit location @fallback

root PFAD-ZUM-ORDNER-DER-FEHLERWEBSEITE; Dies ist die Angabe, in welchem Ordner sich die Dateien der Webseite befinden. Meine Fehlerseite befindet sich z.B. in /var/epage/ also steht in der Konfiguration root /var/epage/;

if (!-f $request_filename) {
    rewrite ^ /index.html break;
}

Dieser Code zeigt, wenn die aufgerufene Datei niocht gefunden wurde, immer wieder die index.html Seite an. So wird diese Seite auch angezeigt, wenn der Fehler beim Aufrufen von www.astrogd.eu/xyz passiert und nicht nur bei www.astrogd.eu/

SSL Verschlüsselung mit Certbot und Let's Encrypt

Gerade heute ist Verschlüsselung wichtiger denn je. Ohne Verschlüsselung können sensible Daten wie Passwörter, Kundendaten, Mail-Adressen und vieles mehr auf ihrem Weg zur oder von der Webseite abgefangen und manipuliert werden. Für bestimmte Daten ist eine Absicherung mittels SSL-Zertifikat in der EU sogar vorgeschrieben. Seit einigen Jahren bietet Let's Encrypt neben den kostenpflichtigen Anbietern eine kostenlose Möglichkeit, SSL Zertifikate auszustellen und für die eigenen Seiten zu verwenden. In diesem Absatz zeige ich, wie Zertifikate mit Hilfe von Certbot erstellt und eingerichtet werden.

Um Certbot zu installieren, werden folgende Befehle verwendet:

sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Die größte Arbeit ist nun schon erledigt. Um Zertifikate für bereits in der NGINX Konfiguration eingerichtete Webseiten zu erhalten und einzurichten, wird dieser Befehl verwendet:

sudo certbot --nginx

Nach Auswahl der Webseite(n) und Angabe einer Benachrichtigungs-E-Mail wird das Zertifikat eingerichtet und schon ist alles fertig.

Zum Schluss muss NGINX die neue Konfiguration laden: sudo service nginx reload und die ausgewählten Webseiten sind nun abgesichert.