Skip to content

raghavyuva/caddygo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

4 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

CaddyGo

Go Version Go Report Card License

A simple Go library for managing Caddy server configurations through its admin API. CaddyGo provides a clean, intuitive interface to add, remove, and configure domains with automatic or custom TLS certificates, following Go best practices and clean architecture principles.

โœจ Features

  • Domain Management: Add and remove domains with ease
  • Automatic TLS: Support for Let's Encrypt and other ACME providers
  • Custom Certificates: Use your own TLS certificates
  • Security Headers: Configurable security headers (HSTS, X-Frame-Options, etc.)
  • Compression: Enable gzip and zstd compression
  • Redirects: Support for www/non-www redirects
  • Configuration Reload: Force Caddy to reload configurations
  • Clean Architecture: Well-organized, maintainable codebase

๐Ÿ“ฆ Installation

go get github.com/raghavyuva/caddygo

Quick Start

package main

import (
    "log"
    "github.com/raghavyuva/caddygo"
)

func main() {
    // Create a new client
    client := caddygo.NewClient("http://localhost:2019")
    
    // Configure domain options
    options := caddygo.DomainOptions{
        EnableSecurityHeaders: true,
        EnableHSTS:           true,
        EnableCompression:    true,
        RedirectMode:         "www_to_domain",
    }
    
    // Add a domain with automatic TLS
    err := client.AddDomainWithAutoTLS("example.com", "localhost", 8080, options)
    if err != nil {
        log.Fatal(err)
    }
    
    // Reload configuration
    err = client.Reload()
    if err != nil {
        log.Fatal(err)
    }
    
    log.Println("Domain configured successfully!")
}

Package Architecture

CaddyGo is organized into focused, single-responsibility modules:

caddygo/
โ”œโ”€โ”€ types.go      # Type definitions and interfaces
โ”œโ”€โ”€ client.go     # HTTP client and request handling
โ”œโ”€โ”€ domain.go     # Domain management operations
โ”œโ”€โ”€ tls.go        # TLS and certificate management
โ”œโ”€โ”€ config.go     # Configuration helpers and utilities
โ””โ”€โ”€ caddygo.go    # Package entry point

API Reference

Core Types

Client

The main client for interacting with Caddy's admin API.

type Client struct {
    BaseURL    string        // Base URL of Caddy's admin API
    HTTPClient *http.Client  // HTTP client for API requests
}

DomainOptions

Configuration options for domain setup.

type DomainOptions struct {
    EnableSecurityHeaders bool   // Enable security-related HTTP headers
    EnableHSTS           bool   // Enable HTTP Strict Transport Security
    FrameOptions         string // X-Frame-Options header value
    EnableCompression    bool   // Enable gzip and zstd compression
    RedirectMode         string // Redirect behavior: "www_to_domain" or "domain_to_www"
}

Client Methods

NewClient

Creates a new Caddy API client.

func NewClient(baseURL string) *Client

Parameters:

Returns: A configured Client instance

AddDomainWithAutoTLS

Adds a domain with automatic TLS configuration using Let's Encrypt or other ACME providers.

func (c *Client) AddDomainWithAutoTLS(domain, target string, targetPort int, options DomainOptions) error

Parameters:

  • domain: The domain name to configure (e.g., "example.com")
  • target: The target hostname or IP address
  • targetPort: The target port number
  • options: Configuration options for security, compression, and redirects

Returns: Error if configuration fails

AddDomainWithTLS

Adds a domain with a custom TLS certificate.

func (c *Client) AddDomainWithTLS(domain, target string, targetPort int, certificate, privateKey string, options DomainOptions) error

Parameters:

  • domain: The domain name to configure
  • target: The target hostname or IP address
  • targetPort: The target port number
  • certificate: PEM-encoded certificate content
  • privateKey: PEM-encoded private key content
  • options: Configuration options

Returns: Error if configuration fails

DeleteDomain

Removes a domain configuration and all associated routes, TLS policies, and automation rules.

func (c *Client) DeleteDomain(domain string) error

Parameters:

  • domain: The domain name to remove

Returns: Error if deletion fails

Reload

Forces a reload of the Caddy configuration with cache invalidation.

func (c *Client) Reload() error

Returns: Error if reload fails

Usage Examples

Basic Domain Setup with Auto TLS

client := caddygo.NewClient("http://localhost:2019")

