Zum Inhalt

LAMP-Stack unter Ubuntu – Performant & Sicher

Stand: 04/2025
Apache HTTP Server-Logo

MariaDB-Logo

PHP-Logo
Verwendete Software
- Ubuntu 24.04 LTS
- Apache 2.4.58
- MariaDB 11.4.5
- PHP 8.4
Weitere Dokumentationen:

Vorwort

Diese Dokumentation beschreibt die Einrichtung eines performanten und sicher konfigurierten LAMP-Stacks mit Apache, PHP und MariaDB auf Ubuntu 24.04 LTS. Ziel ist ein Setup, das moderne Sicherheits- und Performance-Standards erfüllt und als Grundlage für produktive Webanwendungen geeignet ist – inklusive gehärteter Konfiguration.

Es sind Grundkenntnisse im Umgang mit Linux erforderlich, da die Vorgehensweise, wie sie hier beschrieben ist, in manchen Teilen abweichen kann. Kein System ist wie das Andere. Die Dokumentation wurde sorgfältig von mir geprüft. Dennoch kann ich keinerlei Haftung für Schäden an Ihrem System oder eine Gewährleistung übernehmen. Bitte verwenden Sie diese Dokumentation auf eigene Gefahr.

✅ Bei vollständiger Umsetzung dieser Anleitung erreicht Ihr Server ein A+ Rating im SSL-Test von Qualis SSL-Labs.

Was muss ich in der Konfiguration anpassen?

Einige Parameter müssen auf Ihre Umgebung angepasst werden. Im Verlauf dieser Dokumentation müssen Sie nur die Parameter anpassen, die in der nachfolgenden Tabelle aufgelistet sind. Sie können also ganz einfach durch die Funktion "Suchen und Ersetzen" (STRG + H), die Konfigurationsdateien auf Ihre Umgebung anpassen. Das Gleiche gilt für auszuführende Kommandos.

Folgende Parameter werden verwendet:

Allgemein
Hostname www.example.com Ersetzen Sie diesen Wert durch den FQDN Ihres Servers.
Domain example.com Ersetzen Sie diesen Wert durch Ihre Domain.
SSL
SSL-Zertifikat /etc/letsencrypt/live/www.example.com/fullchain.pem Ersetzen Sie diesen Wert durch den Pfad und den Namen Ihres SSL-Zertifikats.
SSL-Zertifikat Private Key /etc/letsencrypt/live/www.example.com/privkey.pem Ersetzen Sie diesen Wert durch den Pfad und den Namen des private Keys Ihres SSL-Zertifikats.
MySQL
root SicheresRootPasswortVerwenden! MySQL-Passwort für den Benutzer root. Ersetzen Sie dieses Passwort durch ein eigenes sicheres Passwort.



Konfigurations-Dateien werden immer nach dem gleichen Muster erstellt. Unter jeder Datei, die eine Anpassung erfordert, finden Sie die nötigen Hinweise.
Dateien, die zwar Parameter aber keine eigentliche Konfiguration enthalten, werden nach dem vorgegebenen Syntax erstellt.

Beispiel:
Im folgenden Beispiel ist die Datei /home/beispiel.conf zu erstellen und der Parameter domain anzupassen.

Erstellen Sie eine neue Datei /home/beispiel.conf mit folgendem Inhalt:

nano /home/beispiel.conf
beispiel.conf
content = Dokumentationen

domain  = example.com
owner   = root
Anzupassende Parameter:
[...]
domain  = example.com
[...]


Im folgenden Beispiel ist die Datei /home/beispiel.map mit einer Liste Ihrer E-Mail-Adressen zu erstellen.

Erstellen Sie eine neue Datei /home/beispiel.map nach folgendem Syntax:
nano /home/beispiel.map



Server vorbereiten

Root-Rechte einräumen

Während der gesamten Dokumentation werden Root-Rechte benötigt. Um auf das Voranstellen von sudo zu verzichten, verschaffen Sie sich für die gesamte Sitzung erhöhte Rechte mit:

sudo -i


Hostname vergeben

Vergeben Sie den hostname für den Webserver:

hostnamectl set-hostname www

Editieren Sie die Datei /etc/hosts und ändern Sie den Hostnamen nach folgendem Syntax:
nano /etc/hosts
/etc/hosts
127.0.1.1       www.example.com www
[...]


Update durchführen

Bringen Sie den Server auf den aktuellen Patchstand:

apt update && apt upgrade

Software installieren

Da PHP 8.4 nicht im offiziellen Ubuntu-Repository von Ubuntu 24.04 enthalten ist, fügen wir zunächst das bewährte Drittanbieter-Repository ppa:ondrej/php hinzu:

apt install apt-transport-https
LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php
apt update


Auch die aktuelle Version von MariaDB ist noch nicht im Ubuntu-Repository von Ubuntu 24.04 enthalten. Fügen Sie daher das MariaDB-Repository hinzu:

curl -LsS https://r.mariadb.com/downloads/mariadb_repo_setup | sudo bash -s -- --mariadb-server-version="mariadb-11.4"
apt update


Installieren Sie Apache, MariaDB und PHP:
(enthält empfohlene PHP-Module für Performance, Sicherheit und Kompatibilität im Grundbetrieb; weitere Module je nach Anwendung erforderlich)

apt install apache2 mariadb-server php8.4-fpm php8.4-mysql php8.4-apcu php8.4-opcache php8.4-curl php8.4-mbstring php8.4-xml php8.4-zip php8.4-gd


MariaDB konfigurieren

Zugriffsrechte initial vergeben

Vergeben Sie ein Root-Passwort und die Zugriffsrechte für den MySQL-Server.
Ersetzen Sie SicheresRootPasswortVerwenden! durch ein eigenes Passwort.

mysql_secure_installation
    [...]
    Enter current password for root (enter for none): "Enter"
    [...]
    Switch to unix_socket authentication [Y/n] n
    [...]
    Change the root password? [Y/n] :y
    New password: SicheresRootPasswortVerwenden!
    Re-enter new password: SicheresRootPasswortVerwenden!
    [...]
    Remove anonymous users? [Y/n] :y
    [...]
    Disallow root login remotely? [Y/n] :y
    [...]
    Remove test database and access to it? [Y/n] :y
    [...]
    Reload privilege tables now? [Y/n] :y
    [...]
    Thanks for using MariaDB!


Info

Da wir im vorherigen Schritt die klassische Passwort-Authentifizierung für den Benutzer root eingerichtet haben, ist die Anmeldung an der MySQL-Konsole aktuell nur mit Passwort möglich.
Wenn Sie stattdessen die passwortlose Unix-Socket-Authentifizierung aktivieren möchten – also eine Anmeldung per sudo mysql ohne Passwort – führen Sie folgende Befehle aus:

sudo mysql -u root -p
    MariaDB [(none)]> ALTER USER 'root'@'localhost' IDENTIFIED VIA unix_socket;
    MariaDB [(none)]> FLUSH PRIVILEGES;
Prüfen Sie, ob die Änderung erfolgreich übernommen wurde:
    MariaDB [(none)]> SELECT user, host, plugin FROM mysql.user WHERE user = 'root';
    +------+-----------+-------------+
    | user | host      | plugin      |
    +------+-----------+-------------+
    | root | localhost | unix_socket |
    +------+-----------+-------------+
    [...]
    MariaDB [(none)]> QUIT;

Ab jetzt erfolgt die Anmeldung zur MySQL-Konsole ausschließlich über das Betriebssystem – das heißt, nur Benutzer mit Root-Rechten (z.B. per sudo) können darauf zugreifen. Eine weitere Passwort-Eingabe ist nicht mehr erforderlich, unberechtigter Zugriff durch normale Benutzer aber weiterhin ausgeschlossen.

sudo mysql


Einstellungen optimieren

Hinweis!

Diese Konfigurationsdatei optimiert zentrale Werte für kleine bis mittelgroße Serverinstallationen mit Fokus auf Performance und Ressourcenschonung. Die innodb_buffer_pool_size und max_connections sind auf realistische Werte für 1–2 GB RAM optimiert. Passen Sie diese Parameter ggf. an Ihre Hardware an.

Optional: TCP-Zugriff deaktivieren

Wenn ausschließlich lokal auf die Datenbank zugegriffen wird (z. B. durch PHP über den Unix-Socket), kann die Netzwerkschnittstelle von mysqld vollständig deaktiviert werden:

skip-networking

Dadurch werden TCP/IP-Verbindungen (z. B. an Port 3306) deaktiviert. Die Kommunikation erfolgt ausschließlich über den schnelleren und sichereren Unix-Socket (/var/run/mysqld/mysqld.sock).

Wichtig: Falls Sie Tools verwenden, die explizit mit -h 127.0.0.1 arbeiten, oder remote per SSH-Tunnel zugreifen möchten, darf dieser Parameter nicht gesetzt werden.


Erstellen Sie eine neue Datei /etc/mysql/conf.d/mysqld_settings.cnf mit folgendem Inhalt:

nano /etc/mysql/conf.d/mysqld_settings.cnf
mysqld_settings.cnf
[mysqld]
#skip-networking
bind-address                    = 127.0.0.1
skip-name-resolve

interactive_timeout             = 600
wait_timeout                    = 600

key_buffer_size                 = 256K
max_allowed_packet              = 64M
table_open_cache                = 600
table_definition_cache          = 600

sort_buffer_size                = 2M
net_buffer_length               = 16K
read_buffer_size                = 128K
read_rnd_buffer_size            = 128K
join_buffer_size                = 8M
innodb_buffer_pool_size         = 512M

thread_cache_size               = 128
max_connections                 = 75

max_heap_table_size             = 128M
tmp_table_size                  = 128M

innodb_file_per_table           = 1
innodb_flush_method             = O_DIRECT
innodb_log_file_size            = 64M

performance_schema              = ON


Logging konfigurieren

Erstellen Sie eine neue Datei /etc/mysql/conf.d/mysqld_logging.cnf mit folgendem Inhalt:

nano /etc/mysql/conf.d/mysqld_logging.cnf
mysqld_logging.cnf
[mysqld]
# Binärlogs für Replikation und PITR (optional)
# Achtung: Kann bei hoher Schreiblast viel Speicherplatz beanspruchen
#log-bin                         = mysql-bin
#expire_logs_days                = 21

log_warnings                    = 1
log_error                       = /var/log/mysql/mariadb.err

slow_query_log
slow_query_log_file             = /var/log/mysql/mariadb-slow.log

long_query_time                 = 5


MariaDB starten

Starten Sie MariaDB neu, damit die Konfiguration angewendet wird:

service mariadb restart


Apache konfigurieren

Let's Encrypt-Zertifikat erstellen

Installieren Sie zunächst snapd und certbot:

apt update
apt install snapd
snap install core
snap refresh core
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot


Erstellen Sie das Zertifkat. Geben Sie als Common Name den FQDN des Webservers an. Das Zertifkat befindet sich unter /etc/letsencrypt/live/www.example.com/.

sudo certbot certonly --apache -d www.example.com


Let's Encrypt-Zertifikate haben eine Gültigkeit von 30 Tagen. Danach werden sie automatisch erneuert. Damit apache2 erneuerte Zertifikate verwendet, müssen diese nachgeladen werden. Erstellen Sie hierzu einen Deploy-Hook:

nano /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh

reload-services.sh
#!/bin/bash
services=(
    apache2
)

for service in "${services[@]}"; do
    if systemctl is-active --quiet "$service"; then
        echo "[Certbot-Hook] Reloading $service"
        systemctl reload "$service"
    else
        echo "[Certbot-Hook] $service is not active"
    fi
done


Vergeben Sie die benötigte Berechtigung, damit die Datei ausgeführt werden kann:

chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh


SSL konfigurieren

Info

