letsencrypt

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 5, 2025 License: MIT Imports: 24 Imported by: 0

README

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.

Go Reference

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/GoCodeAlone/modular/modules/letsencrypt

Quick Start

Basic Usage with HTTP Challenge
package main

import (
    "context"
    "log/slog"
    "os"

    "github.com/GoCodeAlone/modular"
    "github.com/GoCodeAlone/modular/modules/letsencrypt"
    "github.com/GoCodeAlone/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, // Set to true for testing
            StoragePath: "./certs",
            AutoRenew:   true,
            RenewBefore: 30, // Renew 30 days before expiration
        },
        HTTPServer: httpserver.HTTPServerConfig{
            Host: "0.0.0.0",
            Port: 443,
            TLS:  &httpserver.TLSConfig{Enabled: true},
        },
    }

    configProvider := modular.NewStdConfigProvider(config)
    app := modular.NewStdApplication(configProvider, logger)

    // Register modules
    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
Field Type Description Default
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:

// The HTTP server module will automatically use certificates from Let's Encrypt
app.RegisterModule(letsencrypt.NewLetsEncryptModule())
app.RegisterModule(httpserver.NewHTTPServerModule())

Advanced Usage

Custom Certificate Handling
// Get certificate service for custom handling
var certService httpserver.CertificateService
app.GetService("certificateService", &certService)

// Get certificate for a specific domain
cert := certService.GetCertificate("example.com")
Manual Certificate Operations
letsEncryptModule := letsencrypt.NewLetsEncryptModule()

// Force certificate renewal
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

  1. Use Staging for Testing: Always test with use_staging: true to avoid rate limits
  2. Secure Storage: Ensure certificate storage directory has proper permissions
  3. Monitor Renewals: Set up monitoring for certificate renewal failures
  4. Backup Certificates: Regularly backup your certificate storage directory
  5. DNS Challenge for Wildcards: Use DNS challenges for wildcard certificates

Troubleshooting

Common Issues
  1. Rate Limits: Use staging environment for testing
  2. DNS Propagation: DNS challenges may take time to propagate
  3. Firewall: Ensure port 80 is accessible for HTTP challenges
  4. 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.

Documentation

Overview

Package letsencrypt provides a module for automatic SSL certificate generation via Let's Encrypt for the modular framework.

Package letsencrypt provides a module for automatic SSL certificate generation via Let's Encrypt for the modular framework.

Package letsencrypt provides a module for automatic SSL certificate generation via Let's Encrypt for the modular framework.

Index

Constants

View Source
const (
	// CAStaging is the URL for Let's Encrypt's staging environment
	CAStaging = "https://acme-staging-v02.api.letsencrypt.org/directory"
	// CAProduction is the URL for Let's Encrypt's production environment
	CAProduction = "https://acme-v02.api.letsencrypt.org/directory"
)

Constants for Let's Encrypt URLs

View Source
const ModuleName = "letsencrypt"

ModuleName is the name of this module

Variables

This section is empty.

Functions

This section is empty.

Types

type CertificateService

type CertificateService interface {
	// GetCertificate returns a certificate for the given ClientHello
	GetCertificate(*tls.ClientHelloInfo) (*tls.Certificate, error)

	// GetCertificateForDomain returns a certificate for the specified domain
	GetCertificateForDomain(domain string) (*tls.Certificate, error)

	// Domains returns a list of domains this service can provide certificates for
	Domains() []string
}

CertificateService defines the interface for a service that can provide TLS certificates

type ChallengeHandler

type ChallengeHandler interface {
	// PresentChallenge is called when a challenge token needs to be made available
	PresentChallenge(domain, token, keyAuth string) error

	// CleanupChallenge is called when a challenge token needs to be removed
	CleanupChallenge(domain, token, keyAuth string) error
}

ChallengeHandler defines the interface for handlers that can handle ACME challenges

type CloudflareConfig

type CloudflareConfig struct {
	Email    string `yaml:"email" json:"email"`
	APIKey   string `yaml:"api_key" json:"api_key"`
	APIToken string `yaml:"api_token" json:"api_token"`
}

CloudflareConfig holds the configuration for Cloudflare DNS API

type DNSProviderConfig

type DNSProviderConfig struct {
	// Provider is the name of the DNS provider (e.g., "cloudflare", "route53", etc.)
	Provider string `yaml:"provider" json:"provider"`

	// Parameters is a map of provider-specific configuration parameters
	Parameters map[string]string `yaml:"parameters" json:"parameters"`

	// Provider-specific configurations
	Cloudflare   *CloudflareConfig   `yaml:"cloudflare,omitempty" json:"cloudflare,omitempty"`
	Route53      *Route53Config      `yaml:"route53,omitempty" json:"route53,omitempty"`
	DigitalOcean *DigitalOceanConfig `yaml:"digitalocean,omitempty" json:"digitalocean,omitempty"`
}

DNSProviderConfig defines the configuration for DNS challenge providers

type DigitalOceanConfig

type DigitalOceanConfig struct {
	AuthToken string `yaml:"auth_token" json:"auth_token"`
}

DigitalOceanConfig holds the configuration for DigitalOcean DNS API

type HTTPProviderConfig

