FreeBSD 12 & Nginx & Kirby CMS
freebsd, nginx, server, web
Damit ich nicht jedes Mal von Neuem suchen und zusammenpuzzlen muss (Quellen s.u.), wie man sein PHP CMS mit TLS usw. usf. aufsetzt, habe ich hier mal alle Schritte (Disclaimer: funktioniert so für mich, für die angegebenen Versionen) aufgelistet.
Nachdem ich meinen Server eingerichtet habe (in diesem Fall einen VPS mit FreeBSD 12) gehe ich erstmal sicher, dass mein System auf dem aktuellen Stand ist und installiere danach alle nötigen Pakete.
# freebsd-update fetch install
# pkg update && pkg upgrade -y
# pkg install -y sudo bash vim-console unzip wget \
nginx py37-certbot py37-certbot-nginx php73 \
php73-extensions php73-mbstring php73-curl \
php73-ctype php73-gd php73-json php73-filter
Um zu vermeiden, dass ich auf dem Server alles als root
machen muss, erstelle ich meinen eigenen Nutzer, füge ihn der wheel
-Gruppe hinzu und editiere die sudo
-config dahingehend, dass Nutzer der wheel
-Gruppe alle Befehle ausführen dürfen. Alsdann wechsle ich zu meinem neuen User und stelle die Zeitzone ein.
# adduser
...
group: wheel
...
# visudo
# uncomment %wheel ALL=(ALL) ALL
# su - $USER
$ sudo tzsetup
Weil Kirby ein PHP Programm ist, muss ich jetzt die lokale PHP und PHP-FPM Installation konfigurieren. Insbesondere muss ich dem FPM-Service sagen, dass er auf einem UNIX-Socket zuhören soll und welchen Nutzer- und Zugriffsrechten er unterliegt.
$ sudo ln -s /usr/local/etc/php.ini-production /usr/local/etc/php.ini
$ sudo vim /usr/local/etc/php-fpm.d/www.conf
...
listen = 127.0.0.1:9000 -> listen = /var/run/php73-fpm.sock
...
# uncomment:
listen.owner = www
listen.group = www
listen.mode = 0660
Ist das erledigt, aktiviere ich den php_fpm
-Service mit sysrc
, sodass er beim Server-Neustart automatisch angeschmissen wird.
$ sudo sysrc php_fpm_enable=yes
$ sudo service php-fpm start
Das gleiche mache ich dann schonmal mit Nginx, bevor es dann an die eigentlichen Einstellungen geht:
$ sudo sysrc nginx_enable=yes
$ sudo service nginx start
Hierfür erstelle ich ein permanentes Verzeichnis für die Website und gebe meinem Nutzer Zugriffsrechte darauf.
$ sudo mkdir -p /usr/local/www/$DOMAIN
$ sudo chown -R $USER:$GROUP /usr/local/www/$DOMAIN
Weil ich einige Anläufe und Hilfe aus dem Kirby-Forum dafür gebraucht habe, um die Config hinzubekommen, schreibe ich sie hier mal komplett hin, in der Hoffnung, dass es irgendjemand (im Zweifel ich) nützlich finden könnte.
Insbesondere leitet diese Config allen HTTP-Verkehr auf HTTPS um (weiter
unten richte ich dafür noch Let’s Encrypt ein), setzt einige
Rewrite-Regeln fest und konfiguriert das fastcgi.
$ sudo vim /usr/local/etc/nginx/$DOMAIN.conf
server {
listen 80;
listen [::]:80;
return 301 https://$DOMAIN$request_uri;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl;
server_name $DOMAIN www.$DOMAIN;
ssl on;
ssl_certificate /usr/local/etc/letsencrypt/live/$DOMAIN/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/$DOMAIN/privkey.pem;
root /usr/local/www/$DOMAIN;
index index.html index.php;
# don't hint these as folders
rewrite ^/(content|site|kirby)$ /error last;
# block content
rewrite ^/content/(.*).(txt|md|mdown)$ /error last;
# block all files in the site and kirby folder from being accessed directly
rewrite ^/(site|kirby)/(.*)$ /error last;
# site links
location / {
try_files $uri $uri/ /index.php?$uri&$args;
}
# prevent clients from accessing to backup/config/source files
location ~ (?:\.(?:bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)|~)$ {
deny all;
}
location ~ \.php$ {
try_files $uri = 404;
fastcgi_pass unix:/var/run/php73-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Damit die Config auch gelesen wird, muss ich jetzt noch include $DOMAIN.conf;
in den http
-Block der Original-nginx.conf
schreiben.
Let’s Encrypt hat es innerhalb von kurzer Zeit möglich gemacht, dass man einfach, kostenlos und automatisiert den Verkehr zu seinem Webserver mit TLS verschlüsseln kann. Es gehört mittlerweile zum guten Ton, das in jedem Fall zu tun, auch wenn http
ausreichen würde. Da mein CMS aber eine Login-Funktion hat und also Benutzerdaten und Passwörter über die Leitungen geschickt werden, will ich meinen Traffic auf jeden Fall verschlüsseln.
certbot
ist das offizielle Skript von Let’s Encrypt, das die Automatisierung der ganzen Zertifikats-Angelegenheiten möglich macht. Hier noch eine kleine FreeBSD-Besonderheit, auf die ich erstmal kommen musste: dort heißt nicht nur das Paket certbot-36
sondern auch die Binary. (Anm. 2019-09-14: Anscheinend ist dem nicht mehr so! Die folgenden Anweisungen habe ich unten entsprechend korrigiert. Anm. 2020-04-24: Der Port heißt jetzt py37-certbot
und ist um einiges aktueller. Das Upgrade geschieht aber nicht von selbst, also py36-certbot*
deinstallieren, py37-certbot{-nginx}
installieren. Außerdem gibt es jetzt eine Konfiguration zum automatischen Aktualisieren in /etc/periodic.conf
, nämlich weekly_certbot_enable="YES"
)
Die folgenden Zeilen erstellen dann Zertifikate für die beiden angegebenen Domains, testen im Trockenen ob das Erneuern auch funktioniert und erneuern sie.
$ sudo certbot certonly --webroot -w /usr/local/www/$DOMAIN -d $DOMAIN -d www.$DOMAIN
$ sudo certbot renew --dry-run
$ sudo certbot renew
Da die Let’s Encrypt-Zertifikate nur ein paar Monate am Stück gültig sind, richten wir noch einen crontab
ein, der in zufälligen Abständen unsere Zertifikate erneuert.
$ crontab -e
0 0,12 * * * python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew
Wenn bis hierhin alles gut gegangen ist, wird sich Nginx beim Testen der Config nicht beschweren und durch’s Neustarten setzen wir alle Änderungen in Kraft.
$ sudo nginx -t
$ sudo service nginx reload
Jetzt sind wir endlich da angekommen, wo wir die ganze Zeit hinwollten: wir können Kirby installieren! Dafür laden wir uns die neueste Version auf den PC, bauen unsere Website und benutzen dann unser liebstes sftp/scp-Tool (nicht vergessen, die ssh/ftp-daemons einzurichten!) um die Dateien in das Verzeichnis zu laden, das wir oben erstellt haben.
Sollte jetzt alles funktionieren, geben wir dem Webserver (bzw. dem Nutzer, der den Webserver ausführt) noch die Verfügung über das Verzeichnis.
$ sudo chown -R www:www /usr/local/www/$DOMAIN
Quellen