23354
Kommentar: Typo
|
← Revision 20 vom 2023-06-30 15:15:44 ⇥
0
|
Gelöschter Text ist auf diese Art markiert. | Hinzugefügter Text ist auf diese Art markiert. |
Zeile 1: | Zeile 1: |
Einige [[https://riseup.net/en/security/resources/radical-servers|Technik-Kollektive]] bieten Wordpress-Hosting auf Basis von [[https://wordpress.org/support/article/create-a-network/|Wordpress-Multisite]] an. Beispiele dafür sind die tollen Angebote von [[https://blackblogs.org/|blackblogs.org]] und [[https://noblogs.org/|noblogs.org]]. In der Regel ist die Funktionalität von Wordpress beschränkt, so dass sich nur eine Auswahl von Themes und Plugins installieren lassen. Ein anderer Ansatz ist der Betrieb einzener Wordpress-Seiten in einem abgesichertem Hosting. Diese Seite beschreibt die Einrichtung eines solchen Hostings. Entgegen anderen Anleitungen verwenden wir Apache, um mittels [[http://httpd.apache.org/docs/2.4/mod/mod_macro.html|Macros]] die Seiteneinrichtung zu vereinfachen. Zur Absicherung verwenden wir ein WikiPediaDe:chroot, basierend auf PHP-FPM. <<TableOfContents>> = Einführung = Dieser Anleitung basiert auf anderen sehr gut Howtos. Für ein grundlegendes Verständnis solltest du diese auch lesen: * [[https://nickyreinert.de/blog/2019/04/12/mehrere-virtuelle-server-mit-nginx-und-php-fpm-fur-wordpress-teil-1-3/|nickyreinert.de]] für einen allgemeinen Überblick * [[https://blog.kthx.at/2015/09/23/php-fpm-chroot/|blog.kthx]] zum Setup-Skript * [[https://www.vennedey.net/resources/3-Secure-webspaces-with-NGINX-PHP-FPM-chroots-and-Lets-Encrypt|vennedey.net]] zu den Sicherheitimplikation von NSCD und opcache * [[https://binary-butterfly.de/artikel/das-perfekte-php-wordpress-setup/|binary-butterfly.de]] zur Verwendung von `mknod` statt den mount-binds == Variablen, Versionen und Pfade == Zur Veranschaulichung werden die nachfolgenden Variablen und Werte in der Anleitung genutzt: || Beispiel-Domain || example.org || || Benutzerkonto || katja || || PHP-Version || 7.3 || || Quota-Partition (ext4) || /data || || Skript-Verzeichnis || /usr/local/bin || || Wordpress-Speicherort || /data/wordpress || || IP des Reverse-Proxys || 192.168.0.1 || Bitte beachte, dass sich einzelnen Pfadangaben teilweise in mehreren Konfigurationsdateien benutzt werden. Bei Änderungen eines Pfades musst du also alle Vorkommen ändern. = Benutzerkonto zur PHP-Ausführung = * Ein Systemnutzer mit eingeschränkten Rechten ist für die Auführung des PHP-Prozesses zuständig. Die Anmeldung per Passwort<<FootNote(Die Anmeldung per ssh-Schlüssel ist weiterhin möglich)>> und das Anlegen eines Home-Verzeichnissen werden deaktiviert:{{{ adduser --disabled-login --disabled-password --no-create-home --gecos katja}}} * Im späteren Verlauf wird das Wordpress-Verzeichnis diesem neuen Benutzerkonto übergeben. = Quotas einrichten = * Disk-Quotas sorgen dafür, dass eine einzelne Wordpress-Instanz nicht den gesamten Speicherplatz auf einer Partition aufbrauchen kann. Läuft Wordpress in einem KVM-Gast muss ein Kernel installiert werden<<FootNote(Damit die Quota-Kernelmodule verfügbar sind)>>:{{{ apt install linux-image-amd64 quota}}} * Anschließend werden der ext4-Partition in `/etc/fstab` die notwendigen Parameter übergeben:{{{ /dev/vdb /data auto noatime,nodiratime,usrjquota=aquota.user,jqfmt=vfsv1 0 0}}} * Die Partition mit den neuen Werten remounten:{{{ mount -vo remount /data}}} * Den Quota-Index erstellen und Quotas aktivieren<<FootNote(Falls `quotaon` den Fehler `Devive or ressource busy anzeigt`, Quota deaktivieren und erneut aktivieren)>>:{{{ quotacheck -cum quotaon -v /data}}} * Nun können für den neuen Nutzer die Quota-Regeln erstellt werden:{{{ edquota katja}}} * Weitere Hinweise dazu im [[https://wiki.archlinux.org/index.php/Disk_quota|Arch-Wiki]] = Apache: Seitenkonfiguration mit Macros = * Durch Apache-Macros ist es möglich, nur eine Seitenkonfiguration für alle Wordpress-Instanzen zu erstellen. * Die Seitenkonfiguration `/etc/apache/sites-available/wordpress.conf` basiert auf dem später näher erläuterten Verzeichnisaufbau. Die Konfiguration verhindert durch Rewriting die Installation von eigenen Themes und Modulen über das Dashboard<<FootNote(Die Installation über das Wordpress Theme- und Pluginverzeichnis ist weiterhin möglich)>>. Zudem wird eine optionale htaccess-Datei eingebunden. Damit lassen sich einzelnen Wordpress-Seiten per htacess zusätzlich schützen:{{{ <Macro WPSite $domain $pool> <VirtualHost *> ServerName $domain SetEnv HTTPS on DocumentRoot /data/wordpress/$domain/htdocs ErrorLog /var/log/apache2/$domain.error IncludeOptional /data/wordpress/_htaccess.d/$domain.conf Include /etc/apache2/conf-available/wordpress-cache.conf # Installation von eigenen Themes und Plugins verhindern <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_URI} ^/wp-admin/update.php RewriteCond %{QUERY_STRING} action=upload-(plugin|theme) RewriteRule (.*) /wp-admin/plugin-install.php [QSD,R=302,L] </IfModule> <Directory /data/wordpress/$domain/htdocs> Require all granted Options SymLinksIfOwnerMatch MultiViews IncludesNoExec AllowOverride AuthConfig FileInfo Indexes Limit Options # https://wordpress.org/support/article/hardening-wordpress/#securing-wp-includes <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^wp-admin/includes/ - [F,L] RewriteRule !^wp-includes/ - [S=3] RewriteRule ^wp-includes/[^/]+\.php$ - [F,L] RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L] RewriteRule ^wp-includes/theme-compat/ - [F,L] </IfModule> </Directory> <IfModule proxy_fcgi_module> <FilesMatch ".+\.ph(ar|p|tml)$"> SetHandler "proxy:unix:/run/php/php-fpm-$pool.sock|fcgi://$domain" </FilesMatch> <FilesMatch ".+\.phps$"> Require all denied </FilesMatch> <FilesMatch "^\.ph(ar|p|ps|tml)$"> Require all denied </FilesMatch> <Files xmlrpc.php> Require all denied </Files> <Files wp-config.php> Require all denied </Files> </IfModule> </VirtualHost> </Macro> # Includieren der Variablen Include /etc/apache2/conf-available/wordpress-sites.conf UndefMacro WPSite}}} * Alle Variablen werden in `/etc/apache2/conf-available/wordpress-sites.conf` definiert. Die `pool`-Variable bezeichnet den Namen des PHP-FPM-Pools:{{{ # Muster: Use WPSite $domain $pool Use WPSite example.org katja}}} * Anschließend werden alle benötigten Module und die Seite aktiviert:{{{ a2enmod macros a2ensite wordpress.conf systecmtl reload apache2}}} = Chroot-Verzeichnis-Struktur = * Oberste Ebene eines jeden chroots ist das jeweilige Domain-Verzeichnis. Für die Beispieldomain ist es `data/wordpress/example.org`. * Das `tmp`-Verzeichnis hat eine doppelte Funktion: Es markiert ein chroot-Verzeichnis. Das ist für das später vorgestellte chroot-setup-Skript wichtig. Zudem werden dort temporäre Daten gespeichert. * Wordpress selbst liegt unter `htdocs`. Daraus ergibt sich folgende Struktur:{{{ ├── data/wordpress/example.org │ ├── dev/ │ ├── etc/ │ ├── htdocs/ │ │ └── index.php │ ├── lib/ │ ├── run/ | ├── sessions/ | ├── tmp/ | ├── usr/ | └── var/}}} * `htdocs`, `tmp` und `sessions` gehören dem oben erstellten Benutzerkonto `katja:katja`. Alle anderen Verzeichnisse `root:root`. = Chroot-Setup-Skript = * Das Skript `/usr/local/bin/php-fpm-chroot-setup` nimmt die Ersteinrichtung des chroots und der Verzeichnisstruktur vor. Es kopiert zudem die notwendigen Daten in das chroot. * Im Wesentlichen handelt es sich um Daten für die Namensauflösung, das Überprüfen von Zertifikaten und den mysql-Socket:{{{ #!/bin/sh set -eu BASE_DIR="/data/wordpress" CHROOT_DIRS=$(find "$BASE_DIR" -mindepth 1 -maxdepth 1 -type d) COPY_SOURCES=" /etc/hosts /etc/resolv.conf /etc/ssl/certs /lib/x86_64-linux-gnu/libnss_dns.so.2 /usr/lib/ssl/openssl.cnf /usr/share/zoneinfo" MOUNTS="/var/run/mysqld" MKNOD_DIRS=" dev logs sessions tmp" create_mounts() { local chroot_dir="$1" shift local mount_dir for mount_dir in "$@"; do if [ -d "$mount_dir" ]; then # $mount_dir ist ein Pfad zu einem Verzeichnis mkdir -p "$chroot_dir/$mount_dir" mount --bind -o ro "$mount_dir" "$chroot_dir/$mount_dir" else # $mount_dir ist ein Pfad zu einer Datei mkdir -p "$chroot_dir/$(dirname "$mount_dir")" touch "$chroot_dir/$mount_dir" mount --bind -o ro "$mount_dir" "$chroot_dir/$mount_dir" fi done } remove_chroot() { local chroot_dir="$1" shift if [ -d "$chroot_dir/tmp" ]; then echo "Loese $chroot_dir auf..." for f in "$@"; do umount "$chroot_dir/$f" || continue if [ -d "$chroot_dir/$f" ]; then # Leeren Ordner loeschen rmdir "$chroot_dir/$f" elif [ -f "$chroot_dir/$f" ]; then # Datei loeschen rm "${chroot_dir}${f}" fi done fi } if [ $# -ge 1 ]; then ACTION=$1 shift else ACTION=help fi case "$ACTION" in init) [ $# -ne 1 ] && echo "action 'init' requires one parameter: domain - e.g. 'example.org'" && exit 1 DOMAIN="$1" CHROOT_SITE_DIR="$BASE_DIR/$DOMAIN" for i in $MKNOD_DIRS; do mkdir -p "$CHROOT_SITE_DIR/$i" done for i in $COPY_SOURCES; do cp -urpL --parents "$i" "$CHROOT_SITE_DIR" done mknod -m 666 "$CHROOT_SITE_DIR/dev/null" c 1 3 mknod -m 444 "$CHROOT_SITE_DIR/dev/random" c 1 8 mknod -m 444 "$CHROOT_SITE_DIR/dev/urandom" c 1 9 mknod -m 666 "$CHROOT_SITE_DIR/dev/zero" c 1 5 mkdir -p "$CHROOT_SITE_DIR/tmp" create_mounts "$CHROOT_SITE_DIR" "$MOUNTS" ;; start) for chroot_dir in $CHROOT_DIRS; do # Nur in Ordnern mit eigenem /tmp Verzeichnis als Markierung einen Chroot aufsetzen if [ -d "$chroot_dir/tmp" ]; then # Berechtigungen von /tmp korrigieren chmod 777 "$chroot_dir/tmp" chmod +t "$chroot_dir/tmp" echo "Setting up ${chroot_dir} ..." create_mounts "$chroot_dir" $MOUNTS for i in $COPY_SOURCES; do cp -urpL --parents "$i" "$chroot_dir" done fi done ;; stop) for chroot_dir in $CHROOT_DIRS; do remove_chroot "$chroot_dir" "$MOUNTS" done ;; restart) "$0" stop 2>/dev/null "$0" start ;; remove) DOMAIN="$1" CHROOT_SITE_DIR="$BASE_DIR/$DOMAIN" remove_chroot "$CHROOT_SITE_DIR" "$MOUNTS" ;; help|--help) echo "Usage: $(basename "$0") { start | stop | restart | init | remove }" echo exit 1 ;; *) "$0" help >&2 exit 1 ;; esac }}} * Nähere Erläuterungen zu dem Skript findest du [[https://blog.kthx.at/2015/09/23/php-fpm-chroot/|hier]]. * Zudem ist [[https://www.vennedey.net/blog/3-NSCD-socket-in-a-PHP-FPM-chroot-leaks-user-database|hier]] erklärt, weshalb die Verwendung von NSCD zur Namensauflösung keine gute Idee ist. Als Alternative kopiert das Skript `/etc/resolv.conf` und `libnss_dns.so.2`. == Initieren beim Start == * Einige Daten (im Beispiel der mysql-Socket) werden durch das Skript per bind-mount in das chroot gemountet. Diese müssen bei jedem Start wieder hergestellt werden. Dies übernimmt der systemd-Service `/etc/systemd/system/php-fpm-chroot.service`:{{{ [Unit] Description=Set up PHP-FPM chroot mounts After=network.target php7.3-fpm.service mysqld.service [Service] Type=forking ExecStart=/usr/local/bin/php-fpm-chroot-setup start ExecStop=/usr/local/bin/php-fpm-chroot-setup stop RemainAfterExit=yes [Install] WantedBy=multi-user.target}}} * Den Service aktivieren und den Deamon neu laden:{{{ systemctl enable php-fpm-chroot.service systemctl daemon-reload}}} = Konfiguration des PHP-FPM-Pools mit Chroot = * Die Konfigurarion des PHP-FPM-Pools basiert auf den Pfadangaben, die in der [[#Apache: Seitenkonfiguration mit Macros|Apachekonfiguration]] und in der [[#Chroot-Verzeichnis-Struktur|Verzeichnisstruktur]] verwenden werden. * Damit das PHP-FPM-Socket gefunden wird:{{{ php_admin_value[doc_root] = /htdocs php_admin_value[cgi.fix_pathinfo] = 0}}} * [[https://bugs.php.net/bug.php?id=69090|Sicherheitseinstellugnen]] für opcache:{{{ php_admin_value[opcache.validate_permission] = 1 php_admin_value[opcache.validate_root] = 1}}} * Angabe des Cert-Pfades, damit die Validierung klappt:{{{ php_admin_value[openssl.capath] = /etc/ssl/certs}}} * Alles in allem die vollständige FPM-Konfiguration:{{{ [katja] prefix = /data/wordpress/example.org user = $pool group = www-data listen = /run/php/php-fpm-$pool.sock listen.owner = $pool listen.group = www-data listen.mode = 0660 listen.allowed_clients = 127.0.0.1 pm = ondemand pm.max_children = 5 pm.start_servers = 2 pm.process_idle_timeout = 10s; pm.max_requests = 100 chroot = $prefix chdir = / security.limit_extensions = .php .php3 .php4 .php5 php_admin_value[doc_root] = /htdocs php_admin_value[cgi.fix_pathinfo] = 0 php_admin_value[opcache.validate_permission] = 1 php_admin_value[opcache.validate_root] = 1 php_admin_value[session.save_path] = /sessions php_admin_value[openssl.capath] = /etc/ssl/certs php_admin_value[disable_functions] = mail,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_exec,passthru,system,proc_get_status,proc_close,proc_nice,proc_terminate,proc_open,curl_ini,parse_ini_file,show_source,dl,symlink,system_exec,exec,shell_exec,phpinfo}}} = Verwaltung mit wpcli = * [[https://wp-cli.org/de/|Wpcli]] ist ein Werkzeug für die Kommandozeile, um Wordpress-Seiten zu verwalten. * Die Installation geht recht [[https://wp-cli.org/de/#installation|einfach]]. * Zu beachten ist, dass `wpcli` stehts als der angelegte Wordpress-Nutzer ausgeführt wird (und nicht als root). = Seitengeschwindigkeit optimieren = Mittels Caching sollen Seitenaufrufe beschleunigt werden. == Webserver-Caching == * Wir weisen den Browser an, Mediendateien, css und javascript zu cachen. Dafür wirf in `/etc/apache2/conf-available/wordpress-cache.conf` ein globaler Cache definiert:{{{ <IfModule mod_expires.c> ExpiresActive on # whitelist expires rules ExpiresDefault "access 1 month" # Favicon (cannot be renamed) ExpiresByType image/x-icon "access plus 1 week" # Media: images, video, audio ExpiresByType image/gif "access plus 1 month" ExpiresByType image/png "access plus 1 month" ExpiresByType image/jpg "access plus 1 month" ExpiresByType image/jpeg "access plus 1 month" ExpiresByType video/ogg "access plus 1 month" ExpiresByType audio/ogg "access plus 1 month" ExpiresByType video/mp4 "access plus 1 month" ExpiresByType video/webm "access plus 1 month" # Webfonts ExpiresByType application/x-font-ttf "access plus 1 year" ExpiresByType font/opentype "access plus 1 year" ExpiresByType application/x-font-woff "access plus 1 year" ExpiresByType image/svg+xml "access plus 1 year" # CSS and JavaScript ExpiresByType text/css "access plus 1 month" ExpiresByType text/javascript "access plus 1 month" ExpiresByType application/javascript "access plus 1 month" <IfModule mod_headers.c> Header append Cache-Control "public" </IfModule> </IfModule>}}} * Nun noch das entsprechende Modul neu laden und den Webserver neu laden:{{{ a2enmod macros expires systemctl reload apache2}}} == Redis-Caching == * Redis ist ein persistenter Objekt-Cache zur Zwischenspeicherung von Daten * In der `wp-config.php` muss der Cache_Salt angegeben werden. Das ist wichtig, damit bei der Verwendung von nur einer Redis-Datenbank mit mehreren Wordpress-Seiten die Inhalte des Caches korrekt zugeordnet werden können:{{{ wp config set WP_CACHE_KEY_SALT example.org_}}} * Die Nutzung setzt ein Plugin voraus, bspw. [[https://wordpress.org/plugins/wp-redis|WP-Redis]]:{{{ wp plugin install wp-redis wp plugin acticate wp-redis}}} * Anschließend lässt sich die Redis-Nutzung per `wpcli` aktivieren:{{{ wp redis enable wp redis info}}} * Wird Redis per TCP-Verbindung angesprochen, muss nichts weiter konfiguriert werden. Soll die Verbindung über das Socket hergestellt werden, müssen die Serverangaben in `wp-config.php` ergänzt werden:{{{ $redis_server = array( 'host' => '/run/redis/redis-server.sock', 'port' => 0, );}}} * Zudem muss der Wordpress-Nutzer zur Redis-Gruppe hinzugefügt werden:{{{ usermod -a -G redis katja}}} == Varnish-Caching == Alternativ zu Redis kann [[http://varnish-cache.org|Varnish]] als Caching-Lösung eingesetzt werden. Dadurch lassen sich die Caching-Einstellungen ziemlich detailliert anpassen. Die nachfolgenden Punkte orientieren sich an den Blog-Artikeln [[https://www.getpagespeed.com/server-setup/varnish/varnish-virtual-hosts|Varnish Virtual Hosts. The Right Way]] sowie [[https://info.varnish-software.com/blog/failure-to-purge-a-story-about-client.ip-and-proxies|Purge and proxies, a love-hate affair]]. In der Wordpress-[[https://codex.wordpress.org/Varnish|Dokumentation]] ist ein umfangreiches Konfigurationsbeispiel für Varnish enthalten. Dort werden unnötigerweise viele Sachen gedoppelt, die Varnish durch seine ''Built-in vcl_recv'' sowieso macht<<FootNote(Siehe [[https://info.varnish-software.com/the-varnish-book|The Varnish Book]], Kapitel 7.8 "Built-in vcl_recv")>>. * Installation über die Paketquellen:{{{ apt install varnish}}} * Varnish lauscht anschließend auf Port `6081` auf Verbindungen. * Da die freie Version keine SSL-Terminierung unterstützt, muss Varnish hinter einem Reverse-Proxy laufen * Die Konfiguration in `/etc/varnish/default.vcl` sieht so aus:{{{ vcl 4.0; acl local { "localhost"; "192.168.0.2"; "192.168.0.1"; } import std; backend default { .host = "127.0.0.1"; .port = "80"; } sub vcl_recv { } sub vcl_backend_response { } sub vcl_deliver { unset resp.http.server; unset resp.http.via; unset resp.http.x-powered-by; unset resp.http.x-runtime; unset resp.http.x-varnish; } include "vhosts.vcl";}}} * Hier werden folgende Sachen konfiguriert: * Die ACL-Regel ''local'' besagt, dass der Cache nur von berechtigten Adresse gelöscht werden kann. ''192.168.0.1'' ist in diesem Fall der Reverse-Proxy. * Das Modul ''std'' wird importiert - es wird für die ACL-Regel benötigt. * Unter '' sub vcl_deliver'' wir die Auslieferung verschiedener Header unterdrückt. * Die Konfiguration von einzelnen Seiten erfolgt über die Einbindung der Datei `/etc/varnish/hosts.vcl`. * In `/etc/varnish/hosts.vcl` werden wiederum lediglich weitere Seiten inkludiert:{{{ include "sites.d/example.org.vcl";}}} * Im anzulegenden Verzeichnis `/etc/varnish/sites.d` befinden sich dann die spezielle Seitenkonfiguration `example.org.vcl`:{{{ sub vcl_recv { if (req.http.host == "example.org") { set req.backend_hint = default; } include "sites.d/wordpress.vcl"; } sub vcl_backend_response { if (beresp.ttl == 120s) { set beresp.ttl = 1h; } } }}} * Hier werden folgende Sachen festgelegt: * Inkludieren der allgemeinen Wordpress-Konfiguration * Konfigurieren der Haltbarkeit der gecachten Sachen * Letzendlich sieht die `sites.d/wordpress.vcl` so aus:{{{ if (req.http.Upgrade ~ "(?i)websocket") { return (pipe); } if (req.url ~ "wp-admin|wp-login|login") { return (pass); } set req.http.cookie = regsuball(req.http.cookie, "wp-settings-\d+=[^;]+(; )?", ""); set req.http.cookie = regsuball(req.http.cookie, "wp-settings-time-\d+=[^;]+(; )?", ""); set req.http.cookie = regsuball(req.http.cookie, "wordpress_test_cookie=[^;]+(; )?", ""); if (req.http.cookie == "") { unset req.http.cookie; } if (req.method == "PURGE") { if (std.ip(req.http.x-real-ip, "0.0.0.0") ~ local) { return (purge); } else { return (synth(403)); } } }}} * Damit die ACL-Regel funktioniert und nur berechtigte IP-Adressen den Cache löschen können, muss der Reverse-Proxy den Header ''X-Real-IP'' setzen. * Zum automatischen Löschen der Caches bei Änderungen an der Seite kann das Plugin [[https://it.wordpress.org/plugins/varnish-http-purge/|Proxy Cache Purge]] verwendet werden. = Abschließende Hinweise = * In der obigen Apachekonfiguration wird mittels rewrite die Installation von eigenen Themes und Plugins unterbunden. Ergänzend dazu kann die Bearbeitung vorhandener Themes und Plugins im Dashboard verhindert werden:{{{ # wp-config.php ... define('DISALLOW_FILE_EDIT', true)}}} * Ein paar Abweichungen von den gängigen Anleitungen zur Einrichtung von PHP-FPM seien noch erwähnt: * Das Mounten oder Kopieren von `sendmail` in das chroot für Mailfunktionalität: Das funktioniert so nicht. Sendmail hat weitere Abhängigkeiten und braucht Zugriff auf verschiedene Verzeichnisse. Als Aternative wird [[https://www.acme.com/software/mini_sendmail/|mini_sendmail]] vorgeschlagen. Mittels der oben dargestellten PHP-FPM-Konfiguration wird `mail()` eh deaktiviert. Sendmail ist also in diesem Setup nicht notwendig. Der Mailversand aus Wordpress erfolgt mittels eines SMTP-Plugins. * Das Mounten oder Kopieren von `/etc/ssl/certs` in das chroot: Die Zertikate alleine reichen für die volle Funktionalität nicht aus. PHP benötigt zudem Zugriff auf `/usr/lib/ssl/openssl.cnf`. ---- '''Hinweise und Links''' * [[https://unix.wroclaw.pl/igort/en/php-fpm-chroot-fopen-url-problems.html|Validierung von Zertifikaten]] im chroot debuggen * Anpassen der [[https://www.getpagespeed.com/server-setup/nginx-and-php-fpm-what-my-permissions-should-be|Benutzerrechte]] für PHP-PFM * [[https://blog.kernl.us/2020/02/should-i-use-memcached-or-redis-for-wordpress-caching/|Performancevergleich]] zwischen Memcached und Redis * [[https://github.com/pantheon-systems/wp-redis|Doku]] zum WP-Redis-Plugin CategorySystemausfall '''Fussnoten''' |