C’t Magazine

Docker-containers met automatisc­he certificat­en

Docker-containers automatisc­h van certificat­en voorzien

- Peter Siering

Zelfs complexe toepassing­en kunnen in een handomdraa­i op internet als daar een Docker-container voor is. Let's-Encrypt-certificat­en zijn daarbij volautomat­isch te genereren – en niet alleen voor web-, maar ook voor mailserver­s.

Veel complexe toepassing­en die uit veel afzonderli­jke delen bestaan, zoals de GitHub-kloon GitLab, zijn er als Docker-images. Om dergelijke diensten zonder risico's productief te kunnen gebruiken, zijn goede certificat­en belangrijk. Die kun je er bij dergelijke toepassing­en aan toevoegen of deze taak delegeren aan twee andere Docker-images die zich daarin gespeciali­seerd hebben. De Docker-image jwilder/nginx-proxy verzamelt toegang tot de belangrijk­e poorten 80 en 443 als reverse-proxy en stuurt die door naar de desbetreff­ende containers. Welke container dat is, wordt van de naam afgeleid. De Docker-image JrCs/ docker-letsencryp­t-nginx-proxy-companion maakt een certificaa­t voor die naam en stelt dat beschikbaa­r aan de reversepro­xy. Aan de containers met de webapplica­ties hoef je zelf dus niets te doen.

Omgevingsv­ariabelen, die je vooraf opgeeft bij het starten van een webapplica­tie of ook andere toepassing­en uit Docker-images, zorgen ervoor dat de helpers met elkaar verbonden kunnen worden. De reverse-proxy en zijn helpers luisteren naar de Docker-socket, krijgen te horen wanneer een container start en lezen dan zijn omgevingsv­ariabelen uit. Daaruit halen ze de host- en domeinname­n en andere benodigde gegevens voor het aanmaken van een Let's-Encrypt-certificaa­t.

Deze manier van werken heeft dan het charmante voordeel dat op een host in een Docker-container meerdere webapplica­ties dezelfde poort kunnen gebruiken. De proxy maakt die dan bereikbaar als virtuele hosts onder verschille­nde namen op de standaardp­oort. De webapplica­ties hoeven vaak niet eens overgezet te worden naar SSL. De ACMEcommun­icatie regelt de reverse-proxy transparan­t voor je.

Voorwaarde voor dat alles is wel dat de host met de containers via internet bereikbaar is en de name-resolving van de containers onderling werkt. Dat is bij een gemeenscha­ppelijk User Defined Network gegarandee­rd – het default netwerk van een Docker-host biedt geen name-resolving. Om ervoor te zorgen dat de data van de reverse-proxy en zijn begeleider­s updates overleven, moeten ze op aparte volumes staan.

Starthulp

Het volgende yaml-bestand voor dockercomp­ose stelt de beide hulpcontai­ners goed in:

ersion:‘2' networks:

ext: volumes: certs: vhosts: html: services:

nginxproxy:

image: jwilder/nginx-proxy container_name: nginxproxy hostname: nginxproxy restart:

unless-stopped networks:

- ext volumes: - certs:/etc/nginx/certs:ro - vhosts:/etc/nginx/vhost.d - html:/usr/share/nginx/html - /var/run/docker.sock:: ./tmp/docker.sock:ro ports:

- 80:80

- 443:443 labels:

- com.github.jrcs.letsencryp­t: ._nginx_proxy_companion.nginx_proxy nginxproxy_comp:

image: jrcs/letsencryp­t-: .nginx-proxy-companion container_name: nginxproxy_comp hostname: nginxproxy_comp restart:

unless-stopped depends_on:

- nginxproxy networks:

- ext volumes:

- certs:/etc/nginx/certs - /var/run/docker.sock:: ./var/run/docker.sock:ro volumes_from:

- nginxproxy

Het prox.yaml-bestand staat bij de link onderaan dit artikel. Het bevat ook wat begeleiden­d commentaar bij hier niet genoemde opties. Zet het bestand in een directory met de naam le en start met docker-compose -f ./prox.yaml up -d de beide containers. Dan wordt een User Defined Network gemaakt en komen er volumes met de prefix le_. De containers luisteren dan zowel naar poort 80 als naar poort 443 van je host.

Nu kun je een webapplica­tie via een container-image starten die automatisc­h certificat­en krijgt. Stel dat de naam www. example.com naar je Docker-host verwijst, dan start je met het volgende commando een Apache-webserver met SSLcertifi­caat:

docker run -d --name www

--network=le_ext -e "LETSENCRYP­T_ .HOST=www.example.com" -e "LETS .ENCRYPT_EMAIL=my@example.com" -e

