Mein perfektes Serversetup – Teil 1

Dieser Blogeintrag soll der erste von mehreren sein, mit welchem ich mein eigenes Serversetup beschreiben und dokumentieren werde. Auf dem Server wurde ein Debian 10 vorinstalliert und durch mich wurden Web-, Dankenbank und Mailserver installiert und konfiguriert.

Was auf dem Server am laufen ist…

  • NGINXals Webserver mit PHP7.4 im FPM Modus
  • MariaDB als Datenbankserver
  • Postfix und Dovecot als Mailserver
  • Rspam als Spamschutz
  • Fail2ban um unerwünschte IPs zu sperren
  • Automx2 um automatische Mailclientkonfigurationen bereitstellen zu können
  • acme.sh zum Let’s Encrypt SSL Zertifikate zu erhalten

Abgrenzungen

Zu allererst sei gesagt, alle hier aufgefürten Konfigurationen sind keine Eigenentwicklungen, sondern alles schon existierende Lösungen, die ich für meine eigenen Anforderungen zusammen gewürfelt habe.

Sämtliche Nginx Initialkonfigurationen habe ich auf NGINXConfig bei DigitalOcean generiert. Mailserver und Antispam Konfigurationen habe ich mir selber zusammengesetzt aus den Howtos von workaround.org und dem Blog von Thomas Leister.

Lizenz

Dieses Werk ist lizenziert unter einer Creative Commons Namensnennung 4.0 International Lizenz.

Server Informationen

Für dieses Setup wird kein besonders grosser Server benötigt, hier folgende die Eckdaten meines VPS – ich schreibe diese Informationen bewusst nieder, da alle diese Informationen über DNS Abfragen schnell in Erfahrung gebracht werden können.

  • Hostname: vincent.chileo.ovh
  • IP Adresse: 51.255.50.76 / 2001:41d0:404:300::647

Software installieren

Ich nutze bewusst zusätzliche externe Paketquellen und nicht ausschliesslich Debian Pakete. Hier gibt es viele Diskussionen mit genug Pro und Contra Argumenten zufinden – für mich stimmen die eingesetzten externen Quellen. Zumal mir eine gewisste Aktualität wichtiger als «rock-solid» ist.

Beginnen wir mit dem Tool pwgen, um schnell sichere Passwörter generieren zu können:

apt install pwgen

Um ein neues sicheres Passwort mit 32 Zeichen zu generieren reicht folgender Befehl:

pwgen -s 32 1

Wichtig: Das Passwort wird nur auf der Konsole ausgegeben und nicht gespeichert.

Weiter geht’s mit dem einbinden zusätzlicher Quellen für die inoffiziellen PHP und MariaDB Pakete:


apt install apt-transport-https lsb-release ca-certificates curl software-properties-common dirmngr
wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
sh -c 'echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" & /etc/apt/sources.list.d/php.list'
apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc'
add-apt-repository 'deb [arch=amd64,arm64,ppc64el] http://mariadb.mirrors.ovh.net/MariaDB/repo/10.6/debian buster main'
apt update

LEMP Pakete installieren

LEMP steht für Linux NGINX MariaDB und PHP – ich installiere gerne alle diese Pakete auf einen Schlag und konfiguriere dann Webserver und MariaDB einzeln – die hier installieren drei PHP Pakete reichen für einen initialen Start, für Applikationen wie z.B. phpMyAdmin oder ein Webmail werden unter Umständen weitere benötigt:

apt install nginx mariadb-server mariadb-client php7.4 php7.4-cli php7.4-fpm php7.4-mysql

acme.sh installieren

Let’s Encrypt Zertifikate können auf eine vielzahl von Möglichkeiten gelöst werden – da meine Domains alle bei OVH gehostet sind, nutze ich die DNS Validierungsmöglichkeit von acms.sh in Verbindung mit der OVH Api. Alternativ können Zertifikate auch mittels certbot gelöst werden, wie z.B. hier beschrieben.

