cdmon-acme
Issue Let's Encrypt certificates (including wildcard) using cdmon DNS (dns-01) via pycdmon.
Features
- Wildcard support (
*.example.com) - Fully Python implementation
- DNS TXT automation on cdmon
- DNS propagation wait loop
- Retries/backoff for DNS record create/delete
- Lock file to prevent parallel issuance
- Commands:
issue,renew,inspect - Outputs:
cert.pem,chain.pem,fullchain.pem, private key
Install
pip install -e .
Usage
export CDMON_API_KEY="..."
# Staging first (recommended)
cdmon-acme issue \
--domain example.com \
--wildcard \
--email admin@example.com \
--staging \
--out ./certs
# Production
cdmon-acme issue \
--domain example.com \
--wildcard \
--email admin@example.com \
--out ./certs
# Renew (same flow, reusable keys + lock)
cdmon-acme renew \
--domain example.com \
--wildcard \
--email admin@example.com \
--out ./certs \
--lock-file ./.state/issue.lock \
--post-hook "systemctl reload nginx"
# Inspect existing cert
cdmon-acme inspect --cert ./certs/fullchain.pem
Security notes
- Never commit private keys (
secrets/,certs/) - Rotate/revoke credentials if exposed
- Use staging first to avoid Let's Encrypt rate limits
Repo structure
src/cdmon_acme/issuer.pyACME + issuance flowsrc/cdmon_acme/dns_solver.pycdmon DNS TXT create/delete + propagationsrc/cdmon_acme/cert_info.pycertificate inspection helperssrc/cdmon_acme/cli.pyCLI
GitHub Actions renew example
Add repository secrets:
CDMON_API_KEYACME_EMAIL
Then use a scheduled workflow (example in .github/workflows/renew-example.yml).
Releases
This repository supports automatic releases from main using Python Semantic Release and Conventional Commits.
Why this approach
This is a Python package, so the release automation is Python-native:
- no
package.json - versioning is configured in
pyproject.toml - the workflow uses
python-semantic-release,build, and optional PyPI publication
Conventional Commits are only the input convention used to determine the version bump.
How it works
- merge changes into
main - GitHub Actions runs validation (
ruff check .andpytest) python-semantic-releaseinspects commit messages since the last tag- if a release is warranted, it will:
- determine the next version
- update
pyproject.toml - create the release commit and tag
- publish the GitHub Release
- the workflow always creates the Git tag and GitHub Release when a release is warranted
- if
PYPI_TOKENis defined in repository secrets, the workflow also publishes to PyPI - if
PYPI_TOKENis not defined butPYPI_MASTER_TOKENexists, the workflow falls back to that token for PyPI publication - if neither token exists, the workflow skips the PyPI upload but still publishes the GitHub Release
Commit conventions
Use Conventional Commits so release automation can infer version bumps:
fix:-> patch releasefeat:-> minor releasefeat!:or any commit withBREAKING CHANGE:-> major releasedocs:,test:,chore:-> no release by default
Example:
git commit -m "fix: correct TXT record handling for cdmon DNS challenge"
Notes
- The release workflow only runs on pushes to
main. - The repository must allow GitHub Actions to push release commits and tags using
GITHUB_TOKEN. - If branch protection is strict, make sure it still permits the release workflow to push the generated release commit.
Status
MVP+ ready. Next recommended steps:
- Add integration tests against LE staging + disposable domain
- Add deploy target adapters (nginx/caddy/traefik)
- Add optional webhook/slack notification on renew
Metadata
Release files for cdmon-acme 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cdmon_acme-1.0.0.tar.gz | 8.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cdmon_acme-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 17.0 kB
Release files / cdmon_acme-1.0.0.tar.gz
| Download URL | cdmon_acme-1.0.0.tar.gz |
|---|---|
| Size | 8.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
459d6da0e6a675200db7206559044ba3b1ac878cd962c29f60ca6585efbd4eec
|
|
BLAKE2b-256 checksum How to use checksums |
2539c675716cbfb4f8ac1d4077316ae91fd014dc6cd199e2259f752b7ce94353
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.13
|
Release files / cdmon_acme-1.0.0-py3-none-any.whl
| Download URL | cdmon_acme-1.0.0-py3-none-any.whl |
|---|---|
| Size | 8.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
999f5cc28f0bf851957c6c2929d4dc57e36f2e4566f7f3554600e887d9245fe4
|
|
BLAKE2b-256 checksum How to use checksums |
c49f66b55c2005c543e4112701bee570aa2be22204c6708dfd4aef6aec0d4e1f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.13
|