Reverse Proxy Anfänger mit enormen Problemen

sasbro97

Lt. Junior Grade
Registriert
Nov. 2014
Beiträge
417
Moin. Ich bin ein absolut blutiger, unwissender Anfänger in Bezug auf Proxys allgemein. Wofür brauche ich einen Reverse-Proxy? Ich möchte gerne NextCloudPi und WordPress und (wenn es geht aber ist sonst egal) PiHole jeweils in einem Docker Container auf meinem Ubuntu System laufen lassen. Läuft alles auf einem Einplatinencomputer mit 4GB RAM etc. also Leistung ist kein Problem.

Nach dem Durchforsten des halben Internets habe ich es geschafft mit nginx einen Reverse-Proxy für NextCloudPi zu erstellen. Läuft auch echt gut und flott, aber jetzt kommt ja erst der Spaß mit den anderen Dingen. Grundsätzlich frage ich mich da gibt es einen anfängerfreundlichen Reverse-Proxy? Kenne ja für den Zweck nginx, traefik und insbesondere https://github.com/jwilder/nginx-proxy. Nur leider bin ich auch was die ganzen SSL Zertifikate angeht sehr neu. Also im Grunde genommen habe ich echt keine Ahnung.

Mit Docker kenne ich mich schon einigermaßen aus, aber das ist zu viel. Die Anleitung der ich gefolgt bin ist folgende: https://phip1611.de/2019/12/program...-compose-behind-nginx-reverse-proxy-with-tls/

Was ich noch nicht verstanden habe ist woher man überhaupt weiß was man da bei nginx in die Konfiguration einträgt und vor allem habe ich so viele Variationen gesehen. Die einen Ändern die default-sites, manche erstellen neue, diese Anleitung beschäftigt sich nur mit dem direkten nginx.conf... Ich frage mich auch wie das vom Aufbau her gehen soll insgesamt. Meine Cloud läuft öffentlich unter xyz.spdns.de. Wenn ich nun eben auch die WordPress Seite öffentlich schalten möchte geht dieselbe Domain ja nicht. Dann habe ich Anleitungen gefunden die sagen WordPress vor oder unter der NextCloud und ich will weder noch, denn sie soll ja durch die Container quasi daneben und unabhängig voneinander laufen.

Sorry ich weiß eben nicht mal wo ich anfangen soll mit meinen Fragen. Wenn jemand auch einen Anfängerguide zum allgemeinen Einlesen kennt, immer her damit!
 
Im einfachsten Fall hast du pro Webseite (also nextcloud, wordpress, etc) eine eigene (Sub-)Domain. In dem Szenario legst du pro Webseite einen Serverblock in nginx an und setzt den server_name auf den passenden Domainnamen.

Variante zwei hat alle Seiten hinter einer Domain laufen und du differenzierst die Webseiten über die URL. Beispielsweise leitet "a.b.de/nextcloud" zu deiner Nextcloudinstanz und "/blog" zu deinem wordpress. Dafür muss aber die Webseite auch passend konfigurierbar sein (Stichwort basepath oder ähnlich), was bei nextcloud und wordpress kein Problem sein sollte.

Für Zertifikate kannst du dir lets encrypt per certbot anschauen. Gibts auch als Container und ist eigentlich recht einfach zu benutzen.
 
@KillerCow okay das wäre auch mein Plan dann lieber bspw. einmal xyz.spdns.de und einmal abc.spdns.de nur mal angenommen halt als Domain. Ich verstehe nur nicht wie ich das mache, weil sich die beiden ja die Ports eben teilen müssen, was ja der Sinn hinter Reverse-Proxy ist.
Hier mal meine aktuelle Konfiguration. Und das hier ja so durch dieses http gesetzt ist wüsste ich auch nicht wie ich da eine zweite Domain angeben soll. Wie gesagt alles nach Tutorial.

Code:
worker_processes auto;