options := caddygo.DomainOptions{
    EnableSecurityHeaders: true,
    EnableHSTS:           true,
    EnableCompression:    true,
}

err := client.AddDomainWithAutoTLS("myapp.com", "localhost", 3000, options)
if err != nil {
    log.Fatalf("Failed to configure domain: %v", err)
}

err = client.Reload()
if err != nil {
    log.Fatalf("Failed to reload config: %v", err)
}

Custom Certificate Configuration

certificate := `-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKoK/OvH8T5TMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTkwMzI2MTIzNDU5WhcNMjAwMzI1MTIzNDU5WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAu1SUU7/3KryQigDTTw8cFDIehIUWqqK9t20Df1StvAhx3Xmddp/Wm3H
-----END CERTIFICATE-----`

privateKey := `-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7VJTUt9Us8cKj
MzEfYyjiWA4R4/M2bS1GB4t7NXp98C3SC6dVMvDuictGeurT8jNbvJZHtCSuYEvu
NMoSfm76oqFvAp8Gy0iz5sxjZmSnXyCdPEovGhLa0VzMaQ8s+CLOyS56YyCFGeJZ
-----END PRIVATE KEY-----`

options := caddygo.DomainOptions{
    EnableSecurityHeaders: true,
    EnableHSTS:           true,
    FrameOptions:          "SAMEORIGIN",
    EnableCompression:     true,
}

err := client.AddDomainWithTLS("secure.myapp.com", "localhost", 8443, certificate, privateKey, options)

Bulk Domain Management

domains := []struct {
    name   string
    target string
    port   int
}{
    {"api.myapp.com", "localhost", 3001},
    {"admin.myapp.com", "localhost", 3002},
    {"cdn.myapp.com", "localhost", 3003},
}

for _, d := range domains {
    options := caddygo.DomainOptions{
        EnableSecurityHeaders: true,
        EnableCompression:     true,
        RedirectMode:          "www_to_domain",
    }
    
    err := client.AddDomainWithAutoTLS(d.name, d.target, d.port, options)
    if err != nil {
        log.Printf("Failed to add domain %s: %v", d.name, err)
        continue
    }
    
    log.Printf("Successfully configured domain: %s", d.name)
}

// Reload all configurations at once
err := client.Reload()
if err != nil {
    log.Fatalf("Failed to reload configuration: %v", err)
}

Domain Cleanup

// Remove a specific domain
err := client.DeleteDomain("old.example.com")
if err != nil {
    log.Printf("Failed to remove domain: %v", err)
}

// Remove multiple domains
domainsToRemove := []string{"staging.example.com", "test.example.com"}
for _, domain := range domainsToRemove {
    err := client.DeleteDomain(domain)
    if err != nil {
        log.Printf("Failed to remove %s: %v", domain, err)
    }
}

// Reload to apply changes
err = client.Reload()

Configuration Options

Security Headers

options := caddygo.DomainOptions{
    EnableSecurityHeaders: true,
    EnableHSTS:           true,
    FrameOptions:          "DENY", // Options: "DENY", "SAMEORIGIN", "ALLOW-FROM"
}

Compression

options := caddygo.DomainOptions{
    EnableCompression: true, // Enables both gzip and zstd compression
}

Redirects

options := caddygo.DomainOptions{
    RedirectMode: "www_to_domain", // Options: "www_to_domain", "domain_to_www"
}

Error Handling

CaddyGo provides descriptive errors for various failure scenarios:

err := client.AddDomainWithAutoTLS("example.com", "localhost", 8080, options)
if err != nil {
    switch {
    case strings.Contains(err.Error(), "failed to get current config"):
        log.Println("Unable to connect to Caddy admin API")
    case strings.Contains(err.Error(), "failed to marshal"):
        log.Println("Configuration serialization error")
    case strings.Contains(err.Error(), "failed to update config"):
        log.Println("Failed to update Caddy configuration")
    default:
        log.Printf("Unexpected error: %v", err)
    }
    return
}

Requirements

  • Go: 1.21 or later
  • Caddy: v2 with admin API enabled
  • Network: Access to Caddy's admin endpoint

Testing

Run the test suite:

go test -v

Run with coverage:

go test -cover

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ™ Acknowledgments


Made with โค๏ธ for the Go community

About

A simple Go library for managing Caddy server configurations through its admin API.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages