Skip to main content

Proxy-Container NGINX

Vorwort

Um für mehrere Container einen einheitlichen Zugriff zu gewährleisten, kann ein öffentlicher Nginx Proxy-Container genutzt werden. Alle Verbindungen nach Außen, sowie die dazugehörige Verschlüsselung per Letsencrypt SSL-Zertifikat, sind möglich.

Nginx-Konfiguration

Eine Nginx lebt von einer nginx.conf-Datei und den Konfigurationen für jeden virtuellen Host (server).

Docker-Container

Über die folgende docker-compose.yml-Datei wird eine einfacher Proxy-Container aufgesetzt.

version: '3.4'
 
services:
  proxy:
    image: nginx:latest
    container_name: proxy
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./sites-enabled:/etc/nginx/sites-enabled
      - ./logs:/var/log/nginx
      - ./cache:/etc/nginx/cache
    ports:
      - 80:80
      - 443:443
    environment:
      - TZ=Europe/Berlin
    network_mode: "host"

nginx.conf

user  nginx;
worker_processes  1;
 
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
 
events {
    worker_connections  1024;
}
 
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
 
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
 
    access_log  /var/log/nginx/access.log  main;
 
    sendfile        on;
 
    keepalive_timeout  65;
 
    gzip  on;
 
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Virtueller Host

Ein virtueller Host stellt die Schnittstelle zwischen dem Nginx-Container und einem beliebigen anderen Container im lokalen Netzwerk dar.
Die Datei wird in dem Ordner site-enabled hinterlegt.
Nach der Erstellung bzw. Bearbeitung dieser Datei ist ein Neustart des Proxy-Containers notwendig!

Port 80

Wenn eine unverschlüsselte Verbindung verwendet werden möchte (nicht zu empfehlen!), ist folgende Konfiguration nötig.

server {
        listen 80;
        listen [::]:80;
 
        ; Beispiel der FQDN: [www].google.de
        server_name [SUB_NAME].DOMAIN.TLD;
 
         location / {
                client_max_body_size 1024m;
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://[UPSTREAM_NAME];
        }
 
        error_log  /var/log/nginx/[NAME_DER_FQDN]-http-error.log;
        access_log /var/log/nginx/[NAME_DER_FQDN]-http-access.log;
}
 
upstream [UPSTRAM_NAME] {
        server 0.0.0.0:[PORT];
}

Port 443

server {
        listen 80;
        listen [::]:80;
  
        ; for example: [www].google.de
        server_name [SUB_NAME].DOMAIN.TLD;
 
        # Redirect any HTTP request to HTTPS
        location / {
                return 301 https://$server_name$request_uri;
        }
 
        error_log  /var/log/nginx/[NAME_DER_FQDN]-http-error.log;
        access_log /var/log/nginx/[NAME_DER_FQDN]-http-access.log;
}
 
upstream [UPSTRAM_NAME] {
        server 0.0.0.0:[PORT];
}
 
server {
        listen 443 ssl;
        listen [::]:443 ssl;
 
        server_name [SUB_NAME].DOMAIN.TLD;
  
        proxy_read_timeout 600s;
 
        # config to enable HSTS(HTTP Strict Transport Security)
        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains;";
 
        ssl_certificate /PFAD/ZUR/FULLCHAIN/ZERTIFIKAT/DATEI/fullchain.pem;
        ssl_certificate_key /PFAD/ZUR/PRIVATEKEY/DATEI/privkey.pem;
 
        location / {
                client_max_body_size 1024m;
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;v
                proxy_pass http://[UPSTREAM_NAME];
        }
  
        error_log  /var/log/nginx/[NAME_DER_FQDN]-https-error.log;
        access_log /var/log/nginx/[NAME_DER_FQDN]-https-access.log;
}

Catchall

Ein Catchall virtueller Host nimmt alle Verbindungen auf, die nicht über eine eigene virtuelle Host-Konfiguration verarbeitet werden.

Für die Catchall-HTTPS-Verbindung kann ein selbst signiertes Zertifikat genutzt werden. Oder man richtet eine eigene Domain dafür ein.

server {
        listen 80;
        listen [::]:80;
  
        server_name _;
 
        location / {
                return 301 https://[SUB_DOMAIN].DOMAIN.TLD;
        }
 
        error_log  /var/log/nginx/catchall-http-error.log;
        access_log /var/log/nginx/catchall-http-access.log;
}
 
server {
        listen 443 ssl;
        listen [::]:443 ssl;
 
        server_name _;
  
        proxy_read_timeout 600s;
 
        # config to enable HSTS(HTTP Strict Transport Security)
        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains;";
 
        ssl_certificate /PFAD/ZUR/FULLCHAIN/ZERTIFIKAT/DATEI/fullchain.pem;
        ssl_certificate_key /PFAD/ZUR/PRIVATEKEY/DATEI/privkey.pem;
 
        location / {
                return 301 https://[SUB_DOMAIN].DOMAIN.TLD;
        }
   
        error_log  /var/log/nginx/catchall-https-error.log;
        access_log /var/log/nginx/catchall-https-access.log;
}

Letsencrypt Zertifikate

Mit Letsencrypt Zertifikaten lässt sich eine einfache und sichere HTTPS-Verbindung erstellen.

Wird der erste Container mit einem Zertifikat erstellt, muss dieser zuerst mit einem selbst signierten Zertifikat gestartet sein, damit dieser zum Einen von Außerhalb erreichbar ist und zum Zweiten Letsencrypt eine erfolgreiche Autorisierung durchführen kann.

Docker-Container

Die Konfigurationsdatei des Proxy-Docker-Containers muss um die Bereitstellung des letsencrypt.conf-Datei erweitert werden.
Der Ordner /tmp/.well-known muss auf dem Hostsystem vorhanden sein und dient zur Autorisierung für Letsencrypt-Anfragen.

volumes:
  - ./snippets/letsencrypt.conf:/etc/nginx/snippets/letsencrypt.conf
  - /tmp/.well-known:/tmp/.well-known

letsencrypt.conf

location ^~ /.well-known/acme-challenge/ {
        default_type „text/plain“;
        root /tmp/.well-known;
        allow all;
}

Virtueller Host

Die Sektionen für die HTTP-Verbindung muss in den Konfigurationsdateien der virtuellen Hosts entsprechend um das Snippet erweitert werden.

include /etc/nginx/snippets/letsencrypt.conf;

Letsencrypt Zertifikat-Challenge

  1. Ist der Virtuelle Host korrekt mit einem selbst signierten Zertifikat eingerichtet und erreichbar, kann mit der Challenge begonnen werden.
    Für die Durchführung wird eine laufende Letsencrypt-Installation vorausgesetzt
  2. Durchführen der Challenge

    certbot certonly --webroot -w /tmp/.well-known -d [FQDN]
  3. Sobald die Challenge erfolgreich durchgeführt wurde, kann das neue Fullchain-Zertifikat und der Privat-Key in der Virtueller Host-Datei hinterlegt werden
  4. Den Proxy-Container neu starten und die neue Adresse testen