include /etc/nginx/modules-enabled/*.conf;

events {
  worker_connections 1024;
}

http {
  gzip            on;
  gzip_min_length 1000;
  gzip_proxied    expired no-cache no-store private auth;
  gzip_types      text/plain text/css text/xml
                  application/javascript application/json application/xml application/rss+xml image/svg+xml;

  server_names_hash_bucket_size 64;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  more_clear_headers 'server';

  ssl_certificate     /etc/letsencrypt/live/xyz.spdns.de/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/xyz.spdns.de/privkey.pem;
  ssl_dhparam         /etc/ssl/dhparam.pem;
  ssl_protocols       TLSv1.2 TLSv1.3;
  ssl_session_cache      shared:SSL:10m;
  ssl_session_timeout 10m;
  ssl_ciphers         "EECDH-AESGCM:EDH+ESGCM:AES256+EECDH:AES256+EDH";
  ssl_prefer_server_ciphers on;
  add_header          Strict-Transport-Security "max-age=31557600; includeSubdomains" always;

  server {
    listen 80 default_server;
    listen [::]:80 default_server;
    return 301 https://$host$request_uri;
  }

  # NextCloudPi
    
  server {
    server_name nextcloud.xyz.spdns.de;
    
    listen 443 ssl http2;
    listen [::]:433 ssl http2;
 
    client_max_body_size 100G;
    
    location / {
      more_clear_headers 'upgrade';
      more_clear_headers 'Strict-Transport-Security';

      proxy_ssl_verify off;
      proxy_pass https://nextcloudpi;
      proxy_set_header 'X-Forwarded-Host' nextcloud.xyz.spdns.de;
      proxy_set_header 'X-Forwarded-Proto' https;
      proxy_set_header 'X-Forwarded-For' $remote_addr;
      proxy_set_header 'X-Forwarded-IP' $remote_addr;

      proxy_pass_header x-requested-by;
      proxy_pass_header requesttoken;
    }
  }
    
  # NextCloudPi Konfiguration Web-Interface
    
  server {
    server_name nextcloud.xyz.spdns.de;
    
    listen 4443 ssl http2;
    listen [::]:4433 ssl http2;

    location / {
      more_clear_headers 'upgrade';
      more_clear_headers 'Strict-Transport-Security';

      proxy_ssl_verify off;
      proxy_pass https://nextcloudpi:4443;

      proxy_pass_header Authorization;
      
      proxy_set_header 'X-Forwarded-Host' nextcloud.xyz.spdns.de;
      proxy_set_header 'X-Forwarded-Proto' https;
      proxy_set_header 'X-Forwarded-For' $remote_addr;
      proxy_set_header 'X-Forwarded-IP' $remote_addr;
    }
  }
 
Das mit dem Port ist kein Problem. Wichtig ist nur, dass jeder Serverblock über Servername und Portkombination eindeutig identifizierbar ist. Bei mir in der Firma laufen z.B. mehrere Dutzend Subdomains über Port 443. Da kümmert sich der nginx drum, das jeweils in die richtige Bahn zu leiten.
 
nginx automated configuration creator
********************************************************************************************************************
Code:
docker run -d \
    --name nginx-gen \
    --volumes-from nginx \
    -v /container/webproxy/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro \
    -v /var/run/docker.sock:/tmp/docker.sock:ro \
    -e ENABLE_IPV6=true \
    jwilder/docker-gen:latest \
    -notify-sighup nginx -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
Wichtig, du brauchst das Template: https://raw.githubusercontent.com/jwilder/docker-gen/master/templates/nginx.tmpl, bei mir liegt das hier "-v /container/webproxy/nginx.tmpl"


letsencrypt container for nginx webproxy
********************************************************************************************************************
Code:
docker run -d \
    --name nginx-letsencrypt \
    -e "NGINX_DOCKER_GEN_CONTAINER=nginx-gen" \
    --volumes-from nginx \
    -v /container/webproxy/certs:/etc/nginx/certs:rw \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    jrcs/letsencrypt-nginx-proxy-companion:latest
hier hab ich die Zertifikate auf die Festplatte ablegen lassen: "-v /container/webproxy/certs" damit die das Löschen und neu erstellen des Containers überleben


nginx webproxy container
********************************************************************************************************************
Code:
docker run -d -p 80:80 -p 443:443 \
    --name nginx \
    -v /container/webproxy/certs:/etc/nginx/certs:ro \
    --label com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true \
    nginx:alpine
hier ist das certs-Verzeichnis eingebunden

hier ein Beispiel für NodeRed
********************************************************************************************************************
Code:
docker run -d --name=nodered -v /container/nodered/config:/data -e VIRTUAL_HOST=nodered.domain.tld -e LETSENCRYPT_HOST=nodered.domain.tld -e LETSENCRYPT_EMAIL=admin@domain.tld -p 1880:1880 nodered/node-red-docker:latest



Wichtig ist halt auch dass deine Domain dann auf deine öffentliche IP zeigt und du den Port 80 und 443 zu deinem Gerät weiterleitest auf dem Docker läuft!
 
Zuletzt bearbeitet:
@LieberNetterFlo danke dir ich muss jetzt erstmal weg, aber werde mit Sicherheit auf dich zurück kommen! Und @KillerCow dir natürlich auch danke :)
Was ist eigentlich der beste Anbieter in Preis-Leistung bzgl. .de-Domain?
 
Du hast in der Config 2 mal einen Serverblock mit den selben server_name auf 2 verscheidenen Ports, alles was du damit bezweckst ist die gleiche Seite auf 2 verschieden Ports verfügbar zu machen. Hier mal ein vereinfachtes Beispiel wie es ungefähr vom Prinzip aussehen kann:

Code:
server {
    server_name nextcloud.xyz.spdns.de;
   
    listen 443 ssl http2;
    listen [::]:433 ssl http2;
   
      proxy_pass https://ip_vom_dockercontainer_nextcloud;
  }

  server {
    server_name wordpress.xyz.spdns.de;
   
    listen 443 ssl http2;
    listen [::]:433 ssl http2;
   
      proxy_pass https://ip_vom_dockercontainer_wordpress;
  }
 
ich glaube aber dass es mit Traefik V2 wesentlich einfacher ist als mit dem Konstrukt aus den 3 Containern ;) als ich das genutzt habe gabs das halt noch nicht.

bzgl. Domain habe ich meine .de bei murauer-it.at, die kostet da 4,30€ im Jahr, und DNS mach ich via Cloudflare (kostenlos)
 
  • Gefällt mir
Reaktionen: sasbro97
Vielleicht erstmal zum Reverse-Proxy: Der ist im Prinzip dazu gedacht, dass er sich primär um alle eintreffenden HTTP Anfragen kümmert sowie um die Verschlüsselung. Vor allem wenn mehrere Dienste auf dem gleichen Port laufen sollen kümmert er sich praktisch um die Delegation, an welchen deiner Dienste weitergeleitet wird. Dazu muss man ein wenig wissen, wie so ein HTTP Request aussieht und was der Reverse-Proxy damit anstellt.
Der HTTP Request enthält zum einen den Befehl (GET, PUT, POST ...) sowie den Pfad zum angeforderten Objekt, also bspw
Code:
GET /index.htm
Das schlägt nun beim Reverse-Proxy auf, aber daran kann man noch nicht entscheiden, an welchen deiner Dienste diese Anfrage nun soll. Deshalb gibt es nun 2 Möglichkeiten. Die etwas einfachere bzw. "transparentere" Lösung ist die Nutzung des Host-Parameters der Anfrage. Denn im Anschluss an die obige Zeile, kommt noch mehr.
Code:
GET /index.htm 
Host: subdomain.domain.de
Der Host-Part ist das, was bspw. der Anwender in seinen Browser eingegeben hat, freundlicherweise senden die Browser das in der Anfrage mit.
Hat man allerdings nicht die Möglichkeit Subdomains einzurichten, dann bleibt nur übrig, den Teil nach dem GET zu zerlegen und daran zu entscheiden. Etwas salopp gesagt: Deine Dienste wandern in "Unterordner".
Code:
GET /owncloud/index.php
Wichtig ist, dass hier sowohl die Anwendung, als auch die Konfiguration im Container mit dem laufenden Dienst stimmen. Man kann nun eben diesen Part nämlich auch durch den Proxy umschreiben lassen (rewrite), sodass dann am Owncloud-Zielcontainer nur ein
Code:
GET /index.php
ankommt. Das wird aber in der Anwendung zu Problemen führen, denn alle Links die sie auf ihrer Seite erzeugt, referieren dann wieder nur auf bspw. "/style/main.css". Genau den Pfad würde der Reverse-Proxy dann irgendwann wieder vorgesetzt bekommen und ihm fehlt hier wieder das "/owncloud/.." um entscheiden zu können.
Das kann ein paar Nächte Einrichtung und ausprobieren kosten. Viel Erfolg!
 
Ich persönlich nutze Caddy (https://caddyserver.com/v1/) als Docker Container (https://github.com/abiosoft/caddy-docker) als reverse proxy. Habe früher auch nginx benutzt, allerdings finde ich die Config von Caddy wesentlich übersichtlicher.

Ein einfacher config block kann dabei so simpel sein:
Code:
nextcloud.example.org {
        proxy / http://xxx.xxx.xxx.xxx:80 {
                transparent
        }
}
 
@LieberNetterFlo das musst du mir kurz erklären. Die Docker-Container hab ich gerne wegen Wartbarkeit und einfach herunterzufahren etc. Und auch so, wenn mal etwas crasht, dann einfach nur neues Linux Image aufziehen und die compose ausführen und alles geht wie vorher. Wie soll Traefik da helfen gegen 3 Container? Dachte ist nur ein Reverse-Proxy?

@Azshania die Frage ist für mich aber immer welche von den 36000 Parametern brauche ich. Siehe meine Konfig oben. Ist alleine wie das ganze http Konstrukt ist usw. Da seh ich keine Chance für eine zweite Domain so wie das aufgebaut ist.

@Ebrithil auch schon mal gehört irgendwo. Wie sieht es da leistungstechnisch aus? Nginx ist halt verdammt schnell im Gegensatz zum normalen integrierten Apache von NCP.

@tony_mont4n4 kenn ich, aber Apache Proxy bringt mir nichts...
 
@sasbro97 Solange du da keine 100Gbit Leitung dran hängen hast, wird der Proxy (egal welcher) dir keine Probleme machen. Sicherlich ist nginx vermutlich schneller, aber schnell genug ist Caddy allemal immer noch.
 
Traefik ist ebenfalls im Docker Container verfügbar und hat halt den Charme dass es nur ein Container ist und nicht 3 wie bei meiner nginx Lösung... Das Endergebnis ist aber das gleiche ;)
 
Ich muss sagen, Traefik, und docker-gen basierte container wie zb https://github.com/jwilder/nginx-proxy sind mir zuviel "automagic". Ich hab gern die Kontrolle darüber, was wie exposed wird. Teilweise hab ich zb 3 verschiedene domains/urls die auf den selben Service zeigen. Oder auch teilweise Services die nicht in Docker sondern auf anderen Hosts laufen, all das kriege ich mit Caddy easy hin. Mit den automatischen Lösungen würde das alles schwierig werden.
 
Hey Leute. Sorry ich kam zeitlich einfach nicht dazu weiterzumachen und sitze deshalb nun dran. Versuche es für WordPress und noch erstmal mit einem normalen NGINX Container. Jedenfalls ja fast. Der Container wird so erstelllt:

Code:
FROM nginx:1.17.9
# to get nginx_more_headers
RUN apt-get update && apt-get install -y nginx-extras
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx
VOLUME /var/log/nginx

Und der Versuch meinerseits aus nun die nginx.conf anzupassen geht sehr schief. Fehler:
nginx: [emerg] host not found in upstream "wordpress" in /etc/nginx/nginx.conf:113

Code:
worker_processes auto;

include /etc/nginx/modules-enabled/*.conf;

events {
  worker_connections 1024;
}

http {
  gzip            on;
  gzip_min_length 1000;
  gzip_proxied    expired no-cache no-store private auth;
  gzip_types      text/plain text/css text/xml
                  application/javascript application/json application/xml application/rss+xml image/svg+xml;

  server_names_hash_bucket_size 64;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  more_clear_headers 'server';

  ssl_certificate     /etc/letsencrypt/live/xyz.spdns.de/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/xyz.spdns.de/privkey.pem;
  ssl_dhparam         /etc/ssl/dhparam.pem;
  ssl_protocols       TLSv1.2 TLSv1.3;
  ssl_session_cache      shared:SSL:10m;
  ssl_session_timeout 10m;
  ssl_ciphers         "EECDH-AESGCM:EDH+ESGCM:AES256+EECDH:AES256+EDH";
  ssl_prefer_server_ciphers on;
  add_header          Strict-Transport-Security "max-age=31557600; includeSubdomains" always;

  server {
    listen 80 default_server;
    listen [::]:80 default_server;
    return 301 https://$host$request_uri;
  }

  # NextCloudPi
    
  server {
    server_name nextcloud.xyz.spdns.de;
    
    listen 443 ssl http2;
    listen [::]:433 ssl http2;
 
    client_max_body_size 100G;
    
    location / {
      more_clear_headers 'upgrade';
      more_clear_headers 'Strict-Transport-Security';

      proxy_ssl_verify off;
      proxy_pass https://nextcloudpi;
      proxy_set_header 'X-Forwarded-Host' nextcloud.xyz.spdns.de;
      proxy_set_header 'X-Forwarded-Proto' https;
      proxy_set_header 'X-Forwarded-For' $remote_addr;
      proxy_set_header 'X-Forwarded-IP' $remote_addr;

      proxy_pass_header x-requested-by;
      proxy_pass_header requesttoken;
    }
  }
    
  # NextCloudPi Konfiguration Web-Interface
    
  server {
    server_name nextcloud.xyz.spdns.de;
    
    listen 4443 ssl http2;
    listen [::]:4433 ssl http2;

    location / {
      more_clear_headers 'upgrade';
      more_clear_headers 'Strict-Transport-Security';

      proxy_ssl_verify off;
      proxy_pass https://nextcloudpi:4443;

      proxy_pass_header Authorization;
      
      proxy_set_header 'X-Forwarded-Host' nextcloud.xyz.spdns.de;
      proxy_set_header 'X-Forwarded-Proto' https;
      proxy_set_header 'X-Forwarded-For' $remote_addr;
      proxy_set_header 'X-Forwarded-IP' $remote_addr;
    }
  }
 
  # WordPress
 
    server {
        listen 80;
        listen [::]:8080;

        server_name dies-das.de www.dies-das.de;

        index index.php index.html index.htm;

        root /var/www/html;

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

        location / {
                try_files $uri $uri/ /index.php$is_args$args;
        }

        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass wordpress:9000;
                fastcgi_index index.php;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param PATH_INFO $fastcgi_path_info;
        }

        location ~ /\.ht {
                deny all;
        }

        location = /favicon.ico {
                log_not_found off; access_log off;
        }
        location = /robots.txt {
                log_not_found off; access_log off; allow all;
        }
        location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
                expires max;
                log_not_found off;
        }
    }
 
  }

Ich glaube so ist das eh falsch und problematisch und sorry ich bin halt auf dem Gebiet absoluter Neuling. Hab nämlich nun eine de-Domain gekauft und will hier ja quasi einmal meine kostenlose Domain und meine gekaufte Domain laufen lassen. Oder ist das gar nicht möglich mit einem Reverse-Proxy, wenn es 2 komplett unterschiedliche Domains sind?
 
Läuft der Wordpress Container schon wenn du den nginx startest? Ansonsten kreigst du nämlich die nginx: [emerg] host not found in upstream "wordpress" Fehlermeldung.
 
@Ebrithil hab es mittlerweile gefixt und keine Fehler mehr. Aber da ich nicht auf die Domains zugreifen kann, weil ich nicht weiß wie es zu konfigurieren ist, kann ich nicht prüfen.
 
Zurück
Oben