Let's Encrypt Module
The Let's Encrypt module provides automatic SSL/TLS certificate generation and management using Let's Encrypt's ACME protocol. It integrates seamlessly with the Modular framework to provide HTTPS capabilities for your applications.

Features
- Automatic Certificate Generation: Obtain SSL/TLS certificates from Let's Encrypt automatically
- Multiple Challenge Types: Support for HTTP-01 and DNS-01 challenges
- Auto-Renewal: Automatic certificate renewal before expiration
- Multiple DNS Providers: Support for various DNS providers (Cloudflare, Route53, Azure DNS, etc.)
- Staging Environment: Use Let's Encrypt's staging environment for testing
- Certificate Storage: Persistent storage of certificates and account information
- Production Ready: Built with best practices for production deployments
Installation
go get github.com/CrisisTextLine/modular/modules/letsencrypt
Quick Start
Basic Usage with HTTP Challenge
package main
import (
"context"
"log/slog"
"os"
"github.com/CrisisTextLine/modular"
"github.com/CrisisTextLine/modular/modules/letsencrypt"
"github.com/CrisisTextLine/modular/modules/httpserver"
)
type AppConfig struct {
LetsEncrypt letsencrypt.LetsEncryptConfig `yaml:"letsencrypt"`
HTTPServer httpserver.HTTPServerConfig `yaml:"httpserver"`
}
func main() {
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
config := &AppConfig{
LetsEncrypt: letsencrypt.LetsEncryptConfig{
Email: "your-email@example.com",
Domains: []string{"example.com", "www.example.com"},
UseStaging: false,
StoragePath: "./certs",
AutoRenew: true,
RenewBefore: 30,
},
HTTPServer: httpserver.HTTPServerConfig{
Host: "0.0.0.0",
Port: 443,
TLS: &httpserver.TLSConfig{Enabled: true},
},
}
configProvider := modular.NewStdConfigProvider(config)
app := modular.NewStdApplication(configProvider, logger)
app.RegisterModule(letsencrypt.NewLetsEncryptModule())
app.RegisterModule(httpserver.NewHTTPServerModule())
if err := app.Run(); err != nil {
logger.Error("Application error", "error", err)
os.Exit(1)
}
}
DNS Challenge with Cloudflare
config := &AppConfig{
LetsEncrypt: letsencrypt.LetsEncryptConfig{
Email: "your-email@example.com",
Domains: []string{"*.example.com", "example.com"},
UseStaging: false,
StoragePath: "./certs",
AutoRenew: true,
UseDNS: true,
DNSProvider: &letsencrypt.DNSProviderConfig{
Name: "cloudflare",
},
DNSConfig: map[string]string{
"CLOUDFLARE_EMAIL": "your-email@example.com",
"CLOUDFLARE_API_KEY": "your-api-key",
},
},
}
Configuration
LetsEncryptConfig
email | string | Email address for Let's Encrypt registration | Required |
domains | []string | List of domain names to obtain certificates for | Required |
use_staging | bool | Use Let's Encrypt staging environment | false |
storage_path | string | Directory for certificate storage | "./letsencrypt" |
renew_before | int | Days before expiry to renew certificates | 30 |
auto_renew | bool | Enable automatic renewal | true |
use_dns | bool | Use DNS-01 challenges instead of HTTP-01 | false |
DNS Provider Configuration
For DNS challenges, configure the DNS provider:
letsencrypt:
email: "your-email@example.com"
domains:
- "example.com"
- "*.example.com"
use_dns: true
dns_provider:
name: "cloudflare"
dns_config:
CLOUDFLARE_EMAIL: "your-email@example.com"
CLOUDFLARE_API_KEY: "your-api-key"
Supported DNS Providers
- Cloudflare:
cloudflare
- Route53 (AWS):
route53
- Azure DNS:
azuredns
- Google Cloud DNS:
gcloud
- DigitalOcean:
digitalocean
- Namecheap:
namecheap
Each provider requires specific environment variables or configuration parameters.
Integration with HTTP Server
The Let's Encrypt module works seamlessly with the HTTP Server module by implementing the CertificateService interface:
app.RegisterModule(letsencrypt.NewLetsEncryptModule())
app.RegisterModule(httpserver.NewHTTPServerModule())
Advanced Usage
Custom Certificate Handling
var certService httpserver.CertificateService
app.GetService("certificateService", &certService)
cert := certService.GetCertificate("example.com")
Manual Certificate Operations
letsEncryptModule := letsencrypt.NewLetsEncryptModule()
if err := letsEncryptModule.RenewCertificate("example.com"); err != nil {
log.Printf("Failed to renew certificate: %v", err)
}
Environment Variables
You can configure the module using environment variables:
LETSENCRYPT_EMAIL=your-email@example.com
LETSENCRYPT_DOMAINS=example.com,www.example.com
LETSENCRYPT_USE_STAGING=false
LETSENCRYPT_STORAGE_PATH=./certs
LETSENCRYPT_AUTO_RENEW=true
Best Practices
- Use Staging for Testing: Always test with
use_staging: true to avoid rate limits
- Secure Storage: Ensure certificate storage directory has proper permissions
- Monitor Renewals: Set up monitoring for certificate renewal failures
- Backup Certificates: Regularly backup your certificate storage directory
- DNS Challenge for Wildcards: Use DNS challenges for wildcard certificates
Troubleshooting
Common Issues
- Rate Limits: Use staging environment for testing
- DNS Propagation: DNS challenges may take time to propagate
- Firewall: Ensure port 80 is accessible for HTTP challenges
- Domain Validation: Verify domain ownership and DNS configuration
Debug Mode
Enable debug logging to troubleshoot issues:
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelDebug,
}))
Examples
See the examples directory for complete working examples:
- Basic HTTPS server with Let's Encrypt
- Multi-domain certificate management
- DNS challenge configuration
Dependencies
- lego - ACME client library
- Works with the httpserver module for HTTPS support
License
This module is part of the Modular framework and is licensed under the MIT License.