Acme-dns on CentOS 7
Setting up acme-dns on CentOS 7 and configuring a client
In this post an acme-dns server will be set up and a client will acquire a Let’s Encrypt certificate using the DNS-01 challenge.
Acme-dns provides a simple API exclusively for TXT record updates and should be used with ACME magic “_acme-challenge” - subdomain CNAME records. This way, in the unfortunate exposure of API keys, the effects are limited to the subdomain TXT record in question.
Network topology
In this post the following is assumed:
The future acme-dns server has an IP address of 192.0.2.100
. The following DNS records have been created:
acme-dns.example.com. A 192.0.2.100
a.acme-dns.example.com. NS acme-dns.example.com.
If you manage your own DNS or your provider supports it, you can just use acme-dns.example.com. NS acme-dns.example.com.
. Cloudflare does not support records for a host if a different nameserver was set, so I will use the subdomain a.
for the acme-dns-managed DNS entries.
Prerequisites
To install acme-dns we need git, gcc and go.
sudo yum install git gcc -y
# install go:
wget https://dl.google.com/go/go1.11.4.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.11.4.linux-amd64.tar.gz
sudo ln -s /usr/local/go/bin/* /usr/local/bin
Install acme-dns as a service
The following will build and install the acme-dns binary.
go get github.com/joohoi/acme-dns/...
sudo mv ~/go/bin/acme-dns /usr/local/bin/acme-dns
Now we need to add a user for the acme-dns service and set up the service itself
sudo adduser --system --home /var/lib/acme-dns acme-dns
sudo mkdir /var/lib/acme-dns
sudo chown acme-dns: /var/lib/acme-dns
sudo wget -O /etc/systemd/system/acme-dns.service https://raw.githubusercontent.com/joohoi/acme-dns/master/acme-dns.service
sudo systemctl daemon-reload
As I was getting errors trying to set the capabilities (allow binding to a port <1000) in the service configuration, I removed that part from the configuration and gave the executable the required permissions directly:
sudo sed -i 's/AmbientCapabilities/#AmbientCapabilities/g' /etc/systemd/system/acme-dns.service
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/acme-dns
sudo systemctl daemon-reload
Configure acme-dns
We can use the example configuration file with our own dns-name and ip address.
sudo mkdir /etc/acme-dns
sudo wget -O /etc/acme-dns/config.cfg https://raw.githubusercontent.com/joohoi/acme-dns/master/config.cfg
sudo sed -i 's/^listen = .*/listen = ":53"/g' /etc/acme-dns/config.cfg
sudo sed -i 's/auth.example.org/a.acme-dns.example.com/g' /etc/acme-dns/config.cfg
sudo sed -i 's/198.51.100.1/192.0.2.100/g' /etc/acme-dns/config.cfg
sudo sed -i 's/^connection = .*/connection = "\/var\/lib\/acme-dns\/acme-dns.db"/g' /etc/acme-dns/config.cfg
Acme-dns supports acquiring it’s own SSL certificate via Let’s Encrypt and serving it’s API on https.
sudo sed -i 's/^tls = .*/tls = "letsencrypt"/g' /etc/acme-dns/config.cfg
sudo sed -i 's/^port = .*/port = "443"/g' /etc/acme-dns/config.cfg
sudo sed -i 's/^api_domain = .*/api_domain = "acme-dns.example.com"/g' /etc/acme-dns/config.cfg
sudo sed -i 's/^acme_cache_dir = .*/acme_cache_dir = "/var/lib/acme-dns/cert"/g' /etc/acme-dns/config.cfg
Starting the service
sudo systemctl enable acme-dns.service
sudo systemctl start acme-dns.service
Client-side
Now we can switch to the client that is supposed to get it’s own certificate issued. First we need to register a new subdomain on the acme-dns server. The response will contain the details needed for the next steps.
curl -X POST https://acme-dns.example.com/register
{
"username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
"password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
"fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.a.acme-dns.example.com",
"subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
"allowfrom": []
}
We can now set up DNS accordingly. In this example, the response contains the subdomain d420c923-bbd7-4056-ab64-c3ca54c9b3cf
and we want to set up the domain server01.example.com
so that a certificate can be issued using acme-dns.
_acme-challenge.server01.example.com. CNAME d420c923-bbd7-4056-ab64-c3ca54c9b3cf.a.acme-dns.example.com.
When the entries finished propagating we can install acme.sh
and issue a certificate using the acme-dns method. All settings will be saved and the certificate will be renewed automatically.
curl https://get.acme.sh | sh
export ACMEDNS_UPDATE_URL="https://acme-dns.example.com/update"
export ACMEDNS_USERNAME="eabcdb41-d89f-4580-826f-3e62e9755ef2"
export ACMEDNS_PASSWORD="pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0"
export ACMEDNS_SUBDOMAIN="d420c923-bbd7-4056-ab64-c3ca54c9b3cf"
~/.acme.sh/acme.sh --issue --dns dns_acmedns -d server01.example.com
On success, the newly issued certificate will be located in ~/.acme.sh/server01.example.com/
which can be changed using the parameters --cert-file
, --key-file
, --ca-file
and --fullchain-file
. Using the parameter --reloadcmd
we can issue a command on every future successful renewal.