Die Konfiguration schaltet alle unsicheren SSL/TLS-Protokolle aus und erlaubt ausschließlich TLS 1.2 und 1.3 – beides aktuell als sicher eingestuft. Die gewählten Cipher Suites priorisieren Forward Secrecy (ECDHE) und moderne Algorithmen wie AES-GCM und ChaCha20.
Die Direktiven SSLProtocol, SSLCipherSuite und SSLOpenSSLConfCmd Curves bestimmen maßgeblich, welche TLS-Versionen und Verschlüsselungsverfahren auf dem Server erlaubt sind:

  • SSLProtocol -ALL +TLSv1.2 +TLSv1.3
    Nur TLS 1.2 und TLS 1.3 sind zugelassen. Ältere und unsichere Protokolle wie SSLv3 oder TLS 1.0 werden explizit deaktiviert.

  • SSLCipherSuite
    Hier wird definiert, welche Cipher Suites erlaubt sind – in dieser Konfiguration nur starke Algorithmen ohne bekannte Schwächen.

  • SSLOpenSSLConfCmd Curves
    Gibt die bevorzugten elliptischen Kurven für Perfect Forward Secrecy an – darunter X25519 als moderne Standardwahl.

Diese Einstellungen zielen auf maximale Sicherheit und eine Bewertung von A+ bei Tools wie Qualys SSL Labs ab.


Erstellen Sie zunächst einen neuen Ordner /etc/apache2/conf-includes:

mkdir /etc/apache2/conf-includes

Erstellen Sie eine neue Datei /etc/apache2/conf-includes/ssl-common.conf mit folgendem Inhalt:

nano /etc/apache2/conf-includes/ssl-common.conf
ssl-common.conf
# SSL-Basiskonfiguration
SSLEngine on
SSLUseStapling on
SSLCompression Off
SSLHonorCipherOrder on
SSLProtocol -ALL +TLSv1.2 +TLSv1.3
SSLCipherSuite EECDH+AESGCM:EECDH+CHACHA20:HIGH:!aNULL:!MD5:!3DES:!RC4:!SHA1:!CAMELLIA:!SEED:!EDH:!DSS
SSLOpenSSLConfCmd Curves X25519:secp521r1:secp384r1:prime256v1


SSL-Caching konfigurieren

Info

Für eine bessere Performance und geringere Last bei der Aushandlung von SSL-Verbindungen empfiehlt es sich, den SSL-Session-Cache sowie OCSP-Stapling (Online Certificate Status Protocol) global zu aktivieren.


Erstellen Sie eine neue Datei /etc/apache2/conf-available/php8.4-fpm-custom.conf mit folgendem Inhalt::

nano /etc/apache2/conf-available/ssl-cache.conf
ssl-cache.conf
# SSL-Caching und OCSP-Stapling (global)

# OCSP-Stapling-Cache (für Zertifikatgültigkeitsprüfung per TLS-Erweiterung)
SSLStaplingCache shmcb:/var/run/apache2/stapling_cache(128000)

# SSL-Session-Cache zur Wiederverwendung von TLS-Sessions
SSLSessionCache shmcb:/var/run/apache2/ssl_scache(512000)
SSLSessionCacheTimeout 300


PHP-FPM konfigurieren

PHP-FPM-Pool Konfiguration

Info

Die www-custom.conf ersetzt die Standardkonfiguration von PHP-FPM und definiert, wie Anfragen durch den PHP-Interpreter verarbeitet werden. Die gewählten Werte für pm.*-Direktiven sind auf kleine bis mittelgroße Server mit begrenztem RAM (1-2 GB) abgestimmt. Der Modus dynamic erlaubt eine flexible Skalierung der PHP-Prozesse – ideal für sparsame, aber reaktionsschnelle Setups. Über die php_admin_value-Einträge lassen sich zentrale PHP-Werte wie Speicherlimits oder maximale Upload-Größen pro Pool direkt setzen, unabhängig von der globalen php.ini.


Benennen Sie zunächst die /etc/php/8.4/fpm/pool.d/www.conf um, damit Sie eine Sicherheitskopie der Original-Datei haben:

mv /etc/php/8.4/fpm/pool.d/www.conf /etc/php/8.4/fpm/pool.d/www.conf.bak


Erstellen Sie eine neue Datei /etc/php/8.4/fpm/pool.d/www-custom.conf mit folgendem Inhalt::

nano /etc/php/8.4/fpm/pool.d/www-custom.conf
/etc/php/8.4/fpm/pool.d/www-custom.conf
[www]
user                                    = www-data
group                                   = www-data