type HTTPProviderConfig struct {
	// Use the built-in HTTP server for challenges
	UseBuiltIn bool `yaml:"use_built_in" json:"use_built_in"`

	// Port to use for the HTTP challenge server (default: 80)
	Port int `yaml:"port" json:"port"`
}

HTTPProviderConfig defines the configuration for HTTP challenge providers

type LetsEncryptConfig

type LetsEncryptConfig struct {
	// Email is the email address to use for registration with Let's Encrypt
	Email string `yaml:"email" json:"email"`

	// Domains is a list of domain names to obtain certificates for
	Domains []string `yaml:"domains" json:"domains"`

	// UseStaging determines whether to use Let's Encrypt's staging environment
	// Set to true for testing to avoid rate limits
	UseStaging bool `yaml:"use_staging" json:"use_staging"`

	// UseProduction is the opposite of UseStaging, for clarity in configuration
	UseProduction bool `yaml:"use_production" json:"use_production"`

	// StoragePath is the directory where certificates and account information will be stored
	StoragePath string `yaml:"storage_path" json:"storage_path"`

	// RenewBefore sets how long before expiry certificates should be renewed (in days)
	RenewBefore int `yaml:"renew_before" json:"renew_before"`

	// RenewBeforeDays is an alias for RenewBefore for backward compatibility
	RenewBeforeDays int `yaml:"renew_before_days" json:"renew_before_days"`

	// AutoRenew enables automatic certificate renewal
	AutoRenew bool `yaml:"auto_renew" json:"auto_renew"`

	// UseDNS indicates whether to use DNS challenges instead of HTTP
	UseDNS bool `yaml:"use_dns" json:"use_dns"`

	// DNSProvider configuration for DNS challenges
	DNSProvider *DNSProviderConfig `yaml:"dns_provider,omitempty" json:"dns_provider,omitempty"`

	// DNSConfig is a map of DNS provider specific configuration parameters
	DNSConfig map[string]string `yaml:"dns_config,omitempty" json:"dns_config,omitempty"`

	// HTTPProvider configuration for HTTP challenges
	HTTPProvider *HTTPProviderConfig `yaml:"http_provider,omitempty" json:"http_provider,omitempty"`

	// HTTPChallengeHandler is an HTTP handler for HTTP-01 challenges
	HTTPChallengeHandler http.Handler `yaml:"-" json:"-"`

	// CustomCACertificate is a custom CA certificate to be trusted
	CustomCACertificate []byte `yaml:"-" json:"-"`
}

LetsEncryptConfig defines the configuration for the Let's Encrypt module.

func (*LetsEncryptConfig) Validate

func (c *LetsEncryptConfig) Validate() error

Validate checks if the configuration is valid and sets default values where appropriate.

type LetsEncryptModule

type LetsEncryptModule struct {
	// contains filtered or unexported fields
}

LetsEncryptModule represents the Let's Encrypt module

func New

func New(config *LetsEncryptConfig) (*LetsEncryptModule, error)

New creates a new Let's Encrypt module

func (*LetsEncryptModule) Config

func (m *LetsEncryptModule) Config() interface{}

Config returns the module's configuration

func (*LetsEncryptModule) Domains

func (m *LetsEncryptModule) Domains() []string

Domains returns the list of domains this service can provide certificates for

func (*LetsEncryptModule) GetCertificate

func (m *LetsEncryptModule) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error)

GetCertificate implements the CertificateService.GetCertificate method to be used with tls.Config.GetCertificate

func (*LetsEncryptModule) GetCertificateForDomain

func (m *LetsEncryptModule) GetCertificateForDomain(domain string) (*tls.Certificate, error)

GetCertificateForDomain returns a certificate for the specified domain

func (*LetsEncryptModule) Name

func (m *LetsEncryptModule) Name() string

Name returns the name of the module

func (*LetsEncryptModule) RevokeCertificate

func (m *LetsEncryptModule) RevokeCertificate(domain string) error

RevokeCertificate revokes a certificate for the specified domain

func (*LetsEncryptModule) Start

func (m *LetsEncryptModule) Start(ctx context.Context) error

Start initializes the module and starts any background processes

func (*LetsEncryptModule) Stop

func (m *LetsEncryptModule) Stop(ctx context.Context) error

Stop stops any background processes

type Route53Config

type Route53Config struct {
	AccessKeyID     string `yaml:"access_key_id" json:"access_key_id"`
	SecretAccessKey string `yaml:"secret_access_key" json:"secret_access_key"`
	Region          string `yaml:"region" json:"region"`
	HostedZoneID    string `yaml:"hosted_zone_id" json:"hosted_zone_id"`
}

Route53Config holds the configuration for AWS Route53 DNS API

type User

type User struct {
	Email        string
	Registration *registration.Resource
	Key          crypto.PrivateKey // Changed from certcrypto.PrivateKey to crypto.PrivateKey
}

User implements the ACME User interface for Let's Encrypt

func (*User) GetEmail

func (u *User) GetEmail() string

GetEmail returns the email address for the user

func (*User) GetPrivateKey

func (u *User) GetPrivateKey() crypto.PrivateKey

GetPrivateKey returns the private key for the user

func (*User) GetRegistration

func (u *User) GetRegistration() *registration.Resource

GetRegistration returns the registration resource

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL