Zammad auf Debian mit externem NGINX Reverse-Proxy aufsetzen

Die Installation ist ziemlich einfach: Elasticsearch installieren, Zammad installieren, Elasticsearch konfigurieren, fertig (siehe Link unten).

Bei mir ist dann noch ein Problem mit HTTPS (Token-Error) aufgetreten, das ließ sich folgendermaßen lösen:

Bei jedem X-Forwarded-Proto statt $scheme https reinschreiben:

server {
        listen 80;
        server_name zammad.example.com;
        return 301 https://$server_name$request_uri;
}
server {
        listen 443 ssl;

        server_name zammad.example.com;

        # SSL
        ssl_certificate /etc/letsencrypt/live/zammad.example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/zammad.example.com/privkey.pem;
        ssl_trusted_certificate /etc/letsencrypt/live/zammad.example.com/fullchain.pem;

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

    client_max_body_size 50M;

    location ^~ / {
        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header CLIENT_IP $remote_addr;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https; 
# siehe https://community.zammad.org/t/fresh-install-3-2-x-csrf-token-verification-failed/3080/32v
        proxy_read_timeout 300;
        proxy_pass http://IP.OF.ZAMMAD.MACHINE/;

    }
        include _general.conf;
}
Links und Credit

https://docs.zammad.org/en/latest/install/debian.html

standardnotes selbst hosten

Ich habe mir eine Standard-Notes-Instanz zuhause selbst aufgesetzt, so einfach wie das ist nur selten etwas: Einfach die Anleitungen (siehe unten) befolgen, einmal eine nginx-Instanz auf der Docker-VM, einmal eine nginx-Instanz auf dem Reverse-Proxy (falls ihr einen eigenen habt), und die Sache läuft.

Links und Credit

https://docs.standardnotes.org/self-hosting/docker
https://docs.standardnotes.org/self-hosting/https-support

Gitlab CE mit nginx-Reverse-Proxy aufsetzen

Hier die nginx Reverse-Proxy-Config für gitlab-ce

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

