caddyserver/caddy · error

failed to load network_proxy module: %v

Error message

failed to load network_proxy module: %v

What it means

Returned while building the ACME issuer template (modules/caddytls/acmeissuer.go:271) when ctx.LoadModule fails to load the configured network proxy module for the issuer (network_proxy directive, JSON "network_proxy_raw"). Wrapped causes: the proxy module name is not registered in this build, or the module's own provisioning failed (bad proxy URL, unsupported scheme).

Source

Thrown at modules/caddytls/acmeissuer.go:271

func (iss *ACMEIssuer) makeIssuerTemplate(ctx caddy.Context) (certmagic.ACMEIssuer, error) {
	template := certmagic.ACMEIssuer{
		CA:                iss.CA,
		TestCA:            iss.TestCA,
		Email:             iss.Email,
		Profile:           iss.Profile,
		AccountKeyPEM:     iss.AccountKey,
		CertObtainTimeout: time.Duration(iss.ACMETimeout),
		TrustedRoots:      iss.rootPool,
		ExternalAccount:   iss.ExternalAccount,
		NotAfter:          time.Duration(iss.CertificateLifetime),
		Logger:            iss.logger,
	}

	if len(iss.NetworkProxyRaw) != 0 {
		proxyMod, err := ctx.LoadModule(iss, "NetworkProxyRaw")
		if err != nil {
			return template, fmt.Errorf("failed to load network_proxy module: %v", err)
		}
		if m, ok := proxyMod.(caddy.ProxyFuncProducer); ok {
			template.HTTPProxy = m.ProxyFunc()
		} else {
			return template, fmt.Errorf("network_proxy module is not `(func(*http.Request) (*url.URL, error))``")
		}
	}

	if iss.Challenges != nil {
		if iss.Challenges.HTTP != nil {
			template.DisableHTTPChallenge = iss.Challenges.HTTP.Disabled
			template.AltHTTPPort = iss.Challenges.HTTP.AlternatePort
		}
		if iss.Challenges.TLSALPN != nil {
			template.DisableTLSALPNChallenge = iss.Challenges.TLSALPN.Disabled
			template.AltTLSALPNPort = iss.Challenges.TLSALPN.AlternatePort
		}
		if iss.Challenges.DNS != nil {

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Check caddy list-modules for the network proxy module; if absent, build with xcaddy and the plugin's --with flag
  2. Read the wrapped error for the module's own provisioning failure and fix its options (valid URL, supported scheme)
  3. Correct the module name spelling to match its registered ID
  4. If direct egress works, remove the network_proxy directive

Example fix

# before
 example.com {
   tls {
     issuer acme {
       network_proxy connect {
         address proxy.internal:3128
       }
     }
   }
 }

# after: build with the proxy plugin first
xcaddy build --with github.com/mholt/caddy-network-proxy-connect
# keep config; verify module present:
caddy list-modules | grep network_proxy
Defensive patterns

Strategy: validation

Validate before calling

# before deploying a config with network_proxy, assert the module is built in
caddy list-modules | grep -q 'network_proxy' || {
  echo "network_proxy module missing; rebuild: xcaddy build --with <plugin>"; exit 1; }

Try / catch

if err := issuer.Provision(ctx); err != nil {
    if strings.Contains(err.Error(), "failed to load network_proxy module") {
        // missing plugin (rebuild binary) or invalid proxy options (fix address/scheme)
    }
    return err
}

Prevention

When it happens

Trigger: Configuring an ACME issuer with network_proxy <module> where the module is a third-party plugin (e.g. forwarded_connect or custom HTTP connect proxies) not compiled into the binary, or where the module's options (address, scheme) are invalid so its Provision errors.

Common situations: Routing ACME traffic through a corporate proxy on air-gapped networks; configs migrated from an xcaddy build to the stock binary; plugin renamed or its option schema changed between versions; typo in the module name.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/35ea52168d5ad5ce. Report an issue: GitHub.