1. The problem I’m having:
When specifying local_certs
in global options, and while running in alpine, I get a warning that the root cert can’t be installed. I presume this is happening when the local un-trusted CA is created and Caddy (smallstep/truststore?) tries to inject the CA into the system trust.
Neither package is listed in Alpine. I found nss
, installed it, and I still get the same error. I looked into the caddy and truststore code, it seems this log message prints when it tries to install the CA certificate into the mozilla profiles, which are almost definitely not part of an alpine container.
Looking through the code, I don’t see any way to conditionally skip this step.
I’d like to eliminate the warning.
2. Error messages and/or full log output:
{"level":"warn","ts":1746819871.0233943,"logger":"pki.ca.local","msg":"installing root certificate (you might be prompted for password)","path":"storage:pki/authorities/local/root.crt"}
2025-05-09T19:44:31.024384967Z {"level":"info","ts":1746819871.0243294,"msg":"warning: \"certutil\" is not available, install \"certutil\" with \"apt install libnss3-tools\" or \"yum install nss-tools\" and try again"}
3. Caddy version:
Caddy version v2.10.0 h1:fonubSaQKF1YANl8TXqGcn4IbIRUDdfAkpcsfI/vX5U=
4. How I installed and ran Caddy:
FROM caddy:2.10.0-builder AS builder
RUN xcaddy build \
--with github.com/caddyserver/cache-handler \
--with github.com/darkweak/storages/badger/caddy \
--with github.com/gamalan/caddy-tlsredis@master
# re-create caddy dockerfile https://github.com/caddyserver/caddy-docker/tree/master
FROM alpine:3.21.3
RUN apk add --no-cache \
ca-certificates \
libcap \
mailcap \
curl
RUN set -eux; \
mkdir -p \
/config/caddy \
/data/caddy \
/etc/caddy \
/usr/share/caddy \
;
# https://github.com/caddyserver/caddy/releases
ENV CADDY_VERSION v2.10.0
# See https://caddyserver.com/docs/conventions#file-locations for details
ENV XDG_CONFIG_HOME /config
ENV XDG_DATA_HOME /data
VOLUME /config
VOLUME /data
EXPOSE 80
EXPOSE 443
EXPOSE 443/udp
EXPOSE 2019
WORKDIR /srv
#HEALTHCHECK CMD curl -f http://localhost/ || exit 1
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
# Update mime types
COPY ./build/configs/mime.types /tmp/mime.types.tmp
RUN cat /tmp/mime.types.tmp >> /etc/mime.types
COPY ./build/configs/bootstrap.sh /bootstrap.sh
CMD ["sh", "/bootstrap.sh"]
a. System environment:
See dockerfile
above
d. My complete Caddy config:
{
order cache before rewrite
{$caddy_globalOptions}
email {$tls_acmeEmail}
storage redis {
module redis
address {$redis_host}:{$redis_port}
db {$redis_database_caddy}
password {$redis_password}
key_prefix "caddy:"
tls_enabled false
tls_insecure false
aes_key "redistls-x123456789x-caddytls-32"
}
cache {
ttl 60s
badger
}
# When connecting via an IP address, no certificate will be found; this sets a default certificate
default_sni {$site_host}
# listen for connections beyond localhost
admin :2019
#debug
metrics
}
(turbokivaweb) {
encode gzip
log
@sendToOldServer {
header_regexp migrationCookie Cookie {$migration_cookie}=([^;]*)
not {
header x-sentToOldServer 1
}
}
@exploitPaths {
path /wp-login.php /xmlrpc.php /assets/images/s_eval.php
}
handle @exploitPaths {
respond 400
}
handle /static/* {
@nocache {
query v=nocache
}
@cache {
not {
query v=nocache
}
}
# 1 year; version-based cache busting is in place
header @cache Cache-Control "max-age=31536000, immutable"
header @nocache Cache-Control "no-store"
cache {
# cache so gzipped files don't get re-gzipped
ttl 60s
}
header X-Content-Type-Options nosniff
file_server {
root /app/turbokiva/web
}
}
handle /robots.txt {
file_server {
root /app/turbokiva/web/static
}
}
handle /favicon.ico {
file_server {
root /app/turbokiva/web/static/favicon
}
}
handle {$documentUpload_path}* {
reverse_proxy documentrouterandextractor:80
}
handle @sendToOldServer {
reverse_proxy {
to {$migration_oldServerHost}:{$web_portMigration}
header_up x-sentToOldServer 1
}
}
handle {
header Cache-Control no-cache
header X-Content-Type-Options nosniff
header -x-powered-by
php_fastcgi php{$web_upstreamSuffix}:9000
}
handle_errors {
rewrite * /static/errorPages/general.html
templates
file_server
}
}
# Redirect www.
www.{$site_host}:{$web_portSecure} {
redir https://{$site_host}{uri}
}
# The first matcher matches the hostname, the second matcher matches all IP addresses
https://{$site_host}:{$web_portSecure}, https://:{$web_portSecure} {
import turbokivaweb
# Will automatically get HTTPS because prefixed with https://
# Auto-HTTPS will setup http redirect to https
}
# Insecure for reverse proxy during migration
http://{$site_host}:{$web_portMigration} {
import turbokivaweb
# Won't automatically get HTTPS because port isn't 443
}
# Used by unit test on local and teamcity
https://localhost:{$web_portSecure} {
import turbokivaweb
# Will automatically get HTTPS because prefixed with https://
# Auto-HTTPS will setup http redirect to https
}
http://localhost:{$web_port} {
import turbokivaweb
}