server {
    listen 443 ssl http2; 
    listen [::]:443 ssl http2; # OCSP Stapling fetch OCSP records from URL in ssl_certificate and cache them
    server_name DEINE_URL; 

    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_certificate /etc/letsencrypt/live/git.itkfm.at/fullchain.pem; 
    ssl_certificate_key /etc/letsencrypt/live/git.itkfm.at/privkey.pem; 

    resolver 9.9.9.9;
    ssl_ecdh_curve prime256v1;
    add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
        # Server should determine the ciphers, not the client
        ssl_prefer_server_ciphers on;

        # SSL session handling
        ssl_session_timeout 24h;
        ssl_session_cache shared:SSL:50m;
        
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;
        
        location / {
            proxy_pass https://DEINE_IP:443;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Bookstack mit nginx Reverse-Proxy betreiben & E-Mail konfigurieren

Bei Bookstack handelt es sich um eine Anwendung, die eine Dokumentenverwaltung bereitstellt. Leider ist die Doku sehr spärlich ausgeführt, warum ich hier nun kurz zusammenfasse, wie die Applikation hinter einem nginx Reverse-Proxy betreibbar ist.

Die Applikation selbst habe ich mit dem Installationsscript für Ubuntu-Server installiert.

Um E-Mail erfolgreich zu konfigurieren, muss man die Datei „/var/www/bookstack/.env“ bearbeiten, damit sie folgende Einträge enthält:

# Application key
# Used for encryption where needed.
# Run `php artisan key:generate` to generate a valid key.
APP_KEY=censored

# Application URL
# Remove the hash below and set a URL if using BookStack behind
# a proxy, if using a third-party authentication option.
# This must be the root URL that you want to host BookStack on.
# All URL's in BookStack will be generated using this value.
APP_URL=https://your.domain.net

# Database details
DB_HOST=localhost
DB_DATABASE=bookstack
DB_USERNAME=bookstack
DB_PASSWORD=censored

# Mail system to use
# Can be 'smtp', 'mail' or 'sendmail'
MAIL_DRIVER=smtp

MAIL_FROM=test@test.at
MAIL_FROM_NAME=Your Bookstack Server

# SMTP mail options
MAIL_HOST=test.mail.at
MAIL_PORT=465
MAIL_USERNAME=test@test.at
MAIL_PASSWORD=censored
MAIL_ENCRYPTION=ssl


# A full list of options can be found in the '.env.example.complete' file.

Im Reverse-Proxy muss die Config folgendermaßen aussehen:

server {
    listen 80;
    server_name your.domain.net; 
    return 301 https://$server_name$request_uri;
}

# BLOG SITE
server {
 listen 443 ssl http2;
 server_name your.domain.net;

## Source: https://github.com/1activegeek/nginx-config-collection
## READ THE COMMENT ON add_header X-Frame-Options AND add_header Content-Security-Policy IF YOU USE THIS ON A SUBDOMAIN YOU WANT TO IFRAME!

## Certificates from LE container placement
ssl_certificate /etc/letsencrypt/live/your.domain.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your.domain.net/privkey.pem;

ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
ssl_session_timeout  10m;

## NOTE: The add_header Content-Security-Policy won't work with duckdns since you don't own the root domain. Just buy a domain. It's cheap
## Settings to add strong security profile (A+ on securityheaders.io/ssllabs.com)

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none; #SET THIS TO index IF YOU WANT GOOGLE TO INDEX YOU SITE!
add_header Referrer-Policy "strict-origin-when-cross-origin";
proxy_cookie_path / "/; HTTPOnly; Secure"; ##NOTE: This may cause issues with unifi. Remove HTTPOnly; or create another ssl config for unifi.
#more_set_headers "Server: Classified";
#more_clear_headers 'X-Powered-By';
 
 client_max_body_size 0; 
 
  
location / {
    proxy_pass http://DOMAIN.OF.YOUR.BOOKSTACK/;
    } 
}

Collabora-Server in LXC laufen lassen – Nextcloud 15

UPDATE: sollte sich nach einem Kernel-Update der Docker-Dämon nicht mehr starten lassen, dann folgenden Befehl probieren:

rm /var/lib/docker/aufs -rf

Danach den Dämon neu starten, dann sollte ein Neustart des Containers wieder funktionieren! UPDATE ENDE

Mit Nextcloud Version 15 gibt es nun eine neue und sehr interessante Funktion, mit der sich direkt im Webinterface der Self-Hosting-Cloud, und auch der dazugehörigen App, Dokumente, Tabellenkalkulationen und Präsentationen in unterschiedlichsten Dateiformaten ansehen und bearbeiten lassen. Dazu reicht es allerding nicht, die Funktion in der Nextcloud zu aktivieren, sondern es wird ein weiterer Dienst benötigt, der wie folgt mit Docker aufzusetzen ist:

Installation von Docker

Abhängig von eurer Betriebssystemwahl gibt es hier unterschiedliche Methoden, in diesem Beispiel verwendet wird wie immer Debian, allerding in einem LXC. Hier der Link des Herstellers zur Installationsanleitung:
https://docs.docker.com/install/linux/docker-ce/debian/

Da wir das ganze in einem LXC installieren möchten, gibt es vor dem ersten Start eines Containers jedoch eine zusätzliche Maßnahme zu treffen. Dazu einfach in die Konfigurationsdatei des LXC (z.B.: 100.conf) folgende Zeilen hinzufügen (nachzulesen unter
https://www.solaris-cookbook.eu/virtualisation/proxmox/proxmox-lxc-running-docker-inside-container):

# insert docker part below
lxc.apparmor.profile: unconfined
lxc.cgroup.devices.allow: a
lxc.cap.drop:

Nun können wir den Docker-Container mittels folgenden Befehl starten (auf der Nextcloud-Seite wird vorher der Container heruntergeladen, Docker lädt allerdings bei fehlenden lokalen Datein selbständig nach, sodass man sich das hier sparen kann:

docker run -t -d -p 9980:9980 -e 'domain=domain\\.der\\.nextcloud' -e 'dictionaries=de en es ..' --restart always --cap-add MKNOD collabora/code

Im Unterschied zu dem Befehl auf der Nextcloud-Seite habe ich das 127.0.0.1 vor den Ports weggelassen, weil ich später mit einem Reverse-Proxy von einem anderen Container auf den Dienst zugreifen möchte. WICHTIG ist auch zu beachten, dass die Domain, die im Parameter -e angeben wird, NICHT die der Collabora-Instanz, SONDERN DIE DER NEXTCLOUD IST, DIE NACHHER VERWENDET WIRD! (Man kann vielleicht erkennen, das mich dieser Umstand ein wenig verärgert hat, da hat wieder einige Zeit daran geglaubt, da das nicht so genau auf der Nextcloud-Website beschrieben ist).

Nun müssen wir am Reverse-Proxy noch folgende Konfiguration einspielen (Danke an
https://icewind.nl/entry/collabora-online/):

server {
    listen       443 ssl;
    server_name  office.example.com;

    ssl_certificate /path/to/certficate;
    ssl_certificate_key /path/to/key;
    
    # static files
    location ^~ /loleaflet {
        proxy_pass https://192.168.1.2:9980;
        proxy_set_header Host $http_host;
    }

    # WOPI discovery URL
    location ^~ /hosting/discovery {
        proxy_pass https://192.168.1.2:9980;
        proxy_set_header Host $http_host;
    }

   # main websocket
   location ~ ^/lool/(.*)/ws$ {
       proxy_pass https://192.168.1.2:9980;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "Upgrade";
       proxy_set_header Host $http_host;
       proxy_read_timeout 36000s;
   }
   
   # download, presentation and image upload
   location ~ ^/lool {
       proxy_pass https://192.168.1.2:9980;
       proxy_set_header Host $http_host;
   }
   
   # Admin Console websocket
   location ^~ /lool/adminws {
       proxy_pass https://192.168.1.2:9980;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "Upgrade";
       proxy_set_header Host $http_host;
       proxy_read_timeout 36000s;
   }
   location ~ ^/hosting/capabilities {
       proxy_pass https://192.168.1.2:9980;
       proxy_set_header Host $http_host;
   }
}
Links und Credit

https://nextcloud.com/collaboraonline/
https://docs.docker.com/install/linux/docker-ce/debian/
https://www.solaris-cookbook.eu/virtualisation/proxmox/proxmox-lxc-running-docker-inside-container
https://icewind.nl/entry/collabora-online/

WordPress-Migration auf neuen Server – eine Leidensgeschichte

Aufgrund von internen Umstrukturierungen der IT mussten wir nun diesen Blog auf einen neuen Server mit einem neuen Domain-Namen (blog.e9a.at anstatt e9a.at) umsiedeln. Normalerweise verläuft so etwas bei uns relativ problemlos, wir haben das auch schon ein paar mal gemacht. Allerdings war es für uns ein Novum, eine WordPress-Instanz über die Kommandozeile zu migrieren. Und wie sich herausstellen sollte, kann es mit WordPress durchaus wilde Komplikationen geben. Vor allem, wenn man es sich zur Aufgabe macht, das ganze mit nginx und mit einem Reverse-Proxy laufen zu lassen. Hier nun eine Anweisung, wie wir schließlich ans Ziel gekommen sind, und welche Steine WordPress uns in den Weg gelegt hat.

Als erstes mussten wir die Seite vom alten Server wegbringen. Dazu haben wir den Ordner /var/www/e9a-webpage als tar.gz verpackt und mittels dem Tool „mysqldump“ die erforderliche Datenbank als SQL-Instruktionen in einer Datei abgespeichert.

Diese Daten haben wir auf dem neuen Server kopiert, fürs erste einmal ins Home-Verzeichnis. Nun mussten wir ein paar Applikationen installieren (wir verwenden Debian 9):

apt install nginx-full php-fpm php-gd php-mysql php-json php-hash mariadb-server

Hier haben wir nun eine nginx-Konfiguration eingepielt

# nginx local where wordpress is hosted
# Location: /etc/nginx/conf.d/blog.e9a.at.conf
# Upstream to abstract backend connection(s) for php
upstream php {
        server unix:/run/php/php7.0-fpm.sock;
        # server 127.0.0.1:9000;
}
server {
        ## Your website name goes here.
        server_name blog.e9a.at;
        ## Your only path reference.
        root /var/www/e9a-webpage;
        ## This should be in your http block and if it is, it's not needed here.
        index index.php;
        location = /favicon.ico {
                log_not_found off;
                access_log off;
        }
        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }
        location / {
                # This is cool because no php is touched for static content. include the "?$args" part so non-default permalinks doesn't break 
                # when using query string
                try_files $uri $uri/ /index.php?$args;
        }
        location ~ \.php$ {
                #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
                include fastcgi.conf;
                fastcgi_intercept_errors on;
                fastcgi_pass php;
        }
        location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
                expires max;
                log_not_found off;
        }
}

Die php.ini von php-fpm müssen wir noch bearbeiten, weil wir den Parameter „cgi.fix_pathinfo = 0“ setzen müssen. Der Dateipfad lautet wie folgt:

/etc/php/7.0/fpm/php.ini

Jetzt haben wir die Backup-Daten in das enstprechende Verzeichnis entpackt und den mysqldump eingespielt. Den MySQL Benutzer und das Passwort wurde in unserem Fall neu gesetzt, wir können aber nicht mit Sicherheit behaupten, ob das auch notwendig war.

Am Reverse-Proxy kopierten wir folgende Konfiguration:

# nginx on Reverse Proxy
server {
    listen 443 ssl http2; 
    listen [::]:443 ssl http2; # OCSP Stapling fetch OCSP records from URL in ssl_certificate and cache them
    server_name blog.e9a.at; 

    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_certificate /etc/letsencrypt/live/blog.e9a.at/fullchain.pem; 
    ssl_trusted_certificate /etc/letsencrypt/live/blog.e9a.at/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/blog.e9a.at/privkey.pem; 

    resolver 9.9.9.9;
    ssl_ecdh_curve prime256v1;
    #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
    #Server should determine the ciphers, not the client
    ssl_prefer_server_ciphers on;

    # SSL session handling
    ssl_session_timeout 24h;
    ssl_session_cache shared:SSL:50m;
       
    #add_header X-Content-Type-Options nosniff;
    #add_header X-XSS-Protection "1; mode=block";
    #add_header X-Robots-Tag none;
    #add_header X-Download-Options noopen;
    #add_header X-Permitted-Cross-Domain-Policies none;
        
        location / {
            proxy_pass http://172.17.0.20:80;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
	    proxy_set_header X-Forwarded-Server $host;
    }
# Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
}

Nach einem kurzen Neustart von nginx und php-fpm war die Konfiguration so weit fertig.

Nun hingen wir an einem Fehler, der uns einige Zeit kostete. Überzeugt davon, die File-Permissions richtig gesetzt zu haben, waren wir doch sehr überrascht, immer wieder nur eine weiße Seite mit einer Fehlermeldung wie „No Input File selected“ zu sehen. Nach einiger Recherche-Arbeit stießen wir dann an über folgenden Link:

https://stackoverflow.com/questions/25774999/nginx-stat-failed-13-permission-denied

Nachdem wir den Befehl (sudo muss nachinstalliert werden, sonst funktioniert es nicht)

sudo -u www-data stat /var/www/e9a-webpage/

wie im Artikel beschrieben probiert hatten, stellte wir tatsächlich fest, dass irgendeine Berechtigung nicht richtig gesetzt war. Wir sind uns bis jetzt nicht sicher, was genau da nicht gepasst hat, aber nachdem wir nochmal chmod und chown über das Verzeichnis gemacht haben, ging der Befehl auf einmal, und nach einem kurzen F5 im Browser hatten wir unsere Seite wieder vor uns. Aber Moment, WAS IST DAS DENN? Man konnte zwar fetzen von e9a.at sehen, aber alles war am falschen Platz. Kurz mit F12 einen Blick darauf geworfen, konnten wir feststellen, dass SSL nicht korrekt werkte und gewisse Inhalte von WordPress über HTTP geladen werden wollten, was dem Browser so gar nicht gefallen wollte.

Hier hat uns dieser Link extrem weitergeholfen:
https://www.variantweb.net/blog/wordpress-behind-an-nginx-ssl-reverse-proxy/

Wichtig ist dabei nur zu beachten, den auf dieser Website beschrieben Block am ANFANG der Config-File und nicht am Ende einzufügen. Ansonsten erwarten euch sehr komische Fehlermeldungen wie etwa “ Du bist leider nicht berechtigt, auf diese Seite zuzugreifen “ im Admin-Bereich… obwohl euer User die immer hatte.

UPDATE: Damit auch alle externen IP-Adressen richtig durchgeleitet werden, muss zusätzlich in die wp-config.php noch folgender Eintrag rein:

if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_X_FORWARDED_FOR"];
}

Der letzte wichtige Punkt ist, dass ihr in der Datenbank, solltet ihr die Website so wie wir unter einem neuen Hostnamen laufen haben, alle Verweise und Links auf die alte URL durch die neue erstetzt. Dies geschieht wie auf dieser Website beschrieben:

https://codex.wordpress.org/Changing_The_Site_URL

Links und Credit

https://stackoverflow.com/questions/25774999/nginx-stat-failed-13-permission-denied
https://www.variantweb.net/blog/wordpress-behind-an-nginx-ssl-reverse-proxy/
https://codex.wordpress.org/Changing_The_Site_URL
https://wordpress.org/support/topic/wordpress-behind-a-reverse-proxyssl-endpoint-slightly-borked/

ghost.org mit Nginx-Reverse-Proxy auf anderem Server

Heute habe ich das erste Mal eine Ghost-Instanz zuhause aufgesetzt. Der Reverse-Proxy hat mir dabei ein wenig Kopfschmerzen bereitet. Schlussendlich bin ich bei folgender Lösung gelandet:

Diese Anleitung bis zu „ghost install“ befolgen: https://docs.ghost.org/install/ubuntu/

Beim Hostnamen geben wir unsere URL mit https an

Alle Parameter so weit eingeben, bis die Frage kommt: Nginx installieren? Wir wollen Nginx nicht auf dieser Instanz, deshalb hier mit Nein beantworten.

Auch SSL wollen wir nicht hier haben, sondern am Reverse-Proxy, deshalb ebenfalls mit Nein

Nun mittels folgendem Befehl die Ghost-Instanz im ganzen LAN erreichbar machen:

ghost config set ip <DEINE IP-ADRESSE>

Nun können wir folgende Nginx-Konfiguration verwenden:

server {
    listen 80;
    # Unter diesem Namen wird Ghost erreichbar sein
    server_name <DEIN DOMAINNAME>;

    # Umleiten auf SSL
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;

    server_name <DEIN DOMAINNAME>;

    ssl_certificate /etc/letsencrypt/live/<DEIN DOMAINNAME>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<DEIN DOMAINNAME>/privkey.pem;

    location / {
        client_max_body_size 10G;

       
        proxy_pass http://<DEINE IP-ADRESSE>:2368;
        proxy_redirect off;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-Host <DEIN DOMAINNAME>;
    }
}

Ich bin mit Nginx kein Profi, Verbesserungsvorschläge sind gerne willkommen, aber so funktioniert es bei mir.

Links und Credit

https://docs.ghost.org/install/ubuntu/

NGINX: Reverse-Proxy

Hin und wieder kommt man in die Verlegenheit, neue Services auf seinem Server zu installieren und etwas zu herumzuprobieren.

Nginx kann wie haproxy Streams per DNS-Name unterscheiden und danach Traffic umleiten. In diesem Beispiel, wollen wir den gesamten mailcow-Traffic umleiten:


server {
         listen 443 ssl http2;
         listen [::]:443 ssl http2;
         include https-ls;
         ssl_certificate /etc/letsencrypt/live/mail.e9a.at/fullchain.pem;
         ssl_certificate_key /etc/letsencrypt/live/mail.e9a.at/privkey.pem;

         #root /var/www/;
         #index index.php index.html index.htm;

         server_name mail.e9a.at;

    location / {
    proxy_pass http://127.0.0.1:8080/;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    client_max_body_size 100m;
  }
}



Nginx HSTS-Security

Da ich viele verschiedene Websites betreue, brauche ich auch verschiedene nginx-Sicherheitsstufen um HSTS und weitere Sicherheitsfeatures zu aktivieren. Leider kann ich nicht immer aufs höchste Niveau gestellt werden, da es leider immer wieder passiert dass Google-Analytics oder andere Dritt-Scripts eingebunden werden.

Ich teile es in folgende Sicherheitsstufen ein

  • HTTPS High-Security
  • HTTPS Standard
  • HTTPS Low Security

Man muss aber anmerken, dass jegliche Konfiguration sicherer ist, als die Standard-Config.

High Security

#
# HTTPSconfig for enhanced security
#
ssl_session_cache shared:SSL:10m; access_log off; # Security headers add_header X-Content-Type-Options nosniff; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Robots-Tag none; add_header X-Download-Options noopen; add_header X-Permitted-Cross-Domain-Policies none; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; add_header Content-Security-Policy "default-src 'self' 'unsafe-inline'; script-src 'self';";
# Allow only newer protocols
# Newer nginx supports also TLS1.3
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 ssl_session_tickets off; # Requires nginx >= 1.5.9 ssl_stapling on; # Requires nginx >= 1.3.7 ssl_stapling_verify on; # Requires nginx => 1.3.7 resolver 91.239.100.100 89.233.43.71 valid=300s; resolver_timeout 5s;
# Diffie-Hellmann params ssl_dhparam /etc/ssl/private/dhparams.pem;
#Hide nginx version server_tokens off;

Standard Security

Diese erlaubt ein Laden von Drittresourcen, ideal beispielsweise für eine Nextcloud. HSTS ist aber immer noch für die Haupt- und Subdomains erzwungen.

#
# HTTPSconfig for enhanced security
#
ssl_session_cache shared:SSL:10m; access_log off;
# Security headers add_header X-Content-Type-Options nosniff; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Robots-Tag none; add_header X-Download-Options noopen; add_header X-Permitted-Cross-Domain-Policies none; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; add_header Content-Security-Policy "default-src https: "; add_header Referrer-Policy: same-origin;
# Allow only newer protocols ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+AESGCM:EECDH:EDH::DHE-RSA-AES256-GCM-SHA384:!MD5:!RC4:!LOW:!MEDIUM:!CAMELLIA:!ECDSA:!DES:!DSS:!3DES:!NULL"; # ssl_ecdh_curve secp384r1:prime256v1; Not compatible with Chrome ssl_session_tickets off; # Requires nginx >= 1.5.9 ssl_stapling on; # Requires nginx >= 1.3.7 ssl_stapling_verify on; # Requires nginx => 1.3.7 resolver 91.239.100.100 89.233.43.71 valid=300s; resolver_timeout 5s; ssl_ecdh_curve auto;
# Diffie-Hellmann params ssl_dhparam /etc/ssl/private/dhparams.pem;
# Hide nginx version server_tokens off;

Low Security

Dies ist eine herabgesetzte Config, die HSTS nicht erzwingt. Ideal für Websites, die nicht komplett in der alleinigen Kontrolle sind.

#
# HTTPSconfig for low security
#
ssl_session_cache shared:SSL:10m; access_log off;
# Security headers add_header X-Content-Type-Options nosniff; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Robots-Tag none; add_header X-Download-Options noopen; add_header X-Permitted-Cross-Domain-Policies none; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'";
# Allow only newer protocols ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 ssl_session_tickets off; # Requires nginx >= 1.5.9 ssl_stapling on; # Requires nginx >= 1.3.7 ssl_stapling_verify on; # Requires nginx => 1.3.7 resolver 91.239.100.100 89.233.43.71 valid=300s; resolver_timeout 5s;
# Diffie-Hellmann params ssl_dhparam /etc/ssl/private/dhparams.pem;
# Hide nginx version server_tokens off;

Weitere Absicherungsmöglichkeiten

In den Configs wurde bereits ein ssl_dhparam erwähnt. Durch moderne Algorithmen werden Diffie-Hellmann-Parameter zwar seltener verwendet, aber der Standard liegt bei 1024-Bit und damit sehr unsicher.

Wir generieren einen Key mit 4096-Bit Größe, um ausreichend abgesichert zu sein:

openssl dhparam -out dhparams.pem 4096