Wildcard Selfhosting

1. My Caddy version (caddy version):

v1.0.4

2. How I run Caddy:

for now as a command but eventually as a systemd service

a. System environment:

ubuntu 18.04

I’m a completely new to caddy. I’m not sure if i’m framing my question right

this is what i want to achieve

  1. Have a wildcard acme cert for *.domain.com

  2. create reverse proxy entries for

bitwarden.domain.com, listening on 192.168.10.50:8088 (http)

nextcloud.domain.com, listening on 192.168.10.50:8080 (http)

running in docker containers on the same docker host

i tested my basic config & it works. i’m able to get a cert . i’m getting stuck on the reverse proxy thing

this is what i have in my Caddyfile.

*.domain.com {

tls {
dns cloudflare
wildcard
}

#bitwarden
proxy / 192.168.10.50:8088 {
}
errors /opt/bitwarden/bw_errors.log
gzip
}

i dont know how to make bitwarden use the same wildcard cert

I also want to access these subdomain via reverse proxy from inside the network

for e.g. i want to use https://bitwarden.domain.com from the LAN as well

My network is behind a pfsense firewall.

any ideas will be of great help

Hi @Yoda, welcome to the Caddy community.

You need some way to tell Caddy to handle requests for the different subdomains differently.

There’s two ways you can go about it. You can split this site up into two separate sites - you can still have them both share the same wildcard cert if you need it - or you can use some hacky rewrites based on placeholders to differentiate (v2 is infinitely better in this regard than v1).

Example one - two sites:

bitwarden.example.com {
  tls {
    dns cloudflare
    wildcard
  }

  proxy / 192.168.10.50:8088
  errors /opt/bitwarden/bw_errors.log
}

nextcloud.example.com {
  tls {
    dns cloudflare
    wildcard
  }

  proxy / 192.168.10.50:8080
}

Example two - one site with rewrite hacks:

*.example.com {
  tls {
    dns cloudflare
  }

  rewrite {
    if {label1} is bitwarden
    to /bitwarden{uri}
  }
  proxy /bitwarden 192.168.10.50:8088 {
    without /bitwarden
  }

  rewrite {
    if {label1} is nextcloud
    to /nextcloud{uri}
  }
  proxy /nextcloud 192.168.10.50:8080 {
    without /nextcloud
  }
}

Note that with this method there is no way to have error logging separate - it’s across the whole site or nothing. Also, tls { wildcard } is redundant in your own example (i.e. the one-site method), because the site is already a wildcard (*.example.com). You only need to specify wildcard when you want Caddy to pretend that a fully qualified domain name is in fact a wildcard (for the purposes of getting a certificate for it).

1 Like

Hi there

thank you for the quick reply.

in method 2 where should i declare the log file . its ok if its across all sites for now

i’m just worried that in example 1 i dont exceed any ACME limits

Also where can i specify to use staging ACME endpoint till i figure this all out?

i tried setting
ExecStart=/usr/local/bin/caddy -log stdout -log-timestamps=false -agree=true -conf=/etc/caddy/Caddyfile -root=/var/tmp -ca “https://acme-staging-v02.api.letsencrypt.org/directory

in my caddy.service, but it doesnt seem to take it

Oh! BTW i’ve now upgraded to 2.0 beta 15

Anywhere inside the site. Before the proxies, between the proxies, above the TLS declaration. Usually I prefer to put general stuff like error logging at the top of the site, though, so I’d probably put it above the TLS as a matter of preference.

The earliest ACME limit likely to apply to you is Certificates per Registered Domain (50 per week). That means you could get 50 subdomains this week, and then 50 after 7 days, without problem.

The other noteworthy rate limit is 300 New Orders per account per 3 hours. A new order is essentially any new certificate request.

I would wager that you are not likely to go anywhere near either of these limits, and it would be simpler to simply stick with individual certificates and let Caddy manage them.

