caddyserver/caddy · error
configuring ACME DB: %v
Error message
configuring ACME DB: %v
What it means
Returned when the smallstep ACME nosql layer (acmeNoSQL.New over the CA's bbolt database) fails to initialize its table schema on the ACME database. This happens during provisioning of the `acme_server` handler, after the authority is created. The %v wraps the underlying nosql/bbolt error (usually file open, permissions, or corruption).
Source
Thrown at modules/caddypki/acmeserver/acmeserver.go:197
Claims: &provisioner.Claims{
MinTLSDur: &provisioner.Duration{Duration: 5 * time.Minute},
MaxTLSDur: &provisioner.Duration{Duration: 24 * time.Hour * 365},
DefaultTLSDur: &provisioner.Duration{Duration: time.Duration(ash.Lifetime)},
},
},
},
},
DB: database,
}
ash.acmeAuth, err = ca.NewAuthority(authorityConfig)
if err != nil {
return err
}
ash.acmeDB, err = acmeNoSQL.New(ash.acmeAuth.GetDatabase().(nosql.DB))
if err != nil {
return fmt.Errorf("configuring ACME DB: %v", err)
}
ash.acmeClient, err = ash.makeClient()
if err != nil {
return err
}
ash.acmeLinker = acme.NewLinker(
ash.Host,
strings.Trim(ash.PathPrefix, "/"),
)
// extract its http.Handler so we can use it directly
r := chi.NewRouter()
r.Route(ash.PathPrefix, func(r chi.Router) {
api.Route(r)
})
ash.acmeEndpoints = rView on GitHub (pinned to 50e54ee279)
Solutions
- Check the wrapped cause — bbolt errors like `timeout` indicate the file is locked by another process; find and stop it
- Verify write permissions on the storage path returned by `caddy list-modules`/AppDataDir (typically ~/.local/share/caddy/acme_server/<ca-id>/)
- If the db file is corrupt and the CA data is expendable, stop Caddy, remove the acme_server/<key> folder (clients must re-enroll), and restart
- Ensure only one Caddy instance uses the same data dir
Example fix
# before: read-only volume mount docker run -v /caddy-data:/data:ro caddy # after: writable mount docker run -v /caddy-data:/data caddy
Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight the database path before provisioning the handler:
dir := filepath.Join(caddy.AppDataDir(), "acme_server", key)
if f, err := os.OpenFile(filepath.Join(dir, "db"), os.O_RDWR, 0o600); err != nil {
return fmt.Errorf("acme db not writable: %w", err)
} else { f.Close() } Try / catch
// On provisioning failure, distinguish lock contention (retryable) from corruption (not):
if err := ash.provision(); err != nil {
if strings.Contains(err.Error(), "timeout") || strings.Contains(err.Error(), "locked") {
time.Sleep(time.Second) // then retry once with backoff
} else {
return err // corrupt db / permissions: needs manual intervention
}
} Prevention
- Ensure only one Caddy instance owns a given data dir
- Mount the acme_server data dir on a writable, fsync-safe volume
- Snapshot the acme_server folder alongside regular config backups
When it happens
Trigger: Two `acme_server` handlers pointed at the same CA but racing to init the DB during overlapping config loads; the data dir file ($AppDataDir/acme_server/<key>/db) is corrupt, truncated, or locked by another process; disk full or read-only filesystem where bbolt cannot create/open the file.
Common situations: Running Caddy in a container with the data dir on a read-only volume or a volume that lost data mid-write; migrating data dirs between Caddy versions; another Caddy instance or a leftover process holding a flock on the bbolt file; a previously killed Caddy leaving a torn db file.
Related errors
- making folder for CA database: %v
- certificate lifetime (%s) should be less than intermediate c
- resolver address must have exactly one address; cannot call
- acme challenge %q is not supported
- loading trusted root CA's PEM file: %s: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/4f0823f45ba42f5f.
Report an issue: GitHub.