Help us shape the future of Go! Take the 2026 Go Developer Survey

autotls

package module
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 13 Imported by: 254

README

autotls

Run Tests Trivy Security Scan Go Reference

Support Let's Encrypt for a Go server application.

Listening addresses

Use RunWithOptions(ctx, handler, options...) to choose both listening addresses without changing the existing Run, RunWithContext, or custom-manager APIs:

err := autotls.RunWithOptions(ctx, r,
  autotls.WithHTTPAddr("192.0.2.10:80"),
  autotls.WithHTTPSAddr("192.0.2.10:443"),
  autotls.WithDomains("example.com"),
)

Replace the sample IP with an address assigned to the intended interface and the domain with one you control. For IPv6, use brackets, such as [2001:db8::10]:443. Empty addresses default to :80 and :443 (all interfaces). Both listeners use the supplied addresses, including the HTTPS listener; no package-wide mutable address setting is needed.

Use WithManager instead of WithDomains to supply a custom autocert.Manager and host policy. A non-nil manager with non-empty domains is an error. A nil manager uses the default disk cache and accepts the CA terms of service; explicitly list domains to limit issuance. WithTLSConfig is optional and its configuration is cloned before installing the manager's certificate callback and ALPN protocols.

Options are applied in order; the last option for each setting wins. Nil options are rejected. WithDomains copies its input, so changing the original slice does not change the option. Existing callers can continue using the original Run helpers without adopting this new entry point.

Both listeners must bind before serving. A startup failure closes any listener already opened. Canceling ctx shuts down both servers, allowing up to five seconds for active requests before closing remaining connections. Successful shutdown returns nil; a context canceled before startup returns its error.

Binding an internal address does not make it reachable to the CA. Public TCP port 80 (HTTP-01) or 443 (TLS-ALPN-01) must still reach the appropriate challenge handler, directly or through forwarding. The new entry point uses autocert's default HTTP fallback: GET/HEAD redirect with 302 to public HTTPS port 443, preserving path and query, and other methods receive 400. The redirect does not use the local WithHTTPSAddr port. Existing helpers keep their existing behavior.

Before running the examples

Replace example1.com and example2.com with public domain names you control. Point their DNS records to your server and allow inbound traffic on TCP ports 80 and 443. The Run example uses TLS-ALPN-01 validation on public port 443, so a TLS-terminating proxy in front of it must not intercept that challenge.

Visit https://your-domain.example/ping using your configured domain, rather than https://localhost:443/ping. The hostname selects the certificate during the TLS handshake. Let's Encrypt does not issue certificates for localhost, and merely editing your local hosts file does not make your server reachable to its public validation service. See Let's Encrypt's localhost guidance.

For a local HTTP-only check of the /ping handler, replace the example's autotls.Run(...) line with log.Fatal(r.Run("127.0.0.1:8080")) and remove the unused autotls import. Then visit http://127.0.0.1:8080/ping; the response should be pong. For local HTTPS, use a locally trusted development certificate with Gin's RunTLS instead of requesting a public certificate for localhost.

example

example for 1-line LetsEncrypt HTTPS servers.

package main

import (
  "log"
  "net/http"

  "github.com/gin-gonic/autotls"
  "github.com/gin-gonic/gin"
)

func main() {
  r := gin.Default()

  // Example handler
  r.GET("/ping", func(c *gin.Context) {
    c.String(http.StatusOK, "pong")
  })

  // Start HTTPS server with automatic Let's Encrypt certificate management and HTTP-to-HTTPS redirection.
  // The server runs until interrupted and shuts down gracefully.
  log.Fatal(autotls.Run(r, "example1.com", "example2.com"))
}

example for custom autocert manager.

package main

import (
  "log"
  "net/http"

  "github.com/gin-gonic/autotls"
  "github.com/gin-gonic/gin"
  "golang.org/x/crypto/acme/autocert"
)

func main() {
  r := gin.Default()

  // Example handler
  r.GET("/ping", func(c *gin.Context) {
    c.String(http.StatusOK, "pong")
  })

  // Advanced: Use a custom autocert.Manager for certificate management.
  // This allows for custom cache location, host policy, and other settings.
  m := autocert.Manager{
    Prompt:     autocert.AcceptTOS,
    HostPolicy: autocert.HostWhitelist("example1.com", "example2.com"),
    Cache:      autocert.DirCache("/var/www/.cache"),
  }

  // Start HTTPS server with the custom autocert.Manager and HTTP-to-HTTPS redirection.
  log.Fatal(autotls.RunWithManager(r, &m))
}
Custom TLS settings

Use RunWithManagerAndTLSConfig to configure TLS settings, including tls.Config.CipherSuites. See the runnable custom TLS example.

