Überarbeitung der Apache-Konfiguration für Ubuntu 20.04

Aus Debacher-Wiki
Wechseln zu:Navigation, Suche

Meine bisherige Konfiguration für den Webserver stammt noch ursprünglich aus dem Jahr 2006. Ich habe sie dann mit jedem neuen Server immer nur auf die dann aktuellere Linux-Version angepasst. Dabei entstand zwar immer ein funktionsfähiges System, aber viele Dinge sind nicht mehr einfach nachvollziehbar.

Momentan habe ich meinen alten Hetzner-Server nicht im produktiven Einsatz, habe ihn auf Ubuntu 20.04 aktualisiert und bin dabei die einzelnen Komponenten systematisch zu konfigurieren. Ich werde dabei aber nicht alle Altlasten wirklich los werden, immerhin müssen die reichlich vorhandenen Systeme aktualisierbar bleiben ohne große Verschiebe-Prozesse.

Für die Aktualisierung des Mailservers habe ich einen eigenen Text erstellt Überarbeitung der Mail-Konfiguration für Ubuntu 20.04.

Diese Seite beschreibt die Einrichtung und Konfiguration von virtuellen Servern und beinhaltet:

  • MySQL
  • Apache
  • letsencrypt


Datenbank-MySQL

Zur Installation von Server und Client dient der folgende Aufruf:

apt install mysql-client mysql-server mysql-common

Ich habe dann die Konfigurationsdatei /etc/mysql/mysql.conf.d/mysqld.cnf ergänzt

#ergänzt von U.D.
innodb_flush_log_at_trx_commit = 2

und die Datenbank neu gestartet. Den Datenbankzugriff sollte man nicht über das Netz erlauben, also auch in der Firewall den entsprechenden Port nicht öffnen. Die Datenbank wird ja in der Regel nur über lokale Anwendungen genutzt und über PHPMyAdmin administriert.


MySQL-Passwort

In aktuellen Datenbank-Versionen hat der Benutzer root keinen Zugriff mittels Passwort und kann daher z.B. auch nicht per phpmyadmin arbeiten. Der folgende MySQL-Befehl zeigt die Einstellung

mysql> SELECT user,authentication_string,plugin,host FROM mysql.user;
+---------------------+-------------------------------------------+-----------------------+-----------+
| user                | authentication_string                     | plugin                | host      |
+---------------------+-------------------------------------------+-----------------------+-----------+
| root                |                                           | auth_socket           | localhost |
| mysql.session       | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
| mysql.sys           | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
...

Ändern lässt sich diese Einstellung mittels:

use mysql;
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
flush privileges;

Dann ergibt sich:

mysql> select user,authentication_string,plugin,host FROM mysql.user;
+---------------------+-------------------------------------------+-----------------------+-----------+
| user                | authentication_string                     | plugin                | host      |
+---------------------+-------------------------------------------+-----------------------+-----------+
| root                | *A9172BC315E0BF4D14D201C4CD16374ED187B2B3 | mysql_native_password | localhost |
| mysql.session       | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |
| mysql.sys           | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE | mysql_native_password | localhost |


Damit ist das Passwort gesetzt. Will man es später einmal ändern, so muss man berücksichtigen, dass sich das Passwort für MySQL nicht mehr mit den altbekannten Kommandos setzen lässt, weil das Passwort nicht mehr im Feld password, sondern im Feld authentication_string zu finden ist:

use mysql;
UPDATE user SET authentication_string= password('password') WHERE User = 'root';
flush privileges;

Siehe auch https://stackoverflow.com/questions/30692812/mysql-user-db-does-not-have-password-columns-installing-mysql-on-osx

und

https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-ubuntu-20-04-de

Nachdem das Passwort gesetzt ist, kann sich der Benutzer root auch per phpmyadmin anmelden.


MySQL im Zusammenspiel mit phpmyadmin

Eine etwas einfachere Lösung das Passwort-Problem zu lösen gibt es, wenn mit phpmyadmin gearbeitet wird. In der Datei /etc/mysql/debian.cnf sind die Zugangsdaten für einen bei der Installation angelegten User zu finden:

# Automatically generated for Debian scripts. DO NOT TOUCH!
[client]
host     = localhost
user     = debian-sys-maint
password = BmhrjzFR0D0521NX
socket   = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
host     = localhost
user     = debian-sys-maint
password = BmhrjzFR01D021NX
socket   = /var/run/mysqld/mysqld.sock


Mit dem hier befindlichen Benutzer und dem hier befindlichen zufällig generiertem Passwort kann man per phpmyadmin auf die Datenbank zugreifen. Hier kann man dann bequem einen Benutzer mit allen gewünschten Rechten anlegen.

Man muss also nicht dem Benutzer root den Zugriff ermöglichen. Aus Sicherheitsgründen ist es sowieso sinnvoller einen individuellen Benutzer anzulegen, da oft genug versucht wird sich über phpmyadmin einzuloggen. Ich habe mich auch angewöhnt in der Datei /etc/apache2/conf-available/phpmyadmin.conf die Alias-Zeile auszukommentieren:

#Alias /phpmyadmin /usr/share/phpmyadmin

So kann ich erreichen, dass das Tool nicht allen virtuellen Systemen zur Verfügung steht, sondern die Berechtigung aktiv konfiguriert werden muss.

letsencrypt

Für die verschlüsselte Übertragung von Webseiten werden Zertifikate von letsencrypt benötigt. Das notwendige Paket ist bei Ubuntu dabei:

apt install certbot

Für jede meiner virtuellen Domains habe ich dann eine letsencrypt.ini erstellt, mit folgendem Inhalt:

# Aufruf mit: /usr/bin/certbot certonly --config /var/www/vhosts/meine-maildomain.de/letsencrypt.ini
# Wir nutzen 4096 bit RSA key statt 2048
rsa-key-size = 4096

# allgemeine Angaben
email = uwe@meine-maildomain.de
authenticator = webroot

# Domains fuer die wir Zertifikate beantragen, die erste in
# der liste legt den Hauptnamen fest. Alle Domains müssen beim
# Aufruf erreichbar sein
domains = meine-maildomain.de, www.meine-maildomain.de

# Dies ist das Verzeichnis zur Domain, wo letsencrypt seinen Hash in
# /.well-known/acme-challenge schreiben will. Der Pfad muss auf / enden
# es muss in der vserver.conf stehen:   Alias /.well-known   /var/www/htdocs/.well-known
webroot-path = /var/www/htdocs/

Die Reihenfolge der Domains spielt insofern eine Rolle, als die erste Domain als Bezeichner für die Verzeichnisstruktur innerhalb von /etc/letsencrypt benutzt wird. Es bietet sich also an mit einer kürzeren Angabe zu beginnen.

Zum Erzeugen der Zertifikate dient dann der Aufruf:

/usr/bin/certbot certonly --config /var/www/vhosts/meine-maildomain.de/letsencrypt.ini

Die täglichen Aktualisierungsversuche für die Zertifikate übernimmt ein Con-Job, der automatisch angelegt wird (/etc/cron.d/certbot). Leider bekommt man dann keine Mails mehr, sondern muss in die Logdateien schauen, ob alles geklappt hat. Falls mir das auf Dauer nicht gefällt, so mache ich das wieder über den eigenen Cron-Job.

Was ich jetzt erst entdeckt habe ist das Prinzip der Hooks. Man kann bei letsencript an mehreren Stellen Scripten hinterlegen, die bei Aktualisierung eines Zertifikates aufgerufen werden. Damit kann man z.B. den Webserver oder den Mailserver neu starten.


Zertifikate erweitern

Das Erweitern von letsencrypt Zertifikaten ist relativ einfach. Ich ergänze eine die Domains-Zeile in der Konfigurationsdatei und rufe den Erzeugungsprozess neu auf. Letsencrypt erkennt die Situation und fragt, ob ich das Zertifikat erweitern oder erneuern möchte. Wählt man hier erweitern, so wird das passende Zertifikat neu erzeugt.


Zertifikat reduzieren

Manchmal soll eine Domain aus einem Zertifikat entfernt werden, weil man eventuell sie an anderer Stelle benötigt, oder sie nicht mehr verfügbar ist. Ich habe bisher keinen direkten Weg gefunden, wenn man vorgeht wie beim Erweitern und einfach die Liste verkürzt, dann legt Letsenctypt ein zusätzliches Zertifikat an, mit der Ergänzung -0001 am Namen. Man muss also das Zertifikat löschen und neu erstellen.

certbot delete --cert-name MeineDomain

Es geht auch interaktiv mit

certbot delete

es erscheint eine Liste der vorhandenen Zertifikate und man gibt die Nummer des Zertifikates an, das man löschen möchte.

Anschließend legt man das Zertifikat mit der verkleinerten Liste neu an.

Man muss aber damit rechnen, dass man von Letsencrypt Hinweis-Mails bekommt, wenn sich das eigentlich gelöschte Zertifikat dem Ablauf-Zeitpunkt nähert. So weit geht die Lösung nämlich nicht.

Apache

Der Apache Webserver ist ein enorm umfangreiches Stück Software. Ich hoffe, dass meine Konfiguration einigermaßen sinnvoll ist.

Installation

Die folgenden grundlegenden Pakete habe ich installiert

apt install apache2 apache2-bin apache2-data apache2-doc apache2-utils		

Dann ein paar Pakete für PHP

apt install libapache2-mod-php  php php-auth-sasl php-bz2 php-cli php-db php-gd php-geoip php-imap php-log php-mail php-curl php-imagick php-intl
apt install php-mbstring php-mdb2 php-mysql php-net-smtp php-phpseclib php-soap php-tcpdf php7.4-zip phpmyadmin 
apt install php-apcu php7.4-opcache

Da sind eventuell noch Doppelungen drin, sowohl das Paket, als auch das Metapaket. Es ist aber das, was mir

dpkg --get-selections | grep php

lieferte.

Nicht vorhanden waren die Pakete php-gettext und php-recode, die Ursache muss ich noch recherchieren.

Nun noch ein paar Perl-Pakete:

apt install libapache2-mod-perl2 libapache2-reload-perl libapparmor-perl libarchive-zip-perl libauthen-sasl-perl libbsd-resource-perl libcairo-perl
apt install libcgi-fast-perl libfile-basedir-perl libfile-desktopentry-perl libfile-mimeinfo-perl libfont-afm-perl libgd-graph-perl libglib-perl libgtk2-perl
apt install libhtml-form-perl libhtml-format-perl libhtml-template-perl libhttp-daemon-perl libimage-magick-perl libmailtools-perl libnet-dbus-perl libtie-ixhash-perl
apt install libx11-protocol-perl libxml-xpathengine-perl libdbi-perl libdbd-mysql libclass-dbi-mysql-perl

Nach erfolgter Konfiguration (s.u.) darf man nicht vergessen die notwendigen Ports in der Firewall frei zu geben:

ufw allow "Apache Full"


Server-Module

Vorsichtshalber noch einmal ein paar Apache-Module aktivieren:

a2enmod perl
a2enmod cgi
a2enmod expires
a2enmod headers 
a2enmod rewrite
a2enmod ssl
a2dismod status
service apache2 restart


für Typo3

Da ich viel mit Typo3 arbeite habe ich etwas an den PHP-Einstellungen gedreht in der /etc/php/7.4/apache2/php.ini:

post_max_size=12M
upload_max_filesize=12M
max_execution_time=240
max_input_vars = 1500

Typo3 benötigt unbedingt imagemagick (oder alternativ graphicsmagick)

apt install imagemagick imagemagick-doc
apt install graphicsmagick ghostscript webalizer

Reihenfolge-Probleme bei der Apache-Konfiguration

Bei der Apache-Konfiguration muss man sehr auf die Reihenfolge der einzelnen Einstellungen achten. Dabei spielt der Aufbau der Hauptkonfigurationsdatei /etc/apache2/apache2.conf eine wichtige Rolle. Hier werden der Reihe nach alle Dateien aus folgenden Unterverzeichnissen eingebunden:

  • mods-enabled
  • conf-enabled
  • sites-enabled

Die Dateien aus den einzelnen Verzeichnissen werden dann jeweils in alphabetischer Reihenfolge eingebunden, intern entsteht dabei eine einzige große Konfigurationsdatei. Innerhalb dieser virtuellen Datei spielen die Reihenfolgen eine Rolle.

