Skip to main content

SSL/TLS certificate automation using Cloudflare DNS

Project description

Cloudflare Request Cert

Python Version PyPI Build Coverage License

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
  • 🔄 Support for certificate 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

  1. Log in to your Cloudflare dashboard
  2. Go to My ProfileAPI Tokens
  3. 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):

  1. Command-line arguments (highest priority)
  2. .env file
  3. 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cloudflare_request_cert-0.1.7.tar.gz (91.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cloudflare_request_cert-0.1.7-py3-none-any.whl (8.0 kB view details)

Uploaded Python 3

File details

Details for the file cloudflare_request_cert-0.1.7.tar.gz.

File metadata

  • Download URL: cloudflare_request_cert-0.1.7.tar.gz
  • Upload date:
  • Size: 91.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for cloudflare_request_cert-0.1.7.tar.gz
Algorithm Hash digest
SHA256 5dd3cc674927d592602c10d8370c24471b1fed35348826e1597d7f15fe8a979e
MD5 d3b5ff7f89a8215321c4e001e7d8a168
BLAKE2b-256 9a22739eb6cd4410d12c50590e9fa02a45de077ad5f5bfacf65e08f0d9f4cd81

See more details on using hashes here.

Provenance

The following attestation bundles were made for cloudflare_request_cert-0.1.7.tar.gz:

Publisher: ci.yml on hellqvio86/cloudflare-request-cert

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cloudflare_request_cert-0.1.7-py3-none-any.whl.

File metadata

File hashes

Hashes for cloudflare_request_cert-0.1.7-py3-none-any.whl
Algorithm Hash digest
SHA256 9cb7ba21f252a0b6ede131bb1a0a3a91145fdc7a73e59f8be1e3f7488ca57c2c
MD5 75c7f6069d44427a96291a510da69605
BLAKE2b-256 121411eaae3575ae4365d0b0a68984d713a406234e884716773801bb53f63eda

See more details on using hashes here.

Provenance

The following attestation bundles were made for cloudflare_request_cert-0.1.7-py3-none-any.whl:

Publisher: ci.yml on hellqvio86/cloudflare-request-cert

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page