An automated SSL certificate management system enabling registration of custom domains for canisters on the Internet Computer (IC) using the ACME protocol and Let's Encrypt.
- Automated Certificate Lifecycle
- Issue, renew, and revoke SSL certificates for custom domains
- Update domain-to-canister mappings
- Automatic renewal before expiration
- DNS-01 Challenge Support
- Uses Cloudflare DNS API for ACME challenges
- Internet Computer Integration
- Certificates and mappings stored in a canister (key-value store)
- Canister acts as a task queue for workers
- Domain Validation
- DNS record checks (CNAME, TXT)
- Canister ownership via asset file
/.well-known/ic-domains - No conflicting ACME challenge records
- RESTful API
- HTTP endpoints for registration, status, validation, and management
- Worker System
- Multiple background workers for certificate operations
- Encrypted Storage
- Certificates and private keys are encrypted in the canister
- Rate Limiting
- Configurable rate limiting for API endpoints
- OpenAPI Documentation
- Swagger UI for API exploration and testing
- Backend API (
backend/): Axum-based HTTP REST API server for domain management - Base Library (
base/):- Worker system: Fetches and executes certificate lifecycle tasks from the canister
- Utilities: Domain validation, encryption, error handling
- Canister Backend (
canister/canister_backend/):- Key-value store for domains, certificates, and tasks
- Metrics
- Canister API (
canister/api/):- Shared types and API definitions for canister communication
- Canister Client (
canister_client/):- Library for backend/workers to interact with the canister
- Examples (
examples/):- Example server startup and configuration (
custom_domains_example.rs)
- Example server startup and configuration (
- Tests (
tests/):- End-to-end and canister integration tests
- Issue: Initial certificate issuance for new domains
- Renew: Automatic certificate renewal before expiration
- Update: Update canister mapping for existing domains
- Delete: Certificate revocation and cleanup
Deploy the storage canister to mainnet or locally:
$ cd canister/canister_backend
$ dfx deploy canister_backend --mode=reinstall --network=playgroundSet required environment variables:
$ export CANISTER_ID=...
$ export CLOUDFLARE_API_TOKEN=...Start the API server and a worker:
$ cargo run --example custom_domains_example --features openapiOpen Swagger UI to explore and test API endpoints:
http://127.0.0.1:3000/swagger-ui
POST /v1/example.comGET /v1/example.comGET /v1/example.com/validate{
"status": "success",
"message": "Domain registration request accepted and may take a few minutes to process",
"data": {
"domain": "example.org",
"canister_id": "laqa6-raaaa-aaaam-aehzq-cai"
}
}Domains are validated through:
- DNS Configuration: Required CNAME and TXT records
- Canister Ownership: Domain listed in
/.well-known/ic-domainsasset file - No Conflicting Records: No existing ACME challenge records
- Certificates and private keys encrypted in the canister
- Secure canister communication with authorization
- Ownership checks before issuing or deleting certificates
- Configurable rate limiting for API endpoints
- Certificate revocation on domain deletion/renewals
custom-domains/
├── backend/ # Axum REST API server
├── base/ # Worker system, validation, encryption
├── canister/
│ ├── api/ # Canister API
│ └── canister_backend/ # Canister implementation
├── canister_client/ # Canister communication library
├── examples/ # Example of the system startup
├── tests/ # E2E and canister tests
├── CustomDomains.svg # Architecture diagram
External code contributions are currently not being accepted to this repository.
This project is licensed under the Apache License, Version 2.0. See the LICENSE file for more details.