Bei der Reihenfolge von Alias (auch SriptAlias) Anweisungen und Redirects, die in unterschiedlichen Kontexten auftreten, werden die Direktiven nach den üblichen Zusammenführungsregeln verarbeitet. Wenn jedoch mehrere Aliase oder Redirects im gleichen Kontext (z.B. im gleichen Abschnitt) auftreten, werden sie in einer bestimmten Reihenfolge verarbeitet.

Zunächst werden alle Umleitungen verarbeitet, bevor Aliase verarbeitet werden, und daher werden auf eine Anforderung, die mit einer Umleitung oder einer RedirectMatch übereinstimmt, niemals Aliase angewendet. Zweitens werden die Aliase und Redirects in der Reihenfolge verarbeitet, in der sie in den Konfigurationsdateien erscheinen, wobei die erste Übereinstimmung Vorrang hat.

Wenn also in der /etc/apache2/conf-available/postfixadmin.conf steht

Alias /postfixadmin /usr/share/postfixadmin/public

kann ich dies nicht im allgemeinen Teil der /etc/apache2/sites-available/000-default.conf überschreiben, weil die erst später inkludiert wird. Nur innerhalb einer Directory oder VirtualHost Struktur kann ich Veränderungen vornehmen, weil dies spezieller ist.

Aus dem gleichen Grund muss man, wenn zwei oder mehr dieser Direktiven auf denselben Unterpfad angewendet werden, den spezifischsten Pfad zuerst auflisten, damit alle Direktiven eine Wirkung haben. Zum Beispiel wird die folgende Konfiguration wie erwartet funktionieren:

 ScriptAlias /cgi-bin/mailman/ /usr/lib/cgi-bin/mailman/
 ScriptAlias /cgi-bin/ "/var/www/vhosts/default/cgi-bin/"

Aber wenn die beiden oben genannten Richtlinien in umgekehrter Reihenfolge angewendet würden, würde der /cgi-bin vor dem /cgi-bin/mailman-Alias stehen, so dass die letztere Richtlinie ignoriert würde.

Es ist sinnvoll beim Start von Apache auf die Meldungen im Syslog zu achten. Habe ich z.B. den Alias /postfixadmin bei den conf-enabled nicht auskommentiert, so erscheint bei meiner Konfiguration (s.u.) die Meldung

The Alias directive in /etc/apache2/sites-enabled/000-default.conf at line 19 will probably never match because it overlaps an earlier Alias.

/etc/apache2/sites-available/000-default.conf

Diese Datei besteht bei mir aus drei Teilen:

  • Zuerst die allgemeinen Einstellungen, die dann für alle virtuellen Systeme gelten, sofern sie nicht überschrieben werden.
  • Dann der virtuelle Default-Server für Port 80. Er würde aufgerufen, wenn jemand über die IP-Adresse, den Namen beim Provider (static.w.x.y.z.clients.your-server.de) oder eine nicht vorgesehene Domain kommt.
  • Der entsprechende virtuelle Default-Server für Port 443.

Die virtuellen Standard-Server sind auch im Zusammenhang mit letsencrypt-Zertifikaten für den Mailserver ganz praktisch. Ich muss nicht für mail.meine-maildomain.de eine Webseite konfigurieren, wenn ich ein Zertifikat erstellen oder erweitern möchte. Letsencrypt landet im Zweifelsfall hier und kann den Zugriff verifizieren. Der Standard-Server auf Port 443 erleichtert dann die Kontrolle der erstellten Zertifikate für den Mailserver, wenn das hier angegebene Zertifikat auch im Mailsystem genutzt wird.

