Générer un certificat autosigné dans Debian et mapper les ports docker et hôte

Cet article fait suite à l’article sur la mise en place d’un serveur web Nginx et php-fpm, suivi de Postgresql.

J’avais déjà fait par le passé un blog sur comment configurer pour Apache un https, il suffisait de pointer vers les certificats SSL dans le fichier vhost

Un certificat autosigné ne sert que lors de la phase de développement. EN effet si vous l’utilisez en production, il y a aura des avertissements. Les certificats permettent une marque de confiance, donc d’une autorité tierce de confiance. De ce fait un certificat autosigné n’aura aucue valeur, puisuqe c’est l’éditeur de site qui le génère. Il faut que ce soit un tiers indépendant qui le fasse, comme par exemple Lets Encrypt. Ce dernier ne génère que des certificat ordinaires, mais utilisable en production. Si vous voulez des certificats plus qualitatifs, comme les certificats EV, il faudra les acheter sur des sites spécialisés.

Nous allons générer un certificat SSL autosigné

mkdir -p /etc/ssl/private/mycert && cd /etc/ssl/private/mycert

ou vous pouvez aller dans le répertoire mycert pour avoir une commande plus courte
cd /etc/ssl/private

mkdir -p /mycert && cd mycert

Le flag -p permet de créer les dossier parents manquant dans la commande mkdir

Génération du certificat (ce sont deux fichiers)

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout selfsigned.key \
  -out selfsigned.crt \
  -subj "/C=FR/ST=France/L=Paris/O=MonEntreprise/CN=localhost"
  • -x509 : pour un certificat autosigné.
  • -nodes : ne pas chiffrer la clé privée (pas de mot de passe).
  • -days 365 : durée de validité (365 jours).
  • -newkey rsa:2048 : crée une nouvelle clé RSA 2048 bits.
  • -keyout : chemin vers la clé privée.
  • -out : chemin vers le fichier de certificat.
  • -subj : informations du certificat.

Maintenant dans le répertoire mycert vous avez les fichiers selfsigned.crt et selfsigned.key

Modification du fichier de configuration Nginx qu’on a vu dans cet article

# Redirection HTTP vers HTTPS (optionnel mais recommandé)
server {
    listen 80;
    server_name phpsite;
    return 301 https://$host$request_uri;
}

# Bloc HTTPS avec certificat autosigné
server {
    listen 443 ssl;
    server_name phpsite;

    ssl_certificate     /etc/ssl/private/mycert/selfsigned.crt;
    ssl_certificate_key /etc/ssl/private/mycert/selfsigned.key;

    root /var/www/phpsite;
    index index.php index.html;

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass 127.0.0.1:9000;
    }
}

Votre site non https va rediriger vers le https.

$ curl https://phpsite/info.php
// néanmoins vous aurez un erreur de type 
curl: (60) SSL certificate problem: self-signed certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Ceci est dû au fait que ce soit un certificat autocertifié. Pour bypasser cette vérification, il faut rajouter le flag -k à la requête

curl -k https://phpsite/info.php

Redémarrer votre container docker et redémarrer les services