listen                                  = /run/php/php8.4-fpm.sock
listen.owner                            = www-data
listen.group                            = www-data

pm                                      = dynamic
pm.max_children                         = 5
pm.start_servers                        = 2
pm.min_spare_servers                    = 1
pm.max_spare_servers                    = 3
pm.max_requests                         = 500
request_terminate_timeout               = 30s

php_admin_value[date.timezone]          = Europe/Berlin
php_admin_value[upload_max_filesize]    = 64M
php_admin_value[post_max_size]          = 64M
php_admin_value[memory_limit]           = 512M


Starten Sie PHP-FPM neu, damit die Konfiguration angewendet wird:

service php8.4-fpm restart


Apache Konfiguration

Info

Diese Datei sorgt dafür, dass PHP über den FastCGI Process Manager (FPM) effizient verarbeitet wird – eine moderne, performante Alternative zu mod_php. Der Code stellt sicher, dass nur vorhandene Dateien verarbeitet werden, schützt vor dem Auslesen von Quellcode-Dateien (.phps), und reicht den Authorization-Header korrekt weiter. Die SetHandler-Direktive bindet PHP über den Unix-Socket an – das ist schneller und sicherer als TCP-basierte Kommunikation zwischen Apache und PHP-FPM.


Erstellen Sie eine neue Datei /etc/apache2/conf-available/php8.4-fpm-custom.conf mit folgendem Inhalt::

nano /etc/apache2/conf-available/php8.4-fpm-custom.conf
php8.4-fpm-custom.conf
# Nur laden, wenn mod_php nicht aktiv ist (Vermeidung von doppelter PHP-Verarbeitung)
<IfModule !mod_php8.c>
<IfModule proxy_fcgi_module>
    # Authorization Header weiterreichen (z. B. für REST-APIs, JWT, etc.)
    <IfModule setenvif_module>
        SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
    </IfModule>

    # Nur existierende PHP-Dateien an FPM übergeben
    <FilesMatch "\.ph(?:ar|p|tml)$">
        <If "-f %{REQUEST_FILENAME}">
            SetHandler "proxy:unix:/run/php/php8.4-fpm.sock|fcgi://localhost"
        </If>
    </FilesMatch>

    # Zugriff auf rohe PHP-Quellen verbieten
    <FilesMatch "\.phps$">
        Require all denied
    </FilesMatch>

    # Kein Zugriff auf Dateien ohne Dateinamen
    <FilesMatch "^\.ph(?:ar|p|ps|tml)$">
        Require all denied
    </FilesMatch>
</IfModule>
</IfModule>


VirtualHost-Dateien anlegen

default.conf

Info

Diese Konfiguration sorgt dafür, dass alle unverschlüsselten HTTP-Anfragen automatisch auf HTTPS umgeleitet werden.
Vorteile:

  • Erzwingt verschlüsselte Verbindungen und schützt Benutzer vor Man-in-the-Middle-Angriffen.

  • Verbessert SEO, da Suchmaschinen verschlüsselte Verbindungen bevorzugen.

  • Schützt Login- und Formulardaten, indem keine Inhalte unverschlüsselt übertragen werden.

Die Umleitung erfolgt per Statuscode 301 (permanent redirect), was auch von Browsern und Crawlern dauerhaft gespeichert wird.


Erstellen Sie eine neue Datei /etc/apache2/sites-available/www.example.com-default.conf mit folgendem Inhalt::

nano /etc/apache2/sites-available/www.example.com-default.conf
www.example.com-default.conf
<VirtualHost *:80>
    ServerName www.example.com

    RewriteEngine On
    RewriteRule ^ https://www.example.com%{REQUEST_URI} [L,R=301]

    LogLevel warn
    ErrorLog ${APACHE_LOG_DIR}/www.example.com-redirect-error.log
    CustomLog ${APACHE_LOG_DIR}/www.example.com-redirect-access.log combined
