⚠️ Early-stage project Expect rough edges, changing interfaces, and incomplete pieces.
acmed (ACME Daemon) is an ACME-first broker service for internal infrastructure.
I built it because ACME automation gets awkward fast in segmented networks. HTTP challenges are often not reachable, DNS challenges can require broader permissions than you want to hand out, and many appliances support only part of the ecosystem. The result is usually a pile of one-off scripts and host-specific workarounds.
acmed puts one service in the middle so that policy and request handling live in one place instead of being reinvented per host. It accepts ACME requests, tracks state, applies local authorization/proof rules, and hands issuance work to an adapter.
A key design choice is that acmed does not reimplement issuance tooling. It calls existing tools such as certbot and acme.sh, then focuses on orchestration and policy. Right now the scope is intentionally narrow: ACME-first flow plus controlled backend delegation. The structure leaves room for more broker-like behavior later (for example multiple backends), but that is secondary to keeping the current flow understandable and predictable.
In short, the request path is:
- client sends ACME request
acmedvalidates and stores it- worker resolves policy and proof handling
- issuer adapter runs the external issuance/challenge flow
- result is exposed back through normal ACME resources
- Python
3.11+(for source installs and local development) - Docker and Docker Compose (for container quick start)
Choose one of the following installation paths.
From source:
git clone https://github.com/rohzb/acmed.git
cd acmed
python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -e .From GitHub release artifacts:
python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
# Download wheel/sdist from:
# https://github.com/rohzb/acmed/releases
# Example:
pip install ./acmed-X.Y.Z-py3-none-any.whlFrom published Docker image:
docker pull ghcr.io/rohzb/acmed:latestPublished image tags:
ghcr.io/rohzb/acmed:latestghcr.io/rohzb/acmed:Xghcr.io/rohzb/acmed:X.Yghcr.io/rohzb/acmed:X.Y.Z
If you cloned the repository, the easiest way to try acmed is Docker Compose:
cp docker/.env.example docker/.env
cp docker/config/config.allow-all.yml docker/config/config.yml
docker compose -f docker/docker-compose.yml --env-file docker/.env up --buildWarning
config.allow-all.yml is for local development/testing only. Do not use it in production.
To run from the published image directly:
mkdir -p /opt/acmed/config
cp config.example.yml /opt/acmed/config/config.yml
docker run --rm \
--name acmed \
-p 8443:8443 \
-e ACMED_TOKEN_ADMIN='replace-with-random-token' \
-v /opt/acmed/config/config.yml:/app/config/config.yml:ro \
ghcr.io/rohzb/acmed:latestQuick check:
curl http://127.0.0.1:8443/healthz
curl http://127.0.0.1:8443/acme/directoryConfiguration is YAML-based around three parts:
- authorizers: who is allowed
- proof handlers: how ownership is checked
- issuer adapters: how certificates are issued
Have a look at config.example.yml for a starting point.
pytestpython -m acmed.main <config.yml>CI workflows:
ci: Python test matrix (3.11through3.14) plus package build validation.docker-ci: Docker image build and runtime smoke test (/healthz).security-checks: Trivy (vuln/misconfig) + Gitleaks + TruffleHog security checks.
Docs are under docs/ (start with docs/README.md).
Versioning and release policy is defined in docs/reference/versioning.md.
Human-facing docs are separate from machine-oriented contracts in docs/models/.
Project is MIT licensed (LICENSE).
Release automation is wired through GitHub Actions on tag push.
Trigger it with an annotated SemVer tag that matches pyproject.toml:
git tag -a vX.Y.Z -m "acmed vX.Y.Z"
git push origin vX.Y.ZOn each vX.Y.Z tag push, CI will:
- validate tag format and ensure it matches
project.version - verify
CHANGELOG.mdcontains that version - run tests
- build Python artifacts (
sdistandwheel) - build and push Docker image tags to GHCR:
X.Y.ZX.YXlatest
- create a GitHub Release with generated notes and attached build artifacts
Feedback and PRs are welcome.