vous avez installé nginx, php-fpm, postgresql, et configuré votre vhost. Le soucis c’est la prochaine que vous faites un docker start <Id container> (après avoir stoppé votre container (ce ne sera pas le cas si vous fiates un exit de votre container), il faut redémarrer les services. Vous pouvez intégrer une commande

De même le vhost que vous avez ajouté dans /etc/hosts a disparu ! ceci est dû à la nature éphémère du container docker, mais heureusement il existe un flag pour ajouter le vhost quand vous faites un run

docker run -d \
  --name mon-site \
  -p 80:80 \
  --add-host=phpsite:127.0.0.1 \
  mon-image

// ce qui donne dans notre cas sauf qu'on est en mode interactif

docker run -it \
  --name phpsite \
  -p 80:80 \
  --add-host=phpsite:127.0.0.1 \
  debian-nginx

// il nous manque la commande bash pour démarrer php-fpm et nginx (remplacez le nom de l'image par votre image)
docker run -it \
  --name phpsite \
  -p 80:80 \
  --add-host=phpsite:127.0.0.1 \
  nginx_postgres_image \
  bash -c "/usr/sbin/php-fpm8.2 -F && nginx -g 'daemon off;'"


// ce qui donne en une seul ligne
docker run -it --name phpsite -p 80:80 --add-host=phpsite:127.0.0.1 nginx_postgres_image  bash -c "/usr/sbin/php-fpm8.2 -F && nginx -g 'daemon off;'"

// en non interactif
docker run -d --name phpsite -p 80:80 -p 443:443 --add-host=phpsite:127.0.0.1 nginx_postgres_image  bash -c "/usr/sbin/php-fpm8.2 -F && nginx -g 'daemon off;'"

Attention avec la syntaxe ci-dessus pour le bash bash -c « /usr/sbin/php-fpm8.2 -F && nginx -g ‘daemon off;' », ça ne va pas marcher car php-fpm étant lancé en foreground, il ne laissera pas la main à nginx pour démarrer, donc il faut remplacer le double && par le simple & , qui va lancer php-fpm en background

docker run -d --name phpsite -p 80:80 -p 443:443 --add-host=phpsite:127.0.0.1 nginx_postgres_image  bash -c "/usr/sbin/php-fpm8.2 -F & nginx -g 'daemon off;'"

On peut améliorer ceci en mettant dans un script bash. Nous pouvons aussi inclure le démarrage de postgresql afin d’avoir une stack complète pour développer.

Accéder au site phpsite depuis l’hôte

La partie intéressante est de se connecter à notre site dans docker depuis notre navigateur ou curl, car on a mappé les ports de docker et de l’hôte. Pour ce faire nous devons ajouter au fichier hosts de l’hôte : 127.0.0.1 phpsite.

//  depuis l'hôte

curl -k https://phpsite/info.php

// depuis votre navigateur vous aurez un avertissement de site non sécurisé, confirmez l'exception.

Prochaine étape nous allons plutôt explorer les volumes docker afin de pouvoir héberger les scripts php sur notre hôte.

Les volumes sous Docker c’est quoi?

C’est un répertoire sur l’hôte, qui sert à herberger des fichiers de code, mais accessible par le container docker, voyez ça comme un mount d’un drive sur un système de fichier Linux. Cela permet de travailler plus facilement et efficacement avec des container Docker. En effet notreIDE préféré est sur notre hôte et pas sur un container docker.

Dans la suite, mon répertoire se trouve dans le drive E: sur Windows dans le répertoire volume_nginx

docker run -d --name phpsite -p 80:80 -p 443:443 -v E:\volume_nginx:/var/www/phpsite --add-host=phpsite:127.0.0.1 nginx_postgres_image  bash -c "/usr/sbin/php-fpm8.2 -F & nginx -g 'daemon off;'"


// avec la ligne -v E:\volume_nginx:/var/www/phpsite on monte le répertoire hôte dans le container docker, du coup ce dernier va être masqué par le répertoire windows

// connextez vous en interactif dans le container en question

$ docker exec -it <idContainer> bash
// allez dans le répertoire /var/www/phpsite, il est vide pour l'instant mais créez un fichier index.php dedans et faites un ls vous verrez ce fichier. Félicitation vous avez réussi à connecter un volume ! 

Avouez que maintenant vous allez être beaucoup plus confortable pour faire un site web en php !

Générer un meilleur certificat SSL avec Let’s Encrypt

Avec une autorité externe les certificats sont de milleurs qualité. Let’s Encrypt délivre des certificats gratuitement et de grade production. MAIS il faut que votre site soit accessible depuis internet, car Let’s Encrypt va accéder à votre site pour installer des fichiers.

#installation de certbot
apt install certbot

# Génération du certificat
certbot certonly --webroot -w /var/www/html -d votre-domaine.com -d www.votre-domaine.com

Retour en haut