Prefer Go's default cipher suite selection unless your deployment requires an explicit policy. CipherSuites only controls TLS 1.0–1.2; TLS 1.3 cipher suites are not configurable. The example permits TLS 1.2 and newer and illustrates an explicit TLS 1.2 allowlist for both RSA and ECDSA certificates.

The helper sets GetCertificate and NextProtos on the supplied configuration to preserve autocert certificate management and ACME ALPN support. Pass tlsConfig.Clone() if the original configuration is shared or must remain unchanged. See Go's tls.Config documentation for the meaning of each setting.

example usage for graceful shutdown with custom context.

package main

import (
  "context"
  "log"
  "net/http"
  "os/signal"
  "syscall"

  "github.com/gin-gonic/autotls"
  "github.com/gin-gonic/gin"
)

func main() {
  // Create a context that listens for interrupt signals (SIGINT, SIGTERM) from the OS.
  // This enables graceful shutdown of the HTTPS server.
  ctx, stop := signal.NotifyContext(
    context.Background(),
    syscall.SIGINT,
    syscall.SIGTERM,
  )
  defer stop()

  r := gin.Default()

  // Example handler
  r.GET("/ping", func(c *gin.Context) {
    c.String(http.StatusOK, "pong")
  })

  // Start HTTPS server with automatic Let's Encrypt certificate management,
  // HTTP-to-HTTPS redirection, and graceful shutdown support.
  // The server will shut down cleanly when the context is cancelled.
  log.Fatal(autotls.RunWithContext(ctx, r, "example1.com", "example2.com"))
}

Using a different local port

Run, RunWithContext, RunWithManager, and RunWithManagerAndTLSConfig use ports 80 and 443. To use different local ports, pass WithHTTPAddr and WithHTTPSAddr to RunWithOptions; see the runnable custom ports example, which binds HTTP to 127.0.0.1:8080 and HTTPS to 127.0.0.1:8443.

Local listening ports and public ACME validation ports are separate settings. Let's Encrypt's HTTP-01 challenge uses public port 80, and TLS-ALPN-01 uses public port 443. For the example, arrange forwarding from public port 80 to local 8080 and public port 443 to local 8443. TLS-ALPN-01 requires the TLS connection and its ALPN protocol to reach this server; a proxy that terminates TLS must instead allow HTTP-01 to reach the origin. Merely opening public port 8443 is not sufficient for ACME validation.

The example's HTTP redirects target the domain's public HTTPS port 443, not 8443. With forwarding in place, visit https://your-domain.example/ping and expect HTTP 204. Replace the sample domain with one you control and retain the certificate cache on persistent storage. The example handles SIGINT/SIGTERM to shut down both local listeners.

Wildcard certificates

autotls does not obtain wildcard certificates such as *.example.com. Its underlying autocert.Manager supports HTTP-01 and TLS-ALPN-01 validation, while Let's Encrypt requires DNS-01 validation for wildcard certificates.

For a known set of hostnames, pass each name explicitly, for example:

log.Fatal(autotls.Run(r, "example.com", "www.example.com", "api.example.com"))

These names must resolve to your server and be reachable for ACME validation. autocert.HostWhitelist matches exact names; passing *.example.com does not authorize all subdomains or enable DNS-01 support.

If you need a wildcard certificate, obtain and renew it with a separate ACME client that supports your DNS provider, then serve it through your own TLS server or reverse proxy. That client must manage renewal and your TLS server must load renewed certificates; autotls does not manage that external workflow.

Certificate renewal

Yes, autotls renews certificates automatically through autocert.Manager. The manager schedules renewal for certificates it obtains or loads while the server is running; you do not need a separate renewal cron job or a server restart to serve a renewed certificate.

Keep the server running and the domain's ACME challenge endpoint reachable for renewal, just as for initial issuance. Run and RunWithContext use TLS-ALPN-01 on public port 443. The custom-manager helpers also enable HTTP-01 on public port 80. Outbound access to the ACME service is required.

Keep the certificate cache on persistent, writable storage across restarts (including container replacements). The default cache uses an OS-specific golang-autocert directory; set Manager.Cache to an autocert.DirCache on a persistent volume when using RunWithManager. Losing the cache can cause unnecessary issuance requests and CA rate limits.

For custom renewal timing, set Manager.RenewBefore before passing the manager to RunWithManager. Its default timing is defined by the installed autocert version; see the linked Manager documentation. Renewal still depends on successful domain validation and network access, so monitor certificate expiry and server errors.

PSA: Running autotls inside Docker

If you run autotls in minimal Docker images (Debian, Ubuntu, Fedora, or similar), HTTPS and ACME certificate operations will fail unless you ensure the image contains x509 root CA certificates. By default, smaller base images do not include these certificates.

To fix this, add the following steps in your Dockerfile:

