One place for hosting & domains

      Postgres

      Einrichten von Django mit Postgres, Nginx und Gunicorn unter Ubuntu 20.04


      Einführung

      Django ist ein leistungsfähiges Web-Framework, das Ihnen dabei helfen kann, Ihre Python-Anwendung oder Website bereitzustellen. Django umfasst einen vereinfachten Entwicklungsserver zum lokalen Testen Ihres Codes; für alles, was auch nur ansatzweise mit der Produktion zu tun hat, wird ein sicherer und leistungsfähiger Webserver benötigt.

      In diesem Leitfaden zeigen wir, wie sich bestimmte Komponenten zum Unterstützen und Bereitstellen von Django-Anwendungen in Ubuntu 20.04 installieren und konfigurieren lassen. Wir werden anstelle der standardmäßigen SQLite-Datenbank eine PostgreSQL-Datenbank einrichten. Wir werden den Gunicorn-Anwendungsserver als Schnittstelle zu unseren Anwendungen konfigurieren. Dann werden wir Nginx als Reverseproxy für Gunicorn einrichten, damit wir beim Bereitstellen unserer Anwendungen auf dessen Sicherheits- und Leistungsmerkmale zugreifen können.

      Voraussetzungen und Ziele

      Um diesen Leitfaden erfolgreich zu absolvieren, sollten Sie eine neue Ubuntu 20.04-Serverinstanz mit einer einfachen Firewall und einem Nicht-root-Benutzer mit sudo-Berechtigungen konfiguriert haben. In unserem Leitfaden zur Ersteinrichtung des Servers erfahren Sie, wie Sie die Einrichtung vornehmen.

      Wir werden Django in einer virtuellen Umgebung installieren. Wenn Sie Django in einer für Ihr Projekt spezifischen Umgebung installieren, können Sie Ihre Projekte und deren Anforderungen separat verwalten.

      Sobald wir über unsere Datenbank verfügen und die Anwendung ausgeführt wird, installieren und konfigurieren wir den Gunicorn-Anwendungsserver. Dieser wird als Schnittstelle zu unserer Anwendung dienen und Clientanfragen aus HTTP in Python-Aufrufe übersetzen, die unsere Anwendung verarbeiten kann. Dann richten wir Nginx vor Gunicorn ein, um dessen leistungsfähige Verbindungsverwaltungsmechanismen und einfach zu implementierenden Sicherheitsfunktionen nutzen zu können.

      Fangen wir an.

      Installieren der Pakete aus den Ubuntu-Repositorys

      Zu Beginn laden wir alle Elemente, die wir benötigen, aus den Ubuntu-Repositorys herunter und installieren sie. Ein wenig später werden wir mit dem Python-Paketmanager pip zusätzliche Komponenten installieren.

      Wir müssen zuerst den lokalen Paketindex apt aktualisieren und dann die Pakete herunterladen und installieren: Die installierten Pakete hängen davon ab, welche Version von Python Sie für Ihr Projekt verwenden werden.

      Wenn Sie Django mit Python 3 nutzen, geben Sie Folgendes ein:

      • sudo apt update
      • sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

      Django 1.11 ist die letzte Version von Django, die Python 2 unterstützt. Wenn Sie neue Projekte starten, wird dringend empfohlen, Python 3 zu wählen. Wenn Sie Python 2 weiter verwenden müssen, geben Sie Folgendes ein:

      • sudo apt update
      • sudo apt install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx curl

      Dadurch werden pip, die Python-Entwicklungsdateien, die zum späteren Erstellen von Gunicorn benötigt werden, das Postgres-Datenbankysystem, die zum Interagieren damit erforderlichen Bibliotheken sowie der Nginx-Webserver installiert.

      Erstellen der PostgreSQL-Datenbank und des Benutzers

      Wir legen sofort los und erstellen für unsere Django-Anwendung eine Datenbank und einen Datenbankbenutzer.

      Standardmäßig nutzt Postgres ein Authentifizierungschema namens „Peer Authentication“ für lokale Verbindungen. Im Grunde bedeutet dies, dass sich der Benutzer ohne weitere Authentifizierung anmelden kann, wenn der Benutzername des Benutzers im Betriebssystem mit einem gültigen Postgres-Benutzernamen übereinstimmt.

      Während der Postgres-Installation wurde ein Betriebssystembenutzer namens postgres erstellt, der dem administrativen PostgreSQL-Benutzer postgres entspricht. Wir benötigen diesen Benutzer zur Erledigung administrativer Aufgaben. Wir können sudo verwenden und den Benutzernamen mit der Option -u übergeben.

      Melden Sie sich in einer interaktiven Postgres-Sitzung an, indem Sie Folgendes eingeben:

      Ihnen wird eine PostgreSQL-Eingabeaufforderung angezeigt, in der Sie Ihre Anforderungen einrichten können.

      Erstellen Sie zunächst eine Datenbank für Ihr Projekt:

      • CREATE DATABASE myproject;

      Anmerkung: Jede Postgres-Anweisung muss mit einem Semikolon enden; stellen Sie sicher, dass Ihr Befehl auf ein Semikolon endet, falls Probleme auftreten.

      Erstellen Sie als Nächstes einen Datenbankbenutzer für das Projekt. Wählen Sie unbedingt ein sicheres Passwort:

      • CREATE USER myprojectuser WITH PASSWORD 'password';

      Anschließend ändern wir einige der Verbindungsparameter für den gerade erstellten Benutzer. Dadurch werden Datenbankoperationen beschleunigt, sodass die richtigen Werte nicht jedes Mal abgefragt und festgelegt werden müssen, wenn eine Verbindung hergestellt wird.

      Wir legen die Standardkodierung auf UTF-8 fest, was Django erwartet. Außerdem legen wir das standardmäßige Transaktionsisolierungsschema auf „read committed“ fest, um das Lesen von Blöcken aus Transaktionen ohne Commit zu blockieren. Schließlich legen wir die Zeitzone fest. Standardmäßig werden unsere Django-Projekte die Zeitzone UTC verwenden. Dies sind alles Empfehlungen aus dem Django-Projekt selbst:

      • ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
      • ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
      • ALTER ROLE myprojectuser SET timezone TO 'UTC';

      Jetzt können wir unserem neuen Benutzer Zugriff zum Verwalten unserer neuen Datenbank gewähren:

      • GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

      Wenn Sie damit fertig sind, beenden Sie die PostgreSQL-Eingabeaufforderung durch folgende Eingabe:

      Postgres ist nun so eingerichtet, dass Django eine Verbindung herstellen und dessen Datenbankinformationen verwalten kann.

      Erstellen einer virtuellen Python-Umgebung für Ihr Projekt

      Nachdem wir unsere Datenbank erstellt haben, können wir nun damit beginnen, die restlichen Projektanforderungen zu erfüllen. Wir werden unsere Python-Anforderungen zur einfacheren Verwaltung in einer virtuellen Umgebung installieren.

      Dazu benötigen wir zunächst Zugriff auf den Befehl virtualenv. Wir können ihn mit pip installieren.

      Wenn Sie Python 3 verwenden, aktualisieren Sie pip und installieren Sie das Paket durch folgende Eingabe:

      • sudo -H pip3 install --upgrade pip
      • sudo -H pip3 install virtualenv

      Wenn Sie Python 2 verwenden, aktualisieren Sie pip und installieren Sie das Paket durch folgende Eingabe:

      • sudo -H pip install --upgrade pip
      • sudo -H pip install virtualenv

      Nach der Installation von virtualenv können wir mit der Gestaltung unseres Projekts beginnen. Erstellen und wechseln Sie in ein Verzeichnis, in dem wir unsere Projektdateien speichern können.

      • mkdir ~/myprojectdir
      • cd ~/myprojectdir

      Erstellen Sie im Projektverzeichnis durch folgende Eingabe eine virtuelle Python-Umgebung:

      Auf diese Weise wird ein Verzeichnis mit dem Namen myprojectenv in Ihrem Verzeichnis myprojectdir erstellt. Darin wird eine lokale Version von Python und eine lokale Version von pip installiert. Mit ihrer Hilfe können wir für unser Projekt eine isolierte Python-Umgebung installieren und konfigurieren.

      Bevor wir die Python-Anforderungen unseres Projekts installieren, müssen wir die virtuelle Umgebung aktivieren. Geben Sie hierzu Folgendes ein:

      • source myprojectenv/bin/activate

      Ihre Eingabeaufforderung ändert sich und zeigt an, dass Sie jetzt innerhalb einer virtuellen Python-Umgebung arbeiten. Sie sieht etwa wie folgt aus: (myprojectenv)user@host:~/myprojectdir$.

      Bei aktivierter virtueller Umgebung installieren Sie Django, Gunicorn und den PostgreSQL-Adapter psycopg2 mit der lokalen Instanz von pip:

      Anmerkung: Wenn die virtuelle Umgebung aktiviert ist (wenn Ihrer Eingabeaufforderung (myprojectenv) voransteht), verwenden Sie pip anstelle von pip3, selbst wenn Sie Python 3 verwenden. Die Kopie des Tools der virtuellen Umgebung heißt immer pip – unabhängig von der Python-Version.

      • pip install django gunicorn psycopg2-binary

      Sie sollten nun die gesamte für den Start eines Django-Projekts erforderliche Software haben.

      Erstellen und Konfigurieren eines neuen Django-Projekts

      Nach der Installation unserer Python-Komponenten können wir die eigentlichen Django-Projektdateien erstellen.

      Erstellen des Django-Projekts

      Da wir bereits über ein Projektverzeichnis verfügen, werden wir Django anweisen, die Dateien dort zu installieren. Es wird ein Verzeichnis der zweiten Ebene mit dem tatsächlichen Code erstellt, was normal ist, und ein Managementskript in diesem Verzeichnis platziert. Der Schlüssel dazu besteht darin, dass wir das Verzeichnis explizit definieren, anstatt Django Entscheidungen in Bezug auf unser aktuelles Verzeichnis zu ermöglichen:

      • django-admin.py startproject myproject ~/myprojectdir

      An diesem Punkt sollte Ihr Projektverzeichnis (in unserem Fall ~/myprojectdir) folgenden Inhalt haben:

      • ~/myprojectdir/manage.py: Ein Django-Projektmanagement-Skript.
      • ~/myprojectdir/myproject/: Das Django-Projektpaket. Dieses sollte die Dateien __init__.py, settings.py, urls.py, asgi.py und wsgi.py enthalten.
      • ~/myprojectdir/myprojectenv/: Das Verzeichnis der virtuellen Umgebung, die wir zuvor erstellt haben.

      Anpassen der Projekteinstellungen

      Das Erste, was wir mit unseren neu erstellten Projektdateien tun sollten, ist das Anpassen der Einstellungen. Öffnen Sie die Einstellungsdatei in Ihrem Texteditor:

      • nano ~/myprojectdir/myproject/settings.py

      Suchen Sie zunächst nach der Direktive ALLOWED_HOSTS. Dadurch wird eine Liste der Adressen oder Domänennamen des Servers definiert, die zum Herstellen einer Verbindung mit der Django-Instanz genutzt werden können. Alle eingehenden Anfragen mit einem Host, der sich nicht in dieser Liste befindet, werden eine Ausnahme auslösen. Django verlangt, dass Sie dies so festlegen, um eine bestimmte Art von Sicherheitslücke zu verhindern.

      In den quadratischen Klammern listen Sie die IP-Adressen oder Domänennamen auf, die mit Ihrem Django-Projekt verknüpft sind. Jedes Element sollte in Anführungszeichen aufgelistet werden, wobei Einträge durch ein Komma getrennt werden. Wenn Sie Anfragen für eine ganze Domäne und Subdomänen wünschen, stellen Sie dem Anfang des Eintrags einen Punkt voran. Im folgenden Snippet befinden sich einige auskommentierte Beispiele:

      Anmerkung: Stellen Sie sicher, dass localhost als eine der Optionen eingeschlossen ist, da wir Verbindungen über eine lokale Nginx-Instanz vermitteln werden.

      ~/myprojectdir/myproject/settings.py

      . . .
      # The simplest case: just add the domain name(s) and IP addresses of your Django server
      # ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']
      # To respond to 'example.com' and any subdomains, start the domain with a dot
      # ALLOWED_HOSTS = ['.example.com', '203.0.113.5']
      ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']
      

      Als Nächstes suchen Sie nach dem Bereich, der Datenbankzugriff konfiguriert. Er beginnt mit DATABASES. Die Konfiguration in der Datei dient für eine SQLite-Datenbank. Wir haben für unser Projekt bereits eine PostgreSQL-Datenbank erstellt; daher müssen wir die Einstellungen anpassen.

      Ändern Sie die Einstellungen mit Ihren PostgreSQL-Datenbankinformationen. Wir weisen Django an, den mit pip installierten psycopg2-Adapter zu verwenden. Wir müssen den Datenbanknamen, den Namen des Datenbankbenutzers und das Passwort des Datenbankbenutzers angeben. Dann geben wir an, dass sich die Datenbank auf dem lokalen Computer befindet. Sie können die PORT-Einstellung als leere Zeichenfolge belassen:

      ~/myprojectdir/myproject/settings.py

      . . .
      
      DATABASES = {
          'default': {
              'ENGINE': 'django.db.backends.postgresql_psycopg2',
              'NAME': 'myproject',
              'USER': 'myprojectuser',
              'PASSWORD': 'password',
              'HOST': 'localhost',
              'PORT': '',
          }
      }
      
      . . .
      

      Als Nächstes bewegen Sie sich nach unten zum Ende der Datei und fügen eine Einstellung hinzu, die angibt, wo die statischen Dateien platziert werden sollen. Das ist notwendig, damit Nginx Anfragen für diese Elemente verwalten kann. In der folgenden Zeile wird Django angewiesen, sie im grundlegenden Projektverzeichnis in einem Verzeichnis mit dem Namen static zu platzieren:

      ~/myprojectdir/myproject/settings.py

      . . .
      
      STATIC_URL = '/static/'
      STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
      

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

      Abschließen der anfänglichen Projekteinrichtung

      Jetzt können wir das erste Datenbankschema mit dem Managementskript in unsere PostgreSQL-Datenbank migrieren:

      • ~/myprojectdir/manage.py makemigrations
      • ~/myprojectdir/manage.py migrate

      Erstellen Sie durch folgende Eingabe einen administrativen Benutzer für das Projekt:

      • ~/myprojectdir/manage.py createsuperuser

      Sie müssen einen Benutzernamen auswählen, eine E-Mail-Adresse angeben und ein Passwort bestätigen.

      Wir können alle statischen Inhalte am von uns konfigurierten Verzeichnisort sammeln, indem wir Folgendes eingeben:

      • ~/myprojectdir/manage.py collectstatic

      Sie müssen die Operation bestätigen. Die statischen Dateien werden dann in Ihrem Projektverzeichnis in einem Verzeichnis mit dem Namen static platziert.

      Wenn Sie den Leitfaden zur Ersteinrichtung des Servers befolgt haben, sollte Ihre UFW-Firewall Ihren Server schützen. Um den Entwicklungsserver zu testen, müssen wir Zugriff auf den Port gewähren, den wir dazu verwenden möchten.

      Erstellen Sie durch folgende Eingabe eine Ausnahme für Port 8000:

      Schließlich können Sie Ihr Projekt durch Starten des Django-Entwicklungsservers mit diesem Befehl testen:

      • ~/myprojectdir/manage.py runserver 0.0.0.0:8000

      Rufen Sie in Ihrem Webbrowser den Domänennamen oder die IP-Adresse Ihres Servers auf, gefolgt von :8000:

      http://server_domain_or_IP:8000
      

      Sie sollten nun die Indexseite von Django erhalten:

      Django-Indexseite

      Wenn Sie am Ende der URL in der Adressleiste /admin anfügen, werden Sie zur Eingabe des administrativen Benutzernamens und Passworts aufgefordert, die Sie mit dem Befehl createsuperuser erstellt haben:

      Django-Admin-Anmeldung

      Nach der Authentifizierung können Sie auf die standardmäßige Admin-Schnittstelle von Django zugreifen:

      Django-Admin-Schnittstelle

      Wenn Sie mit der Erkundung fertig sind, klicken Sie im Terminalfenster auf Strg+C, um den Entwicklungsserver herunterzufahren.

      Testen der Fähigkeit von Gunicorn zum Bereitstellen des Projekts

      Das Letzte, was wir tun möchten, bevor wir unsere virtuelle Umgebung verlassen, ist Gunicorn zu testen. Dadurch wollen wir sicherstellen, dass die Anwendung bereitgestellt werden kann. Wir geben dazu unser Projektverzeichnis ein und verwenden gunicorn zum Laden des WSGI-Moduls des Projekts:

      • cd ~/myprojectdir
      • gunicorn --bind 0.0.0.0:8000 myproject.wsgi

      Dadurch wird Gunicorn an der gleichen Schnittstelle gestartet, an der auch der Django-Server ausgeführt wurde. Sie können zurückgehen und die Anwendung erneut testen.

      Anmerkung: Die Admin-Schnittstelle wird keinen der verwendeten Stile verwenden, da Gunicorn nicht weiß, wo der dafür zuständige statische CSS-Inhalt zu finden ist.

      Wir haben Gunicorn einem Modul übergeben, indem wir mithilfe der Modulsyntax von Python den relativen Verzeichnispfad zur Datei wsgi.py von Django angegeben haben. Diese ist der Einstiegspunkt für unsere Anwendung. In dieser Datei ist eine Funktion namens application definiert, die zur Kommunikation mit der Anwendung dient. Um mehr über die WSGI-Spezifikation zu erfahren, klicken Sie hier.

      Wenn Sie mit dem Testen fertig sind, drücken Sie im Terminalfenster auf Strg+C, um Gunicorn anzuhalten.

      Wir sind nun fertig mit der Konfiguration unserer Django-Anwendung. Wir können unsere virtuelle Umgebung durch folgende Eingabe verlassen:

      Der Indikator für die virtuelle Umgebung in Ihrer Eingabeaufforderung wird entfernt.

      Erstellen von systemd-Socket- und Service-Dateien für Gunicorn

      Wir haben getestet, ob Gunicorn mit unserer Django-Anwendung interagieren kann. Wir sollten jedoch eine effektivere Methode zum Starten und Anhalten des Anwendungsservers implementieren. Dazu erstellen wir systemd-Service- und Socket-Dateien.

      Das Gunicorn-Socket wird beim Booten erstellt und nach Verbindungen lauschen. Wenn eine Verbindung hergestellt wird, startet systemd automatisch den Gunicorn-Prozess, um die Verbindung zu verwalten.

      Erstellen und öffnen Sie zunächst eine systemd-Socket-Datei für Gunicorn mit sudo-Berechtigungen:

      • sudo nano /etc/systemd/system/gunicorn.socket

      Darin erstellen wir einen Abschnitt [Unit], um das Socket zu beschreiben, einen Abschnitt [Socket], um den Ort des Sockets zu definieren, und einen Abschnitt [Install], um sicherzustellen, dass das Socket zum richtigen Zeitpunkt erstellt wird:

      /etc/systemd/system/gunicorn.socket

      [Unit]
      Description=gunicorn socket
      
      [Socket]
      ListenStream=/run/gunicorn.sock
      
      [Install]
      WantedBy=sockets.target
      

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

      Erstellen und öffnen Sie in Ihrem Texteditor als Nächstes eine systemd-Service-Datei für Gunicorn mit sudo-Berechtigungen. Der Name der Service-Datei sollte mit Ausnahme der Erweiterung mit dem Namen der Socket-Datei übereinstimmen:

      • sudo nano /etc/systemd/system/gunicorn.service

      Beginnen Sie mit dem Abschnitt [Unit], mit dem Metadaten und Abhängigkeiten angegeben werden. Wir werden hier eine Beschreibung unseres Diensts eingeben und das Init-System anweisen, ihn erst zu starten, nachdem das Netzwerkziel erreicht wurde. Da sich unser Dienst auf das Socket aus der Socket-Datei bezieht, müssen wir eine Requires-Direktive einschließen, um diese Beziehung anzugeben:

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      

      Als Nächstes werden wir den Abschnitt [Service] öffnen. Wir werden den Benutzer und die Gruppe angeben, unter denen wir den Prozess ausführen möchten. Wir wollen unserem regulären Benutzerkonto die Prozessverantwortung übergeben, da es alle relevanten Dateien besitzt. Wir werden der Gruppe www-data die Gruppenverantwortung übergeben, damit Nginx einfach mit Gunicorn kommunizieren kann.

      Dann werden wir das Arbeitsverzeichnis zuordnen und den Befehl zum Starten des Diensts angeben. In diesem Fall müssen wir den vollständigen Pfad zur ausführbaren Gunicorn-Datei angeben, die in unserer virtuellen Umgebung installiert ist. Wir werden den Prozess mit dem im Verzeichnis /run erstellten Unix-Socket verknüpfen, damit der Prozess mit Nginx kommunizieren kann. Wir protokollieren alle Daten in der Standardausgabe, damit der journald-Prozess die Gunicorn-Protokolle erfassen kann. Außerdem können wir hier optionale Gunicorn-Optimierungen angeben. Beispielsweise haben wir in diesem Fall drei Workerprozesse angegeben:

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myprojectdir
      ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn 
                --access-logfile - 
                --workers 3 
                --bind unix:/run/gunicorn.sock 
                myproject.wsgi:application
      

      Schließlich werden wir einen Abschnitt [Install] hinzufügen. Dies teilt systemd mit, womit dieser Dienst verknüpft werden soll, wenn wir festlegen, dass er während des Startvorgangs starten soll. Wir wollen, dass dieser Dienst startet, wenn das normale Mehrbenutzersystem arbeitet.

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myprojectdir
      ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn 
                --access-logfile - 
                --workers 3 
                --bind unix:/run/gunicorn.sock 
                myproject.wsgi:application
      
      [Install]
      WantedBy=multi-user.target
      

      Damit ist unsere systemd-Dienstdatei fertiggestellt. Speichern und schließen Sie diese jetzt.

      Wir können nun starten und das Gunicorn-Socket aktivieren. Dadurch wird die Socket-Datei nun unter /run/gunicorn.sock und beim Booten erstellt. Wenn eine Verbindung zu diesem Socket hergestellt wird, startet systemd automatisch den gunicorn.service, um die Verbindung zu verwalten:

      • sudo systemctl start gunicorn.socket
      • sudo systemctl enable gunicorn.socket

      Wir können uns vergewissern, dass der Vorgang erfolgreich war, indem wir nach der Socket-Datei suchen.

      Suchen nach der Gunicorn-Socket-Datei

      Überprüfen Sie den Status des Prozesses, um herauszufinden, ob er gestartet werden konnte:

      • sudo systemctl status gunicorn.socket

      Sie sollten eine Ausgabe wie diese erhalten:

      Output

      ● gunicorn.socket - gunicorn socket Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor prese> Active: active (listening) since Fri 2020-06-26 17:53:10 UTC; 14s ago Triggers: ● gunicorn.service Listen: /run/gunicorn.sock (Stream) Tasks: 0 (limit: 1137) Memory: 0B CGroup: /system.slice/gunicorn.socket

      Überprüfen Sie als Nächstes, ob die Datei gunicorn.sock im Verzeichnis /run vorhanden ist:

      Output

      /run/gunicorn.sock: socket

      Wenn der Befehl systemctl status angegeben hat, dass ein Fehler aufgetreten ist, oder Sie die Datei gunicorn.sock im Verzeichnis nicht finden können, ist dies ein Hinweis darauf, dass das Gunicorn-Socket nicht richtig erstellt wurde. Überprüfen Sie die Protokolle des Gunicorn-Sockets durch folgende Eingabe:

      • sudo journalctl -u gunicorn.socket

      Werfen Sie einen erneuten Blick auf Ihre Datei /etc/systemd/system/gunicorn.socket, um alle vorhandenen Probleme zu beheben, bevor Sie fortfahren.

      Testen der Socket-Aktivierung

      Wenn Sie derzeit nur die Einheit gunicorn.socket gestartet haben, wird der gunicorn.service aktuell noch nicht aktiv sein, da das Socket noch keine Verbindungen erhalten hat. Geben Sie zum Überprüfen Folgendes ein:

      • sudo systemctl status gunicorn

      Output

      ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: inactive (dead)

      Zum Testen des Socket-Aktivierungsverfahrens können wir über curl eine Verbindung an das Socket senden, indem wir Folgendes eingeben:

      • curl --unix-socket /run/gunicorn.sock localhost

      Sie sollten die HTML-Ausgabe von Ihrer Anwendung im Terminal erhalten. Das bedeutet, dass Gunicorn gestartet wurde und Ihre Django-Anwendung bereitstellen konnte. Sie können überprüfen, ob der Gunicorn-Service ausgeführt wird, indem Sie Folgendes eingeben:

      • sudo systemctl status gunicorn

      Output

      ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: active (running) since Fri 2020-06-26 18:52:21 UTC; 2s ago TriggeredBy: ● gunicorn.socket Main PID: 22914 (gunicorn) Tasks: 4 (limit: 1137) Memory: 89.1M CGroup: /system.slice/gunicorn.service ├─22914 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22927 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22928 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> └─22929 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> Jun 26 18:52:21 django-tutorial systemd[1]: Started gunicorn daemon. Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Starting gunicorn 20.0.4 Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Listening at: unix:/run/gunicorn.sock (22914) Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Using worker: sync Jun 26 18:52:21 django-tutorial gunicorn[22927]: [2020-06-26 18:52:21 +0000] [22927] [INFO] Booting worker with pid: 22927 Jun 26 18:52:21 django-tutorial gunicorn[22928]: [2020-06-26 18:52:21 +0000] [22928] [INFO] Booting worker with pid: 22928 Jun 26 18:52:21 django-tutorial gunicorn[22929]: [2020-06-26 18:52:21 +0000] [22929] [INFO] Booting worker with pid: 22929

      Wenn die Ausgabe von curl oder die Ausgabe von systemctl status anzeigt, dass ein Problem aufgetreten ist, prüfen Sie die Protokolle auf weitere Details:

      • sudo journalctl -u gunicorn

      Überprüfen Sie Ihre Datei /etc/systemd/system/gunicorn.service auf Probleme. Wenn Sie Änderungen an der Datei /etc/systemd/system/gunicorn.service vornehmen, laden Sie das Daemon neu, um die Dienstdefinition neu zu lesen, und starten Sie den Gunicorn-Prozess neu, indem Sie Folgendes eingeben:

      • sudo systemctl daemon-reload
      • sudo systemctl restart gunicorn

      Sorgen Sie dafür, dass die oben genannten Probleme behoben werden, bevor Sie fortfahren.

      Konfigurieren von Nginx zur Proxy-Übergabe an Gunicorn

      Nachdem Gunicorn eingerichtet ist, müssen wir nun Nginx so konfigurieren, dass Datenverkehr an den Prozess übergeben wird.

      Erstellen und öffnen Sie zunächst einen neuen Serverblock im Verzeichnis sites-available von Nginx:

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

      Öffnen Sie darin einen neuen Serverblock. Wir geben zunächst an, dass dieser Block am normalen Port 80 lauschen und auf den Domänennamen oder die IP-Adresse unseres Servers reagieren soll:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      }
      

      Als Nächstes weisen wir Nginx an, alle Probleme bei der Suche nach einem Favicon zu ignorieren. Außerdem teilen wir Nginx mit, wo die statischen Assets zu finden sind, die wir in unserem Verzeichnis ~/myprojectdir/static gesammelt haben. Alle diese Dateien verfügen über das Standard-URI-Präfix “/static”; daher können wir einen Ortsblock erstellen, um diese Anfragen abzugleichen:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      
          location = /favicon.ico { access_log off; log_not_found off; }
          location /static/ {
              root /home/sammy/myprojectdir;
          }
      }
      

      Schließlich erstellen wir einen location / {}-Block zum Abgleichen aller anderen Anforderungen. In diesen Block werden wir die standardmäßige Datei proxy_params einschließen, die in der Nginx-Installation enthalten ist, und dann den Datenverkehr direkt an das Gunicorn-Socket übergeben.

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      
          location = /favicon.ico { access_log off; log_not_found off; }
          location /static/ {
              root /home/sammy/myprojectdir;
          }
      
          location / {
              include proxy_params;
              proxy_pass http://unix:/run/gunicorn.sock;
          }
      }
      

      Wenn Sie dies abgeschlossen haben, speichern und schließen Sie die Datei. Jetzt können wir die Datei aktivieren, indem wir sie mit dem Verzeichnis sites-enabled verknüpfen:

      • sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

      Prüfen Sie Ihre Nginx-Konfiguration durch folgende Eingabe auf Syntaxfehler:

      Wenn keine Fehler gemeldet werden, fahren Sie fort und starten Sie Nginx neu, indem Sie Folgendes eingeben:

      • sudo systemctl restart nginx

      Schließlich müssen wir unsere Firewall an Port 80 für normalen Datenverkehr öffnen. Da wir keinen Zugriff mehr auf den Entwicklungsserver benötigen, können wir außerdem die Regel zum Öffnen von Port 8000 entfernen:

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

      Sie sollten nun in der Lage sein, die Domäne oder IP-Adresse Ihres Servers aufzurufen, um Ihre Anwendung anzuzeigen.

      Anmerkung: Nach der Konfiguration von Nginx sollte der nächste Schritt aus dem Sichern des Datenverkehrs zum Server mit SSL/TLS bestehen. Das ist äußerst wichtig, da ohne SSL/TLS alle Informationen, einschließlich Passwörter, in Klartext über das Netzwerk gesendet werden.

      Wenn Sie einen Domänennamen haben, ist Let’s Encrypt der einfachste Weg, um sich ein SSL-Zertifikat zum Sichern Ihres Datenverkehrs zu verschaffen. Folgen Sie diesem Leitfaden zum Einrichten von Let’s Encrypt mit Nginx unter Ubuntu 20.04. Befolgen Sie das Verfahren mit dem Nginx-Serverblock, den wir in diesem Leitfaden erstellt haben.

      Fehlerbehebung bei Nginx und Gunicorn

      Wenn Ihre Anwendung in diesem letzten Schritt nicht angezeigt wird, müssen Sie Probleme mit Ihrer Installation beheben.

      Nginx zeigt anstelle der Django-Anwendung die Standardseite an

      Wenn Nginx die Standardseite und nicht einen Proxy zu Ihrer Anwendung anzeigt, bedeutet das in der Regel, dass Sie den server_name in der Datei /etc/nginx/sites-available/myproject so ändern müssen, dass er auf die IP-Adresse oder den Domänennamen Ihres Servers verweist.

      Nginx verwendet den server_name, um zu bestimmen, welcher Serverblock für Antworten auf Anfragen verwendet werden soll. Wenn Sie die Nginx-Standardseite erhalten, ist das ein Zeichen dafür, dass Nginx die Anfrage nicht explizit mit einem Serverblock abgleichen konnte. Darum greift Nginx auf den Standardblock zurück, der in /etc/nginx/sites-available/default definiert ist.

      Der server_name im Serverblock Ihres Projekts muss spezifischer sein als der im auszuwählenden standardmäßigen Serverblock.

      Nginx zeigt anstelle der Django-Anwendung einen 502-Fehler (Ungültiges Gateway) an

      Ein 502-Fehler zeigt, dass Nginx die Anfrage per Proxy nicht erfolgreich vermitteln kann. Eine Vielzahl von Konfigurationsproblemen äußern sich in einem 502-Fehler; für eine angemessene Fehlerbehebung sind also weitere Informationen erforderlich.

      Der primäre Ort zur Suche nach weiteren Informationen sind die Fehlerprotokolle von Nginx. Generell werden sie Ihnen mitteilen, welche Bedingungen während des Proxying-Ereignisses Probleme verursacht haben. Folgen Sie den Nginx-Fehlerprotokollen, indem Sie Folgendes eingeben:

      • sudo tail -F /var/log/nginx/error.log

      Erstellen Sie nun in Ihrem Browser eine weitere Anfrage zur Generierung eines neuen Fehlers (versuchen Sie, die Seite zu aktualisieren). Sie sollten eine neue Fehlermeldung erhalten, die in das Protokoll geschrieben wird. Wenn Sie sich die Nachricht ansehen, sollten Sie das Problem eingrenzen können.

      Sie erhalten möglicherweise die folgende Meldung:

      connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)

      Das bedeutet, dass Nginx die Datei gunicorn.sock am angegebenen Ort nicht finden konnte. Sie sollten den proxy_pass-Ort, der in der Datei /etc/nginx/sites-available/myproject definiert ist, mit dem tatsächlichen Ort der Datei gunicorn.sock vergleichen, die von der Datei gunicorn.socket generiert wurde.

      Wenn Sie keine gunicorn.sock-Datei im Verzeichnis /run finden können, bedeutet das im Allgemeinen, dass die systemd-Socket-Datei sie nicht erstellen konnte. Kehren Sie zurück zum Abschnitt zum Suchen nach der Gunicorn-Socket-Datei, um die Schritte zur Fehlerbehebung für Gunicorn zu durchlaufen.

      connect() to unix:/run/gunicorn.sock failed (13: Permission denied)

      Das bedeutet, dass Nginx aufgrund von Berechtigungsproblemen keine Verbindung zum Gunicorn-Socket herstellen konnte. Dies kann geschehen, wenn das Verfahren mit dem root user anstelle eines sudo-Benutzers ausgeführt wird. Zwar kann systemd die Gunicorn-Socket-Datei erstellen, doch kann Nginx nicht darauf zugreifen.

      Dies kann geschehen, wenn es an einem beliebigen Punkt zwischen dem root-Verzeichnis (/) der Datei gunicorn.sock begrenzte Berechtigungen gibt. Wir können die Berechtigungen und Verantwortungswerte der Socket-Datei und jedes der übergeordneten Verzeichnisse überprüfen, indem wir den absoluten Pfad zu unserer Socket-Datei dem Befehl namei übergeben:

      • namei -l /run/gunicorn.sock

      Output

      f: /run/gunicorn.sock drwxr-xr-x root root / drwxr-xr-x root root run srw-rw-rw- root root gunicorn.sock

      Die Ausgabe zeigt die Berechtigungen der einzelnen Verzeichniskomponenten an. Indem wir uns die Berechtigungen (erste Spalte), den Besitzer (zweite Spalte) und den Gruppenbesitzer (dritte Spalte) ansehen, können wir ermitteln, welche Art des Zugriffs auf die Socket-Datei erlaubt ist.

      Im obigen Beispiel haben die Socket-Datei und die einzelnen Verzeichnisse, die zur Socket-Datei führen, globale Lese- und Ausführungsberechtigungen (die Berechtigungsspalte für die Verzeichnisse endet mit r-x anstelle von ---). Der Nginx-Prozess sollte erfolgreich auf das Socket zugreifen können.

      Wenn eines der Verzeichnisse, das zum Socket führt, keine globale Lese- und Ausführungsberechtigung aufweist, kann Nginx nicht auf das Socket zugreifen, ohne globale Lese- und Ausführungsberechtigungen zuzulassen oder sicherzustellen, dass die Gruppenverantwortung einer Gruppe erteilt wird, zu der Nginx gehört.

      Django zeigt an: “could not connect to server: Connection refused”

      Eine Meldung, die Sie bei dem Versuch, im Webbrowser auf Teile der Anwendung zuzugreifen, von Django erhalten können, lautet:

      OperationalError at /admin/login/
      could not connect to server: Connection refused
          Is the server running on host "localhost" (127.0.0.1) and accepting
          TCP/IP connections on port 5432?
      

      Das bedeutet, dass Django keine Verbindung zur Postgres-Datenbank herstellen kann. Vergewissern Sie sich durch folgende Eingabe, dass die Postgres-Instanz ausgeführt wird:

      • sudo systemctl status postgresql

      Wenn nicht, können Sie sie starten und so aktivieren, dass sie beim Booten automatisch gestartet wird (wenn sie nicht bereits entsprechend konfiguriert ist); geben Sie dazu Folgendes ein:

      • sudo systemctl start postgresql
      • sudo systemctl enable postgresql

      Wenn Sie weiter Probleme haben, stellen Sie sicher, dass die in der Datei ~/myprojectdir/myproject/settings.py definierten Datenbankeinstellungen korrekt sind.

      Weitere Fehlerbehebung

      Bei der weiteren Fehlerbehebung können die Protokolle dazu beitragen, mögliche Ursachen einzugrenzen. Prüfen Sie sie nacheinander und suchen Sie nach Meldungen, die auf Problembereiche hinweisen.

      Folgende Protokolle können hilfreich sein:

      • Prüfen Sie die Nginx-Prozessprotokolle, indem Sie Folgendes eingeben: sudo journalctl -u nginx
      • Prüfen Sie die Nginx-Zugangsprotokolle, indem Sie Folgendes eingeben: sudo less /var/log/nginx/access.log
      • Prüfen Sie die Nginx-Fehlerprotokolle, indem Sie Folgendes eingeben: sudo less /var/log/nginx/error.log
      • Prüfen Sie die Gunicorn-Anwendungsprotokolle, indem Sie Folgendes eingeben: sudo journalctl -u gunicorn
      • Prüfen Sie die Gunicorn-Socket-Protokolle, indem Sie Folgendes eingeben: sudo journalctl -u gunicorn.socket

      Wenn Sie Ihre Konfiguration oder Anwendung aktualisieren, müssen Sie die Prozesse wahrscheinlich neu starten, damit Ihre Änderungen aktiv werden.

      Wenn Sie Ihre Django-Anwendung aktualisieren, können Sie den Gunicorn-Prozess durch folgende Eingabe neu starten, um die Änderungen zu erfassen:

      • sudo systemctl restart gunicorn

      Wenn Sie Gunicorn-Socket- oder Service-Dateien ändern, laden Sie das Daemon neu und starten Sie den Prozess neu, indem Sie Folgendes eingeben:

      • sudo systemctl daemon-reload
      • sudo systemctl restart gunicorn.socket gunicorn.service

      Wenn Sie die Konfiguration des Nginx-Serverblocks ändern, testen Sie die Konfiguration und dann Nginx, indem Sie Folgendes eingeben:

      • sudo nginx -t && sudo systemctl restart nginx

      Diese Befehle sind hilfreich, um Änderungen zu erfassen, während Sie Ihre Konfiguration anpassen.

      Zusammenfassung

      In diesem Leitfaden haben wir ein Django-Projekt in seiner eigenen virtuellen Umgebung eingerichtet. Wir haben Gunicorn so konfiguriert, dass Clientanfragen übersetzt werden, damit Django sie verwalten kann. Anschließend haben wir Nginx als Reverseproxy eingerichtet, um Clientverbindungen zu verwalten und je nach Clientanfrage das richtige Projekt bereitzustellen.

      Django macht die Erstellung von Projekten und Anwendungen durch Bereitstellung vieler der gängigen Elemente besonders einfach; so können Sie sich ganz auf die individuellen Elemente konzentrieren. Durch Nutzung der in diesem Artikel beschriebenen allgemeinen Tool Chain können Sie die erstellten Anwendungen bequem über einen einzelnen Server bereitstellen.



      Source link

      Cómo configurar Django con Postgres, Nginx y Gunicorn en Ubuntu 20.04


      Introducción

      Django es un poderoso framework que puede ayudarle a poner en marcha su aplicación o sitio web con Python. Incluye un servidor de desarrollo simplificado para probar su código a nivel local. Sin embargo, para cualquier cosa que esté incluso apenas relacionada con la producción se requiere un servidor web más seguro y potente.

      En esta guía, demostraremos la forma de instalar y configurar algunos componentes en Ubuntu 20.04 para que sean compatibles con aplicaciones de Django y permitan su funcionamiento. Configuraremos una base de datos de PostgreSQL en lugar de usar la base de datos predeterminada de SQLite. Configuraremos el servidor de aplicaciones de Gunicorn para que interactúe con nuestras aplicaciones. Luego, configuraremos Nginx para que invierta el proxy de Gunicorn, lo que nos dará acceso a sus funciones de seguridad y rendimiento para nuestras aplicaciones.

      Requisitos previos y objetivos

      Para completar esta guía, debe disponer de una instancia de servidor de Ubuntu 20.04 nueva con un firewall básico y un usuario no root con privilegios sudo configurados. Puede aprender a configurarlo con nuestra guía de configuración inicial para servidores.

      Instalaremos Django en un entorno virtual. Instalar Django en un entorno específico para nuestro proyecto permitirá que sus proyectos y los requisitos de estos se administren por separado.

      Una vez que tengamos nuestra base de datos y la aplicación en funcionamiento, instalaremos y configuraremos el servidor de aplicaciones de Gunicorn. Esto servirá como interfaz para nuestra aplicación, al traducir las solicitudes de los clientes de HTTP a llamadas Python que nuestra aplicación puede procesar. Luego, instalaremos Nginx frente a Gunicorn para aprovechar sus mecanismos de administración de conexiones de alto rendimiento y sus características de seguridad fáciles de implementar.

      Comencemos.

      Instalar los paquetes desde los repositorios de Ubuntu

      Para iniciar este proceso, descargaremos e instalaremos todos los elementos necesarios desde los repositorios de Ubuntu. Usaremos el administrador de paquetes de Python pip para instalar componentes adicionales más tarde.

      Tendremos que actualizar el índice de paquetes apt local y, luego, descargar e instalar los paquetes. Los paquetes que instalemos dependen de la versión de Python que use en su proyecto.

      Si usa Django con Python 3, escriba lo siguiente:

      • sudo apt update
      • sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

      Django 1.11 es la última versión que será compatible con Python 2. Si va a iniciar proyectos nuevos, le recomendamos enfáticamente seleccionar Python 3. Si necesita seguir usando Python 2, escriba lo siguiente:

      • sudo apt update
      • sudo apt install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx curl

      Con esto, se instalarán pip, los archivos de desarrollo de Python necesarios para compilar Gunicorn posteriormente, el sistema de base de datos de Postgres junto con las bibliotecas necesarias para interactuar con él y el servidor web Nginx.

      Crear la base de datos y el usuario de PostgreSQL

      Crearemos una base de datos y un usuario de base de datos para nuestra aplicación de Django.

      Por defecto, Postgres usa un esquema de autenticación llamado “autenticación por pares” para las conexiones locales. Básicamente, esto significa que si el nombre de usuario del sistema operativo del usuario coincide con un nombre de usuario de Postgres válido, ese usuario puede iniciar sesión sin autenticaciones adicionales.

      Durante la instalación de Postgres, se creó un usuario del sistema operativo llamado postgres para que se corresponda con el usuario administrativo postgres de PostgreSQL. Necesitamos usar este usuario para realizar tareas administrativas. Podemos usar sudo y pasar el nombre de usuario con la opción -u.

      Inicie una sesión interactiva de Postgres escribiendo lo siguiente:

      Recibirá un mensaje de PostgreSQL en el que se pueden configurar los requisitos.

      Primero, cree una base de datos para su proyecto:

      • CREATE DATABASE myproject;

      Nota: Cada instrucción de Postgres debe terminar con punto y coma. Por eso, si presenta problemas, debe asegurarse de que su comando tenga esta terminación.

      A continuación, cree un usuario de base de datos para nuestro proyecto. Asegúrese de elegir una contraseña segura.

      • CREATE USER myprojectuser WITH PASSWORD 'password';

      Más adelante, modificaremos algunos de los parámetros de conexión para el usuario que acabamos de crear. Esto acelerará las operaciones de la base de datos para que no sea necesario consultar y fijar los valores correctos cada vez que se establezca una conexión.

      Fijaremos el código predeterminado en UTF-8, que es lo que Django espera. También fijaremos el esquema predeterminado de aislamiento de transacciones en “read committed”, que bloquea las lecturas de transacciones no comprometidas. Por último, configuraremos la zona horaria. Por defecto, nuestros proyectos de Django se configurarán para usar la opción UTC. Estas son todas las recomendaciones del propio proyecto de Django:

      • ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
      • ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
      • ALTER ROLE myprojectuser SET timezone TO 'UTC';

      Ahora, podemos brindar a nuestro nuevo usuario acceso para administrar nuestra nueva base de datos:

      • GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

      Cuando termine, cierre la línea de comandos de PostgreSQL escribiendo lo siguiente:

      Postgres quedará, así, configurado para que Django pueda conectarse y administrar la información de su base de datos.

      Crear un entorno virtual de Python para su proyecto

      Ahora que tenemos nuestra base de datos, podemos empezar a cumplir con el resto de los requisitos de nuestro proyecto. Instalaremos los componentes de Python requeridos en un entorno virtual para facilitar la administración.

      Para hacerlo, primero necesitamos acceso al comando virtualenv. Podemos instalarlo con pip.

      Si usa Python 3, actualice pip e instale el paquete escribiendo lo siguiente:

      • sudo -H pip3 install --upgrade pip
      • sudo -H pip3 install virtualenv

      Si usa Python 2, actualice pip e instale el paquete escribiendo lo siguiente:

      • sudo -H pip install --upgrade pip
      • sudo -H pip install virtualenv

      Con virtualenv instalado, podemos comenzar a dar forma a nuestro proyecto. Cree y un directorio en el que podamos guardar los archivos de nuestro proyecto y posiciónese en él:

      • mkdir ~/myprojectdir
      • cd ~/myprojectdir

      En el directorio del proyecto, cree un entorno virtual de Python escribiendo lo siguiente:

      Con esto, se creará un directorio llamado myprojectenv en su directorio myprojectdir. Dentro de este, se instalarán una versión local de Python y una versión local de pip. Podemos usar esto para instalar y configurar un entorno aislado de Python para nuestro proyecto.

      Antes de instalar los componentes de Python requeridos para nuestro proyecto, debemos activar el entorno virtual. Puede hacerlo escribiendo lo siguiente:

      • source myprojectenv/bin/activate

      Su línea de comandos cambiará para indicar que ahora realiza operaciones en un entorno virtual de Python. Tendrá este aspecto: (myprojectenv)user@host:~/myprojectdir$.

      Con su entorno virtual activo, instale Django, Gunicorn y el adaptador psycopg2 de PostgreSQL con la instancia local de pip:

      Nota: Cuando se active el entorno virtual (cuando (myprojectenv) se encuentre al inicio de su línea de comandos), use pip en lugar de pip3, incluso si emplea Python 3. La copia del entorno virtual de la herramienta siempre se llama pip, independientemente de la versión de Python.

      • pip install django gunicorn psycopg2-binary

      Con esto, debería contar con todo el software necesario para iniciar un proyecto en Django.

      Crear y configurar un nuevo proyecto de Django

      Una vez instalados nuestros componentes de Python, podemos crear los archivos reales del proyecto en Django.

      Crear el proyecto de Django

      Debido a que ya disponemos de un directorio de proyectos, le indicaremos a Django que instale los archivos en él. Se creará un directorio de segundo nivel con el código real, lo cual es normal, y se dispondrá una secuencia de comandos de administración en este directorio. La clave para esto es que definiremos el directorio de forma explícita en lugar de permitir que Django tome decisiones vinculadas con nuestro directorio actual:

      • django-admin.py startproject myproject ~/myprojectdir

      En este punto, el directorio de su proyecto (~/myprojectdir en nuestro caso) debe tener el siguiente contenido:

      • ~/myprojectdir/manage.py: una secuencia de comandos de administración del proyecto de Django.
      • ~/myprojectdir/myproject/: el paquete de proyectos de Django. Este debe contener los archivos __init__.py, settings.py, urls.py, asgi.py y wsgi.py.
      • ~/myprojectdir/myprojectenv/: el directorio del entorno virtual que creamos anteriormente.

      Ajustar la configuración del proyecto

      Lo primero que debemos hacer con los archivos del proyecto recientemente creado es ajustar la configuración. Abra el archivo de configuración en su editor de texto:

      • nano ~/myprojectdir/myproject/settings.py

      Comience por localizar la directiva ALLOWED_HOSTS. Con esto, se define una lista de las direcciones de los servidores o los nombres de dominio que pueden usarse para establecer una conexión con la instancia en Django. Cualquier solicitud entrante con un encabezado de Host que no figure en esta lista generará una excepción. Django necesita que configure esto para evitar una clase de vulnerabilidad de seguridad determinada.

      En los corchetes, enumere las direcciones IP o los nombres de dominio que están asociados con su servidor Django. Cada elemento debe listarse entre comillas y las entradas deben ir separadas por una coma. Si desea solicitudes para un dominio completo y cualquier subdominio, anteponga un punto al comienzo de la entrada. En el fragmento inferior, hay algunos ejemplos comentados que se usan para demostrar lo siguiente:

      Nota: Asegúrese de incluir localhost como una de las opciones, ya que autorizaremos conexiones a través de una instancia local de Nginx.

      ~/myprojectdir/myproject/settings.py

      . . .
      # The simplest case: just add the domain name(s) and IP addresses of your Django server
      # ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']
      # To respond to 'example.com' and any subdomains, start the domain with a dot
      # ALLOWED_HOSTS = ['.example.com', '203.0.113.5']
      ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']
      

      A continuación, busque la sección que configura el acceso a la base de datos. Se iniciará con DATABASES. La configuración del archivo es para una base de datos de SQLite. Ya creamos una base de datos de PostgreSQL para nuestro proyecto. Ahora debemos ajustar las configuraciones.

      Cambie las configuraciones por la información de su base de datos de PostgreSQL. Indicaremos a Django que use el adaptador psycopg2 que instalamos con pip. Debemos proporcionar el nombre de la base de datos, el nombre de usuario y la contraseña del usuario, y luego especificar que la base de datos se encuentra en una computadora local. Puede dejar la configuración de PORT como una secuencia de comandos vacía:

      ~/myprojectdir/myproject/settings.py

      . . .
      
      DATABASES = {
          'default': {
              'ENGINE': 'django.db.backends.postgresql_psycopg2',
              'NAME': 'myproject',
              'USER': 'myprojectuser',
              'PASSWORD': 'password',
              'HOST': 'localhost',
              'PORT': '',
          }
      }
      
      . . .
      

      A continuación, diríjase hasta la parte inferior del archivo y agregue una configuración que indique dónde deben disponerse los archivos estáticos. Esto es necesario para que Nginx pueda manejar las solicitudes de estos elementos. La siguiente línea indica a Django que los disponga en un directorio llamado static en el directorio de proyectos de base:

      ~/myprojectdir/myproject/settings.py

      . . .
      
      STATIC_URL = '/static/'
      STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
      

      Guarde y cierre el archivo cuando termine.

      Completar la configuración inicial del proyecto

      Ahora, podemos migrar el esquema inicial de la base de datos a nuestra base de datos de PostgreSQL usando la secuencia de comandos de administración:

      • ~/myprojectdir/manage.py makemigrations
      • ~/myprojectdir/manage.py migrate

      Cree un usuario administrativo para el proyecto escribiendo lo siguiente:

      • ~/myprojectdir/manage.py createsuperuser

      Deberá seleccionar el nombre de usuario, proporcionar una dirección de correo electrónico y elegir y confirmar una contraseña.

      Podemos recolectar todo el contenido estático en la ubicación del directorio que configuramos escribiendo lo siguiente:

      • ~/myprojectdir/manage.py collectstatic

      Deberá confirmar la operación. Luego, los archivos estáticos se ubicarán en un directorio llamado static, dentro del directorio de su proyecto.

      Si siguió la guía de configuración inicial para servidores, debería proteger su servidor con un firewall UFW. Para probar el servidor de desarrollo, tendremos que permitir el acceso al puerto que usaremos.

      Cree una excepción para el puerto 8000 escribiendo lo siguiente:

      Por último, puede probar su proyecto iniciando el servidor de desarrollo de Django con este comando:

      • ~/myprojectdir/manage.py runserver 0.0.0.0:8000

      En su buscador web, agregue :8000 al final del nombre del dominio o de la dirección IP de su servidor y visítelos:

      http://server_domain_or_IP:8000
      

      Debe obtener como resultado la página de índice predeterminada de Django:

      Página de índice de Django

      Si agrega /admin al final de la URL en la barra de direcciones, se le solicitará el nombre de usuario administrativo y la contraseña que creó con el comando createsuperuser:

      Inicio de sesión de administrador en Django

      Después de la autenticación, puede acceder a la interfaz administrativa predeterminada de Django:

      Interfaz de administración de Django

      Cuando finalice la exploración, presione CTRL-C en la ventana de la terminal para desactivar el servidor de desarrollo.

      Poner a prueba la capacidad de Gunicorn para presentar el proyecto

      Lo último que nos convendrá hacer antes de cerrar nuestro entorno virtual será probar Gunicorn para asegurarnos de que pueda hacer funcionar la aplicación. Podemos hacerlo ingresando a nuestro directorio de proyectos y usando gunicorn para cargar el módulo WSGI del proyecto:

      • cd ~/myprojectdir
      • gunicorn --bind 0.0.0.0:8000 myproject.wsgi

      Con esto se iniciará Gunicorn en la misma interfaz en la que se encontraba en ejecución el servidor de desarrollo en Django. Puede volver y probar la aplicación de nuevo.

      Nota: No se aplicará ninguno de los estilos a la interfaz de administrador, ya que Gunicorn no sabe cómo encontrar el contenido estático de CSS responsable de esto.

      Pasamos un módulo a Gunicorn especificando la ruta relativa del directorio al archivo wsgi.py de Django, que es el punto de entrada a nuestra aplicación, usando la sintaxis del módulo de Python. Dentro de este archivo, se define una función llamada application, que se usa para establecer conexión con la aplicación. Para obtener más información sobre la especificación WSGI, haga clic aquí.

      Cuando termine de realizar las pruebas, presione CTRL-C en la ventana de la terminal para detener Gunicorn.

      Con esto habremos terminado de configurar nuestra aplicación en Django. Podemos cerrar nuestro entorno virtual escribiendo lo siguiente:

      Se eliminará el indicador del entorno virtual en su línea de comandos.

      Crear archivos de socket y servicio de systemd para Gunicorn

      Comprobamos que Gunicorn puede interactuar con nuestra aplicación en Django, pero debemos implementar un mejor método para iniciar y detener el servidor de la aplicación. Para lograr esto, crearemos archivos de servicio y socket systemd.

      El socket Gunicorn se creará en el inicio y escuchará las conexiones. Cuando se establezca una conexión, systemd iniciará de forma automática el proceso de Gunicorn para manejarla conexión.

      Comience por crear y abrir un archivo de socket de systemd para Gunicorn con privilegios sudo:

      • sudo nano /etc/systemd/system/gunicorn.socket

      En su interior, crearemos una sección [Unit] para describir el socket, una sección [Socket] para definir la ubicación del socket y una sección [Install] para asegurarnos de que el socket se cree en el momento adecuado:

      /etc/systemd/system/gunicorn.socket

      [Unit]
      Description=gunicorn socket
      
      [Socket]
      ListenStream=/run/gunicorn.sock
      
      [Install]
      WantedBy=sockets.target
      

      Guarde y cierre el archivo cuando termine.

      A continuación, cree y abra un archivo de servicio systemd para Gunicorn con privilegios sudo en su editor de texto. El nombre del archivo de servicio debe coincidir con el de socket, salvo en la extensión:

      • sudo nano /etc/systemd/system/gunicorn.service

      Empiece por la sección [Unit], que se usa para especificar metadatos y dependencias. Aquí introduciremos una descripción de nuestro servicio e indicaremos al sistema init que lo inicie solo tras haber alcanzado el objetivo de red: Debido a que nuestro servicio se basa en el socket del archivo de sockets, necesitamos incluir una directiva Requires para indicar esta relación:

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      

      A continuación, abriremos la sección [Service]. Especificaremos el usuario y el grupo con los cuales deseamos que se ejecute el proceso. Otorgaremos la propiedad del proceso a nuestra cuenta de usuario normal, ya que tiene la propiedad de todos los archivos pertinentes. Otorgaremos la propiedad del grupo al grupo www-data para que Nginx pueda comunicarse fácilmente con Gunicorn.

      Luego, mapearemos el directorio de trabajo y especificaremos el comando que se usará para iniciar el servicio. En este caso, tendremos que especificar la ruta completa al ejecutable de Gunicorn, que está instalado en nuestro entorno virtual. Vincularemos el proceso con el socket de Unix que creamos en el directorio /run para que el proceso pueda comunicarse con Nginx. Registramos todos los datos a la salida estándar para que el proceso journald pueda recopilar los registros de Gunicorn. También podemos especificar cualquier ajuste opcional de Gunicorn aquí. Por ejemplo, especificamos 3 procesos de trabajadores en este caso:

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myprojectdir
      ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn 
                --access-logfile - 
                --workers 3 
                --bind unix:/run/gunicorn.sock 
                myproject.wsgi:application
      

      Por último, agregaremos una sección [Install]. Esto indicará a systemd a qué deberá vincular este servicio si lo habilitamos para que se cargue en el inicio. Queremos que este servicio se inicie cuando el sistema multiusuario normal esté en funcionamiento:

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myprojectdir
      ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn 
                --access-logfile - 
                --workers 3 
                --bind unix:/run/gunicorn.sock 
                myproject.wsgi:application
      
      [Install]
      WantedBy=multi-user.target
      

      Con eso, nuestro archivo de servicio systemd quedará completo. Guárdelo y ciérrelo ahora.

      Ahora podemos iniciar y habilitar el socket de Gunicorn. Con esto, ahora, se creará el archivo de socket en /run/gunicorn.sock y en el inicio. Cuando se establezca una conexión con ese socket, systemd iniciará gunicorn.service de forma automática para gestionarla:

      • sudo systemctl start gunicorn.socket
      • sudo systemctl enable gunicorn.socket

      Podemos confirmar que la operación se haya completado con éxito revisando el archivo de sockets.

      Verificar el archivo de socket de Gunicorn

      Compruebe el estado del proceso para saber si pudo iniciar lo siguiente:

      • sudo systemctl status gunicorn.socket

      Debería obtener un resultado como este:

      Output

      ● gunicorn.socket - gunicorn socket Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor prese> Active: active (listening) since Fri 2020-06-26 17:53:10 UTC; 14s ago Triggers: ● gunicorn.service Listen: /run/gunicorn.sock (Stream) Tasks: 0 (limit: 1137) Memory: 0B CGroup: /system.slice/gunicorn.socket

      A continuación, compruebe la existencia del archivo gunicorn.sock en el directorio /run:

      Output

      /run/gunicorn.sock: socket

      Si el comando systemctl status indica que se produjo un error o si no encuentra el archivo gunicorn.sock en el directorio, significa que no se pudo crear de forma correcta el socket de Gunicorn. Verifique los registros del socket de Gunicorn escribiendo lo siguiente:

      • sudo journalctl -u gunicorn.socket

      Vuelva a revisar su archivo /etc/systemd/system/gunicorn.socket para solucionar cualquier problema antes de continuar.

      Poner a prueba la activación de sockets

      En este punto, si solo inició la unidad gunicorn.socket, gunicorn.service aún no estará activo, ya que el socket aún no habrá recibido conexiones. Puede comprobarlo escribiendo lo siguiente:

      • sudo systemctl status gunicorn

      Output

      ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: inactive (dead)

      Para probar el mecanismo de activación de sockets, podemos enviar una conexión al socket a través de curl escribiendo lo siguiente:

      • curl --unix-socket /run/gunicorn.sock localhost

      Debería recibir el resultado HTML de su aplicación en la terminal. Esto indica que Gunicorn se inició y pudo presentar su aplicación de Django. Puede verificar que el servicio de Gunicorn funcione escribiendo lo siguiente:

      • sudo systemctl status gunicorn

      Output

      ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: active (running) since Fri 2020-06-26 18:52:21 UTC; 2s ago TriggeredBy: ● gunicorn.socket Main PID: 22914 (gunicorn) Tasks: 4 (limit: 1137) Memory: 89.1M CGroup: /system.slice/gunicorn.service ├─22914 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22927 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22928 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> └─22929 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> Jun 26 18:52:21 django-tutorial systemd[1]: Started gunicorn daemon. Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Starting gunicorn 20.0.4 Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Listening at: unix:/run/gunicorn.sock (22914) Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Using worker: sync Jun 26 18:52:21 django-tutorial gunicorn[22927]: [2020-06-26 18:52:21 +0000] [22927] [INFO] Booting worker with pid: 22927 Jun 26 18:52:21 django-tutorial gunicorn[22928]: [2020-06-26 18:52:21 +0000] [22928] [INFO] Booting worker with pid: 22928 Jun 26 18:52:21 django-tutorial gunicorn[22929]: [2020-06-26 18:52:21 +0000] [22929] [INFO] Booting worker with pid: 22929

      Si el resultado de curl o systemctl status indica que se produjo un problema, verifique los registros para obtener información adicional:

      • sudo journalctl -u gunicorn

      Verifique su archivo /etc/systemd/system/gunicorn.service en busca de problemas. Si realiza cambios en el archivo /etc/systemd/system/gunicorn.service, vuelva a cargar el demonio para volver a leer la definición de servicio y reiniciar el proceso de Gunicorn escribiendo lo siguiente:

      • sudo systemctl daemon-reload
      • sudo systemctl restart gunicorn

      Asegúrese de resolver los problemas mencionados previamente antes de continuar.

      Configurar Nginx para un pase de autorización a Gunicorn

      Ahora que Gunicorn está configurado, debemos configurar Nginx para transferir tráfico al proceso.

      Comience por crear y abrir un nuevo bloque de servidor en el directorio sites-available de Nginx:

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

      Dentro de este, abra un nuevo bloque de servidor. Comenzaremos especificando que este bloque debe escuchar en el puerto normal 80 y responder al nombre de dominio o a la dirección IP de nuestro servidor:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      }
      

      A continuación, indicaremos a Nginx que ignore cualquier problema para encontrar un favicon. También le indicaremos dónde encontrar los activos estáticos que recolectamos en nuestro directorio ~/myprojectdir/static. Todos estos archivos tienen un prefijo URI de “/static”, para que podamos crear un bloque de ubicación que coincida con estas solicitudes:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      
          location = /favicon.ico { access_log off; log_not_found off; }
          location /static/ {
              root /home/sammy/myprojectdir;
          }
      }
      

      Por último, crearemos un bloque location / {} para que coincida con todas las demás solicitudes. Dentro de esta ubicación, agregaremos el archivo proxy_params estándar incluido con la instalación de Nginx y, luego, transferiremos el tráfico directamente al socket de Gunicorn:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      
          location = /favicon.ico { access_log off; log_not_found off; }
          location /static/ {
              root /home/sammy/myprojectdir;
          }
      
          location / {
              include proxy_params;
              proxy_pass http://unix:/run/gunicorn.sock;
          }
      }
      

      Guarde y cierre el archivo cuando termine. Ahora, podemos habilitar el archivo vinculándolo al directorio sites-enabled:

      • sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

      Pruebe su configuración de Nginx para descartar errores de sintaxis escribiendo lo siguiente:

      Si no se notifican errores, reinicie Nginx escribiendo lo siguiente:

      • sudo systemctl restart nginx

      Por último, debemos abrir nuestro firewall al tráfico normal en el puerto 80. Como ya no necesitamos acceso al servidor de desarrollo, podemos eliminar la regla para abrir también el puerto 8000:

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

      Ahora debería poder acceder al dominio o a la dirección IP de su servidor para ver su aplicación.

      Nota: Después de configurar Nginx, el siguiente paso debería ser proteger el tráfico hacia el servidor usando SSL/TLS. Esto es importante porque, si no se aplica, toda la información, incluidas las contraseñas, se envía a través de la red en texto simple.

      Si tiene un nombre de dominio, la alternativa más sencilla para obtener un certificado SSL para proteger su tráfico es usar Let’s Encrypt. Siga esta guía para configurar Let’s Encrypt con Nginx en Ubuntu 20.04. Siga el procedimiento usando el bloque de servidor de Nginx que creamos en esta guía.

      Resolver problemas en Nginx y Gunicorn

      Si con este último paso no se muestra su aplicación, deberá resolver problemas en su instalación.

      Nginx muestra la página predeterminada en lugar de la aplicación de Django

      Si Nginx muestra la página predeterminada en lugar de actualizar su aplicación, normalmente significa que deberá ajustar server_name dentro del archivo /etc/nginx/sites-available/myproject para apuntar a la dirección IP o al nombre de dominio de su servidor.

      Nginx usa el server_name para determinar el bloque de servidor que usará para responder a solicitudes. Si ve la página predeterminada de Nginx, significa que Nginx no pudo hacer coincidir la solicitud con un bloque de servidor de forma explícita, por lo cual sigue recurriendo al bloque por defecto definido en /etc/nginx/sites-available/default.

      El server_name del bloque de servidor de su proyecto debe ser más específico que el del bloque de servidor predeterminado que se seleccionará.

      Nginx muestra un error de puerta de enlace 502 en lugar de la aplicación de Django

      Un error 502 indica que Nginx no puede autorizar con éxito la solicitud. Con el error 502 se transmite una amplia variedad de problemas de configuración, por lo que se necesita más información para resolver los problemas de forma adecuada.

      Los registros de errores de Nginx son el recurso principal para buscar más información. Generalmente, esto le indicará las condiciones que ocasionaron problemas durante el evento de autorización. Siga los registros de errores de Nginx escribiendo lo siguiente:

      • sudo tail -F /var/log/nginx/error.log

      Ahora, realice otra solicitud en su navegador para generar un nuevo error (intente actualizar la página). Debería recibir un mensaje de error nuevo en el registro. Leer el mensaje lo ayudará a determinar el problema.

      Es probable que reciba el siguiente mensaje:

      connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)

      Esto indica que Nginx no pudo encontrar el archivo gunicorn.sock en la ubicación en cuestión. Debería comparar la ubicación de proxy_pass definida en el archivo /etc/nginx/sites-available/myproject con la ubicación actual del archivo gunicorn.sock generado por la unidad de systemd gunicorn.sock.

      Si no puede encontrar un archivo gunicorn.sock en el directorio /run, por lo general significa que el archivo de socket de systemd no pudo crearlo. Regrese a la sección de verificación del archivo de socket de Gunicorn para seguir los pasos de resolución de problemas de Gunicorn.

      connect() to unix:/run/gunicorn.sock failed (13: Permission denied)

      Esto indica que Nginx no pudo conectarse al socket de Gunicorn debido a problemas de permisos. Esto puede ocurrir cuando se sigue el procedimiento con un usuario root en lugar de un usuario sudo. Aunque systemd puede crear el archivo de socket de Gunicorn, Nginx no puede acceder a él.

      Esto puede ocurrir si hay permisos limitados en cualquier punto entre el directorio root (/) y el archivo gunicorn.sock. Podemos revisar los permisos y los valores de propiedad del archivo de socket y cada uno de sus directorios principales pasando la ruta absoluta a nuestro archivo de socket al comando namei:

      • namei -l /run/gunicorn.sock

      Output

      f: /run/gunicorn.sock drwxr-xr-x root root / drwxr-xr-x root root run srw-rw-rw- root root gunicorn.sock

      En el resultado se muestran los permisos de cada uno de los componentes del directorio. Al mirar los permisos (primera columna), el propietario (segunda columna) y el propietario del grupo (tercera columna), podemos averiguar el tipo de acceso permitido para el archivo de socket.

      En el ejemplo anterior, el archivo de sockets y cada directorio que conduce a este tienen permisos mundiales de lectura y ejecución (la columna de permisos para los directorios termina en r-x en lugar de ---). El proceso de Nginx debería poder acceder al socket de forma correcta.

      Si algunos directorios que conducen al socket no tienen permiso mundial de lectura y ejecución, Nginx no podrá acceder al socket sin otorgar permisos mundiales de lectura y ejecución ni asegurarse de que se otorgue propiedad del grupo a un grupo del que forme parte Nginx.

      Django muestra el mensaje “could not connect to server: Connection refused”

      Este es uno de los mensajes que puede recibir de Django al intentar acceder a ciertas partes de la aplicación en el navegador web:

      OperationalError at /admin/login/
      could not connect to server: Connection refused
          Is the server running on host "localhost" (127.0.0.1) and accepting
          TCP/IP connections on port 5432?
      

      Esto indica que Django no puede conectarse a la base de datos de Postgres. Asegúrese de que la instancia de Postgres esté en ejecución escribiendo lo siguiente:

      • sudo systemctl status postgresql

      Si esto no sucede, puede iniciarla y activarla para que se cargue automáticamente en el inicio (si aún no está cargada la configuración para ello) escribiendo lo siguiente:

      • sudo systemctl start postgresql
      • sudo systemctl enable postgresql

      Si todavía experimenta problemas, asegúrese de que los ajustes de la base de datos definidos en el archivo ~/myprojectdir/myproject/settings.py sean correctos.

      Solución de problemas adicionales

      Para resolver problemas adicionales, los registros pueden servir para reducir las causas raíces. Verifique cada uno de ellos por separado y busque mensajes que indiquen las áreas problemáticas.

      Los siguientes registros pueden ser útiles:

      • Verifique los registros de proceso de Nginx escribiendo lo siguiente: sudo journalctl -u nginx.
      • Verifique los registros de acceso de Nginx escribiendo lo siguiente: sudo less /var/log/nginx/access.log
      • Verifique los registros de errores de Nginx escribiendo lo siguiente: sudo less /var/log/nginx/error.log.
      • Verifique los registros de la aplicación de Gunicorn escribiendo lo siguiente: sudo journalctl -u gunicorn.
      • Verifique los registros de sockets de Gunicorn escribiendo lo siguiente: sudo journalctl -u gunicorn.socket.

      Cuando actualice su configuración o aplicación, es probable que necesite reiniciar los procesos para que asimilen sus cambios.

      Si actualiza su aplicación de Django, puede reiniciar el proceso de Gunicorn para que incorpore los cambios escribiendo lo siguiente:

      • sudo systemctl restart gunicorn

      Si cambia los archivos de socket y servicio de Gunicorn, vuelva a cargar el demonio y reinicie el proceso escribiendo lo siguiente:

      • sudo systemctl daemon-reload
      • sudo systemctl restart gunicorn.socket gunicorn.service

      Si cambia la configuración de bloque del servidor de Nginx, pruébela y luego verifique Nginx escribiendo lo siguiente:

      • sudo nginx -t && sudo systemctl restart nginx

      Estos comandos son útiles para incorporar cambios cuando ajusta su configuración.

      Conclusión

      En esta guía, creamos un proyecto de Django en su propio entorno virtual. Configuramos Gunicorn para que traduzca las solicitudes de los clientes a fin de que Django pueda manejarlas. Posteriormente, configuramos Nginx para que actúe como proxy inverso a fin de manejar las conexiones de los clientes y presentar el proyecto correcto según la solicitud del cliente.

      Django simplifica la creación de proyectos y aplicaciones proporcionando muchas de las piezas comunes, lo que le permite centrarse en los elementos únicos. Al aprovechar la cadena general de herramientas descrita en este artículo, puede ofrecer fácilmente las aplicaciones que cree desde un servidor único.



      Source link

      Comment configurer Django avec Postgres, Nginx et Gunicorn sur Ubuntu 20.04


      Introduction

      Django est un framework web puissant qui peut vous aider à lancer votre application ou votre site web en Python. Django comprend un serveur de développement simplifié pour tester votre code en local, mais pour tout ce qui est lié, même légèrement, à la production, un serveur web plus sécurisé et plus puissant est nécessaire.

      Dans ce guide, nous allons montrer comment installer et configurer certains composants d’Ubuntu 20.04 pour soutenir et servir les applications Django. Nous allons mettre en place une base de données PostgreSQL au lieu d’utiliser la base de données SQLite par défaut. Nous allons configurer le serveur d’application Gunicorn pour qu’il s’interface avec nos applications. Nous allons ensuite mettre en place Nginx pour inverser le proxy à Gunicorn, nous donnant accès à ses fonctions de sécurité et de performance pour servir nos applications.

      Conditions prélables et objectifs

      Afin de terminer ce guide, vous devez disposer d’une nouvelle instance de serveur Ubuntu 20.04 avec un pare-feu de base et un utilisateur non root avec des privilèges sudo configurés. Vous pouvez apprendre à paramétrer cette configuration en suivant notre guide de configuration initiale du serveur.

      Nous allons installer Django dans un environnement virtuel. L’installation de Django dans un environnement spécifique à votre projet permettra de traiter séparément vos projets et leurs exigences.

      Une fois que notre base de données et notre application seront opérationnels, nous allons installer et configurer le serveur d’application Gunicorn. Cela servira d’interface à notre application, traduisant les requêtes des clients à partir de HTTP en appels Python que notre application peut traiter. Nous allons ensuite mettre en place Nginx en face de Gunicorn pour tirer parti de ses mécanismes très performants de gestion des connexions et de ses fonctionnalités de sécurité faciles à mettre en œuvre.

      Commençons.

      Installation des paquets à partir des référentiels Ubuntu

      Pour démarrer le processus, nous allons télécharger et installer tous les éléments dont nous avons besoin à partir des référentiels Ubuntu. Nous utiliserons le gestionnaire de paquets Python pip pour installer des composants supplémentaires un peu plus tard.

      Nous devons mettre à jour l’index local du paquet apt et ensuite télécharger et installer les paquets. Les paquets que nous installons dépendent de la version de Python votre projet utilisera.

      Si vous utilisez Django avec Python 3, tapez :

      • sudo apt update
      • sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

      Django 1.11 est la dernière version de Django qui prendra en charge Python 2. Si vous démarrez de nouveaux projets, il est fortement recommandé de choisir Python 3. Si vous avez encore besoin d’utiliser Python 2, tapez :

      • sudo apt update
      • sudo apt install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx curl

      Cela installera pip, les fichiers de développement Python nécessaires pour construire Gunicorn plus tard, le système de base de données Postgres et les bibliothèques nécessaires à l’interaction avec celui-ci, ainsi que le serveur web Nginx.

      Création de la base de données et de l’utilisateur PostgreSQL

      Nous allons tout de suite créer une base de données et un utilisateur de base de données pour notre application Django.

      Par défaut, Postgres utilise un système d’authentification appelé « authentification par les pairs » pour les connexions locales. En gros, cela signifie que si le nom d’utilisateur du système d’exploitation de l’utilisateur correspond à un nom d’utilisateur Postgres valide, cet utilisateur peut se connecter sans autre authentification.

      Au cours de l’installation de Postgres, un utilisateur du système d’exploitation nommé postgres a été créé pour correspondre à l’utilisateur administratif postgres de PostgreSQL. Nous devons utiliser cet utilisateur pour effectuer des tâches administratives. Nous pouvons utiliser sudo et passer dans le nom d’utilisateur avec l’option -u.

      Connectez-vous à une session interactive de Postgres en tapant :

      Vous recevrez une invite PostgreSQL où nous pourrons configurer nos exigences.

      Tout d’abord, créez une base de données pour votre projet :

      • CREATE DATABASE myproject;

      Remarque : chaque instruction de Postgres doit se terminer par un point-virgule, Assurez-vous donc que votre commande se termine bien par un point-virgule si vous rencontrez des problèmes.

      Ensuite, créez un utilisateur de base de données pour votre projet. Sélectionnez un mot de passe sécurisé :

      • CREATE USER myprojectuser WITH PASSWORD 'password';

      Ensuite, nous allons modifier quelques-uns des paramètres de connexion de l’utilisateur que nous venons de créer. Cela accélérera les opérations de la base de données de sorte qu’il ne sera pas nécessaire d’interroger et de définir les valeurs correctes à chaque fois qu’une connexion sera établie.

      Nous réglons l’encodage par défaut à UTF-8, auquel Django s’attend. Nous définissons également le schéma d’isolement des transactions par défaut à « read committed », qui bloque les lectures de transactions non engagées. Enfin, nous définissons le fuseau horaire. Par défaut, nos projets Django seront configurés pour utiliser l’UTC. Ce sont toutes les recommandations du projet Django lui-même :

      • ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
      • ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
      • ALTER ROLE myprojectuser SET timezone TO 'UTC';

      Nous pouvons maintenant donner à notre nouvel utilisateur un accès pour administrer notre nouvelle base de données :

      • GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

      Une fois terminé, quittez l’invite PostgreSQL en tapant :

      Postgres est maintenant configuré de manière à ce que Django puisse se connecter et gérer les informations de sa base de données.

      Création d’un environnement virtuel Python pour votre projet

      Maintenant que nous avons notre base de données, nous pouvons commencer à préparer le reste des exigences de notre projet. Nous allons installer nos exigences Python dans un environnement virtuel pour faciliter la gestion.

      Pour ce faire, nous devons d’abord accéder à la commande virtualenv. Nous pouvons l’installer avec pip.

      Si vous utilisez Python 3, mettez à niveau pip et installez le paquet en tapant :

      • sudo -H pip3 install --upgrade pip
      • sudo -H pip3 install virtualenv

      Si vous utilisez Python 2, mettez à niveau pip et installez le paquet en tapant :

      • sudo -H pip install --upgrade pip
      • sudo -H pip install virtualenv

      Une fois virtualenv installé, nous pouvons démarrer à former notre projet. Créez et accédez à un répertoire où nous pouvons conserver nos fichiers de projet :

      • mkdir ~/myprojectdir
      • cd ~/myprojectdir

      Dans le répertoire du projet, créez un environnement virtuel Python en tapant :

      Cela créera un répertoire appelé myprojectenv dans votre répertoire myprojectdir. Dans ce répertoire, il installera une version locale de Python et une version locale de pip. Nous pouvons l’utiliser pour installer et configurer un environnement Python isolé pour notre projet.

      Avant d’installer les exigences Python de notre projet, nous devons activer l’environnement virtuel. Vous pouvez le faire en saisissant :

      • source myprojectenv/bin/activate

      Votre invite devrait changer pour indiquer que vous travaillez maintenant dans un environnement virtuel Python. Cela ressemblera à quelque chose comme ceci : (myprojectenv)user@host:~/myproject$.

      Une fois votre environnement virtuel actif, installez Django, Gunicorn et l’adaptateur PostgreSQL psycopg2 avec l’instance locale de pip :

      Remarque : Lorsque l’environnement virtuel est activé (lorsque votre invite a (myprojetenv) qui la précède), utilisez pip au lieu de pip3, même si vous utilisez Python 3. La copie de l’environnement virtuel de l’outil est toujours appelée pip, quelle que soit la version de Python.

      • pip install django gunicorn psycopg2-binary

      Vous devriez maintenant disposer de tous les logiciels nécessaires pour démarrer un projet Django.

      Création et Configuration d’un nouveau projet Django

      Une fois nos composants Python installés, nous pouvons créer les fichiers du projet Django.

      Création du projet Django

      Comme nous avons déjà un répertoire de projet, nous allons indiquer à Django d’installer les fichiers ici. Il va créer un répertoire de deuxième niveau avec le code réel, ce qui est normal, et y placera un script de gestion. L’essentiel est que nous définissions explicitement le répertoire au lieu de permettre à Django de prendre des décisions par rapport à notre répertoire actuel :

      • django-admin.py startproject myproject ~/myprojectdir

      À ce stade, votre répertoire de projet (~/myprojectdir dans notre cas) devrait avoir le contenu suivant :

      • ~/myprojectdir/manage.py : un script de gestion de projet Django.
      • ~/myprojectdir/myproject/ : Le paquet du projet Django. Il devrait contenir les fichiers __init__.py, settings.py, urls.py, asgi.py, et wsgi.py.
      • ~/myprojectdir/myprojectenv/ : Le répertoire de l’environnement virtuel que nous avons créé auparavant.

      Ajustement des paramètres du projet

      La première chose que nous devons faire avec nos fichiers de projet nouvellement créés est d’ajuster les paramètres. Ouvrez le fichier de paramètres dans votre éditeur de texte :

      • nano ~/myprojectdir/myproject/settings.py

      Commencez par localiser la directive ALLOWED_HOSTS. Cellle-ci définit une liste des adresses ou des noms de domaine du serveur pouvant être utilisés pour se connecter à l’instance Django. Toute requête entrante dont l’en-tête Host ne figure pas dans cette liste fera l’objet d’une exception. Django vous demande de la définir pour éviter une certaine classe de vulnérabilité de sécurité.

      Dans les crochets , listez les adresses IP ou les noms de domaine associés à votre serveur Django. Chaque élément devrait être listé dans des guillemets avec les entrées séparées par une virgule. Si vous souhaitez des requêtes pour un domaine entier et des sous-domaines, faites précéder l’entrée d’un point. Dans l’extrait ci-dessous, quelques exemples commentés sont utliser pour démontrer :

      Note : veillez à inclure localhost parmi les options, car nous allons utiliser une instance locale de Nginx comme proxy pour les connexions.

      ~/myprojectdir/myproject/settings.py

      . . .
      # The simplest case: just add the domain name(s) and IP addresses of your Django server
      # ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']
      # To respond to 'example.com' and any subdomains, start the domain with a dot
      # ALLOWED_HOSTS = ['.example.com', '203.0.113.5']
      ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']
      

      Ensuite, trouvez la section qui configure l’accès à la base de données. Elle commencera par des DATABASES. La configuration du fichier concerne une base de données SQLite. Nous avons déjà créé une base de données PostgreSQL pour notre projet, nous devons donc ajuster les paramètres.

      Modifiez les paramètres à l’aide des informations de votre base de données PostgreSQL. Nous disons à Django d’utiliser l’adaptateur psycopg2 que nous avons installé avec pip. Nous devons indiquer le nom de la base de données, le nom d’utilisateur de la base de données, le mot de passe de l’utilisateur de la base de données, puis spécifier que la base de données est située sur l’ordinateur local. Vous pouvez laisser le paramètre PORT sous forme de chaîne vide :

      ~/myprojectdir/myproject/settings.py

      . . .
      
      DATABASES = {
          'default': {
              'ENGINE': 'django.db.backends.postgresql_psycopg2',
              'NAME': 'myproject',
              'USER': 'myprojectuser',
              'PASSWORD': 'password',
              'HOST': 'localhost',
              'PORT': '',
          }
      }
      
      . . .
      

      Ensuite, passez au bas du fichier et ajoutez un paramètre indiquant où les fichiers statiques devraient être placés. Ceci est nécessaire pour que Nginx puisse traiter les requêtes pour ces éléments. La ligne suivante indique à Django de les placer dans un répertoire appelé static dans le répertoire du projet de base :

      ~/myprojectdir/myproject/settings.py

      . . .
      
      STATIC_URL = '/static/'
      STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
      

      Enregistrez et fermez le fichier lorsque vous avez terminé.

      Terminer la configuration initiale du projet

      Nous pouvons maintenant migrer le schéma de base de données initiale vers notre base de données PostgreSQL à l’aide du script de gestion :

      • ~/myprojectdir/manage.py makemigrations
      • ~/myprojectdir/manage.py migrate

      Créez un utilisateur administratif pour le projet en tapant :

      • ~/myprojectdir/manage.py createsuperuser

      Vous devrez sélectionner un nom d’utilisateur, fournir une adresse électronique et choisir et confirmer un mot de passe.

      Nous pouvons récupérer tout le contenu statique dans l’emplacement du répertoire que nous avons configuré en tapant :

      • ~/myprojectdir/manage.py collectstatic

      Vous devrez confirmer l’opération. Les fichiers statiques seront ensuite placés dans un répertoire appelé static dans votre répertoire de projet.

      Si vous avez suivi le guide de configuration initiale du serveur, vous devriez disposer d’un pare-feu UFW qui protège votre serveur Afin de tester le serveur de développement, nous allons devoir autoriser l’accès au port que nous utiliserons.

      Créez une exception pour le port 8000 en tapant :

      Enfin, vous pouvez tester notre projet en démarrant le serveur de développement Django avec cette commande :

      • ~/myprojectdir/manage.py runserver 0.0.0.0:8000

      Dans votre navigateur web, accédez au nom de domaine ou à l’adresse IP de votre serveur suivi(e) de :8000 :

      http://server_domain_or_IP:8000
      

      Vous devriez obtenir la page d’index par défaut de Django :

      Page d'index de Django

      Si vous ajoutez /admin à la fin de l’URL dans la barre d’adresse, vous serez invité à fournir le nom d’utilisateur et le mot de passe administratif que vous avez créé avec la commande createsuperuser :

      Connexion à l'interface d'administration de Django

      Une fois l’authentification terminée, vous pouvez accéder à l’interface admin par défaut de Django :

      Interface admin de Django

      Quand vous avez fini d’explorer, appuyez sur CTRL-C dans la fenêtre de terminal pour fermer le serveur de développement.

      Tester la capacité de Gunicorn à servir le projet

      La dernière chose que nous voulons faire avant de quitter notre environnement virtuel est de tester Gunicorn pour nous assurer qu’il peut servir l’application. Nous pouvons le faire en entrant dans notre répertoire de projet et en utilisant gunicorn pour charger le module WSGI du projet :

      • cd ~/myprojectdir
      • gunicorn --bind 0.0.0.0:8000 myproject.wsgi

      Cela démarrera Gunicorn sur la même interface que celle sur laquelle le serveur de développement Django fonctionnait. Vous pouvez revenir en arrière et tester à nouveau l’application.

      Remarque : l’interface admin ne bénéficiera d’aucun des styles appliqués puisque Gunicorn ne sait pas comment trouver le contenu CSS statique responsable de cela.

      Nous avons passé un module à Gunicorn en spécifiant le chemin relatif du répertoire du fichier wsgi.py de Django, qui est le point d’entrée de notre application, en utilisant la syntaxe du module Python. À l’intérieur de ce fichier, une fonction appelée application est définie, qui est utilisée pour communiquer avec l’application. Pour en savoir plus sur la spécification WSGI, cliquez ici.

      Lorsque vous avez terminé les tests, appuyez sur CTRL-C dans la fenêtre du terminal pour arrêter Gunicorn.

      Nous avons maintenant fini de configurer notre application Django. Nous pouvons sortir de notre environnement virtuel en tapant :

      L’indicateur de l’environnement virtuel dans votre invite sera supprimé.

      Création de fichiers de socket et de service systemd pour Gunicorn

      Nous avons testé la capacité de Gunicorn à interagir avec notre application Django, mais nous devrions mettre en place un moyen plus solide de démarrer et d’arrêter le serveur d’application. Pour ce faire, nous allons créer des fichiers de socket et de service de systemd.

      La socket de Gunicorn sera créée au démarrage et écoutera les connexions. Lorsqu’une connexion est établie, systemd démarrera automatiquement le processus de Gunicorn pour gérer la connexion.

      Commencez par créer et ouvrir un fichier de socket de systemd pour Gunicorn avec les privilèges sudo :

      • sudo nano /etc/systemd/system/gunicorn.socket

      À l’intérieur, nous allons créer une section [Unit] pour décrire la socket, une section [Socket] pour définir l’emplacement de la socket et une section [Install] pour nous assurer que la socket est créée au bon moment :

      /etc/systemd/system/gunicorn.socket

      [Unit]
      Description=gunicorn socket
      
      [Socket]
      ListenStream=/run/gunicorn.sock
      
      [Install]
      WantedBy=sockets.target
      

      Enregistrez et fermez le fichier lorsque vous avez terminé.

      Ensuite, créez et ouvrez un fichier de service systemd pour Gunicorn avec des privilèges sudo dans votre éditeur de texte. Le nom de fichier de service devrait correspondre au nom de socket, à l’exception de l’extension :

      • sudo nano /etc/systemd/system/gunicorn.service

      Commencez par la section [Unit], qui est utilisée pour spécifier les métadonnées et les dépendances. Nous ajouterons une description de notre service et disons au système d’initialisation de ne le lancer qu’une fois que l’objectif de mise en réseau a été atteint. Comme notre service repose sur la socket du fichier de socket, nous devons inclure une directive Requires pour indiquer cette relation :

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      

      Ensuite, nous allons ouvrir la section [Service]. Nous indiquerons l’utilisateur et le groupe sous lequel nous voulons que le processus s’exécute. Nous allons donner à notre compte utilisateur habituel la propriété du processus puisqu’il possède tous les fichiers pertinents. Nous allons donner la propriété de groupe au groupe www-data afin que Nginx puisse communiquer facilement avec Gunicorn.

      Nous allons ensuite mapper le répertoire de travail et spécifier la commande à utiliser pour lancer le service. Dans ce cas, nous devrons spécifier le chemin complet de l’exécutable Gunicorn, qui est installé dans notre environnement virtuel. Nous allons lier le processus à la socket Unix que nous avons créée dans le répertoire /run, afin que le processus puisse communiquer avec Nginx. Nous enregistrons toutes les données sur une sortie standard afin que le processus journald puisse recueillir les journaux Gunicorn. Nous pouvons également spécifier tout ajustement optionnel de Gunicorn ici. Par exemple, nous avons spécifié 3 processus de travail dans ce cas :

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myprojectdir
      ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn 
                --access-logfile - 
                --workers 3 
                --bind unix:/run/gunicorn.sock 
                myproject.wsgi:application
      

      Enfin, nous allons ajouter une section [Install]. Cela indiquera à systemd à quoi lier ce service si nous autorisons son démarrage au boot. Nous voulons que ce service démarre lorsque le système multi-utilisateurs normal est opérationnel :

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myprojectdir
      ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn 
                --access-logfile - 
                --workers 3 
                --bind unix:/run/gunicorn.sock 
                myproject.wsgi:application
      
      [Install]
      WantedBy=multi-user.target
      

      Avec cela, notre fichier de service systemd est terminé. Enregistrez-le et fermez-le maintenant.

      Nous pouvons maintenant démarrer et activer la socket Gunicorn. Cela créera le fichier de socket à /run/gunicorn.sock maintenant et au démarrage. Lorsqu’une connexion se fait à cette socket, systemd démarrera automatiquement gunicorn.service pour la gérer :

      • sudo systemctl start gunicorn.socket
      • sudo systemctl enable gunicorn.socket

      Nous pouvons confirmer que l’opération a bien réussi en vérifiant le fichier de socket.

      Vérification du fichier de socket Gunicorn

      Vérifiez l’état du processus pour savoir s’il a pu démarrer :

      • sudo systemctl status gunicorn.socket

      Vous devriez recevoir un résultat semblable à celui-ci :

      Output

      ● gunicorn.socket - gunicorn socket Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor prese> Active: active (listening) since Fri 2020-06-26 17:53:10 UTC; 14s ago Triggers: ● gunicorn.service Listen: /run/gunicorn.sock (Stream) Tasks: 0 (limit: 1137) Memory: 0B CGroup: /system.slice/gunicorn.socket

      Ensuite, vérifiez l’existence du fichier gunicorn.sock dans le répertoire /run :

      Output

      /run/gunicorn.sock: socket

      Si la commande systemctl status indique qu’une erreur s’est produite ou si vous ne trouvez pas le fichier gunicorn.sock dans le répertoire, c’est une indication que la socket Gunicorn n’a pas pu être créée correctement. Vérifiez les journaux de la socket Gunicorn en tapant :

      • sudo journalctl -u gunicorn.socket

      Examinez à nouveau votre fichier /etc/systemd/system/gunicorn.socket pour corriger tous les problèmes avant de continuer.

      Test d’activation de socket

      Actuellement, si vous n’avez démarré que l’unité gunicorn.socket, le gunicorn.service ne sera pas encore actif puisque la socket n’a pas encore reçu de connexion. Vous pouvez vérifier cela en tapant :

      • sudo systemctl status gunicorn

      Output

      ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: inactive (dead)

      Pour tester le mécanisme d’activation de la socket, nous pouvons envoyer une connexion à la socket via curl en tapant :

      • curl --unix-socket /run/gunicorn.sock localhost

      Vous devriez recevoir la sortie HTML de votre application dans le terminal. Cela indique que Gunicorn a démarré et a pu servir votre application Django. Vous pouvez vérifier que le service Gunicorn fonctionne en tapant :

      • sudo systemctl status gunicorn

      Output

      ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: active (running) since Fri 2020-06-26 18:52:21 UTC; 2s ago TriggeredBy: ● gunicorn.socket Main PID: 22914 (gunicorn) Tasks: 4 (limit: 1137) Memory: 89.1M CGroup: /system.slice/gunicorn.service ├─22914 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22927 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22928 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> └─22929 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> Jun 26 18:52:21 django-tutorial systemd[1]: Started gunicorn daemon. Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Starting gunicorn 20.0.4 Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Listening at: unix:/run/gunicorn.sock (22914) Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Using worker: sync Jun 26 18:52:21 django-tutorial gunicorn[22927]: [2020-06-26 18:52:21 +0000] [22927] [INFO] Booting worker with pid: 22927 Jun 26 18:52:21 django-tutorial gunicorn[22928]: [2020-06-26 18:52:21 +0000] [22928] [INFO] Booting worker with pid: 22928 Jun 26 18:52:21 django-tutorial gunicorn[22929]: [2020-06-26 18:52:21 +0000] [22929] [INFO] Booting worker with pid: 22929

      Si la sortie de curl ou la sortie du statut systemctl indique qu’un problème s’est produit, vérifiez les journaux pour obtenir des détails supplémentaires :

      • sudo journalctl -u gunicorn

      Vérifiez votre fichier /etc/systemd/system/gunicorn.service pour tout problème. Si vous apportez des modifications au fichier /etc/systemd/system/gunicorn.service, rechargez le démon pour relire la définition de service et redémarrez le processus Gunicorn en tapant :

      • sudo systemctl daemon-reload
      • sudo systemctl restart gunicorn

      Assurez-vous de résoudre les problèmes ci-dessus avant de continuer.

      Configurer Nginx pour passer par proxy à Gunicorn

      Maintenant que Gunicorn est mis en place, nous devons configurer Nginx pour qu’il transmette le trafic au processus.

      Commencez par créer et ouvrir un nouveau bloc serveur dans le répertoire sites-available de Nginx :

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

      À l’intérieur, ouvrez un nouveau bloc serveur. Nous allons commencer par spécifier que ce bloc devrait écouter sur le port normal 80 et qu’il devrait répondre au nom de domaine ou à l’adresse IP de notre serveur :

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      }
      

      Ensuite, nous allons demander à Nginx d’ignorer tous les problèmes de recherche d’une favicon. Nous allons également lui dire où trouver les éléments statiques que nous avons recueillis dans notre répertoire ~/myprojectdir/static Tous ces fichiers disposent d’un préfixe URI standard de “/static”, nous pouvons donc créer un bloc d’emplacement pour correspondre à ces requêtes :

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      
          location = /favicon.ico { access_log off; log_not_found off; }
          location /static/ {
              root /home/sammy/myprojectdir;
          }
      }
      

      Enfin, nous allons créer un bloc location / {} pour correspondre à toutes les autres requêtes. À l’intérieur de cet emplacement, nous allons inclure le fichier proxy_params standard inclus avec l’installation Nginx et ensuite nous allons passer le trafic directement à la socket Gunicorn :

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      
          location = /favicon.ico { access_log off; log_not_found off; }
          location /static/ {
              root /home/sammy/myprojectdir;
          }
      
          location / {
              include proxy_params;
              proxy_pass http://unix:/run/gunicorn.sock;
          }
      }
      

      Enregistrez et fermez le fichier lorsque vous avez terminé. Nous pouvons maintenant activer le fichier en le reliant au répertoire sites-enabled :

      • sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

      Testez votre configuration Nginx pour détecter les erreurs de syntaxe en tapant :

      Si aucune erreur n’est signalée, continuez et redémarrez Nginx en tapant :

      • sudo systemctl restart nginx

      Enfin, nous devons ouvrir notre pare-feu au trafic normal sur le port 80. Comme nous n’avons plus besoin d’accès au serveur de développement, nous pouvons supprimer la règle d’ouverture du port 8000 également :

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

      Vous devriez maintenant pouvoir accéder au domaine ou à l’adresse IP de votre serveur pour voir votre application.

      Note : Après avoir configuré Nginx, la prochaine étape devrait consister à sécuriser le trafic vers le serveur en utilisant SSL/TLS. Ceci est important car sinon, toutes les informations, y compris les mots de passe, seraient envoyées sur le réseau en texte clair.

      Si vous disposez d’un nom de domaine, la manière la plus simple d’obtenir un certificat SSL pour sécuriser votre trafic consiste à utiliser Let’s Encrypt. Suivez ce guide pour configurer Let’s Encrypt avec Nginx sur Ubuntu 20.04. Suivez la procédure en utilisant le bloc serveur Nginx que nous avons créé dans ce guide.

      Dépanner Nginx et Gunicorn

      Si cette dernière étape ne montre pas votre application, vous devrez dépanner votre installation.

      Nginx affiche la page par défaut au lieu de l’application Django

      Si Nginx affiche la page par défaut au lieu d’utiliser un proxy vers votre application, cela signifie généralement que vous devez ajuster le server_name dans le fichier /etc/nginx/sites-available/myproject pour qu’il pointe vers l’adresse IP ou le nom de domaine de votre serveur.

      Nginx utilise le server_name pour déterminer le bloc serveur à utiliser pour répondre aux requêtes. Si vous recevez la page Nginx par défaut, c’est un signe que Nginx n’a pas pu faire correspondre la requête à un bloc serveur explicitement, donc il revient au bloc par défaut défini dans /etc/nginx/sites-available/default.

      Le server_name dans le bloc serveur de votre projet doit être plus spécifique que celui dans le bloc serveur par défaut pour être sélectionné.

      Nginx affiche une erreur de Bad Gateway 502 au lieu de l’application Django

      Une erreur 502 indique que Nginx n’est pas en mesure de transmettre la requête. Un large éventail de problèmes de configuration s’expriment avec une erreur 502, de sorte que davantage d’informations sont nécessaires pour dépanner correctement.

      L’endroit principal pour trouver plus d’informations se trouve dans les journaux d’erreur de Nginx. Généralement, cela vous indiquera les conditions qui ont causé des problèmes lors de l’événement de proxying. Suivez les journaux d’erreur Nginx en tapant :

      • sudo tail -F /var/log/nginx/error.log

      Maintenant, faites une autre requête dans votre navigateur pour générer une nouvelle erreur (essayez de rafraîchir la page). Vous devriez recevoir un nouveau message d’erreur écrit au journal. Si vous regardez le message, il devrait vous aider à cerner le problème.

      Vous pourriez recevoir le message suivant :

      connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)

      Cela indique que Nginx n’a pas pu trouver le fichier gunicorn.sock à l’endroit indiqué. Vous devriez comparer l’emplacement proxy_pass, défini dans le fichier /etc/nginx/sites-available/myproject à l’emplacement réel du fichier gunicorn.sock généré par l’unité systemd gunicorn.socket.

      Si vous ne trouvez pas de fichier gunicorn.sock dans le répertoire /run, cela signifie généralement que le fichier systemd socket n’a pas pu le créer. Retournez à la section sur la vérification du fichier socket Gunicorn pour parcourir les étapes de dépannage pour Gunicorn.

      connect() to unix:/run/gunicorn.sock failed (13: Permission denied)

      Cela indique que Nginx n’a pas pu se connecter à la socket Gunicorn en raison de problèmes de permission. Cela peut se produire lorsque la procédure est suivie en utilisant un root user au lieu d’un utilisateur sudo. Bien que systemd soit capable de créer le fichier de socket Gunicorn, Nginx n’est pas en mesure d’y accéder.

      Cela peut se produire s’il existe des permissions limitées à un moment quelconque entre le répertoire root (/) et le fichier gunicorn.sock. Nous pouvons examiner les permissions et les valeurs de propriété du fichier socket et de chacun de ses répertoires parents en passant le chemin absolu de notre fichier socket à la commande namei :

      • namei -l /run/gunicorn.sock

      Output

      f: /run/gunicorn.sock drwxr-xr-x root root / drwxr-xr-x root root run srw-rw-rw- root root gunicorn.sock

      La sortie affiche les permissions de chacun des composants du répertoire. En examinant les permissions (première colonne), propriétaire (deuxième colonne) et groupe propriétaire (troisième colonne), nous pouvons comprendre ‘quel type d’accès est autorisé au fichier socket.

      Dans l’exemple ci-dessus, le fichier socket et chacun des répertoires menant au fichier socket ont des permissions de lecture et d’exécution mondiales (la colonne des permissions pour les répertoires se terminent par r-x au lieu de ---). Le processus Nginx devrait pouvoir accéder à la socket avec succès.

      Si l’un des répertoires menant à la socket n’a pas de permission mondiale de lecture et d’exécution, Nginx ne pourra pas accéder à la socket sans autoriser les permissions de lecture et d’exécution mondiales ou sans s’assurer que la propriété du groupe est donnée à un groupe dont Nginx fait partie.

      Django affiche : “n’a pas pu se connecter au serveur : Connexion refusée”

      Un message que vous pouvez recevoir de Django lorsque vous essayez d’accéder à certaines parties de l’application dans le navigateur web est :

      OperationalError at /admin/login/
      could not connect to server: Connection refused
          Is the server running on host "localhost" (127.0.0.1) and accepting
          TCP/IP connections on port 5432?
      

      Cela indique que Django n’est pas en mesure de se connecter à la base de données Postgres. Assurez-vous que l’instance Postgres fonctionne en tapant :

      • sudo systemctl status postgresql

      Si ce n’est pas le cas, vous pouvez la démarrer, et lui permettre de démarrer automatiquement au démarrage (si elle n’est pas déjà configurée pour le faire) en tapant :

      • sudo systemctl start postgresql
      • sudo systemctl enable postgresql

      Si les problèmes persistent, assurez-vous que les paramètres de la base de données définis dans le fichier ~/myprojectdir/myproject/settings.py sont corrects.

      Autres dépannages

      Pour un dépannage supplémentaire, les journaux peuvent vous aider à cerner les causes profondes. Vérifiez chacune d’entre elles à tour de rôle et recherchez les messages indiquant les zones à problèmes.

      Les journaux suivants peuvent être utiles :

      • Vérifiez les journaux du processus Nginx en tapant : sudo journalctl -u nginx
      • Vérifiez les journaux d’accès Nginx en tapant : sudo less /var/log/nginx/access.log
      • Vérifiez les journaux d’erreur Nginx en tapant : sudo less /var/log/nginx/error.log
      • Vérifiez les journaux de l’application Gunicorn en tapant : sudo journalctl -u gunicorn
      • Vérifiez les journaux de socket Gunicorn en tapant : sudo journalctl -u gunicorn.socket

      Lorsque vous mettez à jour votre configuration ou votre application, vous devrez probablement redémarrer les processus pour vous ajuster à vos changements.

      Si vous mettez à jour votre application Django, vous pouvez redémarrer le processus Gunicorn pour récupérer les modifications en tapant :

      • sudo systemctl restart gunicorn

      Si vous modifiez les fichiers de socket ou de service, rechargez le démon et redémarrez le processus en tapant :

      • sudo systemctl daemon-reload
      • sudo systemctl restart gunicorn.socket gunicorn.service

      Si vous modifiez la configuration du bloc serveur Nginx, testez la configuration et ensuite Nginx en tapant :

      • sudo nginx -t && sudo systemctl restart nginx

      Ces commandes sont utiles pour récupérer les modifications à mesure que vous ajustez votre configuration.

      Conclusion

      Dans ce guide, nous avons mis en place un projet Django dans son propre environnement virtuel. Nous avons configuré Gunicorn pour traduire les requêtes client de sorte que Django puisse les gérer. Ensuite, nous avons mis en place Nginx pour qu’il agisse en tant que proxy inverse afin de gérer les connexions client et servir le projet approprié, en fonction de la requête du client.

      Django simplifie la création de projets et d’applications en fournissant un grand nombre d’éléments communs, ce qui vous permet de vous concentrer sur les éléments uniques. En exploitant la chaîne d’outils générale décrite dans cet article, vous pouvez facilement servir les applications que vous créez à partir d’un seul serveur.



      Source link