Python script to deploy & renew certificates from LetsEncrypt to an F5 BIG-IP system. Certificates generated by acme.sh, with Client SSL profiles created using the F5 python SDK.
Tested against BIGIP v13.
A bit rough around the edges.
Repo includes a modified Dockerfile to include python, pip and f5-sdk.
- Docker or;
- Python2 + f5-sdk + acme.sh
This has primarily been tested using Docker, but should work fine without
You need to know two paths in advance: the path acme.sh will put generated certificates & configuration, and the path you will store the f5deploy scripts (the path to f5deploy.py).
All examples assume your certificate path is /tmp/out and script path is /tmp/acme-f5-deploy/f5deploy
chmod +x configure.sh && ./configure.sh
(see Configuration section below for additional details)- Modify creds.json to include the F5 hosts to deploy certificates to (may be multiple) and credentials - credentials must be the same for all hosts.
- Launch acme.sh in docker to issue a certificate
docker run --rm -it \
-v "/tmp/acme-f5-deploy/f5deploy":/acme-f5-feploy
-v "/tmp/out":/acme.sh \
acme_f5 --issue -d xyz.domain.com
- Associate the deploy script with the domain:
docker run --rm -it \
-v "/tmp/acme-f5-deploy/f5deploy":/acme-f5-feploy
-v "/tmp/out":/acme.sh \
acme_f5 --deploy -d xyz.domain.com --deploy-hook f5deploy
At this stage the script should run and successfully create certificates, keys, chains and profiles on the F5 appliances ready for use.
This works correctly for all use cases found at https://github.com/Neilpang/acme.sh/wiki/Run-acme.sh-in-docker including daemon, which will automatically renew and push changes to the F5.
All configuration is in config/creds.json.
{
"f5host": [
{ "host": "192.168.1.92", "port": 8443 },
{ "host": "192.168.2.92" }
],
"f5acct": "admin",
"f5pw": "admin"
"create_cssl": true,
"f5partition": "Common",
"parent_cssl": "/Common/clientssl"
}
- f5host: a dict {host:, port:} of appliances to connect to. If port is ommitted it defaults to 443.
- f5acct and f5pw: shared credentials for all hosts at this stage.
- create_cssl: boolean- create client SSL profile on F5 - default is true.
- f5partition: partition to crete CSSL in - default is Common. Only include partition name without leading or trailing slashes.
- parent_cssl: parent client SSL profile - default is /Common/clientssl. Include full path including partition (may be different to f5partition if the profile is e.g. in /Common/ while the new profile will be in /Specific/
If any of create_cssl, f5partition or parent_cssl are missing they will use their defaults.
Make sure you run ./configure.sh
from the directory you will be keeping the scripts - it will hardcode paths into f5deploy.sh that will require running ./configure.sh
again if f5deploy.py is moved.
./configure.sh
performs the following tasks:
chmod +x ./f5deploy/f5deploy.py
- Replaces the path to the f5deploy.py script in f5deploy.sh with the full path to ./f5deploy/f5deploy.py
- f5deploy.sh.1 is created as a copy of the original file
- Copies f5deploy.sh to the directory specified in
--deploy-path <path>
- Builds the acme_f5 docker image, including the modified f5deploy.sh
- This can be disabled with
--nodocker
- This can be disabled with
This was kept outside of the Dockerfile for support of non-Docker configurations.
This script now tests for if it's running inside or outside of Docker, and launches the f5deploy.py script correctly based on this. ./configure.sh
does the work in setting the correct path.
If you're using docker with the included Dockerfile, the deploy script is copied automatically during build.
If you're not using docker you can run ./configure.sh --nodocker --deploy-path /path/to/.acme.sh/deploy/
, which will pre-fill the path and copy f5deploy.sh to the specified path.
You can then run acme.sh --deploy -d xyz.domain.com --deploy-hook f5deploy
For Docker you would use:
docker run --rm -it \
-v "/tmp/acme-f5-deploy/f5deploy":/acme-f5-feploy
-v "/tmp/out":/acme.sh \
acme_f5 --deploy -d xyz.domain.com --deploy-hook f5deploy
NOTE: When doing --deploy
with a --deploy-hook
the hook is stored permanently in the xyz.domain.com.conf file.
This example assumes:
- Your certificate path is /tmp/out and;
- Your f5deploy.py script path is /tmp/acme-f5-deploy/f5deploy
- You will run the container as a daemon with;
- Automatic renewal
- Automatic restart
- Host networking
cd tmp
git clone https://github.com/farces/acme-f5-deploy.git
cd acme-f5-deploy
chmod +x configure.sh && ./configure.sh
docker run --restart=unless-stopped -itd -v "/tmp/acme-f5-deploy/f5deploy":/acme-f5-deploy \
-v "/tmp/out":/acme.sh --net=host --name=acme_f5 acme_f5 daemon
... modify f5deploy/config/creds.json here ...
docker exec acme_f5 --issue -d sample.domain.com
docker exec acme_f5 --deploy -d sample.domain.com --deploy-hook f5deploy
On the F5 the following is created:
- Certificate & Key: xyz.domain.com
- Chain: xyz.domain.com.le-chain - this includes both the domain certificate and LetsEncrypt Authority.
- Client SSL Profile: cssl.xyz.domain.com. This profile is never overwritten and can be customized as required.
If you're using docker and need to export environment variables for DNS API configuration you can do the following:
docker exec acme_f5 /bin/sh -c "export CF_Key=our_key && export CF_Email=our_email && --issue --dns dns_cf -d sample.domain.com
docker exec acme_f5 --deploy -d sample.domain.com --deploy-hook f5deploy
or edit the account.conf file in /tmp/out manually.
This only needs to be done once.
@f5central for the API script modified from https://github.com/f5devcentral/lets-encrypt-python