Reputation: 103
you know traefik is able to do all the Let's Encrypt stuff (request and renew) for your webservices. But traefik stores the requested certificates as a JSON-file, which isn't the common format for certificates.
I want to use the Let's Encrypt certificates also for my mail-server, so I need them in simple format: *.pem or *.crt.
Here my question: Is it possible that traefik stores the Let's Encrypt certificates in a common format?
Thanks for help!
Upvotes: 7
Views: 7240
Reputation: 18973
The most popular solution is ldez/traefik-certs-dumper
. In case of docker-compose
you need something along the following lines:
version: '3'
services:
traefik:
image: traefik:1.7
command:
--entryPoints='Name:http Address::80'
--entryPoints='Name:https Address::443 TLS'
--defaultentrypoints=http,https
--logLevel=DEBUG
--docker
--docker.exposedByDefault=false
--acme
--acme.acmeLogging=true
--acme.entrypoint=https
--acme.storage=/data/acme.json
--acme.onHostRule=true
--acme.httpChallenge.entryPoint=http
ports:
- 8001:80
- 8002:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- .:/data
traefik-certs-dumper:
image: ldez/traefik-certs-dumper:v2.7.0
entrypoint: sh -c '
apk add jq
; while ! [ -e /data/acme.json ]
|| ! [ `jq ".Certificates | length" /data/acme.json` != 0 ]; do
sleep 1
; done
&& traefik-certs-dumper file --watch
--source /data/acme.json --dest /data/certs'
volumes:
- .:/data
# test service
whoami:
image: containous/whoami
labels:
traefik.enable: true
traefik.frontend.rule: Host:example.com
traefik
ports are published to 8001
and 8002
. I assume here that you need certificates as separate files because you want to put traefik
behind another proxy.
Upvotes: 2
Reputation: 13898
I'm late to the party but meanwhile there are some dockerized solutions that will extract the certificates for you and watch the acme.json
file for changes, e.g. https://github.com/SnowMB/traefik-certificate-extractor (I'm not affiliated in any way with it).
Upvotes: 0
Reputation: 8426
I'm using jq
to do this
export certificate
cat acme.json | jq -r '.Certificates[] | select(.Domain.Main=="'www.example.com'") | .Certificate' | base64 -d > www.example.com.crt
export private key
cat acme.json | jq -r '.Certificates[] | select(.Domain.Main=="'www.example.com'") | .Key' | base64 -d > www.example.com.key
export JSON containing certificate and private key
consul kv get traefik/acme/account/object | gzip -dc | jq -r '.DomainsCertificate.Certs[] | select(.Domains.Main=="'www.example.com'") | .Certificate' > www.example.com.json
export certificate only
consul kv get traefik/acme/account/object | gzip -dc | jq -r '.DomainsCertificate.Certs[] | select(.Domains.Main=="'www.example.com'") | .Certificate.Certificate' | base64 -D > www.example.com.crt
export private key only
consul kv get traefik/acme/account/object | gzip -dc | jq -r '.DomainsCertificate.Certs[] | select(.Domains.Main=="'www.example.com'") | .Certificate.PrivateKey' | base64 -D > www.example.com.key
backup
consul kv get -base64 traefik/acme/account/object > backup-base64
restore
cat -s backup-base64 | base64 --decode | consul kv put traefik/acme/account/object -
Upvotes: 9
Reputation: 3107
Disclaimer: I'm new to Traefik, so there might be a better solution than this that I'm not aware of.
What I've done is used a Python script by JayH5 to extract the keys files from the acme.json file.
def read_domain_certs(acme_json_path, domain):
with open(acme_json_path) as acme_json_file:
acme_json = json.load(acme_json_file)
certs_json = acme_json['DomainsCertificate']['Certs']
domain_certs = [cert['Certificate'] for cert in certs_json
if cert['Domains']['Main'] == domain]
if not domain_certs:
raise RuntimeError(
'Unable to find certificate for domain "%s"' % (domain,))
elif len(domain_certs) > 1:
raise RuntimeError(
'More than one (%d) certificates for domain "%s"' % (domain,))
[domain_cert] = domain_certs
return (base64.b64decode(domain_cert['PrivateKey']),
base64.b64decode(domain_cert['Certificate']))
Depending on your use case, you could skip saving the files and load the keys directly from the JSON file using that code. However, if you do need the PEM files, the script does also writes the key contents, if you need the files on disk.
def write_cert(storage_dir, filename, cert_content):
cert_path = os.path.join(storage_dir, filename)
with open(cert_path, 'w') as cert_file:
cert_file.write(cert_content)
os.chmod(cert_path, 0o600)
Upvotes: 1