</VirtualHost>
Anzupassende Parameter:
[...]
    ServerName www.example.com
    [...]
    RewriteRule ^ https://www.example.com%{REQUEST_URI} [L,R=301]
    [...]
    ErrorLog ${APACHE_LOG_DIR}/www.example.com-redirect-error.log
    CustomLog ${APACHE_LOG_DIR}/www.example.com-redirect-access.log combined
[...]


ssl.conf

Info

Diese Konfiguration legt den SSL-verschlüsselten Zugriff auf Ihre Website fest.
Sie umfasst:

  • Protocols h2 http/1.1
    Aktiviert HTTP/2 für schnelleren Seitenaufbau bei unterstützenden Browsern.

  • Include ssl-common.conf
    Lädt zentrale SSL-Einstellungen (Zertifikate, Ciphers, TLS-Versionen).

  • Header-Direktiven
    Härtung der HTTP-Kommunikation (CSP, Referrer-Policy, XSS-Schutz, etc.).

  • RemoteIPHeader (auskommentiert)
    Optional, nützlich bei Einsatz von Proxies wie Cloudflare.

  • Logging
    Spezifische Log-Dateien für Zugriffe und Fehler dieser Domain.

Diese Datei ist das Herzstück des verschlüsselten Webzugangs. Sie sollte immer aktiviert und regelmäßig auf neue Sicherheitsempfehlungen geprüft werden.

Vorsicht bei Strict-Transport-Security (HSTS)

Der Header Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" weist unterstützende Browser an, sämtliche Verbindungen zur Domain (und optional zu allen Subdomains) für ein ganzes Jahr ausschließlich über HTTPS herzustellen – selbst wenn der Benutzer http:// in die Adresszeile eingibt.

Achten Sie unbedingt darauf, dass auf dieser Domain ausschließlich verschlüsselte Verbindungen möglich sind. Falls eine Subdomain oder ein Dienst noch unverschlüsselt erreichbar sein muss, verzichten Sie auf includeSubDomains oder den Header vollständig, bis eine vollständige HTTPS-Abdeckung sichergestellt ist.

Tipp: Verwenden Sie hstspreload.org, wenn Sie die Domain dauerhaft in den HSTS-Preload-Listen der Browser registrieren möchten. Dies sollte jedoch nur bei absoluter Sicherheit erfolgen, da sich dieser Schritt praktisch nicht mehr rückgängig machen lässt.


Erstellen Sie eine neue Datei /etc/apache2/sites-available/www.example.com-ssl.conf mit folgendem Inhalt::

nano /etc/apache2/sites-available/www.example.com-ssl.conf
www.example.com-ssl.conf
<VirtualHost _default_:443>
    ServerName www.example.com
    ServerAdmin [email protected]

    Protocols h2 http/1.1
    DocumentRoot /var/www/html

    # SSL-Einstellungen laden
    Include /etc/apache2/conf-includes/ssl-common.conf

    # Zertifikatspfad (z. B. von Let's Encrypt)
    SSLCertificateFile /etc/letsencrypt/live/www.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem

    # Echte Client-IP übernehmen (z.B. für Cloudflare Proxy) (optional)
    #RemoteIPHeader CF-Connecting-IP

    ########################################
    # Header-Härtung

    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header set Content-Security-Policy "default-src https: 'self' data: 'unsafe-inline' www.example.com; script-src https: 'self' 'unsafe-inline' 'unsafe-eval' www.example.com; img-src 'self' data: www.example.com"
    Header always append X-Frame-Options "sameorigin"
    Header always set Referrer-Policy "no-referrer"
    Header always set Permissions-Policy "geolocation=(); midi=(); notifications=(); push=(); sync-xhr=(); microphone=(); camera=(); magnetometer=(); gyroscope=(); speaker=(); vibrate=(); fullscreen=(); payment=();"
    Header set X-Content-Type-Options nosniff
    Header set X-XSS-Protection "1; mode=block"
    Header always unset "X-Powered-By"
    Header unset "X-Powered-By"

    ########################################
    # Logging

    LogLevel warn
    ErrorLog /var/log/apache2/www.example.com-ssl-error.log
    CustomLog /var/log/apache2/www.example.com-ssl-access.log "%h %l %u %t \"%r\" %>s %b %D \"%{Referer}i\" \"%{User-Agent}i\""
