J’ai récemment voulu héberger un mediawiki sur mes serveurs openbsd, voici un résumé des étapes.
Les outils utilisés :
Installation des programmes qu’il faut :
pkg_add php56_fpm nginx mariadb-server
Premièrement, la configuration du serveur web nginx : pour l’instant sans la partie sécurisée.
# nginx, changer "domain" par votre nom de domaine
server {
listen 80;
listen [::]:80;
server_name domain www.domain;
location /.well-known/acme-challenge {
alias /htdocs/challenges/;
location ~ /.well-known/acme-challenge/(.*) {
add_header Content-Type application/jose+json;
}
}
location / {
rewrite ^ https://domain$request_uri? permanent;
}
}
Nginx est mis en chroot
, donc les programmes n’ont pas accès à la résolution de noms si le fichier resolv.conf
n’est pas copié dans le chroot.
mkdir /var/www/etc/
cp /etc/resolv.conf /var/www/etc/
Let’s encrypt : téléchargement d’un programme qui permet de faire signer notre certificat.
# changez partout "domain" par votre nom de domaine
cd /etc/ssl/
git clone https://github.com/diafygi/acme-tiny.git
# création d'une clé de compte
openssl genrsa 4096 > account.key
# générer une clé de domaine
openssl genrsa 4096 > domain.key
# pour un seul domaine
openssl req -new -sha256 -key domain.key -subj "/CN=domain" > domain.csr
# répertoire où se trouveront les fichiers de test
mkdir /var/www/htdocs/challenges
#run the script on your server
python3.5 acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /var/www/htdocs/challenges/ > ./signed.crt
wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > intermediate.pem
cat signed.crt intermediate.pem > chained-domain.pem
rcctl restart nginx
La partie sécurisée de la configuration de nginx, maintenant qu’on a notre certificat ça va bien se passer.
# nginx, changer "domain" par votre nom de domaine
server {
listen 443;
listen [::]:443;
server_name domain www.domain;
root /var/www/htdocs/domain/;
index index.php index.html;
ssl on;
ssl_certificate /etc/ssl/le/chained-domain.pem;
ssl_certificate_key /etc/ssl/le/domain.key;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:1m;
ssl_ciphers HIGH:!aNULL:!MD5:!RC4;
ssl_prefer_server_ciphers on;
location / {
root /var/www/htdocs/domain/;
}
location ~ \.php$ {
try_files $uri $uri/ =404;
fastcgi_pass unix:/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location /.well-known/acme-challenge {
alias /htdocs/challenges/;
location ~ /.well-known/acme-challenge/(.*) {
add_header Content-Type application/jose+json;
}
}
}
Configuration de php : on rajoute des extensions pour mediawiki et on ajoute des lignes dans le fichier /etc/php-5.6.ini
.
# installation de bibliothèques pour PHP
pkg_add php-gd-5.6 php-intl php-xcache
# fichier /etc/php-5.6.ini
extension=curl.so
extension=gd.so
extension=intl.so
extension=mysql.so
# redémarrer PHP FPM
rcctl restart php56_fpm
# vérifier les extensions disponibles, voir si ça a été pris en compte
php-5.6 -m
Les modules installés se trouvent dans /usr/local/lib/php-5.6/modules/intl.so
.
Ensuite, j’ai voulu installer un mariadb, pour ça j’ai simplement suivi mes propres conseils de la page dédiée à l’installation d’un mysql, cette fois en changeant mysql-server
par mariadb-server
.
Ensuite, quelques commandes pour mettre en place la BDD telle qu’on la voudrait :
# le % est là pour indiquer que cet utilisateur peut se connecter à partir de n'importe-quelle adresse IP
# mettre "localhost" si votre sgbd est sur la même machine que le serveur web
create database dbname;
create user username@"%";
set password for username@"%" = password('your-password');
grant all on username.* to dbname@"%";
Enfin, si votre sgbd est sur une autre machine, il faut qu’il accepte les connexions non locales. Pour ça on va dans le fichier /etc/my.cnf
et on modifie la ligne bind-address
par :
bind-address = 0.0.0.0
Ensuite, pour mettre à jour les certificats, je me suis fait un script que j’ai mis dans /etc/ssl/le/renew-certs.sh
:
#!/usr/bin/sh
DOMAIN=$1
LEDIR=/etc/ssl/le
ACMEDIR=/var/www/htdocs/challenges
python3.5 ./acme-tiny/acme_tiny.py --account-key $LEDIR/account.key --csr $LEDIR/$DOMAIN.csr --acme-dir $ACMEDIR > tmpsigned.crt || exit
ftp -o intermediate.pem https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem
cat tmpsigned.crt intermediate.pem > $LEDIR/chained-$DOMAIN.pem
rm tmpsigned.crt
Puis un script que j’ai placé dans /usr/local/bin/update-domain-certs
pour lancer mes autres scripts.
# /usr/local/bin/update-domain-certs
#!/bin/sh
LEDIR=/etc/ssl/le
cd $LEDIR || exit 1
sh ./renew-certs.sh domain1 || exit 2
sh ./renew-certs.sh domain2 || exit 2
# ...
Pour lancer le script précédent, les droits de l’utilisateur www
suffisent, donc on configure doas :
# /etc/doas.conf
permit nopass keepenv root as www cmd /usr/local/bin/update-domain-certs
Et pour que ça se fasse tous les mois (donc largement avant la limite des 90 jours pour l’expiration des certificats let’s encrypt), il suffit de faire appel à cron :
# fichier /etc/monthly.local
doas -u www /usr/local/bin/update-domain-certs && rcctl reload nginx
Je ne détaille pas l’installation de mediawiki, je pense qu’il n’y a pas grand chose à dire. Le site est à mettre dans le répertoire /var/www/htdocs/domain/
.
Pour conclure je dirais que vivement que httpd gère SNI. La configuration devrait être encore plus légère et simple côté serveur web, et je serai un peu plus confiant puisque le développement est fait par des gens d’openbsd. fanboy detected.