Running smallstep behind caddy

1. The problem I’m having:

I am trying to make my ca available from public internet. I successfully did it by forwarding the whole port :9000 on my router (my step-ca operates on this port via https://).

However I would like to follow this advice, but I do not know how to do it with Caddy (note: my caddy and my smallstep are on 2 different internal hosts).

I tried this in Caddyfile: {
  reverse_proxy https://odroid.lan:9000 {
    transport http {

but when issuing on client

step ca certificate --ca-url= lukasz tmp3.crt tmp3.key

2. Error messages and/or full log output:

I am getting

client GET failed: x509: certificate signed by unknown authority

I suppose my current setup makes Caddy to wrap and sign again communication using its own cert. And smallstep does not expect that.

3. Caddy version:

v2.7.5 h1:HoysvZkLcN2xJExEepaFHK92Qgs7xAiCFydN5x5Hs6Q=

4. How I installed and ran Caddy:

a. System environment:

Docker version 20.10.24+dfsg1, build 297e128

b. Command:

docker compose up

c. Service/unit/compose file:

    image: caddy:latest
    restart: always
    container_name: caddy
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./certs:/certs
      - ./config:/config
      - ./data:/data
      - ./sites:/srv
    network_mode: host

d. My complete Caddy config: {
  reverse_proxy https://odroid.lan:9000 {
    transport http {

5. Links to relevant resources:

FYI @maraino if you have any insight?

I don’t know what the smallstep CA needs from an HTTP standpoint, so I’m not sure what to suggest.

There are different things going on here. The actual problem here is that you should have a root certificate in your STEPPATH (step path) which defaults to ~/.step/certs/root_ca.crt. The cli will default to that one unless you provide the --root flag. You are probably getting a Web PKI from zerrossl/letsencrypt and that doesn’t match the root in that file.

Because step ca commands are intended to be used with an step-ca, they require a root certificate and it will not trust the system settings. So if you need to tell step to use a root or a root bundle that includes the root certificate for you zerossl/letsencrypt intermediate. Different OS install those in files like in /etc/ssl/certs or similar paths or in their own keychain.

Although you can configure a HTTP reverse proxy and step with the right with the right root and it will work. step is not designed to work like that, it’s a CA for an private PKI.

A better approach would be, either use a layer 4 proxy (TCP proxy) see Modules - Caddy Documentation, or tell caddy to use a certificate from an ACME server from step-ca like this:

my.public.dns {
  reverse_proxy https://ca.lan:9000 {
    transport http {
      tls_trusted_ca_certs "/path/to/step-ca/root_ca.crt"
  tls {
    ca https://ca.lan:9000/acme/acme/directory

Depending on the provisioner that you use, this configuration won’t be enough, for example for using the default JWK provisioner, the CA expects the audience to match one of its dnsNames in the ca.json, in the above case, to use JWK you will need to add my.public.dns to you ca.json.

1 Like

Thank you. I will give it a try after holiday.

For others, I found this - explaining details of ACME.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.