Skip to main content

lacme

CI PyPI Python License

Modern, async-native Python ACME client library for embedding TLS certificate automation.

What is lacme?

lacme fills the gap between full-featured CLI tools like certbot (not designed for embedding) and low-level ACME protocol libraries that leave orchestration to you. It provides a high-level Client.issue() one-liner alongside full access to every step of the ACME workflow. lacme has three runtime dependencies -- HTTPX2, cryptography, and idna -- and supports Python 3.11+.

Features

  • Async-native with sync wrapper -- Client for asyncio, SyncClient for blocking code
  • DNS and IP identifiers -- IPv4 and IPv6 SANs through the high-level ACME issuance APIs
  • HTTP-01 and DNS-01 challenges -- built-in handlers with pluggable DNS providers (Cloudflare, Route 53, shell hooks)
  • Built-in Certificate Authority -- CertificateAuthority for issuing private CA certs, ideal for mTLS
  • ACME Responder -- ACMEResponder ASGI app backed by the built-in CA for internal PKI
  • Framework integrations -- first-class support for Starlette, FastAPI, and Uvicorn
  • CLI tool -- lacme issue, lacme renew, lacme revoke from the command line
  • Auto-renewal -- RenewalManager runs in the background and re-issues expiring certificates
  • Rate limit tracking -- client-side awareness of Let's Encrypt rate limits with warnings and blocking
  • Event system + Prometheus metrics -- EventDispatcher with typed events; optional MetricsCollector
  • MockACMEServer for testing -- in-process mock ACME server via httpx2.MockTransport

Quick Start

pip install lacme
import asyncio
from lacme import Client
from lacme.challenges.http01 import HTTP01Handler

async def main():
    handler = HTTP01Handler()
    async with Client(
        directory_url="https://acme-v02.api.letsencrypt.org/directory",
        contact="mailto:you@example.com",
        challenge_handler=handler,
    ) as client:
        server = await handler.start_server()  # port 80
        bundle = await client.issue("example.com")
        server.close()
        await server.wait_closed()
    print(bundle.fullchain_pem.decode())

asyncio.run(main())

Private CA / mTLS

from lacme import CertificateAuthority, client_ssl_context, server_ssl_context

ca = CertificateAuthority()
ca.init()

server_cert = ca.issue("myservice.internal")
client_cert = ca.issue("worker-1", client=True)

server_ctx = server_ssl_context(
    cert_pem=server_cert.fullchain_pem,
    key_pem=server_cert.key_pem,
    ca_cert_pem=ca.root_cert_pem,  # require client certs
)
client_ctx = client_ssl_context(
    cert_pem=client_cert.cert_pem,
    key_pem=client_cert.key_pem,
    ca_cert_pem=ca.root_cert_pem,
)

CLI

# Issue a certificate via Let's Encrypt staging
lacme --staging --contact you@example.com issue example.com

# Renew all certificates expiring within 30 days
lacme renew --days 30

# Revoke a certificate
lacme revoke example.com

Documentation

Full documentation is available at turnstonelabs.github.io/lacme. See the changelog for release notes and upgrade guidance.

License

Apache-2.0

Metadata

Release files for lacme 1.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lacme 1.2.0
File Size Uploaded
lacme-1.2.0.tar.gz 241.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lacme 1.2.0
File Interpreter ABI Platform
lacme-1.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 324.1 kB

Release files / lacme-1.2.0.tar.gz

Download URL lacme-1.2.0.tar.gz
Size 241.0 kB
Tags Source
SHA-256 checksum
How to use checksums
b35b22c6c91e69573eb93c51d365c18e1b1a78baf7bb98e82853881d025ac4df
BLAKE2b-256 checksum
How to use checksums
2fd72255677546b99b6847901d469727081625276bda38f6880ccc20d80bc7c8
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 13, 2026.

Transparency log

Release files / lacme-1.2.0-py3-none-any.whl

Download URL lacme-1.2.0-py3-none-any.whl
Size 83.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fb0a54c57ec5995f32abf8f65f49af5a2d5863bc545946787b0df41b616205e8
BLAKE2b-256 checksum
How to use checksums
d7108ebadbc278cea0290d835625ab9f0dd114e218c8e46ab4b406eda247e0ae
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 13, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.2.0 This release

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page