Cloudflare Request Cert
A Python tool for requesting and renewing SSL/TLS certificates using Cloudflare DNS API with Let's Encrypt. Built with modern Python tooling using uv for fast dependency management.
Disclaimer: This project is not affiliated with, endorsed by, or supported by Cloudflare.
Features
- 🔒 Automated SSL/TLS certificate requests using DNS-01 challenge
- ☁️ Cloudflare DNS API integration
- ⚡ Fast dependency management with uv
- 🛠️ Simple Makefile interface
- 🔄 Compatible with certbot's automatic renewal
- 🧪 Staging environment support for testing
- 📝 Configuration via .env file or command-line arguments
- 🔧 Flexible: use .env, CLI args, or both
Prerequisites
- Python 3.10 or higher
- A Cloudflare account with API token
- Domain managed by Cloudflare DNS
Installation
Quick Setup
# Install dependencies (will install uv if not present)
make install
Manual uv Installation
If you prefer to install uv manually:
curl -LsSf https://astral.sh/uv/install.sh | sh
Configuration
1. Get Cloudflare API Token
- Log in to your Cloudflare dashboard
- Go to My Profile → API Tokens
- Create a token with these permissions:
- Zone:DNS:Edit for the zones you want to manage
- Zone:Zone:Read for all zones
2. Set Up Credentials
Create a .env file in the project root:
# Copy the example file
cp .env.example .env
# Edit with your credentials
nano .env
Your .env file can contain:
# Required
CLOUDFLARE_API_TOKEN=your_cloudflare_api_token_here
# Optional (can also be passed as CLI arguments)
DOMAIN=example.com
EMAIL=admin@example.com
# Optional settings
STAGING=0 # Set to 1 for staging/test certificates
PROPAGATION_SECONDS=10 # DNS propagation wait time
Security Note: The .env file is already in .gitignore. Never commit API tokens to version control.
Usage
Three Ways to Use This Tool
1. Using .env File Only
Set everything in .env and run without arguments:
# .env file contains: CLOUDFLARE_API_TOKEN, DOMAIN, EMAIL
cloudflare-request-cert
2. Using Command-Line Arguments Only
# Provide all parameters via CLI (API token still from .env or environment)
cloudflare-request-cert -d example.com -e admin@example.com
3. Mix of Both (Recommended)
# Store sensitive data in .env, pass domain/email via CLI
# This is useful when managing multiple domains
cloudflare-request-cert -d example.com -e admin@example.com
Using Make Commands
Request a certificate with Make:
# Basic usage
make run DOMAIN=example.com EMAIL=admin@example.com
# Test with staging first (recommended)
make run DOMAIN=example.com EMAIL=admin@example.com STAGING=1
Advanced Options
# Custom DNS propagation time
cloudflare-request-cert \
-d example.com \
-e admin@example.com \
--propagation-seconds 30
# Use staging environment for testing
cloudflare-request-cert \
-d example.com \
-e admin@example.com \
--staging
# Use custom .env file
cloudflare-request-cert \
-d example.com \
-e admin@example.com \
--env-file /path/to/custom.env
Priority Order
When the same setting is provided in multiple places, this is the priority order (highest to lowest):
- Command-line arguments (highest priority)
- .env file
- Environment variables (lowest priority)
Example:
# .env has DOMAIN=old.com
# This will use new.com (CLI argument takes precedence)
cloudflare-request-cert -d new.com -e admin@example.com
Makefile Commands
| Command | Description |
|---|---|
make help |
Show all available commands |
make venv |
Create virtual environment |
make install |
Install uv and sync dependencies (alias for venv) |
make sync |
Sync dependencies with uv |
make dev |
Install development dependencies |
make run |
Run the certificate request tool |
make lint |
Lint code with ruff |
make format |
Format code with ruff |
make check |
Run all checks (lint + format) |
make test |
Run tests |
make sbom |
Generate SBOM (Software Bill of Materials) |
make clean |
Remove virtual environment and cache |
Certificate Locations
After successful certificate generation, your certificates will be stored at:
/etc/letsencrypt/live/your-domain.com/
├── cert.pem # Your certificate
├── chain.pem # The certificate chain
├── fullchain.pem # cert.pem + chain.pem
└── privkey.pem # Your private key
DNS Propagation Time
The tool waits for DNS changes to propagate before Let's Encrypt validates your domain. Default is 10 seconds, but you can adjust this:
# Via CLI
cloudflare-request-cert -d example.com -e admin@example.com --propagation-seconds 30
# Via .env
PROPAGATION_SECONDS=30
Automatic Renewal
Certbot automatically handles renewal. Set up a cron job or systemd timer:
# Cron example (runs daily at 2 AM)
0 2 * * * certbot renew --quiet
# Or use systemd timer (recommended)
sudo systemctl enable --now certbot-renew.timer
Development
Install Development Dependencies
make dev
Run Tests
make test
Run Linting
make lint
Format Code
make format
Run All Checks
make check
Generate SBOM
Generate a Software Bill of Materials (SBOM) in CycloneDX JSON format:
make sbom
The SBOM will be saved to bom.json.
Example Workflows
First Time Setup
# 1. Install dependencies
make install
# 2. Set up configuration
cp .env.example .env
nano .env # Add your Cloudflare API token
# 3. Test with staging (won't affect rate limits)
cloudflare-request-cert -d example.com -e admin@example.com --staging
# 4. Get production certificate
cloudflare-request-cert -d example.com -e admin@example.com
Managing Multiple Domains
# Store API token in .env
echo "CLOUDFLARE_API_TOKEN=your_token" > .env
# Request certificates for different domains
cloudflare-request-cert -d site1.com -e admin@site1.com
cloudflare-request-cert -d site2.com -e admin@site2.com
cloudflare-request-cert -d site3.com -e admin@site3.com
Automated Script
#!/bin/bash
# renew-certs.sh
DOMAINS=("site1.com" "site2.com" "site3.com")
EMAIL="admin@example.com"
for domain in "${DOMAINS[@]}"; do
echo "Requesting certificate for $domain..."
cloudflare-request-cert -d "$domain" -e "$EMAIL"
done
Troubleshooting
"certbot not found"
Install certbot and the Cloudflare plugin:
make install
# or
uv sync
"CLOUDFLARE_API_TOKEN is required"
Make sure your .env file exists and contains:
CLOUDFLARE_API_TOKEN=your_actual_token_here
"DOMAIN is required" or "EMAIL is required"
Either set them in .env:
DOMAIN=example.com
EMAIL=admin@example.com
Or pass them as arguments:
cloudflare-request-cert -d example.com -e admin@example.com
API Token Permissions
Ensure your Cloudflare API token has:
- Zone:DNS:Edit permissions
- Zone:Zone:Read permissions
DNS Propagation Issues
If validation fails, try increasing propagation time:
cloudflare-request-cert -d example.com -e admin@example.com --propagation-seconds 60
Or set in .env:
PROPAGATION_SECONDS=60
Rate Limits
Let's Encrypt has rate limits. Use staging for testing:
# Set in .env
STAGING=1
# Or via CLI
cloudflare-request-cert -d example.com -e admin@example.com --staging
Comparison with Original
This is a Cloudflare remake of the loopia-request-cert tool with several improvements:
- Uses Cloudflare instead of Loopia DNS
- Uses uv for faster dependency management (10-100x faster than pip)
- Modern pyproject.toml configuration
- Improved Makefile with more commands
- Better error handling and user feedback
- Flexible configuration: .env file, CLI args, or both
- Type hints for better code quality
- Ruff for linting and formatting
- Comprehensive tests
License
MIT License
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Resources
Metadata
Release files for cloudflare-request-cert 0.1.20
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cloudflare_request_cert-0.1.20.tar.gz | 99.6 kB | With provenance | Details for cloudflare_request_cert-0.1.20.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cloudflare_request_cert-0.1.20-py3-none-any.whl | Python 3 | none | any | Details for cloudflare_request_cert-0.1.20-py3-none-any.whl |
Total release size: 108.6 kB
Release files / cloudflare_request_cert-0.1.20.tar.gz
| Download URL | cloudflare_request_cert-0.1.20.tar.gz |
|---|---|
| Size | 99.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
609a6dd94de1bd81bf7f78d3537de63f9a8c8001cdfdb006ca94ff59823dfaee
|
|
BLAKE2b-256 checksum How to use checksums |
b0d37a6c0bbfdf8203d08fd37fbceba08f791c26957a082ab8c8f7fea57d15b2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 24, 2026.
Transparency logRelease files / cloudflare_request_cert-0.1.20-py3-none-any.whl
| Download URL | cloudflare_request_cert-0.1.20-py3-none-any.whl |
|---|---|
| Size | 8.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c116212d8bb04340214d9cf3aeb2d729ded81b1ae5e24b44ceb0616805ec5326
|
|
BLAKE2b-256 checksum How to use checksums |
1bca02ac65f49dc6d822bab99a9219661b72f5a70dcb715d0edd1f9d0705d144
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 24, 2026.
Transparency logSecurity for cloudflare-request-cert 0.1.20
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for cloudflare_request_cert-0.1.20.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 24, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.