apt install git
git clone https://github.com/acmesh-official/acme.sh.git
./acme.sh --install  \
--home /etc/letsencrypt/ \
--config-home /etc/letsencrypt/data \
--cert-home  /etc/letsencrypt/certs \
--accountemail  "my@example.com"

Danach erstelle ich mir ein Wildcard Zertifikat für meine Domain chileo.ovh:

export OVH_AK="..."
export OVH_AS="..."
acme.sh --issue -d chileo.ovh -d *.chileo.ovh --dns dns_ovh --server letsencrypt

Die erstellten Zertifikate finden sich nun unter /etc/letsencrypt/certs/chileo.ovh/

NGINX vHost chileo.ovh

Für individuelle vHosts erstelle ich mir pro Domain resp. Subdomain eine Konfiguration unter /etc/nginx/sites-available, z.B. chileo.ovh:

server {
    listen                  443 ssl http2;
    listen                  [::]:443 ssl http2;
    server_name             chileo.ovh;
    set                     $base /var/www/chileo.ovh;
    root                    $base/public;

    # SSL
    ssl_certificate         /etc/letsencrypt/certs/chileo.ovh/fullchain.cer;
    ssl_certificate_key     /etc/letsencrypt/certs/chileo.ovh/chileo.ovh.key;
    ssl_trusted_certificate /etc/letsencrypt/certs/chileo.ovh/ca.cer;

    # ssl settings
    include                 snippets/ssl-config.conf;

    # security
    include                 snippets/security.conf;

    # logging
    access_log              /var/log/nginx/chileo.ovh.access.log;
    error_log               /var/log/nginx/chileo.ovh.error.log warn;

    # index.php
    index                   index.php index.html;

    # additional config
    include                 snippets/general.conf;

    # handle .php
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        include      snippets/php_fastcgi.conf;
    }
}

# HTTP redirect
server {
    listen      80;
    listen      [::]:80;
    server_name chileo.ovh;

    location / {
        return 301 https://chileo.ch$request_uri;
    }
}

snippets/ssl-config.conf:

ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
ssl_session_tickets off;

ssl_dhparam /etc/nginx/dh4096.pem;

# intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;

# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;

resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] 8.8.8.8 8.8.4.4 [2001:4860:4860::8888] [2001:4860:4860::8844] 208.67.222.222 208.67.220.220 [2620:119:35::35] [2620:119:53::53] valid=60s;
resolver_timeout       2s;

snippets/security.conf:

# security headers
add_header X-XSS-Protection          "1; mode=block" always;
add_header X-Content-Type-Options    "nosniff" always;
add_header Referrer-Policy           "strict-origin-when-cross-origin" always;
add_header Permissions-Policy        "interest-cohort=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# . files
location ~ /\.(?!well-known) {
    deny all;
}

snippets/general.conf:

# favicon.ico
location = /favicon.ico {
    log_not_found off;
    access_log    off;
}

# robots.txt
location = /robots.txt {
    log_not_found off;
    access_log    off;
}

snippets/php_fastcgi.conf:

# 404
try_files                     $fastcgi_script_name =404;

# default fastcgi_params
include                       fastcgi_params;

# fastcgi settings
fastcgi_index                 index.php;
fastcgi_buffers               8 16k;
fastcgi_buffer_size           32k;

# fastcgi params
fastcgi_param DOCUMENT_ROOT   $realpath_root;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$base/:/usr/lib/php/:/tmp/";

Konfiguration aktivieren, indem ein Symlink nach sites-enabled:

ln -s /etc/nginx/sites-available/chileo.ovh /etc/nginx/sites-enabled

Eigene dhparams mit 4096 Bits erstellen:

openssl dhparam -out dhparams.pem 4096

Falls die Generierung zu lange dauert, können hilftmittel verwendet werden, wie z.B. haveged. Weiter Infos dazu können z.B. hier bei Cyberciti nachgelesen werden.

Bevor nun die NGINX Konfiguration neugeladen wird, kann mittels nginx -t kontrolliert werden, ob sich auch keine Fehler einegschlichen haben:

root@vincent:/etc/nginx # nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
systemctl reload nginx php7.4-fpm

Schreiben Sie einen Kommentar

Ihre E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.