From d55d065a581d55e734f83c507481236ead07179c Mon Sep 17 00:00:00 2001 From: Jan Broer Date: Sun, 13 Dec 2015 21:22:31 +0100 Subject: [PATCH] Refactor plugin / Add instructions for non-chroot --- README.md | 19 +++++++++-------- acme-http01-webroot.lua | 47 ++++++++++++++++++++++++----------------- cert-renewal-haproxy.sh | 2 +- haproxy.cfg.example | 9 ++++++-- 4 files changed, 46 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 6606d18..62e0d96 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ The plugin is compatible with ACME clients supporting webroot authentication for ### Zero-Downtime No need to take HAProxy offline to issue or reissue certificates. -### Self-Contained & Lean +### Self-Contained -No need to leverage a backend webserver for the trivial task of serving a key authorization from a file. +No need to leverage a backend webserver for the trivial task of serving a key authorization file once every three months per domain. ## Installation instructions @@ -31,13 +31,13 @@ If there is a line similar to this you are good to go: Built with Lua support -If your binary doesn't come with Lua bindings, you can download Debian and Ubuntu packages of the latest v1.6 release from the [Debian HAProxy packaging team](http://haproxy.debian.net/). +If your binary doesn't come with Lua bindings, you can download Debian/Ubuntu packages of the latest v1.6 release from the [Debian HAProxy packaging team](http://haproxy.debian.net/). ### HAProxy configuration -Copy `acme-http01-webroot.lua` to a location accessible by HAProxy. +Copy `acme-http01-webroot.lua` to a location accessible by HAProxy. In case that you don't run HAProxy chrooted (`chroot` config option), you need to edit the plugin and set the `non_chroot_webroot` parameter to the path of the directory you want to use as 'webroot'. -Only minimal changes to your existing `haproxy.cfg` are necessary. In fact you just need to add **three lines**: +To activate the plugin you just need to add **three lines** to your `haproxy.cfg`: In the `global` section insert @@ -45,12 +45,12 @@ In the `global` section insert to invoke the Lua plugin. -In the `frontend` section serving the domain(s) for which you want to create/renew certificates insert +In the `frontend` section serving the domain(s) for which you want to create/renew certificates insert: acl url_acme_http01 path_beg /.well-known/acme-challenge/ http-request use-service lua.acme-http01 if METH_GET url_acme_http01 -to pass ACME http-01 validation requests to the Lua plugin. +This will pass ACME http-01 validation requests to the Lua plugin handler. *Note:* ACME protocol stipulates validation on port 80. If your HTTP frontend listens on a non-standard port, make sure to add a port 80 bind directive. @@ -83,10 +83,11 @@ Follow the [official guide](https://letsencrypt.readthedocs.org/en/latest/using. We are ready to create our certificate. Let's roll! -What happens here is, we invoke the `letsencrypt` client with the [webroot method](https://letsencrypt.readthedocs.org/en/latest/using.html#webroot) and pass our email address and the `WEBROOT` path configured in the Lua plugin. The domain validation is then be performed against the running HAProxy instance. +We invoke the `letsencrypt` client with the [webroot method](https://letsencrypt.readthedocs.org/en/latest/using.html#webroot). +`--webroot-path` must be set to the value of the `chroot` parameter in your `haproxy.cfg`. If you are not running HAProxy chrooted you need to set it to the value of the `non_chroot_webroot` parameter configured in the Lua plugin. $ sudo ./letsencrypt-auto certonly --text --webroot --webroot-path \ - /var/temp -d www.example.com --renew-by-default --agree-tos \ + /var/lib/haproxy -d www.example.com --renew-by-default --agree-tos \ --email your@email.com Next, concat the certificate chain and private key to a `PEM` file suitable for HAProxy: diff --git a/acme-http01-webroot.lua b/acme-http01-webroot.lua index cf1c0f6..4311c79 100644 --- a/acme-http01-webroot.lua +++ b/acme-http01-webroot.lua @@ -22,25 +22,30 @@ -- ./letsencrypt-auto certonly --text --webroot --webroot-path /var/tmp -d blah.example.com --renew-by-default --agree-tos --email my@email.com -- --- --- Configuration begin --- - --- Path passed to letsencrypt via the '--webroot-path' parameter must match this -WEBROOT = "/var/tmp" +acme = {} +acme.version = "0.1.0" -- --- Configuration end +-- Configuration -- +-- When HAProxy is *not* configured with the 'chroot' option you must set an absolute path here and pass +-- that as 'webroot-path' to the letsencrypt client -VERSION = "0.1.0" +acme.conf = { + ["non_chroot_webroot"] = "" +} -core.Info("[acme] http-01 plugin v." .. VERSION .. " loaded"); +-- +-- Startup +-- +acme.startup = function() + core.Info("[acme] http-01 plugin v" .. acme.version); +end -- -- ACME http-01 validation endpoint -- -core.register_service("acme-http01", "http", function(applet) +acme.http01 = function(applet) local response = "" local reqPath = applet.sf:path() local src = applet.sf:src() @@ -72,7 +77,7 @@ core.register_service("acme-http01", "http", function(applet) applet:add_header("Content-Type", "text/plain") applet:start_response() applet:send(response) -end) +end -- -- strip chars that are not in the URL-safe Base64 alphabet @@ -88,11 +93,15 @@ end -- get key auth from token file -- function getKeyAuth(token) - local keyAuth = "" - local f = io.open(WEBROOT .. "/.well-known/acme-challenge/" .. token, "rb") - if f ~= nil then - keyAuth = f:read("*all") - f:close() - end - return keyAuth -end \ No newline at end of file + local keyAuth = "" + local path = acme.conf.non_chroot_webroot .. "/.well-known/acme-challenge/" .. token + local f = io.open(path, "rb") + if f ~= nil then + keyAuth = f:read("*all") + f:close() + end + return keyAuth +end + +core.register_init(acme.startup) +core.register_service("acme-http01", "http", acme.http01) \ No newline at end of file diff --git a/cert-renewal-haproxy.sh b/cert-renewal-haproxy.sh index 7d2777e..e4d2b2f 100755 --- a/cert-renewal-haproxy.sh +++ b/cert-renewal-haproxy.sh @@ -18,7 +18,7 @@ LE_CLIENT="/path/to/letsencrypt-auto" HAPROXY_RELOAD_CMD="service haproxy reload" -WEBROOT="/var/tmp" +WEBROOT="/var/lib/haproxy" # Enable to redirect output to logfile (for silent cron jobs) # LOGFILE="/var/log/certrenewal.log" diff --git a/haproxy.cfg.example b/haproxy.cfg.example index 1b43c0b..9c30d76 100644 --- a/haproxy.cfg.example +++ b/haproxy.cfg.example @@ -1,10 +1,15 @@ global - #daemon - #log /dev/log local0 + user haproxy + group haproxy + daemon + log /dev/log local0 + log /dev/log local1 info + chroot /var/lib/haproxy crt-base /etc/letsencrypt/live lua-load /etc/haproxy/acme-http01-webroot.lua defaults + log global mode http option httplog timeout connect 5000