One place for hosting & domains

      sichern

      Skalieren und Sichern einer Django-Anwendung mit Docker, Nginx und Let’s Encrypt


      Einführung

      In cloudbasierten Umgebungen gibt es mehrere Möglichkeiten, eine Django-Anwendung zu skalieren und zu sichern. Durch horizontale Skalierung und die Ausführung mehrerer Kopien Ihrer Anwendung können Sie ein fehlertolerantes und hochverfügbares System aufbauen und gleichzeitig den Durchsatz erhöhen, sodass Anfragen gleichzeitig verarbeitet werden können. Eine Möglichkeit zur horizontalen Skalierung einer Django-Anwendung besteht darin, zusätzliche App-Server bereitzustellen, die Ihre Django-Anwendung und Ihren WSGI-HTTP-Server (wie Gunicorn oder uWSGI) ausführen. Um eingehende Anfragen über diesen Satz von App-Servern zu leiten und zu verteilen, können Sie einen Load Balancer und Reverse Proxy wie Nginx verwenden. Nginx kann auch statische Inhalte zwischenspeichern und Transport Layer Security-Verbindungen (TLS-Verbindungen) beenden, die zur Bereitstellung von HTTPS- und sicheren Verbindungen zu Ihrer Anwendung verwendet werden.

      Die Ausführung Ihrer Django-Anwendung und des Nginx-Proxys innerhalb von Docker-Containern stellt sicher, dass sich diese Komponenten unabhängig von der Umgebung, in der sie bereitgestellt werden, gleich verhalten. Darüber hinaus bieten Container viele Funktionen, die das Paketieren und Konfigurieren Ihrer Anwendung erleichtern.

      In diesem Tutorial skalieren Sie eine containerisierte Django- und Gunicorn-Umfrageanwendung horizontal, indem Sie zwei App-Server bereitstellen, die jeweils eine Kopie eines Django- und Gunicorn-Anwendungscontainers ausführen.

      Des Weiteren aktivieren Sie HTTPS, indem Sie einen dritten Proxy-Server bereitstellen und konfigurieren, auf dem ein Nginx Reverse-Proxy-Container und ein Certbot-Client-Container ausgeführt werden. Certbot stellt TLS-Zertifikate für Nginx von der Let’s Encrypt Zertifizierungsstelle bereit. Dadurch wird sichergestellt, dass Ihre Website von SSL Labs eine hohe Sicherheitsbewertung erhält. Dieser Proxy-Server empfängt alle externen Anfragen Ihrer Anwendung und sitzt vor den beiden upstream Django-App-Servern. Schließlich härten Sie dieses verteilte System ab, indem Sie den externen Zugriff auf nur den Proxy-Server beschränken.

      Voraussetzungen

      Um dieser Anleitung zu folgen, benötigen Sie:

      • Drei Ubuntu 18.04-Server:

        • Zwei Server werden App-Server sein, die zum Ausführen Ihrer Django- und Gunicorn-Anwendung verwendet werden.
        • Ein Server wird ein Proxy-Server sein, auf dem Nginx und Certbot ausgeführt werden.
        • Alle Server sollten einen Nicht-Root-Benutzer mit sudo-Berechtigungen und eine aktive Firewall haben. Eine Anleitung für das Setup finden Sie im Leitfaden für die Ersteinrichtung des Servers.
      • Auf allen drei Servern installiertes Docker. Eine Anleitung zur Installation von Docker finden Sie in den Schritten 1 und 2 von Installieren und Verwenden von Docker unter Ubuntu 18.04.

      • Einen registrierten Domänennamen. In diesem Tutorial wird durchgängig your_domain.com verwendet. Einen Domänennamen können Sie kostenlos bei Freenom erhalten oder Sie nutzen eine Domänenregistrierungsstelle Ihrer Wahl.

      • Einen DNS-A-Eintrag mit your-domain.com, der auf die öffentliche IP-Adresse Ihres Proxy-Servers verweist. Falls Sie ein DigitalOcean-Konto nutzen, können Sie in dieser Einführung in DigitalOcean-DNS im Einzelnen nachlesen, wie Sie ihn hinzufügen.

      • Einen S3-Objektspeicher-Bucket wie beispielsweise einen DigitalOcean Space zur Speicherung der statischen Dateien Ihres Django-Projekts und einen Satz von Zugriffsschlüsseln für diesen Space. Um zu erfahren, wie Sie einen Space erstellen können, lesen Sie die Produktdokumentation Erstellen von Spaces. Um zu erfahren, wie Sie Zugriffsschlüssel für Spaces erstellen können, lesen Sie Zugriff auf Spaces mit Zugriffsschlüsseln gemeinsam nutzen. Mit geringfügigen Änderungen können Sie jeden Objektspeicherdienst verwenden, der das Plugin django-storages verwendet.

      • Eine PostgreSQL-Server-Instanz, Datenbank und Benutzer für Ihre Django-Anwendung. Mit geringfügigen Änderungen können Sie jede Datenbank verwenden, die Django unterstützt.

      Schritt 1 – Konfigurieren des ersten Django-App-Servers

      Wir klonen zunächst das Django-Anwendungs-Repository auf den ersten App-Server. Dann konfigurieren und erstellen wir das Docker-Image und testen die Anwendung durch Ausführung des Django-Containers.

      Anmerkung: Wenn Sie von Erstellen einer Django- und Gunicorn-Anwendung mit Docker fortfahren, haben Sie Schritt 1 bereits abgeschlossen und können mit Schritt 2 fortfahren, um den zweiten App-Server zu konfigurieren.

      Beginnen Sie mit der Anmeldung beim ersten der beiden Django-App-Server und verwenden Sie git, um den Zweig polls-docker der Django Tutorial Umfrageanwendung GitHub-Repository zu klonen. Dieses Repository enthält Code für die Umfrage-Beispielanwendung der Django-Dokumentation. Der Zweig polls-docker enthält eine dockerisierte Version der Umfrageanwendung. Um zu erfahren, wie die Umfrageanwendung modifiziert wurde, um effektiv in einer containerisierten Umgebung zu arbeiten, lesen Sie bitte Erstellen einer Django- und Gunicorn-Anwendung mit Docker.

      • git clone --single-branch --branch polls-docker https://github.com/do-community/django-polls.git

      Navigieren Sie in das Verzeichnis django-polls:

      cd django-polls
      

      Dieses Verzeichnis enthält den Python-Code der Django-Anwendung, ein Dockerfile, das Docker zum Erstellen des Container-Images verwendet, sowie eine Datei env, die eine Liste von Umgebungsvariablen enthält, die an die laufende Umgebung des Containers übergeben werden müssen. Prüfen Sie das Dockerfile mit cat:

      cat Dockerfile
      

      Output

      FROM python:3.7.4-alpine3.10 ADD django-polls/requirements.txt /app/requirements.txt RUN set -ex && apk add --no-cache --virtual .build-deps postgresql-dev build-base && python -m venv /env && /env/bin/pip install --upgrade pip && /env/bin/pip install --no-cache-dir -r /app/requirements.txt && runDeps="$(scanelf --needed --nobanner --recursive /env | awk '{ gsub(/,/, "nso:", $2); print "so:" $2 }' | sort -u | xargs -r apk info --installed | sort -u)" && apk add --virtual rundeps $runDeps && apk del .build-deps ADD django-polls /app WORKDIR /app ENV VIRTUAL_ENV /env ENV PATH /env/bin:$PATH EXPOSE 8000 CMD ["gunicorn", "--bind", ":8000", "--workers", "3", "mysite.wsgi"]

      Dieses Dockerfile verwendet das offizielle Python 3.7.4 Docker-Image als Basis und installiert die Python-Paketanforderungen von Django und Gunicorn, wie sie in der Datei django-polls/requirements.txt definiert sind. Anschließend entfernt es einige unnötige Builddateien, kopiert den Anwendungscode in das Image und legt den Ausführungspfad PATH fest. Schließlich gibt es an, dass Port 8000 verwendet wird, um eingehende Container-Verbindungen zu akzeptieren und gunicorn mit 3 Workern ausgeführt wird, die Port 8000 abhören.

      Um mehr über die einzelnen Schritte in diesem Dockerfile zu erfahren, lesen Sie bitte Schritt 6 von Erstellen einer Django- und Gunicorn-Anwendung mit Docker.

      Erstellen Sie nun das Image mit docker build:

      Wir benennen das Image polls mit dem Flag -t und übergeben im aktuellen Verzeichnis als Build-Kontext den Satz von Daten, auf den beim Erstellen des Images verwiesen werden soll.

      Nachdem Docker das Image erstellt und mit Tags versehen hat, listen wir die verfügbaren Images mit docker images auf:

      docker images
      

      Sie sollten die polls-Images aufgelistet sehen:

      Output

      REPOSITORY TAG IMAGE ID CREATED SIZE polls latest 80ec4f33aae1 2 weeks ago 197MB python 3.7.4-alpine3.10 f309434dea3a 8 months ago 98.7MB

      Bevor wir den Django-Container ausführen, müssen wir seine Betriebsumgebung mithilfe der im aktuellen Verzeichnis vorhandenen Datei env konfigurieren. Diese Datei wird an den Befehl docker run übergeben, der zum Ausführen des Containers verwendet wird, und Docker injiziert die konfigurierten Umgebungsvariablen in die Betriebsumgebung des Containers.

      Öffnen Sie die Datei env mit nano oder Ihrem bevorzugten Editor:

      nano env
      

      Wir werden die Datei wie nachfolgend beschrieben konfigurieren und Sie müssen einige zusätzliche Werte hinzufügen.

      django-polls/env

      DJANGO_SECRET_KEY=
      DEBUG=True
      DJANGO_ALLOWED_HOSTS=
      DATABASE_ENGINE=postgresql_psycopg2
      DATABASE_NAME=polls
      DATABASE_USERNAME=
      DATABASE_PASSWORD=
      DATABASE_HOST=
      DATABASE_PORT=
      STATIC_ACCESS_KEY_ID=
      STATIC_SECRET_KEY=
      STATIC_BUCKET_NAME=
      STATIC_ENDPOINT_URL=
      DJANGO_LOGLEVEL=info
      

      Geben Sie die fehlenden Werte für die folgenden Schlüssel ein:

      • DJANGO_SECRET_KEY: Setzen Sie diesen auf einen eindeutigen, nicht vorhersagbaren Wert, wie in den Django-Dokumentationen beschrieben. Eine Methode zur Generierung dieses Wertes wird in Anpassen der Anwendungseinstellungen in dem Tutorial Skalierbare Django-Anwendung angeboten.
      • DJANGO_ALLOWED_HOSTS: Diese Variable sichert die Anwendung und verhindert HTTP-Host-Header-Angriffe. Setzen Sie diese Variable für Testzwecke auf *, einen Platzhalter, der auf alle Hosts zutrifft. In der Produktion sollten Sie diese Variable auf your_domain.com setzen. Um mehr über diese Django-Einstellungen zu erfahren, konsultieren Sie die Core-Einstellungen der Django-Dokumentation.
      • DATABASE_USERNAME: Setzen Sie diesen auf den in den vorbereitenden Schritten erstellten PostgreSQL Datenbankbenutzer.
      • DATABASE_NAME: Setzen Sie diesen auf polls oder den in den vorbereitenden Schritten erstellten Namen der PostgreSQL-Datenbank.
      • DATABASE_PASSWORD: Setzen Sie dieses auf das in den vorbereitenden Schritten erstellte Passwort für den PostgreSQL Benutzer.
      • DATABASE_HOST: Setzen Sie diesen Wert auf den Hostnamen Ihrer Datenbank.
      • DATABASE_PORT: Setzen Sie diesen Wert auf den Port Ihrer Datenbank.
      • STATIC_ACCESS_KEY_ID: Setzen Sie diesen Wert auf den Zugriffsschlüssel Ihres S3-Buckets oder Space.
      • STATIC_SECRET_KEY: Setzen Sie diesen Wert auf das Zugriffsschlüsselgeheimnis Ihres S3-Bucket oder Space
      • STATIC_BUCKET_NAME: Setzen Sie diesen auf Ihren S3-Bucket- oder Space-Namen.
      • STATIC_ENDPOINT_URL: Setzen Sie diese auf die entsprechenden S3-Bucket- oder Space-Endpunkt-URL, z.B. https://space-name.nyc3.digitaloceanspaces.com, wenn sich Ihr Space in der Region nyc3 befindet.

      Wenn Sie die Bearbeitung abgeschlossen haben, speichern und schließen Sie die Datei.

      Wir verwenden nun docker run, um den CMD-Satz in dem Dockerfile zu überschreiben und das Datenbankschema mit den Befehlen manage.py makemigrations und manage.py migrate zu erstellen:

      docker run --env-file env polls sh -c "python manage.py makemigrations && python manage.py migrate"
      

      Wir führen das Container-Image polls:latest aus, übergeben die von uns gerade modifizierte Umgebungsvariablendatei und überschreiben den Dockerfile-Befehl mit sh -c "python manage.py makemigrations && python manage.py migrate", wodurch das durch den Anwendungscode definierte Datenbankschema erstellt wird. Wenn Sie dies zum ersten Mal ausführen, sollten Sie Folgendes sehen:

      Output

      No changes detected Operations to perform: Apply all migrations: admin, auth, contenttypes, polls, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying polls.0001_initial... OK Applying sessions.0001_initial... OK

      Dies zeigt an, dass das Datenbankschema erfolgreich erstellt wurde.

      Wenn Sie die Migration zu einem späteren Zeitpunkt ausführen, führt Django eine Nulloperation durch, es sei denn, das Datenbankschema wurde geändert.

      Als Nächstes führen wir eine weitere Instanz des Anwendungscontainers aus und verwenden darin eine interaktive Shell, um einen Administratorbenutzer für das Django-Projekt zu erstellen.

      docker run -i -t --env-file env polls sh
      

      Dadurch erhalten Sie eine Shell-Eingabeaufforderung innerhalb des laufenden Containers, die Sie zum Erstellen des Django-Benutzers verwenden können:

      python manage.py createsuperuser
      

      Geben Sie einen Benutzernamen, eine E-Mail-Adresse und ein Passwort für Ihren Benutzer ein. Drücken Sie nach dem Erstellen des Benutzers STRG+D, um den Container zu verlassen und zu beenden.

      Schließlich generieren wir die statischen Dateien für die Anwendung und laden sie mit collectstatic in den DigitalOcean Space hoch. Beachten Sie, dass dies möglicherweise einige Zeit dauern kann.

      docker run --env-file env polls sh -c "python manage.py collectstatic --noinput"
      

      Nachdem diese Dateien generiert und hochgeladen sind, erhalten Sie folgende Ausgabe.

      Output

      121 static files copied.

      Wir können die Anwendung nun ausführen:

      docker run --env-file env -p 80:8000 polls
      

      Output

      [2019-10-17 21:23:36 +0000] [1] [INFO] Starting gunicorn 19.9.0 [2019-10-17 21:23:36 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1) [2019-10-17 21:23:36 +0000] [1] [INFO] Using worker: sync [2019-10-17 21:23:36 +0000] [7] [INFO] Booting worker with pid: 7 [2019-10-17 21:23:36 +0000] [8] [INFO] Booting worker with pid: 8 [2019-10-17 21:23:36 +0000] [9] [INFO] Booting worker with pid: 9

      Hier führen wir den in dem Dockerfile definierten Standardbefehl gunicorn ---bind :8000 --workers 3 mysite.wsgi:application aus und stellen den Container-Port 8000 frei, sodass Port 80 auf dem Ubuntu-Server dem Port 8000 des Containers poll zugeordnet wird.

      Sie sollten nun über Ihren Webbrowser zu der Anwendung polls navigieren können, indem Sie http://APP_SERVER_1_IP in der URL-Leiste eingeben. Da für den Pfad / keine Route definiert ist, erhalten Sie wahrscheinlich einen 404 Page Not Found-Fehler, der zu erwarten ist.

      Warnung: Wenn Sie die UFW-Firewall mit Docker verwenden, umgeht Docker alle konfigurierten UFW-Firewallregeln, wie in diesem GitHub-Problem dokumentiert. Dies erklärt, warum Sie Zugriff auf Port 80 Ihres Servers haben, obwohl Sie in keinem vorbereitenden Schritt explizit eine UFW-Zugriffsregel erstellt haben. In Schritt 5 werden wir diese Sicherheitslücke schließen, indem wir die UFW-Konfiguration patchen. Wenn Sie UFW nicht verwenden und die Cloud Firewalls von DigitalOcean einsetzen, können Sie diese Warnung getrost ignorieren.

      Navigieren Sie zu http://APP_SERVER_1_IP/polls, um die Benutzeroberfläche der Umfrageanwendung zu sehen:

      Oberfläche der Umfrageanwendung

      Um die administrative Oberfläche anzuzeigen, besuchen Sie http://APP_SERVER_1_IP/admin. Sie sollten das Authentifizierungsfenster für den Administrator der Umfrageanwendung sehen:

      Authentifizierungsseite für Polls-Administrator

      Geben Sie den administrativen Benutzernamen und das Passwort ein, das Sie mit dem Befehl createsuperuser erstellt haben.

      Nach der Authentifizierung können Sie auf die administrative Oberfläche der Umfrageanwendung zugreifen:

      Administrative Hauptoberfläche von Polls

      Beachten Sie, dass statische Assets für die Anwendungen admin und polls direkt aus dem Objektspeicher bereitgestellt werden. Um dies zu bestätigen, konsultieren Sie Prüfen der statischen Dateizustellung von Spaces.

      Wenn Sie die Erkundung abgeschlossen haben, drücken Sie Strg+C im Terminalfenster, in dem der Docker-Container ausgeführt wird, um den Container zu beenden.

      Nachdem Sie nun bestätigt haben, dass der App-Container wie erwartet ausgeführt wird, können Sie ihn im getrennten (detached) Modus ausführen, wodurch er im Hintergrund ausgeführt wird und Ihnen ermöglicht, sich von Ihrer SSH-Sitzung abzumelden:

      docker run -d --rm --name polls --env-file env -p 80:8000 polls
      

      Das Flag -d weist Docker an, den Container im getrennten Modus auszuführen, das Flag -rm säubert das Dateisystem des Containers nach dem Verlassen des Containers und wir benennen den Container polls.

      Melden Sie sich von dem ersten Django App-Server ab und navigieren Sie zu http://APP_SERVER_1_IP/polls, um zu bestätigen, dass der Container wie erwartet ausgeführt wird.

      Nachdem Ihr erster Django-App-Server ausgeführt wird, können Sie nun Ihren zweiten Django-App-Server einrichten.

      Schritt 2 – Konfigurieren des zweiten Django-App-Servers

      Da viele der Befehle zur Einrichtung dieses Servers die gleichen sind wie im vorherigen Schritt, werden sie hier in abgekürzter Form dargestellt. Bitte lesen Sie Schritt 1 für weitere Informationen zu einem bestimmten Befehl in diesem Schritt.

      Beginnen Sie damit, sich bei dem zweiten Django-App-Server anzumelden.

      Klonen Sie den Zweig polls-docker des GitHub-Repositorys von django-polls:

      • git clone --single-branch --branch polls-docker https://github.com/do-community/django-polls.git

      Navigieren Sie in das Verzeichnis django-polls:

      cd django-polls
      

      Erstellen Sie das Image mit docker build:

      Öffnen Sie die Datei env mit nano oder Ihrem bevorzugten Editor:

      nano env
      

      django-polls/env

      DJANGO_SECRET_KEY=
      DEBUG=True
      DJANGO_ALLOWED_HOSTS=
      DATABASE_ENGINE=postgresql_psycopg2
      DATABASE_NAME=polls
      DATABASE_USERNAME=
      DATABASE_PASSWORD=
      DATABASE_HOST=
      DATABASE_PORT=
      STATIC_ACCESS_KEY_ID=
      STATIC_SECRET_KEY=
      STATIC_BUCKET_NAME=
      STATIC_ENDPOINT_URL=
      DJANGO_LOGLEVEL=info
      

      Geben Sie die fehlenden Werte wie in Schritt 1 ein. Wenn Sie die Bearbeitung abgeschlossen haben, speichern und schließen Sie die Datei.

      Führen Sie den App-Container anschließend im getrennten Modus aus:

      docker run -d --rm --name polls --env-file env -p 80:8000 polls
      

      Navigieren Sie zu http://APP_SERVER_2_IP/polls, um zu bestätigen, dass der Container wie erwartet ausgeführt wird. Sie können sich sicher von dem zweiten App-Server anmelden, ohne Ihren laufenden Container zu beenden.

      Da beide Django App-Container ausgeführt werden, können Sie mit der Konfiguration des Reverse-Proxy-Containers von Nginx fortfahren.

      Schritt 3 – Konfigurieren des Nginx Docker-Containers

      Nginx ist ein vielseitiger Webserver, der eine Reihe von Funktionen wie Reverse-Proxying, Load Balancing und Caching bietet. In diesem Tutorial haben wir die statischen Assets von Django in den Objektspeicher ausgelagert, sodass wir die Caching-Funktionen von Nginx nicht verwenden werden. Wir werden Nginx jedoch als Reverse-Proxy für unsere beiden Backend-Django-App-Server verwenden und eingehende Anfragen zwischen ihnen verteilen. Darüber hinaus wird Nginx TLS-Terminierung und -Umleitung unter Verwendung eines von Certbot bereitgestellten TLS-Zertifikats durchführen. Das bedeutet, dass es die Clients zwingen wird, HTTPS zu verwenden, und eingehende HTTPS-Anfragen an Port 443 umzuleiten. Anschließend entschlüsselt Nginx HTTPS-Anfragen und leitet sie an die vorgelagerten Django-Server weiter.

      In diesem Tutorial haben wir die Designentscheidung getroffen, die Nginx-Container von den Backend-Servern zu entkoppeln. Abhängig von Ihrem Anwendungsfall können Sie sich dafür entscheiden, den Nginx-Container auf einem der Django-App-Server auszuführen, das Proxying von Anfragen sowohl lokal als auch auf dem anderen Django-Server auszuführen. Eine weitere mögliche Architektur wäre die Ausführung von zwei Nginx-Containern, einer auf jedem Backend-Server, mit einem Cloud Load Balancer davor. Jede Architektur bietet andere Sicherheits- und Leistungsvorteile und Sie sollten Ihr System einem Lasttest unterziehen, um Engpässe aufzudecken. Die in diesem Tutorial beschriebene flexible Architektur ermöglicht es Ihnen, sowohl die Backend-Django-Anwendungsschicht als auch die Nginx-Proxying-Schicht zu skalieren. Sobald der einzelne Nginx-Container zum Engpass wird, können Sie auf mehrere Nginx-Proxys skalieren und einen Cloud Load Balancer oder schnellen L4 Load Balancer wie HAProxy hinzufügen.

      Da beide Django-App-Server ausgeführt werden, können wir mit dem Einrichten des Proxy-Servers beginnen. Melden Sie sich an Ihrem Proxy-Server an und erstellen Sie ein Verzeichnis namens conf:

      mkdir conf
      

      Erstellen Sie mit nano oder Ihrem bevorzugten Editor eine Konfigurationsdatei namens nginx.conf:

      nano conf/nginx.conf
      

      Fügen Sie die folgende Nginx-Konfiguration ein:

      conf/nginx.conf

      
      upstream django {
          server APP_SERVER_1_IP;
          server APP_SERVER_2_IP;
      }
      
      server {
          listen 80 default_server;
          return 444;
      }
      
      server {
          listen 80;
          listen [::]:80;
          server_name your_domain.com;
          return 301 https://$server_name$request_uri;
      }
      
      server {
          listen 443 ssl http2;
          listen [::]:443 ssl http2;
          server_name your_domain.com;
      
          # SSL
          ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
          ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
      
          ssl_session_cache shared:le_nginx_SSL:10m;
          ssl_session_timeout 1440m;
          ssl_session_tickets off;
      
          ssl_protocols TLSv1.2 TLSv1.3;
          ssl_prefer_server_ciphers off;
      
          ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
      
          client_max_body_size 4G;
          keepalive_timeout 5;
      
              location / {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header Host $http_host;
                proxy_redirect off;
                proxy_pass http://django;
              }
      
          location ^~ /.well-known/acme-challenge/ {
              root /var/www/html;
          }
      
      }
      

      Diese Blöcke upstream, server und location konfigurieren Nginx so, dass HTTP-Anfragen an HTTPS umgeleitet werden und sorgen für einen Lastausgleich zwischen den beiden in Schritt 1 und 2 konfigurierten Django-App-Servern. Um mehr über die Nginx-Konfigurationsdatei zu erfahren, lesen Sie bitte in diesem Artikel über das Verstehen der Nginx-Konfigurationsdateistruktur und der Konfigurationskontexte. Außerdem kann dieser Artikel zum Verstehen von Nginx-Server und Location-Block-Auswahlalgorithmen hilfreich sein.

      Diese Konfiguration wurde aus Beispielkonfigurationsdateien zusammengestellt, die von Gunicorn, Certbot und Nginx bereitgestellt wurden, und ist als eine minimale Nginx-Konfiguration gedacht, um diese Architektur betriebsbereit zu machen. Die Feineinstellung dieser Nginx-Konfiguration geht über den Umfang dieses Artikels hinaus, Sie können jedoch ein Tool wie NGINXConfig verwenden, um performante und sichere Nginx-Konfigurationsdateien für Ihre Architektur zu generieren.

      Der Block upstream definiert die Gruppe von Servern, die zum Proxying von Anfragen zur Verwendung der Anweisung proxy_pass verwendet werden:

      conf/nginx.conf

      upstream django {
          server APP_SERVER_1_IP;
          server APP_SERVER_2_IP;
      }
      . . .
      

      In diesem Block nennen wir den upstream django und schließen die IP-Adressen der beiden Django-App-Server ein. Wenn die App-Server auf DigitalOcean ausgeführt werden und VPC Networking aktiviert haben, sollten Sie hier ihre privaten IP-Adressen verwenden. Um zu erfahren, wie Sie VPC-Networking auf DigitalOcean aktivieren können, lesen Sie bitte Aktivieren von VPC-Networking auf vorhandenen Droplets.

      Der erste Block server erfasst Anfragen, die nicht Ihrer Domäne entsprechen und beendet die Verbindung. Beispielsweise würde eine direkte HTTP-Anfrage an die IP-Adresse Ihres Servers von diesem Block bearbeitet werden:

      conf/nginx.conf

      . . .
      server {
          listen 80 default_server;
          return 444;
      }
      . . .
      

      Der nächste Block server leitet HTTP-Anfragen an Ihre Domäne über eine HTTP 301-Umleitung an HTTPS um. Diese Anfragen werden dann vom letzten Block server bearbeitet:

      conf/nginx.conf

      . . .
      server {
          listen 80;
          listen [::]:80;
          server_name your_domain.com;
          return 301 https://$server_name$request_uri;
      }
      . . .
      

      Diese zwei Anweisungen definieren die Pfade zum TLS-Zertifikat und geheimen Schlüssel. Diese werden mit Certbot bereitgestellt und im nächsten Schritt in den Nginx-Container eingebunden.

      conf/nginx.conf

      . . .
      ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
      ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
      . . .
      

      Bei diesen Parametern handelt es sich um die von Certbot empfohlenen SSL-Sicherheitsstandards. Um mehr über sie zu erfahren, lesen Sie bitte das Modul ngx_http_ssl_module der Nginx-Dokumentation. Mozillas Sicherheits-/Serverseitiges TLS ist ein weiterer hilfreicher Leitfaden, den Sie für die Feinabstimmung Ihrer SSL-Konfiguration verwenden können.

      conf/nginx.conf

      . . .
          ssl_session_cache shared:le_nginx_SSL:10m;
          ssl_session_timeout 1440m;
          ssl_session_tickets off;
      
          ssl_protocols TLSv1.2 TLSv1.3;
          ssl_prefer_server_ciphers off;
      
          ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
      . . .
      

      Diese beiden Anweisungen aus Gunicorns Nginx-Beispielkonfiguration legen die maximal zulässige Größe des Client-Anfragekörpers fest und weisen das Timeout für Keep-Alive-Verbindungen mit dem Client zu. Nginx schließt Verbindungen mit dem Client nach keepalive_timeout-Sekunden.

      conf/nginx.conf

      . . .
      client_max_body_size 4G;
      keepalive_timeout 5;
      . . .
      

      Der erste Block location weist Nginx zum Proxying von Anfragen über HTTP an die upstream django-Server an. Er bewahrt zusätzlich Client HTTP-Header auf, die die Ursprungs-IP-Adresse, das zur Verbindung verwendete Protokoll und den Ziel-Host erfassen:

      conf/nginx.conf

      . . .
      location / {
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_set_header Host $http_host;
          proxy_redirect off;
          proxy_pass http://django;
      }
      . . .
      

      Um mehr über diese Anweisungen zu erfahren, lesen Sie bitte Bereitstellen von Gunicorn und das Modul ngx_http_proxy_module der Nginx-Dokumentation.

      Der letzte Block location erfasst Anfragen an den Pfad /well-known/acme-Challenge/, der von Certbot für HTTP-01-Challenges verwendet wird, um Ihre Domäne mit Let’s Encrypt zu verifizieren und TLS-Zertifikate bereitzustellen oder zu erneuern. Weitere Informationen über die von Certbot verwendete HTTP-01-Challenge finden Sie unter Challenge-Arten in der Let’s Encrypt-Dokumentation.

      conf/nginx.conf

      . . .
      location ^~ /.well-known/acme-challenge/ {
              root /var/www/html;
      }
      

      Wenn Sie die Bearbeitung abgeschlossen haben, speichern und schließen Sie die Datei.

      Sie können diese Konfigurationsdatei nun verwenden, um einen Nginx Docker-Container auszuführen. In diesem Tutorial verwenden wir das Image nginx:1.19.0, Version 1.19.0 des offiziellen Docker-Images, das von Nginx verwaltet wird.

      Wenn wir den Container zum ersten Mal ausführen, wird Nginx einen Fehler ausgeben und fehlschlagen, da wir die in der Konfigurationsdatei definierten Zertifikate noch nicht bereitgestellt haben. Wir werden jedoch trotzdem den Befehl zum Herunterladen des Nginx-Images lokal ausführen und testen, ob alles andere korrekt funktioniert:

      docker run --rm --name nginx -p 80:80 -p 443:443 
          -v ~/conf/nginx.conf:/etc/nginx/conf.d/nginx.conf:ro 
          -v /var/www/html:/var/www/html 
          nginx:1.19.0
      

      Hier nennen wir den Container nginx und ordnen die Host-Ports 80 und 443 den jeweiligen Container-Ports zu. Das Flag -v bindet die Konfigurationsdatei unter /etc/nginx/conf.d/nginx.conf in den Nginx-Container ein, für dessen Laden das Nginx-Image vorkonfiguriert ist. Es wird im Modus ro oder „read-only“ eingebunden, sodass der Container die Datei nicht verändern kann. Das Web-Stammverzeichnis /var/www/html ist ebenfalls in den Container eingebunden. Schließlich weist nginx:1.19.0 Docker an, das Image nginx:1.19.0 aus Dockerhub zu ziehen und auszuführen.

      Docker wird das Image ziehen und ausführen, dann wird Nginx einen Fehler ausgeben, wenn es das konfigurierte TLS-Zertifikat und den geheimen Schlüssel nicht findet. Im nächsten Schritt stellen wir diese mithilfe eines dockerisierten Certbot-Clients und der Zertifizierungsstelle Let’s Encrypt bereit.

      Schritt 4 – Konfigurieren von Certbot und Let’s Encrypt-Zertifikaterneuerung

      Certbot ist ein Let’s Encrypt-Client, der von der Electronic Frontier Foundation entwickelt wurde. Er stellt kostenlose TLS-Zertifikate von der Let’s Encrypt-Zertifizierungsstelle zur Verfügung, mit denen Browser die Identität Ihrer Webserver überprüfen können. Da wir auf unserem Nginx-Proxy-Server Docker installiert haben, verwenden wir das Certbot Docker-Image zur Bereitstellung und Erneuerung der TLS-Zertifikate.

      Stellen Sie zunächst sicher, dass Sie über einen DNS-A-Eintrag verfügen, der der öffentlichen IP-Adresse des Proxy-Servers zugeordnet ist. Stellen Sie dann auf Ihrem Proxy-Server eine Staging-Version der Zertifikate unter Verwendung des Docker-Images certbot bereit:

      docker run -it --rm -p 80:80 --name certbot 
               -v "/etc/letsencrypt:/etc/letsencrypt" 
               -v "/var/lib/letsencrypt:/var/lib/letsencrypt" 
               certbot/certbot certonly --standalone --staging -d your_domain.com
      

      Dieser Befehl führt das certbot Docker-Image im interaktiven Modus aus und leitet Port 80 auf dem Host an den Container-Port 80 weiter. Er erstellt zwei Host-Verzeichnisse und bindet sie in die Container ein: /etc/letsencrypt/ und /var/lib/letsencrypt/. certbot wird im Modus standalone ohne Nginx ausgeführt und verwendet die Staging-Server von Let’s Encrypt, um die Domänenvalidierung durchzuführen.

      Geben Sie, wenn Sie dazu aufgefordert werden, Ihre E-Mail-Adresse ein und stimmen Sie den Nutzungsbedingungen zu. Wenn die Domänenvalidierung erfolgreich war, sollten Sie die folgende Ausgabe sehen:

      Output

      Obtaining a new certificate Performing the following challenges: http-01 challenge for stubb.dev Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/your_domain.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/your_domain.com/privkey.pem Your cert will expire on 2020-09-15. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal.

      Sie können das Zertifikat mit cat inspizieren:

      sudo cat /etc/letsencrypt/live/your_domain.com/fullchain.pem
      

      Mit dem bereitgestellten TLS-Zertifikat können wir die im vorherigen Schritt eingebundene Nginx-Konfiguration testen:

      docker run --rm --name nginx -p 80:80 -p 443:443 
          -v ~/conf/nginx.conf:/etc/nginx/conf.d/nginx.conf:ro 
          -v /etc/letsencrypt:/etc/letsencrypt 
          -v /var/lib/letsencrypt:/var/lib/letsencrypt 
          -v /var/www/html:/var/www/html 
          nginx:1.19.0
      

      Dies ist derselbe Befehl, der in Schritt 3 ausgeführt wurde, mit dem Hinzufügen der beiden kürzlich erstellten Let’s Encrypt-Verzeichnisse:

      Sobald Nginx ausgeführt wird, navigieren Sie zu http://your_domain.com. Möglicherweise erhalten Sie in Ihrem Browser eine Warnung, dass die Zertifizierungsstelle ungültig ist. Dies ist zu erwarten, da wir Staging-Zertifikate und keine Produktions-Let’s Encrypt-Zertifikate bereitgestellt haben. Überprüfen Sie die URL-Leiste Ihres Browsers, um zu bestätigen, dass Ihre HTTP-Anfrage an HTTPS umgeleitet wurde.

      Drücken Sie zum Beenden von Nginx in Ihrem Terminal Strg+C und führen Sie den Client certbot erneut aus, diesmal ohne das Flag --staging:

      docker run -it --rm -p 80:80 --name certbot 
               -v "/etc/letsencrypt:/etc/letsencrypt" 
               -v "/var/lib/letsencrypt:/var/lib/letsencrypt" 
               certbot/certbot certonly --standalone -d your_domain.com
      

      Wenn Sie dazu aufgefordert werden, entweder das vorhandene Zertifikat beizubehalten oder es zu erneuern und zu ersetzen, drücken Sie 2 zum Erneuern und dann ENTER, um Ihre Wahl zu bestätigen.

      Wenn das Produktions-TLS-Zertifikat bereitgestellt ist, führen Sie den Nginx-Server erneut aus:

      docker run --rm --name nginx -p 80:80 -p 443:443 
          -v ~/conf/nginx.conf:/etc/nginx/conf.d/nginx.conf:ro 
          -v /etc/letsencrypt:/etc/letsencrypt 
          -v /var/lib/letsencrypt:/var/lib/letsencrypt 
          -v /var/www/html:/var/www/html 
          nginx:1.19.0
      

      Navigieren Sie in Ihrem Browser zu http://your_domain.com. Bestätigen Sie in der URL-Leiste, dass die HTTP-Anfrage an HTTPS umgeleitet wurde. Da für die Umfrageanwendung keine Standardroute konfiguriert ist, sollten Sie den Django-Fehler Page not found (Seite nicht gefunden) sehen. Navigieren Sie zu https://your_domain.com/polls und Sie sehen die Standardoberfläche der Umfrageanwendung:

      Oberfläche der Umfrageanwendung

      Zu diesem Zeitpunkt haben Sie mit dem Certbot Docker-Client ein Produktions-TLS-Zertifikat bereitgestellt und externe Anfragen an die beiden Django-App-Server durch Reverse Proxying und Lastausgleich umgeleitet.

      Die Let’s Encrypt-Zertifikate laufen alle 90 Tage ab. Um sicherzustellen, dass Ihr Zertifikat gültig bleibt, sollten Sie es regelmäßig vor dessen geplantem Ablauf erneuern. Wenn Nginx ausgeführt wird, sollten Sie den Certbot-Client im Modus webroot anstelle des Modus standalone verwenden. Das bedeutet, dass Certbot die Validierung durch die Erstellung einer Datei im Verzeichnis /var/www/html/.well-known/acme-challenge/ durchführt, und die Validierungsanforderungen von Let’s Encrypt an diesen Pfad werden von der in der Nginx-Konfiguration in Schritt 3 definierten Regel location erfasst. Certbot wird dann die Zertifikate rotieren, und Sie können Nginx neu laden, sodass es dieses neu bereitgestellte Zertifikat verwendet.

      Es gibt mehrere Möglichkeiten, um dieses Verfahren zu automatisieren und die automatische Erneuerung von TLS-Zertifikaten geht über den Umfang dieses Tutorials hinaus. Ein ähnliches Verfahren unter Verwendung des Scheduling-Dienstprogramms cron finden Sie in Schritt 6 von Sichern einer containerisierten Node.js-Anwendung mit Nginx, Let’s Encrypt, und Docker Compose.

      Drücken Sie zum Beenden des Nginx-Containers in Ihrem Terminal Strg+C. Führen Sie ihn erneut im getrennten Modus aus, indem Sie das Flag -d anhängen:

      docker run --rm --name nginx -d -p 80:80 -p 443:443 
          -v ~/conf/nginx.conf:/etc/nginx/conf.d/nginx.conf:ro 
          -v /etc/letsencrypt:/etc/letsencrypt 
          -v /var/lib/letsencrypt:/var/lib/letsencrypt 
        -v /var/www/html:/var/www/html 
          nginx:1.19.0
      

      Verwenden Sie mit im Hintergrund ausgeführtem Nginx den folgenden Befehl, um einen Probelauf des Zertifikatserneuerungsverfahrens auszuführen:

      docker run -it --rm --name certbot 
          -v "/etc/letsencrypt:/etc/letsencrypt" 
        -v "/var/lib/letsencrypt:/var/lib/letsencrypt" 
        -v "/var/www/html:/var/www/html" 
        certbot/certbot renew --webroot -w /var/www/html --dry-run
      

      Wir verwenden das Plugin --webroot, geben den Web-Stammpfad ein und verwenden das Flag --dry-run zum Überprüfen der ordnungsgemäßen Funktion, ohne die Zertifikatserneuerung tatsächlich durchzuführen.

      Wenn die Erneuerungssimulation erfolgreich ist, sollten Sie die folgende Ausgabe sehen:

      Output

      Cert not due for renewal, but simulating renewal for dry run Plugins selected: Authenticator webroot, Installer None Renewing an existing certificate Performing the following challenges: http-01 challenge for your_domain.com Using the webroot path /var/www/html for all unmatched domains. Waiting for verification... Cleaning up challenges - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - new certificate deployed without reload, fullchain is /etc/letsencrypt/live/your_domain.com/fullchain.pem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates below have not been saved.) Congratulations, all renewals succeeded. The following certs have been renewed: /etc/letsencrypt/live/your_domain.com/fullchain.pem (success) ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates above have not been saved.) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      In einer Produktionseinstellung sollten Sie nach der Erneuerung von Zertifikaten Nginx neu laden, damit die Änderungen wirksam werden. Führen Sie zum Neuladen von Nginx den folgenden Befehl aus:

      docker kill -s HUP nginx
      

      Dieser Befehl sendet ein HUP Unix-Signal an den Nginx-Prozess, der innerhalb des Docker-Containers nginx ausgeführt wird. Nach Empfang dieses Signals lädt Nginx seine Konfiguration und erneuerten Zertifikate neu.

      Wenn HTTPS aktiviert ist und alle Komponenten dieser Architektur ausgeführt werden, besteht der letzte Schritt darin, die Einrichtung zu sperren, indem der externe Zugriff auf die beiden Backend-App-Server verhindert wird; alle HTTP-Anfragen sollten über den Nginx-Proxy laufen.

      Schritt 5 – Verhindern des externen Zugriffs auf Django-App-Server

      In der in diesem Tutorial beschriebenen Architektur erfolgt die SSL-Terminierung am Nginx-Proxy. Das bedeutet, dass Nginx die SSL-Verbindung entschlüsselt und die Pakete unverschlüsselt an die Django-App-Server weitergeleitet werden. Für viele Anwendungsfälle ist diese Sicherheitsstufe ausreichend. Für Anwendungen mit Finanz- oder Gesundheitsdaten sollten Sie eventuell eine End-to-End-Verschlüsselung implementieren. Sie können dies tun, indem Sie verschlüsselte Pakete über den Load Balancer weiterleiten und auf den App-Servern entschlüsseln oder am Proxy neu verschlüsseln und auf den Django-App-Servern wieder entschlüsseln. Diese Techniken gehen über den Rahmen dieses Artikels hinaus. Um mehr zu erfahren, lesen Sie bitte End-to-End-Verschlüsselung.

      Der Nginx-Proxy fungiert als Gateway zwischen externem Datenverkehr und dem internen Netzwerk. Theoretisch sollten keine externen Clients direkten Zugriff auf die internen App-Server haben, und alle Anfragen sollten über den Nginx-Server laufen. Der Hinweis in Schritt 1 beschreibt kurz ein offenes Problem mit Docker, bei dem Docker standardmäßig die ufw-Firewalleinstellungen umgeht und Ports extern öffnet, die möglicherweise unsicher sind. Um dieses Sicherheitsproblem zu beheben wird empfohlen, bei der Arbeit mit Docker-fähigen Servern Cloud Firewalls zu verwenden. Weitere Informationen zum Erstellen von Cloud Firewalls mit DigitalOcean finden Sie unter Erstellen von Firewalls. Sie können iptables auch direkt manipulieren, anstatt ufw zu verwenden. Um mehr über die Verwendung von iptables mit Docker zu erfahren, lesen Sie bitte Docker und iptables.

      In diesem Schritt ändern wir die UFW-Konfiguration so, dass der externe Zugriff auf die von Docker geöffneten Host-Ports blockiert wird. Bei der Ausführung von Django auf den App-Servern haben wir das Flag -p 80:8000 an docker übergeben, das Port 80 auf dem Host an den Container-Port 8000 weiterleitet. Dadurch wurde Port 80 auch für externe Clients geöffnet, was Sie unter http://your_app_server_1_IP überprüfen können. Um den direkten Zugriff zu verhindern, ändern wir die UFW-Konfiguration mithilfe der im ufw-docker GitHub-Repository beschriebenen Methode.

      Beginnen Sie damit, sich bei dem ersten Django-App-Server anzumelden. Öffnen Sie dann die Datei /etc/ufw/after.rules mit superuser-Berechtigungen, indem Sie nano oder Ihren bevorzugten Editor verwenden:

      sudo nano /etc/ufw/after.rules
      

      Geben Sie bei Aufforderung Ihr Passwort ein und drücken Sie zur Bestätigung ENTER.

      Sie sollten die folgenden ufw-Regeln sehen:

      /etc/ufw/after.rules

      #
      # rules.input-after
      #
      # Rules that should be run after the ufw command line added rules. Custom
      # rules should be added to one of these chains:
      #   ufw-after-input
      #   ufw-after-output
      #   ufw-after-forward
      #
      
      # Don't delete these required lines, otherwise there will be errors
      *filter
      :ufw-after-input - [0:0]
      :ufw-after-output - [0:0]
      :ufw-after-forward - [0:0]
      # End required lines
      
      # don't log noisy services by default
      -A ufw-after-input -p udp --dport 137 -j ufw-skip-to-policy-input
      -A ufw-after-input -p udp --dport 138 -j ufw-skip-to-policy-input
      -A ufw-after-input -p tcp --dport 139 -j ufw-skip-to-policy-input
      -A ufw-after-input -p tcp --dport 445 -j ufw-skip-to-policy-input
      -A ufw-after-input -p udp --dport 67 -j ufw-skip-to-policy-input
      -A ufw-after-input -p udp --dport 68 -j ufw-skip-to-policy-input
      
      # don't log noisy broadcast
      -A ufw-after-input -m addrtype --dst-type BROADCAST -j ufw-skip-to-policy-input
      
      # don't delete the 'COMMIT' line or these rules won't be processed
      COMMIT
      

      Scrollen Sie nach unten und fügen Sie den folgenden Block mit UFW-Konfigurationsregeln ein:

      /etc/ufw/after.rules

      . . .
      
      # BEGIN UFW AND DOCKER
      *filter
      :ufw-user-forward - [0:0]
      :DOCKER-USER - [0:0]
      -A DOCKER-USER -j RETURN -s 10.0.0.0/8
      -A DOCKER-USER -j RETURN -s 172.16.0.0/12
      -A DOCKER-USER -j RETURN -s 192.168.0.0/16
      
      -A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
      
      -A DOCKER-USER -j ufw-user-forward
      
      -A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
      -A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
      -A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
      -A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
      -A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
      -A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 172.16.0.0/12
      
      -A DOCKER-USER -j RETURN
      COMMIT
      # END UFW AND DOCKER
      

      Diese Regeln schränken den öffentlichen Zugriff auf die von Docker geöffneten Ports ein und ermöglichen den Zugriff aus den privaten IP-Bereichen 10.0.0/8, 172.16.0.0/12 und 192.168.0.0/16. Wenn Sie VPC mit DigitalOcean verwenden, dann haben Droplets in Ihrem VPC-Netzwerk über die private Netzwerkschnittstelle Zugriff auf den offenen Port, externe Clients jedoch nicht. Weitere Informationen über VPC finden Sie in der offiziellen VPC-Dokumentation. Um mehr über die in diesem Snippet implementierten Regeln zu erfahren, lesen Sie bitte Funktionsweise in der ufw-docker README.

      Wenn Sie VPC nicht mit DigitalOcean verwenden und die öffentlichen IP-Adressen der App-Server in den Block upstream Ihrer Nginx-Konfiguration eingegeben haben, müssen Sie die UFW-Firewall explizit ändern, um den Datenverkehr vom Nginx-Server über Port 80 auf den Django-App-Servern zuzulassen. Eine Anleitung zur Erstellung von allow-Regeln mit der UFW-Firewall finden Sie unter UFW Grundlagen: Allgemeine Firewallregeln und -befehle.

      Wenn Sie die Bearbeitung abgeschlossen haben, speichern und schließen Sie die Datei.

      Starten Sie ufw neu, damit die neue Konfiguration übernommen wird:

      sudo systemctl restart ufw
      

      Navigieren Sie in Ihrem Webbrowser zu http://APP_SERVER_1_IP, um zu bestätigen, dass Sie über Port 80 nicht mehr auf die App-Server zugreifen können.

      Wiederholen Sie diesen Vorgang auf dem zweiten Django-App-Server.

      Melden Sie sich bei dem ersten App-Server ab oder öffnen Sie ein anderes Terminalfenster und melden Sie sich bei dem zweiten Django-App-Server an. Öffnen Sie dann die Datei /etc/ufw/after.rules mit superuser-Berechtigungen, indem Sie nano oder Ihren bevorzugten Editor verwenden:

      sudo nano /etc/ufw/after.rules
      

      Geben Sie bei Aufforderung Ihr Passwort ein und drücken Sie zur Bestätigung ENTER.

      Scrollen Sie nach unten und fügen Sie den folgenden Block mit UFW-Konfigurationsregeln ein:

      /etc/ufw/after.rules

      . . .
      
      # BEGIN UFW AND DOCKER
      *filter
      :ufw-user-forward - [0:0]
      :DOCKER-USER - [0:0]
      -A DOCKER-USER -j RETURN -s 10.0.0.0/8
      -A DOCKER-USER -j RETURN -s 172.16.0.0/12
      -A DOCKER-USER -j RETURN -s 192.168.0.0/16
      
      -A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
      
      -A DOCKER-USER -j ufw-user-forward
      
      -A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
      -A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
      -A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
      -A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
      -A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
      -A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 172.16.0.0/12
      
      -A DOCKER-USER -j RETURN
      COMMIT
      # END UFW AND DOCKER
      

      Wenn Sie die Bearbeitung abgeschlossen haben, speichern und schließen Sie die Datei.

      Starten Sie ufw neu, damit die neue Konfiguration übernommen wird:

      sudo systemctl restart ufw
      

      Navigieren Sie in Ihrem Webbrowser zu http://APP_SERVER_2_IP, um zu bestätigen, dass Sie über Port 80 nicht mehr auf die App-Server zugreifen können.

      Navigieren Sie abschließend zu https://your_domain_here/polls, um zu bestätigen, dass der Nginx-Proxy weiterhin Zugriff auf die upstream Django-Server hat. Sie sollten die Standardoberfläche der Umfrageanwendung sehen.

      Zusammenfassung

      In diesem Tutorial haben Sie mit Docker-Containern eine skalierbare Django Umfrageanwendung eingerichtet. Wenn Ihr Datenverkehr steigt und die Last auf dem System zunimmt, können Sie jede Schicht separat skalieren: die Nginx-Proxying-Schicht, die Django-Backend-Anwendungsschicht und die PostgreSQL-Datenbankschicht.

      Beim Aufbau eines verteilten Systems müssen Sie oft mehrere Designentscheidungen treffen, und mehrere Architekturen können Ihrem Anwendungsfall gerecht werden. Die in diesem Tutorial beschriebene Architektur ist als flexible Blaupause für den Entwurf skalierbarer Anwendungen mit Django und Docker gedacht.

      Möglicherweise möchten Sie das Verhalten Ihrer Container steuern, wenn sie auf Fehler stoßen, oder Container automatisch ausführen, wenn Ihr System gestartet wird. Zu diesem Zweck können Sie einen Prozessmanager wie Systemd verwenden oder Neustartrichtlinien implementieren. Weitere Informationen hierzu finden Sie unter Automatisches Starten von Containern in der Docker-Dokumentation.

      Wenn Sie im großen Maßstab mit mehreren Hosts arbeiten, die dasselbe Docker-Image ausführen, kann es effizient sein, Schritte mit einem Konfigurations-Managementtool wie Ansible oder Chef zu automatisieren. Um mehr über das Konfigurationsmanagement zu erfahren, lesen Sie bitte Eine Einführung in das Konfigurationsmanagement und Automatisieren der Servereinrichtung mit Ansible: Ein DigitalOcean-Workshop-Kit.

      Anstatt auf jedem Host dasselbe Image zu erstellen, können Sie die Bereitstellung auch mithilfe einer Image-Registrierung wie Docker Hub rationalisieren, bei der Docker-Images zentral erstellt, gespeichert und an mehrere Server verteilt werden. Zusammen mit einer Image-Registrierung kann Ihnen eine kontinuierliche Integrations- und Bereitstellungspipeline dabei helfen, Images zu erstellen, zu testen und auf Ihre App-Server zu verteilen. Weitere Informationen zu CI/CD finden Sie unter Eine Einführung in die CI/CD Best Practices.



      Source link

      Installieren und Sichern von Grafana unter Ubuntu 20.04


      Der Autor hat den COVID-19 Relief Fund dazu ausgewählt, eine Spende im Rahmen des Programms Write for DOnations zu erhalten.

      Einführung

      Grafana ist ein Open-Source-basiertes Visualisierungs- und Überwachungstool für Daten, das sich mit komplexen Daten aus Quellen wie Prometheus, InfluxDB, Graphite und ElasticSearch integrieren lässt. Mit Grafana können Sie Warnungen, Benachrichtigungen und Ad-hoc-Filter für Ihre Daten erstellen und durch integrierte Freigabefunktionen die Zusammenarbeit mit Teamkollegen erleichtern.

      In diesem Tutorial installieren Sie Grafana und sichern die Anwendung mit einem SSL-Zertifikat und einem Nginx-Reverseproxy. Nach der Einrichtung von Grafana haben Sie die Möglichkeit, Benutzerauthentifizierung über GitHub zu konfigurieren, um die Berechtigungen Ihres Teams besser zu organisieren.

      Voraussetzungen

      Um dieser Anleitung zu folgen, benötigen Sie:

      • Zwei Ubuntu 20.04-Server, die gemäß des Leitfadens zur Ersteinrichtung des Servers für Ubuntu 20.04 eingerichtet wurde, einschließlich eines non-root users, der über sudo-Berechtigungen verfügt, und einer mit ufw konfigurierten Firewall.
      • Einen vollständig registrierten Domänennamen. In diesem Tutorial wird durchgehend your_domain verwendet. Sie können einen Domänennamen unter Namecheap günstig erwerben oder einen kostenlosen von Freenom herunterladen oder einfach die Domänenregistrierungsstelle Ihrer Wahl verwenden.
      • Richten Sie die folgenden DNS-Einträge für Ihren Server ein. Sie können Einrichten eines Hostnamens mit DigitalOcean konsultieren, um mehr über das Hinzufügen von Hostnamen zu erfahren.
        • Einen A-Datensatz mit your-domain, der auf die öffentliche IP-Adresse Ihres Servers verweist.
        • Einen A-Eintrag mit www.your_domain, der auf die öffentliche IP-Adresse Ihres Servers verweist.
      • Nginx, eingerichtet anhand des Tutorials zum Installieren von Nginx unter Ubuntu 20.04, einschließlich eines Serverblocks für Ihre Domäne.
      • Einen Nginx-Serverblock mit konfiguriertem Let’s Encrypt; folgen Sie zum Einrichten dieser Komponente Sichern von Nginx mit Let’s Encrypt unter Ubuntu 20.04.
      • Optional benötigen Sie zur Einrichtung der GitHub-Authentifizierung ein GitHub-Konto, das mit einer Organisation verknüpft ist.

      Schritt 1 — Installieren von Grafana

      In diesem ersten Schritt installieren Sie Grafana auf Ihrem Ubuntu 20.04-Server. Sie können Grafana installieren, indem Sie entweder die Anwendung direkt von der offiziellen Website herunterladen oder ein APT-Repository verwenden. Da ein APT-Repository die Installation und Verwaltung von Grafana-Updates erleichtert, wenden wir in diesem Tutorial diese Methode an.

      Laden Sie mit wget den GPG-Schlüssel von Grafana herunter und übergeben Sie dann die Ausgabe an apt-key. Dadurch wird der Schlüssel zur Liste der vertrauenswürdigen Schlüssel Ihrer APT-Installation hinzugefügt. Nun können Sie das GPG-signierte Grafana-Paket herunterladen und verifizieren:

      • wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -

      In diesem Befehl deaktiviert die Option -q die Nachricht zur Statusaktualisierung für wget, während -O die Datei ausgibt, die Sie in das Terminal heruntergeladen haben. Diese beiden Optionen sorgen dafür, dass nur die Inhalte der heruntergeladenen Datei an apt-key übertragen werden.

      Fügen Sie als Nächstes das Grafana-Repository zu Ihren APT-Quellen hinzu:

      • sudo add-apt-repository "deb https://packages.grafana.com/oss/deb stable main"

      Aktualisieren Sie dann den APT-Cache, um Ihre Paketlisten zu aktualisieren:

      Sie können nun mit der Installation fortfahren:

      Sobald Grafana installiert ist, verwenden Sie systemctl, um den Grafana-Server zu starten:

      • sudo systemctl start grafana-server

      Überprüfen Sie als Nächstes, ob Grafana ausgeführt wird, indem Sie den Status des Diensts prüfen:

      • sudo systemctl status grafana-server

      Sie erhalten eine ähnliche Ausgabe wie diese:

      Output

      ● grafana-server.service - Grafana instance Loaded: loaded (/lib/systemd/system/grafana-server.service; disabled; vendor preset: enabled) Active: active (running) since Thu 2020-05-21 08:08:10 UTC; 4s ago Docs: http://docs.grafana.org Main PID: 15982 (grafana-server) Tasks: 7 (limit: 1137) ...

      Diese Ausgabe enthält Informationen über den Prozess von Grafana, einschließlich seines Status, Main Process Identifier (PID) und mehr. active (running) bedeutet, dass der Prozess richtig ausgeführt wird.

      Abschließend aktivieren Sie den Dienst, damit Grafana beim Booten automatisch gestartet wird:

      • sudo systemctl enable grafana-server

      Sie erhalten die folgende Ausgabe:

      Output

      Synchronizing state of grafana-server.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable grafana-server Created symlink /etc/systemd/system/multi-user.target.wants/grafana-server.service → /usr/lib/systemd/system/grafana-server.service.

      Dadurch wird bestätigt, dass systemd die erforderlichen symbolischen Links für den Autostart von Grafana erstellt hat.

      Grafana ist nun installiert und einsatzbereit. Als Nächstes sichern Sie Ihre Verbindung zu Grafana mit einem Reverseproxy und SSL-Zertifikat.

      Schritt 2 — Einrichten des Reverseproxy

      Durch Verwendung eines SSL-Zertifikats wird sichergestellt, dass Ihre Daten sicher sind, indem die Verbindung zu und von Grafana verschlüsselt wird. Um diese Verbindung nutzen zu können, müssen Sie jedoch zunächst Nginx als Reverseproxy für Grafana neu konfigurieren.

      Öffnen Sie die Nginx-Konfigurationsdatei, die Sie beim Einrichten des Nginx-Serverblocks mit Let’s Encrypt in den Voraussetzungen erstellt haben. Sie können einen beliebigen Texteditor verwenden, für dieses Tutorial nutzen wir allerdings nano:

      • sudo nano /etc/nginx/sites-available/your_domain

      Suchen Sie nach dem folgenden Block:

      /etc/nginx/sites-available/your_domain

      ...
          location / {
              try_files $uri $uri/ =404;
          }
      ...
      

      Da Sie Nginx bereits für Kommunikation über SSL konfiguriert haben und der gesamte Webverkehr auf Ihrem Server schon über Nginx läuft, müssen Sie Nginx nur noch dazu anweisen, alle Anfragen an Grafana (standardmäßig an Port 3000) weiterzuleiten.

      Löschen Sie in diesem location block die vorhandene Zeile try_files und ersetzen Sie sie durch die folgende Option proxy_pass:

      /etc/nginx/sites-available/your_domain

      ...
          location / {
              proxy_pass http://localhost:3000;
          }
      ...
      

      Dadurch wird der Proxy dem entsprechenden Port zugeordnet. Sobald Sie damit fertig sind, speichern und schließen Sie die Datei, indem Sie STRG+X, Y und dann die Eingabetaste drücken (wenn Sie nano verwenden).

      Testen Sie nun die neuen Einstellungen, um sich zu vergewissern, dass alles korrekt konfiguriert wurde:

      Sie erhalten die folgende Ausgabe:

      Output

      nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful

      Aktivieren Sie schließlich die Änderungen, indem Sie Nginx neu laden:

      • sudo systemctl reload nginx

      Sie können nun das Standardanmeldefenster von Grafana aufrufen, indem Sie in Ihren Webbrowser https://your_domain eingeben. Wenn Grafana nicht erreichbar ist, prüfen Sie, ob Ihre Firewall so eingerichtet ist, dass Datenverkehr an Port 443 zugelassen wird, und befolgen Sie dann erneut die vorherigen Anweisungen.

      Nachdem Sie die Verbindung zu Grafana verschlüsselt haben, können Sie nun zusätzliche Sicherheitsmaßnahmen implementieren, angefangen beim Ändern der standardmäßigen Anmeldedaten für den Grafana-Administrator.

      Schritt 3 — Aktualisieren von Anmeldedaten

      Da jede Grafana-Installation standardmäßig dieselben Administrator-Anmeldedaten nutzt, sollten Sie die Anmeldedaten so schnell wie möglich ändern. In diesem Schritt aktualisieren Sie die Anmeldedaten zur Verbesserung der Sicherheit.

      Navigieren Sie zunächst über Ihren Webbrowser zu https://your_domain. Dadurch wird das standardmäßige Anmeldefenster mit folgenden Elementen angezeigt: einem Formular, das Sie dazu auffordert, eine E-Mail-Adresse oder Benutzername und ein Passwort einzugeben, einer Schaltfläche zum Anmelden sowie einem Link namens Passwort vergessen? .

      Grafana-Anmeldung

      Geben Sie admin sowohl in das Feld E-Mail-Adresse oder Benutzername und Passwort ein und klicken Sie dann auf die Schaltfläche Anmelden.

      Im nächsten Fenster werden Sie aufgefordert, die Sicherheit Ihres Kontos zu erhöhen, indem Sie das Standardpasswort ändern:

      Passwort ändern

      Geben Sie das Passwort, das Sie verwenden möchten, in die Felder Neues Passwort und Neues Passwort bestätigen ein.

      Jetzt können Sie auf Übermitteln klicken, um die neuen Daten zu speichern, oder auf Überspringen, um diesen Schritt zu überspringen. Wenn Sie den Schritt überspringen, werden Sie dazu aufgefordert, das Passwort bei der nächsten Anmeldung zu ändern.

      Um die Sicherheit Ihrer Grafana-Konfiguration zu erhöhen, klicken Sie auf Übermitteln. Sie gelangen zum Dashboard Willkommen bei Grafana:

      Start-Dashboard

      Sie haben Ihr Konto sicherer gemacht, indem Sie die Standardanmeldedaten geändert haben. Als Nächstes werden Sie Änderungen an Ihrer Grafana-Konfiguration vornehmen, damit ohne Ihre Genehmigung niemand ein neues Grafana-Konto erstellen kann.

      Schritt 4 — Deaktivieren von Grafana-Registrierungen und anonymem Zugriff

      Grafana bietet Optionen, mit denen Besucher für sich selbst Benutzerkonten erstellen und eine Vorschau von Dashboards anzeigen können, ohne sich registrieren zu müssen. Wenn Grafana nicht über das Internet zugänglich ist oder mit öffentlich verfügbaren Daten wie Dienststatus arbeitet, können Sie diese Funktionen ggf. zulassen. Wenn Sie Grafana jedoch online verwenden, um mit sensiblen Daten zu arbeiten, kann anonymer Zugriff ein Sicherheitsproblem darstellen. Um dieses Problem zu beheben, nehmen Sie einige Änderungen an Ihrer Grafana-Konfiguration vor.

      Öffnen Sie zunächst die Hauptkonfigurationsdatei von Grafana zur Bearbeitung:

      • sudo nano /etc/grafana/grafana.ini

      Suchen Sie die folgende Direktive allow_sign_up unter der Überschrift [users]:

      /etc/grafana/grafana.ini

      ...
      [users]
      # disable user signup / registration
      ;allow_sign_up = true
      ...
      

      Wenn Sie diese Direktive mit true aktivieren, wird dem Anmeldefenster eine Schaltfläche zum Anmelden hinzugefügt, damit sich Benutzer registrieren und auf Grafana zugreifen können.

      Durch Deaktivieren dieser Direktive mit false wird die Schaltfläche zum Anmelden entfernt, was die Sicherheit und den Datenschutz von Grafana erhöht.

      Heben Sie die Kommentierung dieser Direktive auf, indem Sie das ;-Zeichen am Anfang der Zeile entfernen und dann die Option auf false setzen:

      /etc/grafana/grafana.ini

      ...
      [users]
      # disable user signup / registration
      allow_sign_up = false
      ...
      

      Als Nächstes suchen Sie nach der folgenden aktivierten Direktive unter der Überschrift [auth.anonymous]:

      /etc/grafana/grafana.ini

      ...
      [auth.anonymous]
      # enable anonymous access
      ;enabled = false
      ...
      

      Wenn Sie enabled auf true setzen, erhalten nicht registrierte Benutzer Zugriff auf Ihre Dashboards; wenn Sie die Option auf false setzen, wird der Zugriff auf das Dashboard auf registrierte Benutzer beschränkt.

      Heben Sie die Kommentierung dieser Direktive auf, indem Sie das ;-Zeichen am Anfang der Zeile entfernen und die Option dann auf false setzen:

      /etc/grafana/grafana.ini

      ...
      [auth.anonymous]
      # enable anonymous access
      enabled = false
      ...
      

      Speichern Sie die Datei und beenden Sie den Texteditor.

      Um die Änderungen zu aktivieren, starten Sie Grafana neu:

      • sudo systemctl restart grafana-server

      Vergewissern Sie sich, ob alles funktioniert, indem Sie den Dienststatus von Grafana überprüfen:

      • sudo systemctl status grafana-server

      Wie zuvor wird die Ausgabe melden, dass Grafana active (running) ist.

      Rufen Sie nun https://your_domain in Ihrem Webbrowser auf. Um zum Fenster zum Anmelden zurückzukehren, bewegen Sie den Cursor links unten im Bildschirm zu Ihrem Avatar und klicken Sie auf die Option Abmelden, die angezeigt wird.

      Vergewissern Sie sich nach dem Abmelden, dass es keine Schaltfläche zum Anmelden gibt und Sie sich nicht anmelden können, ohne Anmeldedaten einzugeben.

      Nun ist Grafana vollständig konfiguriert und einsatzbereit. Als Nächstes können Sie den Anmeldeprozess für Ihre Organisation vereinfachen, indem Sie über GitHub authentifizieren.

      (Optional) Schritt 5 — Einrichten einer GitHub OAuth-Anwendung

      Für einen alternativen Ansatz zur Anmeldung können Sie Grafana für eine Authentifizierung über GitHub konfigurieren, womit allen Mitgliedern autorisierter GitHub-Organisationen Zugriff gewährt wird. Dies kann besonders nützlich sein, wenn Sie möchten, dass verschiedene Entwickler zusammenarbeiten und Metriken aufrufen können, ohne spezielle Anmeldedaten für Grafana erstellen zu müssen.

      Melden Sie sich zunächst bei einem GitHub-Konto, das mit Ihrer Organisation verknüpft ist, an und navigieren Sie dann zu Ihrer GitHub-Profilseite unter https://github.com/settings/profile.

      Wechseln Sie den Einstellungskontext, indem Sie auf der linken Seite des Bildschirms auf Ihren Namen klicken und dann im Dropdown-Menü Ihre Organisation auswählen. Dadurch wird der Kontext von Persönliche Einstellungen in Organisationseinstellungen geändert.

      Im nächsten Bildschirm sehen Sie Ihr Organisationsprofil, in dem Sie Einstellungen wie den Anzeigenamen der Organisation, die E-Mail-Adresse der Organisation und die URL der Organisation ändern können.

      Da Grafana OAuth, einen offenen Standard zum Gewähren von Zugriff auf lokale Ressourcen an andere Remotebenutzer und Authentifizieren von Benutzern über GitHub nutzt, müssen Sie innerhalb von GitHub eine neue OAuth-Anwendung erstellen.

      Klicken Sie auf den Link OAuth-Anwendungen unter Entwicklereinstellungen unten links im Bildschirm.

      Wenn Sie in GitHub nicht bereits über OAuth-Anwendungen verfügen, die mit Ihrer Organisation verknüpft sind, erhalten Sie den Hinweis, dass keine Anwendungen im Besitz der Organisation sind. Andernfalls sehen Sie eine Liste der OAuth-Anwendungen, die bereits mit Ihrem Konto verknüpft sind.

      Klicken Sie auf die Schaltfläche Neue OAuth-Anwendung, um fortzufahren.

      Geben Sie im nächsten Bildschirm folgende Details zu Ihrer Grafana-Installation ein:

      • Anwendungsname: Damit können Sie Ihre verschiedenen OAuth-Anwendungen voneinander unterscheiden.
      • URL der Homepage: Dadurch erfährt GitHub, wo sich Grafana befindet. Geben Sie in dieses Feld https://your_domain ein, wobei Sie your_domain durch Ihre Domäne ersetzen.
      • Anwendungsbeschreibung: Damit wird eine Beschreibung des Zwecks Ihrer OAuth-Anwendung angegeben.
      • Callback-URL für Anwendung: Das ist die Adresse, an die Benutzer nach der erfolgreichen Authentifizierung weitergeleitet werden. Für Grafana muss dieses Feld https://your_domain/login/github lauten.

      Denken Sie daran, dass Grafana-Benutzer, die sich über GitHub anmelden, die Werte sehen, die Sie in den ersten drei vorangehenden Feldern eingegeben haben; geben Sie also sinnvolle und passende Werte ein.

      Am Ende wird das Formular in etwa so aussehen:

      GitHub Register OAuth-Anwendung

      Klicken Sie auf die grüne Schaltfläche Anwendung registrieren.

      Sie werden nun auf eine Seite weitergeleitet, die die Client-ID und das Clientgeheimnis enthält, die mit Ihrer neuen OAuth-Anwendung verknüpft sind. Notieren Sie sich beide Werte, da Sie sie der Hauptkonfigurationsdatei von Grafana hinzufügen müssen, um die Einrichtung abzuschließen.

      Achtung: Bewahren Sie Ihre Client-ID und das Clientgeheimnis an einem sicheren, nicht öffentlichen Ort auf, da diese Daten als Grundlage für Angriffe dienen können.

      Nach der Erstellung Ihrer GitHub OAuth-Anwendung können Sie Grafana nun neu konfigurieren, sodass GitHub zur Authentifizierung genutzt wird.

      (Optional) Schritt 6 — Konfigurieren von Grafana als GitHub OAuth-Anwendung

      Um die GitHub-Authentifizierung für Ihr Grafana-Setup zu abzuschließen, werden Sie nun einige Änderungen an Ihren Grafana-Konfigurationsdateien vornehmen.

      Öffnen Sie zunächst die Grafana-Hauptkonfigurationsdatei.

      • sudo nano /etc/grafana/grafana.ini

      Suchen Sie die Überschrift [auth.github] und heben Sie die Kommentierung dieses Abschnitts auf, indem Sie das ;-Zeichen am Anfang der einzelnen Zeilen entfernen (außer bei ;allowed_domains = und ;team_ids=, die in diesem Tutorial nicht geändert werden).

      Nehmen Sie als Nächstes folgende Änderungen vor:

      • Setzen Sie enabled und allow_sign_up auf true. Dadurch wird die GitHub-Authentifizierung aktiviert und Mitglieder der zugelassenen Organisation können Konten selbst erstellen. Beachten Sie, dass sich diese Einstellung von der Eigenschaft allow_sign_up unter [users] unterscheidet, die Sie in Schritt 4 geändert haben.
      • Setzen Sie client_id und client_secret auf die Werte, die Sie beim Erstellen Ihrer GitHub OAuth-Anwendung erhalten haben.
      • Verwenden Sie für allowed_organizations den Namen Ihrer Organisation, damit sich nur Mitglieder Ihrer Organisation bei Grafana registrieren und anmelden können.

      Die vollständige Konfiguration wird wie folgt aussehen:

      /etc/grafana/grafana.ini

      ...
      [auth.github]
      enabled = true
      allow_sign_up = true
      client_id = your_client_id_from_github
      client_secret = your_client_secret_from_github
      scopes = user:email,read:org
      auth_url = https://github.com/login/oauth/authorize
      token_url = https://github.com/login/oauth/access_token
      api_url = https://api.github.com/user
      ;allowed_domains =
      ;team_ids =
      allowed_organizations = your_organization_name
      ...
      

      Sie haben Grafana nun alles gesagt, was die Anwendung über GitHub wissen muss. Zum Abschließen der Einrichtung müssen Sie Umleitungen hinter einem Reverseproxy aktivieren. Dazu wird ein Wert root_url unter der Überschrift [server] festgelegt.

      /etc/grafana/grafana.ini

      ...
      [server]
      root_url = https://your_domain
      ...
      

      Speichern Sie Ihre Konfiguration und schließen Sie die Datei.

      Starten Sie Grafana anschließend neu, um die Änderungen zu aktivieren:

      • sudo systemctl restart grafana-server

      Vergewissern Sie sich abschließend, dass der Dienst ausgeführt wird.

      • sudo systemctl status grafana-server

      Die Ausgabe wird anzeigen, dass der Dienst active (running) ist.

      Testen Sie Ihr neues Authentifizierungssystem nun durch Navigieren zu https://your_domain. Wenn Sie bereits bei Grafana angemeldet sind, fahren Sie mit der Maus über das Avatar-Logo in der linken unteren Ecke des Bildschirms und klicken Sie im zweiten Menü, das neben Ihrem Namen erscheint, auf Abmelden.

      Auf der Anmeldeseite sehen Sie unter der ursprünglichen Schaltfläche zum Anmelden einen neuen Bereich, der eine Schaltfläche zum Anmelden mit GitHub inklusive des GitHub-Logos enthält.

      Grafana-Anmeldeseite mit GitHub

      Klicken Sie auf die Schaltfläche Anmelden mit GitHub, um an GitHub weitergeleitet zu werden, wo Sie sich bei Ihrem GitHub-Konto anmelden und Ihre Absicht zum Autorisieren von Grafana bestätigen können.

      Klicken Sie auf die grüne Schaltfläche your_github_organization autorisieren.

      Anmerkung: Stellen Sie sicher, dass Ihr GitHub-Konto Mitglied Ihrer zugelassenen Organisation ist und Ihre Grafana-E-Mail-Adresse mit Ihrer GitHub-E-Mail-Adresse übereinstimmt. Wenn Sie versuchen, sich bei einem GitHub-Konto zu authentifizieren, das kein Mitglied Ihrer zugelassenen Organisation ist, erhalten Sie eine Meldung zu Anmeldung fehlgeschlagen, in der Ihnen Folgendes mitgeteilt wird: Benutzer kein Mitglied einer der erforderlichen Organisationen.

      Sie werden nun mit Ihrem vorhandenen Grafana-Konto angemeldet. Wenn für den Benutzer, als der Sie sich angemeldet haben, noch kein Grafana-Konto vorhanden ist, wird Grafana ein neues Benutzerkonto mit Viewer-Berechtigungen erstellen, damit neue Anwender ausschließlich vorhandene Dashboards verwenden können.

      Um die Standardberechtigungen für neue Benutzer zu ändern, öffnen Sie die Hauptkonfigurationsdatei von Grafana zur Bearbeitung.

      • sudo nano /etc/grafana/grafana.ini

      Suchen Sie die Direktive auto_assign_org_role unter der Überschrift [users] und heben Sie die Kommentierung der Einstellung auf, indem Sie das ;-Zeichen am Anfang der Zeile entfernen.

      Setzen Sie die Direktive auf einen der folgenden Werte:

      • Viewer — kann nur vorhandene Dashboards verwenden
      • Editor — kann Dashboards verwenden, ändern und hinzufügen
      • Admin — kann alles tun

      In diesem Tutorial wird die automatische Zuordnung auf Viewer gesetzt:

      /etc/grafana/grafana.ini

      ...
      [users]
      ...
      auto_assign_org_role = Viewer
      ...
      

      Sobald Sie Ihre Änderungen gespeichert haben, schließen Sie die Datei und starten Sie Grafana neu:

      • sudo systemctl restart grafana-server

      Überprüfen Sie den Status des Diensts:

      • sudo systemctl status grafana-server

      Wie zuvor wird der Status active (running) lauten.

      Nun haben Sie Grafana so konfiguriert, dass Mitglieder Ihrer GitHub-Organisation Ihre Grafana-Installation registrieren und verwenden können.

      Zusammenfassung

      In diesem Tutorial haben Sie Grafana installiert, konfiguriert und gesichert und außerdem erfahren, wie sich Mitglieder Ihrer Organisation über GitHub authentifizieren können.

      Um Ihre aktuelle Grafana-Installation zu erweitern, konsultieren Sie die Liste der offiziellen und von der Community entwickelten Dashboards und Plugins. Um mehr über die allgemeine Verwendung von Grafana zu erfahren, konsultieren Sie die offizielle Grafana-Dokumentation oder unsere anderen Überwachungsleitfäden.



      Source link

      Sichern von Nginx mit Let’s Encrypt unter Ubuntu 20.04


      Einführung

      Let´s Encrypt ist eine Zertifizierungsstelle (CA), die eine einfache Möglichkeit bietet, kostenlose TLS/SSL-Zertifikate zu erhalten und zu installieren. Dadurch können Sie die verschlüsselten HTTPS auf Webservern bereitstellen. Es vereinfacht den Prozess, indem ein Software-Client, Certbot, bereitgestellt wird, der versucht, die meisten (wenn nicht alle) der erforderlichen Schritte zu automatisieren. Derzeit ist der gesamte Prozess zum Abrufen und Installieren eines Zertifikats sowohl auf Apache als auch auf Nginx vollständig automatisiert.

      In diesem Tutorial nutzen Sie Certbot, um ein kostenloses SSL-Zertifikat für Nginx auf Ubuntu 20.04 zu erhalten und Ihr Zertifikat so einzurichten, dass es automatisch erneuert wird.

      Dieses Tutorial verwendet eine separate Nginx Serverkonfiguration anstelle der Standarddatei. Wir empfehlen die Erstellung neuer Nginx-Serverblockdateien für jede Domäne, da so häufige Fehler vermieden werden können und die Standarddateien als Fallback-Konfiguration erhalten bleiben.

      Voraussetzungen

      Um dieser Anleitung zu folgen, benötigen Sie:

      • Ein Ubuntu 20.04-Server, der gemäß dem Tutorial Ersteinrichtung des Servers für Ubuntu 20.04 eingerichtet wurde, einschließlich eines Nicht-root-Benutzers mit sudo-Berechtigung und einer Firewall.

      • Einen registrierten Domänennamen. In diesem Tutorial wird durchgehend example.com genutzt. Sie können einen Domänennamen unter Namecheap erwerben oder einen kostenlosen von Freenom herunterladen oder einfach die Domänenregistrierungsstelle Ihrer Wahl verwenden.

      • Die beiden folgenden DNS-Einträge für Ihren Server eingerichtet. Wenn Sie DigitalOcean verwenden, lesen Sie bitte unsere DNS Dokumentation für Details, wie Sie sie hinzufügen.

        • Ein A-Datensatz mit example.com mit Verweis auf die öffentliche IP-Adresse Ihres Servers.
        • Ein A-Datensatz mit www.example.com, der auf die öffentliche IP-Adresse Ihres Servers verweist.
      • Nginx wird gemäß Installieren von Nginx unter Ubuntu 20.04 installiert. Stellen Sie sicher, dass Sie für Ihre Domäne einen Serverblock haben. In diesem Tutorial nutzen wir /etc/nginx/sites-available/example.com als Beispiel.

      Schritt 1 — Installieren von Certbot

      Der erste Schritt zur Nutzung von Let’s Encrypt, um ein SSL-Zertifikat zu erhalten, ist die Installation der Certbot-Software auf Ihrem Server.

      Installieren Sie Certbot und das Nginx Plugin mit apt:

      • sudo apt install certbot python3-certbot-nginx

      Certbot ist nun einsatzbereit, aber damit SSL für Nginx damit automatisch konfiguriert werden kann, müssen wir einige Bereiche der Nginx-Konfiguration überprüfen.

      Schritt 2 — Bestätigen der Nginx-Konfiguration

      Certbot muss in Ihrer Nginx-Konfiguration den richtigen Serverblock finden können, damit SSL automatisch konfiguriert werden kann. Dazu hält er nach einer server_name-Anweisung Ausschau, die zur Domäne passt, für die Sie ein Zertifikat anfordern.

      Wenn Sie den Schritt zur Einrichtung des Serverblocks im Nginx Installations-Tutorial befolgt haben, sollten Sie einen Serverblock für Ihre Domäne unter /etc/nginx/sites-available/example.com mit der Anweisung server_name haben, der bereits entsprechend eingerichtet wurde.

      Um dies zu überprüfen, öffnen Sie die Konfigurationsdatei für Ihre Domäne mit nano oder einem anderen Texteditor:

      • sudo nano /etc/nginx/sites-available/example.com

      Suchen Sie nach der Zeile server_name. Das sollte wie folgt aussehen:

      /etc/nginx/sites-available/example.com

      ...
      server_name example.com www.example.com;
      ...
      

      Wenn Sie sie gefunden haben, schließen Sie den Editor und fahren Sie mit dem nächsten Schritt fort.

      Sollten Sie sie nicht finden, aktualisieren Sie entsprechend. Speichern Sie dann die Datei, beenden Sie den Editor und überprüfen Sie die Syntax Ihrer Konfigurationsbearbeitungen:

      Wenn Sie einen Fehler erhalten, öffnen Sie die Serverblockdatei und überprüfen Sie sie auf Schreibfehler oder fehlende Zeichen. Sobald die Syntax Ihrer Konfigurationsdatei korrekt ist, laden Sie Nginx neu, um die neue Konfiguration zu laden:

      • sudo systemctl reload nginx

      Certbot kann nun den richtigen Serverblock finden und automatisch aktualisieren.

      Als Nächstes aktualisieren wir die Firewall, um den HTTPS-Datenverkehr zu ermöglichen.

      Schritt 3 — Zulassen von HTTPS durch die Firewall

      Wenn Sie die UFW-Firewall aktiviert haben, wie im Leitfaden zu den Voraussetzungen empfohlen, müssen Sie die Einstellungen so anpassen, dass Sie den HTTPS-Datenverkehr zulassen. Praktischerweise registriert Nginx einige Profile mit ufw bei der Installation.

      Sie können die aktuelle Einstellung sehen, indem Sie Folgendes eingeben:

      Sie sieht wahrscheinlich etwa so aus, was bedeutet, dass nur HTTP-Verkehr zum Webserver zugelassen ist:

      Output

      Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere Nginx HTTP ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) Nginx HTTP (v6) ALLOW Anywhere (v6)

      Um den HTTPS-Verkehr zu ermöglichen, erlauben Sie das Nginx Full Profil und löschen Sie die Zulassung des redundanten Nginx HTTP Profils:

      • sudo ufw allow 'Nginx Full'
      • sudo ufw delete allow 'Nginx HTTP'

      Ihr Status sollte nun wie folgt aussehen:

      Output

      Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere Nginx Full ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) Nginx Full (v6) ALLOW Anywhere (v6)

      Als Nächstes führen wir Certbot aus und holen unsere Zertifikate ab.

      Schritt 4 — Abrufen eines SSL-Zertifikats

      Certbot bietet eine Vielzahl von Möglichkeiten, um SSL-Zertifikate über Plugins zu erhalten. Das Nginx-Plugin übernimmt die Neukonfiguration von Nginx und das Neuladen der Konfiguration, wenn nötig. Geben Sie Folgendes ein, um dieses Plugin zu verwenden:

      • sudo certbot --nginx -d example.com -d www.example.com

      Damit wird Certbot mit dem --nginx Plugin ausgeführt, wobei über -d die Domänennamen angegeben werden, für die das Zertifikat gültig sein soll.

      Wenn Sie Certbot zum ersten Mal ausführen, werden Sie aufgefordert, eine E-Mail-Adresse einzugeben und die Bedingungen des Dienstes zu akzeptieren. Danach kommuniziert Certbot mit dem Let’s Encrypt-Server und stellt dann anhand einer Prüfung sicher, dass Sie die Domäne, für die Sie das Zertifikat anfordern, auch kontrollieren.

      Nach erfolgreicher Überprüfung fragt Certbot, wie Sie Ihre HTTPS-Einstellungen konfigurieren möchten.

      Output

      Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1: No redirect - Make no further changes to the webserver configuration. 2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for new sites, or if you're confident your site works on HTTPS. You can undo this change by editing your web server's configuration. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

      Treffen Sie Ihre Wahl und drücken Sie dann ENTER. Die Konfiguration wird aktualisiert und Nginx zum Abholen der neuen Einstellungen neu geladen. Certbot schließt mit einer Mitteilung, dass der Prozess erfolgreich war und wo Ihre Zertifikate gespeichert sind:

      Output

      IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/example.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/example.com/privkey.pem Your cert will expire on 2020-08-18. To obtain a new or tweaked version of this certificate in the future, simply run certbot again with the "certonly" option. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le

      Ihre Zertifikate werden heruntergeladen, installiert und geladen. Versuchen Sie, Ihre Website mit https:// neu zu laden und beachten Sie den Sicherheitsindikator Ihres Browsers. Es sollte angezeigt werden, dass die Seite ordnungsgemäß gesichert ist. Meist sieht man das an einem Schloss-Symbol. Wenn Sie Ihren Server mit dem SSL Labs Server Test testen, erhält er eine A-Bewertung.

      Wir wollen abschließend den Erneuerungsvorgang testen.

      Schritt 5 – Überprüfen der automatischen Erneuerung von Certbot

      Zertifikate von Let’s Encrypt sind nur neunzig Tage gültig. Das soll Benutzer dazu ermutigen, die Erneuerung ihrer Zertifikate zu automatisieren. Das Certbot-Paket, das wir installiert haben, übernimmt diese Aufgabe für uns und fügt hierfür einen systemd Timer hinzu, der sicherstellt, dass sie zweimal täglich ausgeführt wird und jedes Zertifikat automatisch nach dreißig Tagen erneuert wird.

      Sie können den Status des Timers mit systemctl abfragen:

      • sudo systemctl status certbot.timer

      Output

      ● certbot.timer - Run certbot twice daily Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled) Active: active (waiting) since Mon 2020-05-04 20:04:36 UTC; 2 weeks 1 days ago Trigger: Thu 2020-05-21 05:22:32 UTC; 9h left Triggers: ● certbot.service

      Um den Erneuerungsprozess zu testen, können Sie mit certbot einen Probelauf durchführen:

      • sudo certbot renew --dry-run

      Wenn Sie keine Fehler sehen, sind Sie fertig. Bei Bedarf erneuert Certbot Ihre Zertifikate und lädt Nginx neu, um die Änderungen zu übernehmen. Wenn der automatische Erneuerungsprozess jemals fehlschlägt, sendet Let’s Encrypt eine Nachricht an die von Ihnen angegebene E-Mail und warnt Sie, wenn Ihr Zertifikat bald abläuft.

      Zusammenfassung

      In diesem Tutorial haben Sie den Let’s Encrypt-Client Certbot installiert, SSL-Zertifikate für Ihre Domäne heruntergeladen, Nginx so konfiguriert, dass es diese Zertifikate verwendet und die automatische Zertifikatserneuerung eingerichtet. Wenn Sie weitere Fragen zur Verwendung von Certbot haben, ist die Dokumentation ein guter Ausgangspunkt.



      Source link