RUN apt-get update && apt-get install -y ca-certificates
RUN update-ca-certificates

This is not needed with official Golang images or most large distributions, but is essential for cut-down base images.

If omitted, you may get unexplained HTTPS/x509 errors when using autotls.

Documentation

Overview

Package autotls support Let's Encrypt for a Go server application.

package main

import (
  "log"

  "github.com/gin-gonic/autotls"
  "github.com/gin-gonic/gin"
)

func main() {
  r := gin.Default()

  // Ping handler
  r.GET("/ping", func(c *gin.Context) {
    c.String(200, "pong")
  })

  log.Fatal(autotls.Run(r, "example1.com", "example2.com"))
}

Index

Constants

This section is empty.

Variables

View Source
var ReadHeaderTimeout = 3 * time.Second

ReadHeaderTimeout is the maximum duration for reading the headers of the request.

Functions

func Run

func Run(r http.Handler, domain ...string) error

Run starts an HTTPS server with automatic Let's Encrypt certificate management and HTTP to HTTPS redirection. The server runs until interrupted and shuts down gracefully.

func RunWithContext added in v0.0.5

func RunWithContext(ctx context.Context, r http.Handler, domain ...string) error

RunWithContext starts an HTTPS server with automatic Let's Encrypt certificate management, HTTP-to-HTTPS redirection, and graceful shutdown. The provided context controls server lifetime.

func RunWithManager

func RunWithManager(r http.Handler, m *autocert.Manager) error

RunWithManager starts an HTTPS server using a custom autocert.Manager for certificate administration. Useful for advanced autocert settings; includes HTTP to HTTPS redirection.

func RunWithManagerAndTLSConfig added in v0.0.4

func RunWithManagerAndTLSConfig(r http.Handler, m *autocert.Manager, tlsc *tls.Config) error

RunWithManagerAndTLSConfig starts an HTTPS server using a custom autocert.Manager and custom tls.Config, with HTTP to HTTPS redirection. Allows advanced TLS and certificate settings. r - HTTP handler for HTTPS requests m - autocert.Manager, manages certificate issuance and renewal tlsc - Custom TLS configuration to control various certificate and protocol settings

func RunWithOptions added in v1.3.0

func RunWithOptions(ctx context.Context, r http.Handler, options ...Option) error

RunWithOptions serves HTTPS and HTTP ACME challenges on the configured addresses. Non-challenge HTTP requests redirect to HTTPS. Both listeners must start successfully before either server begins serving. The existing Run helpers are unchanged; use this entry point to restrict the listening interfaces.

ACME validation must still reach public port 80 (HTTP-01) or 443 (TLS-ALPN-01), even when a proxy forwards those ports to different local listening ports. Redirects target the standard public HTTPS port, not the local HTTPS listener port. Options are applied in order; the last value for each setting wins. Nil options are rejected. Non-empty WithDomains and a non-nil WithManager cannot be combined. On context cancellation, both servers have up to five seconds to shut down; successful shutdown returns nil. An already-canceled context returns its error.

Types

type Option added in v1.3.0

type Option func(*serverConfig)

Option configures RunWithOptions. Use the With functions to create options.

func WithDomains added in v1.3.0

func WithDomains(domains ...string) Option

WithDomains restricts certificate issuance when no custom manager is supplied. An empty list allows any domain, which is not recommended. The names are copied when the option is created. Do not combine a non-empty list with a non-nil WithManager.

func WithHTTPAddr added in v1.3.0

func WithHTTPAddr(addr string) Option

WithHTTPAddr sets the HTTP challenge and redirect address. Empty means ":80".

func WithHTTPSAddr added in v1.3.0

func WithHTTPSAddr(addr string) Option

WithHTTPSAddr sets the HTTPS application address. Empty means ":443".

func WithManager added in v1.3.0

func WithManager(manager *autocert.Manager) Option

WithManager supplies certificate management and its host policy. Nil selects the default manager. If its Cache is nil, RunWithOptions sets the default disk cache before use. Do not modify or start using the manager concurrently during setup. Do not combine a non-nil manager with non-empty WithDomains.

func WithTLSConfig added in v1.3.0

func WithTLSConfig(config *tls.Config) Option

WithTLSConfig supplies TLS settings. Nil selects the manager's default TLS configuration. A non-nil configuration is cloned before setting GetCertificate and NextProtos from the certificate manager.

Directories

Path Synopsis
_example
custom-ports command
Example non-standard local ports behind public ACME port forwarding.
Example non-standard local ports behind public ACME port forwarding.
custom-tls command
Example custom TLS policy using autotls's existing configuration helper.
Example custom TLS policy using autotls's existing configuration helper.
example1 command
example2 command
example3 command

Jump to

Keyboard shortcuts

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