This Terraform project automates the lifecycle of Let's Encrypt TLS certificates using DNS-01 challenges with F5 Distributed Cloud (F5XC). Issued certificates are uploaded to F5 BIG-IP, where corresponding Client SSL Profiles are created or updated.
When executed on a recurring schedule (e.g., via CI/CD pipelines), the module also handles automatic certificate renewal, ensuring continued trust and uptime. Wildcard certificates are supported.
- ✅ Requests Let's Encrypt certificates (including wildcard domains)
- 🔒 Use DNS-01 challenge via F5 Distributed Cloud
- ⬆️ Uploads both the end-entity certificate and intermediate to BIG-IP
- 📎 Automatically includes the correct Let's Encrypt intermediate CA in the SSL certificate chain
- 🔁 Automatically renews certificates on repeated runs
- 🛡 Creates or updates Client SSL Profiles using uploaded certificates
- 📆 Supports GitLab CI/CD with remote Terraform state and state locking
This repository includes a .gitlab-ci.yaml.dist file which can be renamed to .gitlab-ci.yaml to enable pipeline automation in GitLab.
Benefits of GitLab CI/CD:
- Stores Terraform state securely and remotely
- Enables state locking to prevent concurrent runs
- Automates renewals and deployments on schedule or commit
- Gitops allows approval access using merge requests
To enable remote state with GitLab, rename the backend.tf.dist file to backend.tf:
mv backend.tf.dist backend.tfYour GitLab project must define the following CI/CD variables:
TF_VAR_email_addressTF_VAR_F5XC_API_TOKENTF_VAR_F5XC_TENANT_NAMETF_VAR_F5XC_GROUP_NAMETF_VAR_BIGIP_HOSTTF_VAR_BIGIP_PORTTF_VAR_BIGIP_USERNAMETF_VAR_BIGIP_PASSWORDTF_VAR_global_parent_ssl_profile
❗️ These variables are required for both the pipeline and Terraform execution. Do not hardcode credentials in the codebase.
| Name | Description |
|---|---|
email_address |
Email for Let's Encrypt account registration |
F5XC_API_TOKEN |
API token for F5 Distributed Cloud |
F5XC_TENANT_NAME |
Tenant name in F5XC |
F5XC_GROUP_NAME |
RRset name for DNS validation (alfanum chars) |
BIGIP_HOST |
IP or hostname of the BIG-IP device |
BIGIP_PORT |
Port for BIG-IP REST API (if not 443) |
BIGIP_USERNAME |
Username for BIG-IP REST API |
BIGIP_PASSWORD |
Password for BIG-IP REST API |
global_parent_ssl_profile |
Parent SSL profile to inherit on BIG-IP |
Certificates are defined in the yaml file inside dns_challenge_certs map. See domains.yml.example file.
Required fields per certificate:
cn: Common Name of the certificatesan: Subject Alternative Names (list of domain names)
Optional fields:
partition: BIG-IP partition name (defaults toCommonif not specified)parent_ssl_profile: Overrides the global SSL profile for that specific certificate
dns_challenge_certs:
name_of_the_certificate_object_which_will_appear_in_bigip:
cn: acme1.example.com
san: ["acme1.example.com"]
wildcard.example.com:
cn: *.example.com
san: ["example.com"]
www.example.com:
cn: www.example.com
san: ["www.example.com"]
partition: another_partition
parent_ssl_profile: custom-clientssl- Use GitLab CI/CD to automate recurring runs and certificate renewals
- Enable Terraform state locking to avoid concurrent executions
- Store credentials and sensitive inputs as GitLab CI/CD variables
- Run the pipeline periodically (e.g., daily or weekly) to catch upcoming expirations
- Secrets handling via HashiCorp Vault or GitLab's secret backends
- Renewal monitoring and alerting (e.g., email, Slack)
- More robust error handling and retry logic
MIT License
Maintained by: Martin Kylian