</VirtualHost>
Anzupassende Parameter:
[...]
    ServerName www.example.com
    ServerAdmin [email protected]
    [...]
    SSLCertificateFile /etc/letsencrypt/live/www.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem
    [...]
    Header set Content-Security-Policy "default-src https: 'self' data: 'unsafe-inline' www.example.com; script-src https: 'self' 'unsafe-inline' 'unsafe-eval' www.example.com; img-src 'self' data: www.example.com
    [...]
    ErrorLog /var/log/apache2/www.example.com-ssl-error.log
    CustomLog /var/log/apache2/www.example.com-ssl-access.log "%h %l %u %t \"%r\" %>s %b %D \"%{Referer}i\" \"%{User-Agent}i\""
[...]


Apache härten

Info

Mit diesen beiden Direktiven verringern Sie die Angriffsfläche durch Informationsreduktion:

  • ServerTokens Prod
    sorgt dafür, dass Apache im HTTP-Header nur noch „Apache“ angibt – ohne Versionsnummer oder Zusatzmodule.
  • ServerSignature Off
    entfernt die Apache-Versionsanzeige von automatisch generierten Fehlerseiten und Verzeichnislisten.

Diese Maßnahmen erschweren automatisierte Angriffe, die gezielt auf bekannte Schwachstellen bestimmter Apache-Versionen oder Module ausgerichtet sind.


Editieren Sie die Datei /etc/apache2/conf-available/security.conf und ändern Sie folgende Parameter:

nano /etc/apache2/conf-available/security.conf
Anzupassende Parameter:
[...]
ServerTokens Prod
[...]
ServerSignature Off
[...]
oder verwenden Sie folgende Regex:

  • ServerTokens aktiv setzen oder anhängen, wenn nicht vorhanden

    grep -q '^ServerTokens' /etc/apache2/conf-available/security.conf && \
        sudo sed -i 's/^ServerTokens .*/ServerTokens Prod/' /etc/apache2/conf-available/security.conf || \
        echo 'ServerTokens Prod' | sudo tee -a /etc/apache2/conf-available/security.conf
    

  • Dasselbe für ServerSignature

    grep -q '^ServerSignature' /etc/apache2/conf-available/security.conf && \
        sudo sed -i 's/^ServerSignature .*/ServerSignature Off/' /etc/apache2/conf-available/security.conf || \
        echo 'ServerSignature Off' | sudo tee -a /etc/apache2/conf-available/security.conf
    


Module aktivieren und Apache starten

Deaktivieren Sie die folgenden Module:

a2dismod autoindex status negotiation

Aktivieren Sie die folgenden Module:
(Zusätzlich remoteip, wenn Sie Cloudflare Proxy nutzen)

a2enmod ssl headers proxy proxy_fcgi http2 rewrite setenvif

Aktivieren Sie die folgende Konfigurationen:

a2enconf php8.4-fpm-custom ssl-cache

Deaktivieren Sie die folgenden Site:

a2dissite 000-default.conf

Aktivieren Sie die folgenden Sites:

a2ensite www.example.com-default.conf www.example.com-ssl.conf

Starten Sie Apache neu, damit die Konfiguration angewendet wird:

service apache2 restart


Test

  • Führen Sie das folgende Kommando aus:

    apachectl configtest
    
    Wenn Ihnen Syntax OK angezeigt wird, ist Ihre Konfiguration korrekt.

  • Öffnen Sie im Browser die URL www.example.com. Sie sollten auf https://www.example.com umgeleitet werden und die Apache2 Default Page sehen.

    Apache Default Page

  • Führen Sie den SSL-Test auf Qualis SSL-Labs durch.
    Der hier konfigurierte LAMP-Stack erhält die Bewertung A+.

    SSL-Labs A+

  • Löschen die Apache2 Default Page!

    rm /var/www/html/index.html
    

Abschluss

Sie verfügen jetzt über einen modernen, performanten und sicher konfigurierten LAMP-Server, der aktuellen Best Practices entspricht und eine solide Grundlage für produktive Webanwendungen wie WordPress, Nextcloud oder eigene Projekte bildet.