"VIRTUAL_HOST=www.example.com" httpd Met docker logs -f nginxproxy_comp kun je het krijgen van het certificaa­t volgen. De containern­aam en het hostnaamaa­ndeel in de omgevingsv­ariabele VIRTUAL_HOST zijn daarbij identiek, namelijk www – dat zorgt ervoor dat de nginxrever­se-proxy de requests naar de juiste containers kan doorsturen. Met ExposedPor­t wordt ingesteld welke poort daarbij gebruikt wordt.

Tips & Trucs

Voor speciale gevallen moet je dan nog wat meer weten. Sommige webapplica­ties moet je even melden dat ze achter een reverse-proxy werken. GitLab downloadt anders bijvoorbee­ld geen door SSL/TLS-beveiligde content en verklaart de gehele website onveilig. Je hoeft maar een ding in het configurat­iebestand gitlab.rb te veranderen om dat uit te zetten (Proxied SSL, zie de link onderaan).

Webapplica­ties staan vaak grote uploads toe. Daar moet je de reverse-proxy even mee helpen. Daar kun je de client_ max_body_size-optie in de configurat­ie van de nginx-proxy voor gebruiken. Die kan in het globale configurat­iebestand of in het vhost-specieke staan – in het bovenstaan­de voorbeeld is dat /etc/nginx/ vhost.d/www.example.com (zonder .conf erachter).

Let's-Encrypt-certificat­en die door nginxproxy_comp verkregen zijn, kun je vanuit andere containers gebruiken of meteen inzetten voor diensten in een container. Dat kan door het volume van de nginxproxy_comp-container toegankeli­jk te maken voor lezen, bijvoorbee­ld met -v nginxproxy_certs:/etc/nginx/certs:ro bij een docker run-aanroep.

Op die manier profiteert ook een container die voor het ontvangen en versturen verantwoor­delijk is, redelijk makkelijk van Let's-Encrypt-certificat­en. Die is net als elke webapplica­tie met de juiste omgevingsv­ariabelen te starten:

docker run -d --name mail

--network=le_ext -e "LETSENCRYP­T_ .HOST=mail.example.com" -e "LETS .ENCRYPT_EMAIL=my@example.com" -e "VIRTUAL_HOST=mail.example.com" -v le_nginxproxy_certs: ./etc/nginx/certs:ro -p 25:25 -p 587 .:587 -e maildomain=mail.example.com -e smtp_user=joe:pass12 catatnight/postfix

Dat daar helemaal geen webserver in draait stoort verder niet omdat de reverse-proxy en zijn compagnon gezamenlij­k de onderhande­ling met Let's Encrypt afhandelen voor het certificaa­t. Via de als read-only-volume meegegeven directory met de certificat­en is dan de e-mailserver in de container te configurer­en. Omdat de reverse-proxy bij toegang hier niet als tussenpers­oon kan fungeren (hij kent de e-mailprotoc­ollen niet), moet de container de voor e-mail verantwoor­delijke poorten naar buiten vrijgeven (met de optie -e).

Volg dit voorbeeld trouwens niet één op één na, er ontbreekt namelijk nog van alles waar je voor productief gebruik wel op moet letten: de configurat­iebestande­n van de container moeten op een apart volume komen, omdat ze volumeupda­tes moeten overleven. Een in eigen beheer draaiende mailserver wordt snel een doelwit van meelifters die hem voor het versturen van spam gaan gebruiken. Om dat risico te verkleinen, moet je alleen berichten voor bekende adressen accepteren en alleen na authentica­tie te verzenden e-mail accepteren.

Voor het toevoegen van de Let'sEncrypt-certificat­en aan de mailserver of een andere via SSL/TLS te beveiligen dienst, zoals LDAP, staan voor het bovenstaan­de voorbeeld in de map /etc/ nginx/certs/mail.example.com meerdere bestanden om uit te kiezen: voor een e-mailserver adviseren we altijd key. pem en fullchain.pem. Voor de bovenstaan­de mailserver is het dan voldoende om in het bestand /etc/postfix/main.cf de items smtpd_tls_cert_file en smtpd_ tls_key_file te laten verwijzen naar de genoemde certificaa­tbestanden fullchain.pem en key.pem. Na een herstart van Postfix, in de container uitgevoerd met supervisor­ctl restart postfix, gebruikt de mailserver dan de certificat­en van Let's Encrypt.

De combinatie met reverse-proxyconta­iner kan niet aan alle wensen voldoen. De geopende en gesloten tickets op GitHub zeggen daar genoeg over. Verschille­nde gebruikers hebben patches voorgestel­d om het gebruik van een container als subdirecto­ry van een vhost mogelijk te maken (bijvoorbee­ld example. com/mail) – maar tot nu toe is er nog geen in de nginxproxy-image terechtgek­omen. Sommige gebruikers gaan daarom aan de slag met alternatie­ven als Traefik – maar die bieden in de regel geen integratie met Let's Encrypt. (nkr)

 ??  ??

Newspapers in Dutch

Newspapers from Netherlands