J'aime bien OpenBSD. Malgré sa réputation de vieux système Unix implacable sur la sécurité, il est d'une simplicité déconcertante, cohérent, et bien documenté. Un inconvénient tout de même était la difficulté d'installer les mises à jour (il fallait télécharger et décompresser soi-même les sets, ou booter sur un CDROM) mais ce point a enfin été résolu avec syspatch et sysupgrade. Mettre à jour OpenBSD est désormais aussi simple que n'importe quelle distribution Linux !
Sachez qu'il est possible d'installer OpenBSD chez hetzner, car l'hébergeur fournit un accès kvm (même sur les serveurs virtuels à bas prix) et permet de piocher dans une bibliothèque d'ISOs bootables. NixOS, Arch, FreeBSD, ... et OpenBSD. Un gros +1 pour Hetzner qui laisse cette liberté aux utilisateurs (et en plus ils ont un provider Terraform, si ça c'est pas qualitatif...).
J'ai donc installé un petit serveur OpenBSD afin d'héberger 1 ou 2 sites statiques pour un side project. Le but était surtout de m'amuser et utiliser httpd, le serveur web builtin de ce système d'exploitation.
Commençons par parler des points positifs. OpenBSD et httpd sont très simples à configurer, la lecture des manpage est presque suffisante en soit, alors que pour Linux je commence toujours par regarder des exemples, avant d'attaquer la documentation. Un client acme est également intégré dans le système, il n'y a rien besoin d'installer pour se générer des certificats Let's Encrypt. Et... c'est à peu près tout. Je pourrais dire que httpd est léger et sécurisé, mais quand il s'agit de servir des contenus statiques, c'est à peu près toujours le cas.
Passons maintenant aux points négatifs. Tout d'abord, il y a cette blague (pas drôle) des messages d'erreur en Comic Sans MS (et oui) dont on peut heureusement se débarrasser, au prix d'une petite bidouille. Mais ça ce n'est pas grand chose, car le plus gros problème avec httpd selon moi, c'est qu'il ne fait vraiment pas grand chose, à part servir des pages web. Par exemple il n'est pas possible de spécifier de Header set Cache-Control "max-age=604800, public"
, qui permet d'indiquer aux navigateurs qu'ils doivent mettre en cache les ressources statiques. Et ça se ressent fortement sur le temps de chargement de vos pages.
En fait, httpd a besoin d'être complété par relayd, un reverse-proxy beaucoup plus complet. Le problème est que sa configuration est un poil plus complexe, et que ça m'ennuie un peu d'avoir un reverse-proxy sur la même machine tout ça pour ajouter un simple header dans les réponses. Au final, je suis resté sur du 100% httpd, sans le cache, et mes sites ont du se contenter de performances honorables mais pas optimales.
Aujourd'hui l'expérience est terminée, et j'ai re migré mes sites statiques vers NixOS + Apache.
I have been playing with OpenBSD and httpd lately. It's a really simple and fun webserver to use, despite suffering huge limitations, but I quickly stumble across this horror:
No joke. httpd will serve all errors messages with the infamous Comic sans ms font. It's probably a troll from the maintainers, at least I hope so. Comic sans ms sucks, I don't want that on my server. Fortunately, there is a simple way to disable it.
Add this line into your /etc/httpd.conf:
errdocs "/errdocs"
Then create the file /var/www/errdocs/err.html with the following content:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>$RESPONSE_CODE $HTTP_ERROR</title>
<style type="text/css"><!--
body { background-color: white; color: black; }
hr { border: 0; border-bottom: 1px dashed; }
@media (prefers-color-scheme: dark) {
body { background-color: #1E1F21; color: #EEEFF1; }
a { color: #BAD7FF; }
}
--></style>
</head>
<body>
<h1>$RESPONSE_CODE $HTTP_ERROR</h1>
<hr>
<address>$SERVER_SOFTWARE</address>
</body>
</html>
Then restart httpd:
rcctl restart httpd
Explanation: httpd manage says:
A custom error document may contain the following macros that will be expanded at runtime:
$HTTP_ERROR
The error message text.
$RESPONSE_CODE
The 3-digit HTTP response code sent to the client.
$SERVER_SOFTWARE
The server software name of httpd(8).
So I just took the source code of a 404 error page, removed the Comic sans ms part in the CSS and replaced the values (error code, message, server identity) by the proper variables. Now all errors messages should be generated with this new template, with a fallback font.
Je connais bien OpenBSD pour y avoir fait tourner mon serveur pendant plusieurs mois. J'en ai un bon souvenir, c'est un système simple à comprendre et à configurer grâce à des syntaxes humainement lisibles dans les fichiers de configuration. Malheureusement OpenBSD est encore primitif sur de nombreux points, par exemple les mises à jour. En fait il n'y a aucun dispositif de mise à jour, il faut télécharger les sets en .tgz et les décompresser en écrasant le système, voire même tout recompiler. Deux autres problèmes majeurs que je vois sont d'une part le fs UFS vieillissant et lent (surtout si on compare à FreeBSD et son ZFS) et d'autre part les ports pas toujours à jour car il y a beaucoup moins de mainteneurs disponibles. C'est pourquoi je pense qu'OpenBSD est bien pour certains usages spécialisés qui peuvent se contenter des daemons de base, mais dans beaucoup d'autres cas il se fait éclater par FreeBSD et Linux, par exemple en usage stockage ou desktop.
A l'époque où j'utilisais OpenBSD (2011), le daemon web était un Apache 1.x lourdement modifié et le projet était en cours de migration vers Nginx. Mais ce dernier a été délaissé à son tour au profil de httpd, un serveur maison. Je n'y ai pas vraiment prêté attention jusqu'à récemment avec la lecture du blog de thuban (ou encore De l'épice pour la pensée) qui m'a rendu curieux. Thuban est tellement amoureux d'OpenBSD que quelques temps après l'avoir essayé, il a migré son serveur et écrit un livre.
Exemple simple
Puisqu'on est sur OpenBSD, la configuration sera forcément humainement lisible et centralisée dans un fichier. Le manpage est consultable ici. OMG UN MANPAGE, MER IL ET FOU ! Et oui, sur Linux les manpage sont souvent imbuvables, mais sur OpenBSD ce n'est pas le cas. Pas de panique, on va faire un exemple ensemble :)
On va simplement configurer notre httpd pour servir une page lorsque l'IP du serveur est appelée.
Voici ce qu'on met dans notre /etc/httpd.conf :
server "default" {
listen on * port 80
}
Par défaut, notre serveur travaillera dans /var/www/htdocs et /var/www/logs. On créé une page html de test :
echo "Hello" > /var/www/htdocs/index.html
On autorise httpd à démarrer :
echo httpd_flags="" >> /etc/rc.conf.local
Puis on démarre httpd :
/etc/rc.d/httpd start
En tapant l'adresse IP du serveur dans votre navigateur, vous devriez avoir le Hello sur fond blanc.
Vous pouvez éventuellement jeter un œil aux fichiers de logs :
cat /var/www/logs/access.log
default 192.168.0.3 - - [01/Aug/2016:14:13:14 +0200] "GET / HTTP/1.1" 200 31
Exemple avancé
Afin d'explorer les possibilités de httpd, on va le triturer de la manière suivante :
- Écriture des logs dans /var/log/httpd/
- Fichiers de configuration splittés
- Deux vhosts
- https sur un des vhosts
Commençons par créer les arborescences pour nos deux vhosts, avec deux fichiers index.html :
mkdir /var/www/htdocs/site1
echo "Site1" > /var/www/htdocs/site1/index.html
mkdir /var/www/htdocs/site2
echo "Site2" > /var/www/htdocs/site2/index.html
On créé aussi le répertoire pour les logs et pour nos fichiers splités :
mkdir /var/log/httpd
chown -R www: /var/log/httpd
mkdir /etc/httpd
On génère notre certificat de sécurité :
openssl req -new -x509 -days 365 -nodes -out /etc/ssl/cert.pem -keyout /etc/ssl/key.pem
chmod 600 /etc/ssl/key.pem
ls -l /etc/ssl/*.pem
-r--r--r-- 1 root bin 1180 Aug 1 22:46 /etc/ssl/cert.pem
-rw------- 1 root wheel 1704 Aug 1 22:46 /etc/ssl/key.pem
On édite notre /etc/httpd.conf dans lequel on va définir nos paramètres globaux, ainsi que nos fichiers splittés de vhost :
chroot "/var/www"
logdir "/var/log/httpd"
include "/etc/httpd/site1.conf"
include "/etc/httpd/site2.conf"
Note : la ligne chroot est inutile ici car sa valeur par défaut est déjà /var/www néanmoins je trouve utile de la préciser, par souci de lisibilité.
/etc/httpd/site1.conf :
server "default" {
listen on * port 80
root "/htdocs/site1"
}
/etc/httpd/site2.conf :
server "ssl" {
listen on * tls port 443
root "/htdocs/site2"
tls certificate "/etc/ssl/cert.pem"
tls key "/etc/ssl/key.pem"
}
Note : root doit être un chemin relatif au chroot. Par exemple le /htdocs/site2 se rapporte implicitement à /var/www/htdocs/site2.
Après avoir rechargé httpd, l'accès à notre serveur en http (port 80) doit afficher le site 1 :
Et l'accès en https (port 443) doit afficher le site 2 :
Conclusion
httpd est un serveur web simple à prendre en main qui ne plaisante pas avec la sécurité, le chroot ayant une place importante dans son fonctionnement. Alors faut-il laisser tomber Apache et Nginx ? Pour un usage basique, c'est à dire servir des pages web, pourquoi pas, car c'est simple et robuste. En revanche, pour des usages avancés, non. À part renvoyer les requêtes dans un socket en fastcgi et servir du contenu statique, on ne peut pas faire grand chose. Pas de reverse proxy par exemple, ce rôle étant confié à relayd. Un autre point agaçant est le fait qu'en cas d'erreur le daemon httpd refuse de démarrer mais n'affiche aucune erreur et ne produit aucun log, donc bonne chance pour debugger.
Si vous êtes un amoureux d'OpenBSD, il est évident que vous ne tarderez pas à migrer vers httpd. Si vous n'êtes qu'un simple Linuxien, j'espère que cet article aura chatouillé votre curiosité.