ServerName default
 ServerAdmin Uwe@meine-maildomain.de
 
 ServerTokens Major
 ServerSignature off
 TraceEnable off
 ProxyRequests off
 
 UseCanonicalName Off
 DocumentRoot /var/www/vhosts/default/httpdocs
 
 ErrorLog ${APACHE_LOG_DIR}/error.log
 CustomLog ${APACHE_LOG_DIR}/access.log combined
 
 CustomLog /var/log/apache2/vhosts_access.log vhost_combined
 
 Alias /webmail       /var/www/htdocs/dummy
 Alias /phpmyadmin    /var/www/htdocs/dummy
 Alias /postfixadmin  /var/www/htdocs/dummy
 
 Alias /webstat       /var/www/htdocs/webalizer
 Alias /roundcube     /var/lib/roundcube
 
 <IfDefine MAILMAN>
   ScriptAlias     /mailman/       /var/www/htdocs/dummy
   Alias           /mailmanicons/  /var/www/htdocs/dummy
   Alias           /pipermail/     /var/www/htdocs/dummy
 </IfDefine>
 
 <Directory "/var/www/vhosts">
  AllowOverride All
  Options +SymLinksIfOwnerMatch -Indexes
  Require all granted
 
  <IfModule mod_php7.c>
    php_value date.timezone "Europe/Berlin"
    php_value open_basedir /var/www/:/tmp/
  </IfModule>
 
 </Directory>
 
 <IfModule mod_userdir.c>
  UserDir disabled
 </IfModule>
 
 <IfModule mod_expires.c>
  ExpiresActive On
  ExpiresDefault "access plus 1 month"
  ExpiresByType text/html "access plus 1 week"
  ExpiresByType image/gif "access plus 1 week"
  ExpiresByType image/jpeg "access plus 1 week"
  ExpiresByType image/png "access plus 1 week"
  ExpiresByType text/css "access plus 1 week"
  ExpiresByType text/javascript "access plus 1 week"
  ExpiresByType application/x-javascript "access plus 1 week"
  ExpiresByType text/xml "access plus 1 week"
 </IfModule>
 
 <IfModule mod_setenvif.c>
   # SEO
   BrowserMatchNoCase (mindUp|meanpathbot|seoscanners|AiHitBot|BLEXBot|DotBot|linkdexbot|MJ12bot|SEOkicks-Robot) ist_ein_bot
   # Sammeln Backlinks & Links
   BrowserMatchNoCase (exabot|Baidu|Haosou|Semrush|MegaIndex|AhrefsBot|BacklinkCrawler|dlcbot|spbot) ist_ein_bot
   # Performance Testing
   BrowserMatchNoCase (200PleaseBot|LoadTimeBot) ist_ein_bot
   # BilderSuche
   BrowserMatchNoCase (psbot|Yandex) ist_ein_bot
   # Harvester & Marketing
   BrowserMatchNoCase (MegaIndex|Applebot|XoviBot|CareerBot|GrapeshotCrawler|iCjobs|magpie-crawler|proximic) ist_ein_bot
   # Nutzlos, Schlecht bzw. unbekannt
   BrowserMatchNoCase (PetalBot|360Spider|AfD-Verbotsverfahren|Barkrowler|PeoplePal|ltx71|CalendarAgent|JobboerseBot|GarlikCrawler|Mail.RU_B
   # Per IP
   SetEnvIfNoCase Remote_Addr (62\.138\.0\.25) ist_ein_bot
   # kyivstar.net
   SetEnvIfNoCase Remote_Addr ^(5\.248|46\.118|37\.115|178\.137) ist_ein_bot
   # Einträge von 2020
   BrowserMatchNoCase (MaviBot|oBot|MetaJobBot|seocompany|coccocbot-image|SeznamBot) ist_ein_bot
 </IfModule>
 
 <IfModule mod_ssl.c>
     SSLProtocol All -SSLv2 -SSLv3
     SSLHonorCipherOrder On
     SSLCompression off
     SSLCipherSuite EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA 
 </IfModule>
 
 <VirtualHost *:80>
   Alias /.well-known   /var/www/htdocs/.well-known
   Alias /roundcube       /var/www/htdocs/dummy
 
  <Directory /var/www/vhosts/default/httpdocs>
    AllowOverride All
    Options None
    Require all granted
  </Directory>
 
 </VirtualHost>
 
 <IfModule mod_ssl.c>
  <VirtualHost _default_:443 >
     SSLEngine on
     Alias /roundcube       /var/www/htdocs/dummy
 
 # Wenn das erste Zertifikat mit Letsencryp erstellt ist, dann die Zertifikate austauschen
 #     SSLCertificateFile      /etc/ssl/certs/ssl-cert-snakeoil.pem
 #     SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
      SSLCertificateFile /etc/letsencrypt/live/<dummy>/fullchain.pem
      SSLCertificateKeyFile /etc/letsencrypt/live/<dummy>/privkey.pem
 
     <FilesMatch "\.(cgi|shtml|phtml|php)$">
        SSLOptions +StdEnvVars
     </FilesMatch>
 
     <Directory /var/www/vhosts/default/httpdocs>
        SSLRequireSSL
        AllowOverride All
        Options None
        Require all granted
 
     </Directory>
 
  </VirtualHost>
 
 </IfModule>


Die SSL-Einstellungen der Seite kann man unter https://www.ssllabs.com/ssltest/ testen lassen.

Ursprünglich hatte ich hier auch einen Alias für .well-known mir drin, das führt aber zu Problemen bei z.B. Nextcloud, hier wird mit Unterverzeichnissen von .well-known gearbeitet und dann treten Probleme mit der Reihenfolge auf.

Vserver-Konfiguration

Für jeden weiteren VServer erfolgt die Konfiguration in /etc/apache2/vhosts/sites-available/<dummy>.conf nach folgendem System, wobei <dummy> durch z.B. den Domainnamen ersetzt wird. Das zugehörige Verzeichnis wird dann mit diesem Namen unterhalb von /var/www/vhosts/ angelegt.

<VirtualHost *:80>
 ServerName   www.<dummy>:80
 ServerAlias <dummy>
 DocumentRoot /var/www/vhosts/<dummy>/httpdocs

 CustomLog  /var/log/apache2-vhosts.d/<dummy>_access.log combined
 ErrorLog   /var/log/apache2-vhosts.d/<dummy>_error.log

 CustomLog /var/log/apache2/vhosts_access.log vhost_combined

 ScriptAlias  /cgi-bin/ /var/www/vhosts/<dummy>/cgi-bin/
 Alias  /webstat       /var/www/vhosts/<dummy>/webstat
 Alias /.well-known   /var/www/htdocs/.well-known
# Nur bei Bedarf aktivieren
#  Alias /phpmyadmin /usr/share/phpmyadmin
#  Alias /postfixadmin  /usr/share/postfixadmin/public

 <Directory /var/www/vhosts/<dummy>/httpdocs>

   <IfModule mod_setenvif.c>
     <RequireAll> 
       Require all granted
       Require not env ist_ein_bot
     </RequireAll> 
   </IfModule>

   Options -Includes +ExecCGI
 </Directory>

 <Directory "/var/www/vhosts/<dummy>/cgi-bin">
      AllowOverride None
      Options +ExecCGI -Includes
      Require all granted
 </Directory>

</VirtualHost>

# soll SSL aktiviert werden das _no entfernen
<IfModule mod_ssl_no.c>

<VirtualHost *:443>
 ServerName   www.<dummy>:443
 ServerAlias <dummy>
 UseCanonicalName Off
 DocumentRoot /var/www/vhosts/<dummy>/httpdocs

 CustomLog  /var/log/apache2-vhosts.d/<dummy>_access.log combined
 ErrorLog   /var/log/apache2-vhosts.d/<dummy>_error.log

 CustomLog /var/log/apache2/vhosts_access.log vhost_combined

 ScriptAlias  /cgi-bin/ /var/www/vhosts/<dummy>/cgi-bin/
 Alias  /webstat /var/www/vhosts/<dummy>/webstat
 Alias /.well-known   /var/www/htdocs/.well-known
# Nur bei Bedarf aktivieren
#  Alias /phpmyadmin /usr/share/phpmyadmin
#  Alias /postfixadmin  /usr/share/postfixadmin/public
 SSLEngine on

 <Directory /var/www/vhosts/<dummy>/httpdocs>
   <IfModule mod_setenvif.c>
     <RequireAll> 
       Require all granted
       Require not env ist_ein_bot
     </RequireAll> 
   </IfModule>

   Options -Includes +ExecCGI
 </Directory>

 <Directory "/var/www/vhosts/<dummy>/cgi-bin">
      AllowOverride None
      Options +ExecCGI -Includes
      Require all granted
 </Directory>
 
  SSLCertificateFile /etc/letsencrypt/live/<dummy>/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/<dummy>/privkey.pem

</VirtualHost>

</IfModule>

Verwaltungs-Vserver

Für die Nutzung von

  • postfixadmin
  • phpmyadmin
  • rspamd
  • eigenen CGI Scripten

habe ich mir einen speziellen virtuellen Server erstellt, der keine eigenen Ordner bekommt, sondern auf dem Default-Server aufsetzt. /etc/apache2/vhosts/sites-available/verwaltung.conf

<VirtualHost *:80>
 ServerName   verwaltung.<dummy>:80
 DocumentRoot /var/www/vhosts/default/httpdocs

 CustomLog  /var/log/apache2-vhosts.d/verwaltung_access.log combined
 ErrorLog   /var/log/apache2-vhosts.d/verwaltung_error.log

 CustomLog /var/log/apache2/vhosts_access.log vhost_combined

 ScriptAlias  /cgi-bin/ /var/www/vhosts/default/cgi-bin/
 Alias  /webstat        /var/www/vhosts/default/webstat
 Alias /phpmyadmin      /usr/share/phpmyadmin
 Alias /postfixadmin    /usr/share/postfixadmin/public
 Alias /.well-known   /var/www/htdocs/.well-known
 
 <Directory /var/www/vhosts/default/httpdocs>

   <IfModule mod_setenvif.c>
     <RequireAll> 
       Require all granted
       Require not env ist_ein_bot
     </RequireAll> 
   </IfModule>
 
   Options -Includes +ExecCGI
 </Directory>

 <Directory "/var/www/vhosts/default/cgi-bin">
      AllowOverride None
      Options +ExecCGI -Includes
      Require all granted
 </Directory>

 RewriteEngine On
 ProxyRequests Off
 <Location /rspamd>
      Order allow,deny
      Allow from all
 </Location>
 RewriteRule ^/rspamd$ /rspamd/ [R,L]
 RewriteRule ^/rspamd/(.*) http://localhost:11334/$1 [P,L]

</VirtualHost>

# soll SSL aktiviert werden das _no entfernen
<IfModule mod_ssl_no.c>

 <VirtualHost *:443>
 ServerName   verwaltung.<dummy>:443
 DocumentRoot /var/www/vhosts/default/httpdocs

 CustomLog  /var/log/apache2-vhosts.d/verwaltung_access.log combined
 ErrorLog   /var/log/apache2-vhosts.d/verwaltung_error.log

 ScriptAlias  /cgi-bin/   /var/www/vhosts/default/cgi-bin/
 Alias  /webstat          /var/www/vhosts/default/webstat
 Alias /phpmyadmin        /usr/share/phpmyadmin
 Alias /postfixadmin      /usr/share/postfixadmin/public
 Alias /.well-known   /var/www/htdocs/.well-known

 SSLEngine on

 <Directory /var/www/vhosts/default/httpdocs>

   <IfModule mod_setenvif.c>
     <RequireAll> 
       Require all granted
       Require not env ist_ein_bot
     </RequireAll> 
   </IfModule>

   Options -Includes +ExecCGI
 </Directory>

 <Directory "/var/www/vhosts/default/cgi-bin">
      AllowOverride None
      Options +ExecCGI -Includes
      Require all granted
 </Directory>

  SSLCertificateFile /etc/letsencrypt/live/verwaltung.<dummy>/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/verwaltung.<dummy>/privkey.pem

  RewriteEngine On
  ProxyRequests Off
  <Location /rspamd>
      Order allow,deny
      Allow from all
  </Location>
  RewriteRule ^/rspamd$ /rspamd/ [R,L]
  RewriteRule ^/rspamd/(.*) http://localhost:11334/$1 [P,L]

 </VirtualHost>

</IfModule>

Logdateien

Da ich die Logdateien für meine virtuellen Server in einem zusätzlichen Verzeichnis speichere, brauche ich eine Erweiterung für Logrotate:

/var/log/apache2-vhosts.d/*.log {
   prerotate
       /root/webalizer.sh
   endscript
   compress
   dateext
   maxage 365
   rotate 23
   size=+4096k
   notifempty
   missingok
   create 644 root root
   postrotate
    /bin/systemctl reload apache2.service
   endscript
}

Entweder hängt man diesen Teil an /etc/logrotate.d/apache2 an oder man erstellt eine neue Datei /etc/logrotate.d/apache-vhosts .