You have the correct method (setting the flag -ca https://acme-staging-v02.api.letsencrypt.org/directory when you run Caddy). How do you know it didn’t take?

Glad to hear it! Although, this changes a lot of things, with the Caddyfile especially as it’s almost entirely new. And you’ll want to update to the newer unit file.

thanks

i upgraded to 2.0 beta 15
now my caddy file is in /etc/caddy/Caddyfile

i ran

caddy run --config /etc/caddy/Caddyfile

i get this error message

2020/03/05 02:01:03.879 INFO    using provided configuration    {"config_file": "/etc/caddy/Caddyfile", "config_adapter": ""}
run: adapting config using caddyfile: parsing caddyfile tokens for 'tls': /etc/caddy/Caddyfile:3 - Error during parsing: getting DNS provider module named 'cloudflare': module not registered: tls.dns.cloudflare

In 1.0.4, in installed using the getcaddy bash script, with tls.cloudflare plugin

now how do i do that in 2.0?

is this what the caddy.json does? i have a file in /etc/caddy folder

do i need to modify the caddy.service?

i know i need to RTFM :wink: but i’m chewing more than i can from v1 to v2, sorry about that

As there is, as of yet, no super flash custom build download page for v2 - you’ll have to build v2 manually with the DNS plugin included.

https://github.com/caddyserver/tls.dns
https://github.com/caddyserver/caddy/tree/v2#building-with-plugins

Replace it with this one for v2: https://github.com/caddyserver/dist/blob/master/init/caddy.service

Hi Matthew

“Building” is something i’ve never done before. but will definitely try

Meanwhile i reverted back to 1.0.4 to learn a bit more about caddy.

It works like a charm now…

will look at building route next.

1 Like

is there a guide that i can use to convert my v1 file to v2? i’m using the Example 1 you had suggested

There aren’t any published v1 -> v2 Caddyfile guides I know of.

Nothing official either - at the very least until Caddy v2 is out of beta. There’s still features yet to be add and refined at this stage.

With some of the low level conceptual changes on how v2 handles vs v1, as well, it’s best to start from the top with a fresh understanding of some of the key concepts and functionality. The v2 docs are here:

1 Like

thanks. if possible can you please let me know how Example 1 will look like for v2?

The v2 Caddyfile doesn’t have a tls dns equivalent yet, but it’s configurable in JSON. I can’t find a wildcard-equivalent in JSON either though right now, so example 2 is the way to go.

You could start with this:

*.example.com {
  @bitwarden {
    host bitwarden.example.com
  }
  reverse_proxy @bitwarden 192.168.10.50:8088

  @nextcloud {
    host nextcloud.example.com
  }
  reverse_proxy @nextcloud 192.168.10.50:8080
}

Then run caddy adapt --pretty --validate in the same directory as that Caddyfile to get the JSON equivalent. From there, add your DNS provider to the challenges area of the acme JSON configuration.

2 Likes

ok, just got around to work on this.

compiled the v2 beta 20 with dns

then ran caddy adapt & this is what i got for the json file

{
        "apps": {
                "http": {
                        "servers": {
                                "srv0": {
                                        "listen": [
                                                ":443"
                                        ],
                                        "routes": [
                                                {
                                                        "match": [
                                                                {
                                                                        "host": [
                                                                                "*.example.com"
                                                                        ]
                                                                }
                                                        ],
                                                        "handle": [
                                                                {
                                                                        "handler": "subroute",
                                                                        "routes": [
                                                                                {
                                                                                        "handle": [
                                                                                                {
                                                                                                        "handler": "reverse_proxy",
                                                                                                        "upstreams": [
                                                                                                                {
                                                                                                                        "dial": "192.168.10.74:8088"
                                                                                                                }
                                                                                                        ]
                                                                                                }
                                                                                        ],
                                                                                        "match": [
                                                                                                {
                                                                                                        "host": [
                                                                                                                "bitwarden.example.com"
                                                                                                        ]
                                                                                                }
                                                                                        ]
                                                                                },
                                                                                {
                                                                                        "handle": [
                                                                                                {
                                                                                                        "handler": "reverse_proxy",
                                                                                                        "upstreams": [
                                                                                                                {
                                                                                                                        "dial": "192.168.10.75:5001"
                                                                                                                }
                                                                                                        ]
                                                                                                }
                                                                                        ],
                                                                                        "match": [
                                                                                                {
                                                                                                        "host": [
                                                                                                                "dsm.example.com"
                                                                                                        ]
                                                                                                }
                                                                                        ]
                                                                                }
                                                                        ]
                                                                }
                                                        ],
                                                        "terminal": true
                                                }
                                        ]
                                }
                        }
                }
        }
}

i got these messages when i ran it

2020/03/25 17:48:01 [INFO][cache:0xc0003e1b30] Started certificate maintenance routine
2020/03/25 17:48:01.516 INFO    http    server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS {"server_name": "srv0", "https_port": 443}
2020/03/25 17:48:01.516 INFO    http    enabling automatic HTTP->HTTPS redirects        {"server_name": "srv0"}
2020/03/25 17:48:01 [INFO][cache:0xc0003e1b30] Stopped certificate maintenance routine

the json has a http directive but the cloudflare is under tls.

what should i modify ?

i know i need to use this, please check if this is correct and where do i insert it in the json?

"challenges": {
        "dns": {
                "provider": "cloudflare",
                "api_token": "XXXXXXXXXXXXXXXXXXXXXX"
                "base_url": "https://acme-staging-v02.api.letsencrypt.org/directory"
        }
}

}

The link I gave you last time - for apps/tls/automation/policies/management/acme - has changed since.

Now it’s located at: https://caddyserver.com/docs/json/apps/tls/automation/policies/issuer/acme/

If you follow the link, at the top of the page is the breadcrumb for JSON Config Structure. You can follow that back all the way up to see how each section “nests” in the above section.

This isn’t the correct place to put the LetsEncrypt staging endpoint. This is to override the Cloudflare API endpoint.

You can override the ACME endpoint a few steps higher, in the acme key: https://caddyserver.com/docs/json/apps/tls/automation/policies/issuer/acme/ca/

1 Like