Hinweis: Neben den Anleitungen im Rahmen dieser Serie habe ich mittlerweile fertige Shell Scripte erstellt, die quasi voll automatisch die Installation eines Servers für euch übernehmen. Ihr findet das Ganze auf github.de, wobei ihr entweder den ganzen Server per Script aufsetzen und konfigurieren lassen könnt, oder eben jeden einzelnen Schritt, wie z.B. das Absichern des Servers, oder das Installieren eines LEMP Stacks, mit Hilfe der jeweiligen Scripte erledigen könnt. Die Scripte entsprechen quasi 1:1 zu den Tutorials.
Redis und Co. Cache me if you can!
Es gibt wohl heutzutage nichts nervigeres im Internet, also langsam ladende Websites. Okay, zugegeben, mit Werbung überladende Seiten sind auch kein Hit! Beides führt mitunter dazu, dass die Leute direkt abspringen und stattdessen eine andere Seite aufrufen. Die Ladezeiten eurer Website hängen von einer Vielzahl an Faktoren ab, wovon wir uns heute einen dieser Faktoren mal genauer angucken wollen. Das Caching.
Cache bedeutet nichts anderes, als einen schnellen Zwischenspeicher. Satt also immer und immer wieder neu irgendwelche Dinge zu berechnen, aus einer Datenbank auszulesen, etc. werden die Ergebnisse aller früheren Abfragen local zwischengespeichert, entweder irgendwo auf der Festplatte des Servers, vorzugsweise einer SSD, oder am besten direkt im RAM, je nachdem, welche Methode zum Einsatz kommt.
WordPress z.B. setzt auf PHP. Im Normalfall werden bei jedem Seitenaufruf die Seiten anhand des PHP Codes für den Besucher neu generiert. Wenn es sich dabei jetzt aber nicht um dynamischen Content handelt, wie z.B. ein Video oder dergleichen, reicht es im Prinzip aus, wenn diese Seite ein einziges Mal von eurem Webserver generiert wird. Die fertig generierte Seite wird also zwischengespeichert und steht jedem erneuten Besucher direkt zur Verfügung. Das Spart nicht nur Zeit, sondern auch Ressourcen. Eine dieser Möglichkeiten, dynamische Seiten in Form von statischen Seiten zwischenzuspeichern ist z.B. der fastcgi_cache von nginx. Wie genau dieser für WordPress und Co konfiguriert wird, werden wir uns zu einem späteren Zeitpunkt, im Rahmen der WordPress Installation angucken.
Was wir aber heute machen werden, sind die gängigen, oder zumindest in meinen Augen sinnvollen Caching Methoden, welche auch später in weiteren Tutorials zum Einsatz kommen werden, zu installieren, bzw. zu konfigurieren.
Redis – In-Memory-Datenbank
Bei Redis handelt es sich im eine sog. NoSQL-Datenbank, welche zwar keine komplexen Strukturen wie eben SQL Datenbanken speichern kann, aber dafür wesentlich schneller arbeitet. Ein weiterer Vorteil ist, dass der Redis Server komplett aus dem RAM heraus agiert. Das hat zwar den Nachteil, dass der Cache im Zweifel bei einem ungewollten Neustart des Systems leer ist, sorgt aber auch dafür, dass Anfragen viel schneller beantwortet werden, als beispielsweise von einer SSD oder gar einer HDD.
Auf Grund der Komplexität eignet sich Redis also nicht unbedingt für das Zwischenspeichern kompletter Websites, sondern eher als Object Cache, für einzelne Anfragen. Wir werden Redis aus diesem Grund hauptsächlich nutzen, um Datenbankabfragen zu cachen. Statt also immer und immer wieder Werte aus der SQL Datenbank abzurufen, werden diese mit Hilfe von Redis zwischengespeichert, wobei Redis über keine frei definierbaren Datenbanken wie z.b. MySQL verfügt, sondern lediglich numerische Datenbanken, d.h. mit den Namen 0, 1, 2 … etc. besitzt. Für den Fall, dass man mehrer Datenbanken simultan auf einem Server verwendet, sollte man sich also evtl. irgendwo Notizen dazu machen, welche Datenbank welche Werte zwischenspeichert.
Installation
Wie so oft gibt es auch bei der Installation des Redis Servers verschieden Möglichkeiten. Wir werden im Rahmen des Tutorials allerdings nur die manuelle Installation mit Hilfe der Source Files durchgehen da diese im Gegensatz zu allen anderen Optionen immer die aktuellste Version beinhalten.
Zunächst laden wir hierfür die passenden files herunter, entpacken sie und compilieren, bzw. installieren anschließend den Redis-Server.
Auf den „PREFIX=/usr“ kann theoretisch auch verzichtet werden, die Redis files werden dann statt im Ordner /usr/bin, unter /usr/local/bin abgelegt. Achtet nur am Ende bei der Konfiguration darauf, welchen Pfad ihr gewählt habt.
wget http://download.redis.io/redis-stable.tar.gz tar -xzf redis-stable.tar.gz cd redis-stable make make PREFIX=/usr install cd ..
Die „Installation“ in diesem Sinne ist nun eigentlich fertig, allerdings benötigen wir für die anschließende Konfiguration noch einige Ordner, bzw. Rechte. Da es unklug wäre, den Redis-Server unter dem root user laufen zu lassen, da sonst kein anderer Systembenutzer, wie z.B. www-data später Zugriff darauf hätte, legen wir zusätzlich einen neuen Benutzer, bzw. eine neue Gruppe an, zu der wir auch direkt www-data als Nutzer hinzufügen.
adduser --system --group --no-create-home redis usermod -g www-data redis mkdir /etc/redis mkdir /var/lib/redis mkdir /var/log/redis touch /var/log/redis/redis.log chown -R redis:redis /etc/redis chown -R redis:redis /var/lib/redis chown -R redis:redis /var/log/redis
Für die spätere Kommunikation mit php, installieren wir an dieser Stelle gleich schon mal die Erweiterung php-redis.
apt-get install -y php-redis
Konfiguration
Kommen wir nun zur Konfiguration unseres Redis Servers. Hier haben wir zwei Möglichkeiten, Redis kann entweder per TCP Port erreichbar sein, oder aber per UNIX Socket. Beides Zusammen ist eher weniger Sinnvoll.
Da die Kommunikation via UNIX Socket in der Regel etwas schneller läuft, also übe den TCP Port, ist dieser in meinen Augen immer die bessere Wahl, auch weil der Socket nicht von Außen erreichbar ist und das ganze System somit in sich geschlossen ist. Für den Fall, dass ihr aber lieber den TCP Port verwenden möchtet, weil ihr z.B. Redis auf einem extra Server laufen lassen wollt, werde ich beide Konfigurationen kurz erklären.
Option 1: UNIX Socket
Wir könnten zwar auch das automatische Konfigurations-Script benutzen, erstellen die Config aber lieber von Hand. Hierzu kopieren wir die Beispiel-Config in unser zuvor erstelles redis Verzeichnis.
cp redis-stable/redis.conf /etc/redis/redis.conf
Diese Config können wir nun manuell editieren, oder aber eben wie bereits in zurückliegenden Tutorials, mit Hilfe von sed.
sed -i 's/^logfile .*/'"logfile \/var\/log\/redis\/redis.log/g" /etc/redis/redis.conf sed -i 's/^dir .*/'"dir \/var\/lib\/redis/g" /etc/redis/redis.conf sed -i 's/^pidfile .*/'"pidfile \/var\/run\/redis\/redis-server.pid/g" /etc/redis/redis.conf sed -i 's/^port .*/'"port 0/g" /etc/redis/redis.conf sed -i 's/^# unixsocket .*/'"unixsocket \/var\/run\/redis\/redis.sock/g" /etc/redis/redis.conf sed -i 's/^# unixsocketperm .*/'"unixsocketperm 770/g" /etc/redis/redis.conf sed -i 's/^daemonize .*/'"daemonize yes/g" /etc/redis/redis.conf
Option 2: TCP Port
Die Konfiguration läuft ähnlich ab. Wir kopieren zunächst die config und editieren sie.
cp redis-stable/redis.conf /etc/redis/redis.conf sed -i 's/^logfile .*/'"logfile \/var\/log\/redis\/redis.log/g" /etc/redis/redis.conf sed -i 's/^dir .*/'"dir \/var\/lib\/redis/g" /etc/redis/redis.conf sed -i 's/^pidfile .*/'"pidfile \/var\/run\/redis\/redis-server.pid/g" /etc/redis/redis.conf sed -i 's/^port .*/'"port 6379/g" /etc/redis/redis.conf sed -i 's/^daemonize .*/'"daemonize yes/g" /etc/redis/redis.conf
Da unser Redis Server nun aber via TCP Port online erreichbar ist, also ein potentielles Angriffsziel, benötigen wir noch ein sicheres Passwort. Dieses generiere ich automatisch und füge es der Config hinzu.
redis_secure=$(date +%s | sha256sum | base64 | head -c 32; echo) sed -i 's/^# requirepass .*/'"requirepass $redis_secure/g" /etc/redis/redis.conf echo "Dein Redis Passwort: $redis_secure"
Die Ausgabe „Dein Redis Passwort: ….“ solltest du dir am besten irgendwo notieren, da du das Passwort später immer wieder benötigst, um mit deinem Redis Server zu kommunizieren.
Hinweis: Solltest du vergessen haben das Passwort zu notieren, kannst du es auch einfach jeder zeit in der /etc/redis/redis.conf unter „requirepass“ nachlesen können.
Systemstart
Damit Redis auch nach einem Reboot wieder startet, bzw. um den Redis Server komfortabler zu administrieren, benötigen wir noch ein passendes Service script.
cat > /lib/systemd/system/redis.service <<EOF [Unit] Description=Advanced key-value store After=network.target Documentation=http://redis.io/documentation, man:redis-server(1) [Service] Type=forking ExecStart=/usr/bin/redis-server /etc/redis/$redis_conf ExecStop=/bin/kill -s TERM \$MAINPID PIDFile=/var/run/redis/redis-server.pid TimeoutStopSec=0 Restart=always User=redis Group=www-data RuntimeDirectory=redis RuntimeDirectoryMode=2755 UMask=007 PrivateTmp=yes LimitNOFILE=65535 PrivateDevices=yes ProtectHome=yes ReadOnlyDirectories=/ ReadWriteDirectories=-/var/lib/redis ReadWriteDirectories=-/var/log/redis ReadWriteDirectories=-/var/run/redis NoNewPrivileges=true CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE MemoryDenyWriteExecute=true ProtectKernelModules=true ProtectKernelTunables=true ProtectControlGroups=true RestrictRealtime=true RestrictNamespaces=true RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX # redis-server can write to its own config file when in cluster mode so we # permit writing there by default. If you are not using this feature, it is # recommended that you replace the following lines with "ProtectSystem=full". ProtectSystem=true ReadWriteDirectories=-/etc/redis [Install] WantedBy=multi-user.target Alias=redis.service EOF
Anschließend sorgen wir dafür, dass der Server das Script auch findet und aktivieren Redis beim Systemstart.
ln -s /lib/systemd/system/redis.service /etc/systemd/system/redis.service systemctl daemon-reload systemctl start redis systemctl enable redis
So, das wars auch schon. Nun sollte Redis eigentlich ohne Probleme auf eurem Server laufen.
Aufräumen nicht vergessen.
rm redis-stable.tar.gz rm -rf redis-stable
Testen
Falls ihr überprüfen wollt, ob alles funktioniert habt, könnt ihr das mit Hilfe des „redis-cli“ scripts.
redis-cli ping [Redis Server per TCP Port, ohne Passwort] redis-cli -a <passwort> [Redis Server per TCP Port, mit Passwort] redis-cli -s /var/run/redis/redis.sock ping [Redis Server per Socket]
In jedem Fall sollte die Antwort „PONG“ lauten.
APCu – APC User Cache
APCu ist quasi der Nachfolger von APC – Alternative PHP Cache. APC fungierte zum einen als PHP-Beschleuniger, indem Bytecode im RAM ausgelagert wurde und zum anderen bot es einzelnen PHP Apps die Möglichkeit selbst Daten zu cachen. Die Aufgaben des PHP-Beschleunigers übernimmt mittlerweile OPcache, welches von Haus aus mit PHP zusammen ausgeliefert wird und das Cachen übernimmt nun eben APCu. Aufwendige Datenbankabfragen lassen sich z.B. mit APCu in den Zwischenspeicher legen, was wertvolle Zeit einspart.
Installation
APCu wird leider aktuell nicht als Modul für php7.2 per apt angeboten, weswegen wir es ebenfalls, wie Redis, aus dem Source compilieren.
git clone https://github.com/krakjoe/apcu cd apcu phpize ./configure make make install
Aufräumen nicht vergessen.
rm -rf apcu
Eine weitere Möglichkeit wäre die Installation via PECL.
apt-get install -y php-pear pecl install apcu
Bitte aber nur auf einem Weg installieren!
Konfiguration
Die Konfiguration erledigen wir wieder schnell mit Hilfe von sed via Console. Nicht vergessen php-fpm anschliend neuzustarten.
echo "extension = apcu.so" | tee -a /etc/php7.2/mods-available/apcu.ini ln -s /etc/php7.2/mods-available/apcu.ini /etc/php7.2/fpm/conf.d/30-apcu.ini ln -s /etc/php7.2/mods-available/apcu.ini /etc/php7.2/cli/conf.d/30-apcu.ini ln -s /etc/php7.2/mods-available/apcu_bc.ini /etc/php7.2/fpm/conf.d/30apcu_bc.ini ln -s /etc/php7.2/mods-available/apcu_bc.ini /etc/php7.2/cli/conf.d/30apcu_bc.ini service php7.2-fpm restart
Um zu überprüfen, ob alles funktioniert habt, könnt ihr den Befehl php -m benutzen. Der Output sollte in etwas so aussehen, wobei der Eintrag APCu relevant ist.
root@xf0:~# php -m [PHP Modules] apcu bcmath bz2 calendar Core ctype curl date dom exif fileinfo filter ftp gd gettext hash iconv igbinary intl json libxml mbstring mysqli mysqlnd openssl pcntl pcre PDO pdo_mysql Phar posix readline redis Reflection session shmop SimpleXML sockets sodium SPL standard sysvmsg sysvsem sysvshm tokenizer wddx xml xmlreader xmlwriter xsl Zend OPcache zip zlib [Zend Modules] Zend OPcache
OPcache – On Board Bescheleunier
Wie bereits im vorherigen Schritt erklärt, ist OPcache fester Bestandteil von PHP und fungiert als Beschleuniger. Klingt erst mal ganz gut, ne? Leider aber wird OPcache weder von Haus aus aktiviert, noch konfiguriert. Beides lässt sich aber mit wenigen Handgriffen, bzw. einem copy&paste Befehl beheben.
cat >> /etc/php/php7.2/fpm/conf.d/10-opcache.ini <<EOF opcache.enable=1 opcache.enable_cli=1 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=10000 opcache.memory_consumption=128 opcache.save_comments=1 opcache.revalidate_freq=1 EOF service php7.2-fpm restart
So, damit wären wir auch schon durch. Ihr habt nun 3, bzw. wenn man fastcgi_cache aus dem LEMP Tutorial hinzuzählt, 4 Cache Möglichkeiten, welche sich für unterschiedliche Einsatzzwecke eignen.
Hallo,
die Seite mit WordPress funktioniert nicht. Besteht die Möglichkeit diese wieder herzustellen?
Besten Dank