1. Caddy version (caddy version
):
eeuser@elite-pi:~ $ caddy version
v2.4.0 h1:yHnnbawH2G3ZBP2mAJF4XBLnJanqhULLP/wu01Qi9Io=
2. How I run Caddy:
a. System environment:
$ cat /etc/*release*
PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
NAME="Raspbian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=raspbian
ID_LIKE=debian
...
b. Command:
systemctl start caddy
c. Service/unit/compose file:
# caddy.service
#
# For using Caddy with a config file.
#
# Make sure the ExecStart and ExecReload commands are correct
# for your installation.
#
# See https://caddyserver.com/docs/install for instructions.
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target
[Service]
User=root
Group=root
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/caddy.json
ExecReload=/usr/bin/caddy reload --config /etc/caddy/caddy.json
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
d. My complete Caddyfile or JSON config:
{
"logging": {
"logs": {
"default": {
"exclude": [
"http.log.access.log0"
]
} ,
"log0": {
"writer": {
"filename": "/var/log/caddy/caddy.log",
"output": "file"
} ,
"encoder": {
"format": "console"
} ,
"level": "INFO",
"include": [
"http.log.access.log0"
]
}
}
} ,
"apps": {
"http": {
"http_port": 80,
"https_port": 443,
"servers": {
"demo": {
"listen": [
":443"
],
"routes": [ {
"match": [ {
"host": [
"http://192.168.1.10"
]
}
],
"handle": [ {
"handler": "subroute",
"routes": [ {
"handle": [ {
"handler": "subroute",
"routes": [ {
"handle": [ {
"handler": "authentication",
"providers": {
"jwt": {
"authorizer": {
"access_list": [ {
"action": "allow",
"claim": "roles",
"values": [
"superadmin",
"manager"
]
}
],
"context": "default",
"pass_claims_with_headers": true
}
}
}
}
]
},
{
"handle": [ {
"handler": "reverse_proxy",
"upstreams": [ {
"dial": "localhost:5555"
}
]
}
]
}
]
}
],
"match": [ {
"path": [
"/user-mgr/*"
]
}
]
} , {
"handle": [ {
"handler": "subroute",
"routes": [ {
"handle": [ {
"body": "2.0.0-a",
"handler": "static_response",
"status_code": 200
}
]
}
]
}
],
"match": [ {
"path": [
"/version*"
]
}
]
} , {
"handle": [ {
"handler": "subroute",
"routes": [ {
"handle": [ {
"handler": "subroute",
"routes": [ {
"handle": [ {
"handler": "auth_portal",
"portal": {
"auth_url_path": "/auth",
"backends": [ {
"method": "local",
"name": "local_backend",
"path": "/opt/caddy/auth/user_db.json",
"realm": "local"
}
],
"context": "default",
"cookies": {},
"jwt": {
"token_lifetime": 43200,
"token_name": "access_token",
"token_secret": "AnExampleSecretString123"
} ,
"primary": true,
"registration": {
"dropbox": "/opt/caddy/auth/registrations_db.json",
"title": "User Registration"
} ,
"ui": {
"auto_redirect_url": "",
"custom_css_path": "/opt/caddy/css/custom.css",
"logo_url": "assets/logo.png",
"password_recovery_enabled": false,
"private_links": [ {
"link": "/",
"title": "Example Manager"
} , {
"link": "/auth/settings",
"title": "Auth Portal Settings"
} , {
"link": "/auth/whoami",
"title": "Who Am I Check"
} , {
"link": "/user-mgr/",
"title": "User Management"
}
],
"realms": null,
"templates": {
"generic": "/opt/caddy/templates/em20-tmpl/generic.template",
"login": "/opt/caddy/templates/em20-tmpl/login.template",
"portal": "/opt/caddy/templates/em20-tmpl/portal.template",
"register": "/opt/caddy/templates/em20-tmpl/register.template",
"settings": "/opt/caddy/templates/em20-tmpl/settings.template",
"whoami": "/opt/caddy/templates/em20-tmpl/whoami.template"
} ,
"theme": "basic"
}
}
}
]
}
]
}
],
"match": [ {
"path": [
"/auth*"
]
}
]
}
]
}
],
"match": [ {
"path": [
"/auth*"
]
}
]
} , {
"handle": [ {
"handler": "subroute",
"routes": [ {
"handle": [ {
"handler": "authentication",
"providers": {
"jwt": {
"authorizer": {
"context": "default",
"pass_claims_with_headers": true
}
}
}
}
]
} , {
"handle": [ {
"handler": "reverse_proxy",
"upstreams": [ {
"dial": "localhost:3000"
}
]
}
]
}
]
}
],
"match": [ {
"path": [
"/gr/*"
]
}
]
} , {
"handle": [ {
"handler": "subroute",
"routes": [ {
"handle": [ {
"handler": "authentication",
"providers": {
"jwt": {
"authorizer": {
"context": "default",
"pass_claims_with_headers": true
}
}
}
}
]
} , {
"handle": [ {
"handler": "reverse_proxy",
"upstreams": [ {
"dial": "localhost:1880"
}
]
}
]
}
]
}
],
"match": [ {
"path": [
"/ui/*"
]
}
]
} , {
"handle": [ {
"handler": "subroute",
"routes": [ {
"handle": [ {
"handler": "authentication",
"providers": {
"jwt": {
"authorizer": {
"context": "default",
"pass_claims_with_headers": true,
"primary": true,
"trusted_tokens": [ {
"token_name": "access_token",
"token_secret": "AnExampleSecretString123"
}
]
}
}
}
}
]
} , {
"handle": [ {
"handler": "reverse_proxy",
"upstreams": [ {
"dial": "localhost:1081"
}
]
}
]
}
]
}
],
"match": [ {
"path": [
"/*"
]
}
]
}
]
}
],
"terminal": true
}
],
"logs": {
"logger_names": {
"192.168.1.10": "log0"
}
}
}
}
}
}
}
3. The problem I’m having:
The following configuration effort is based on attempting to control the configuration of the auto-tls’s local certificate authority. In this first step I’m attempting to get our caddy deployment approach converted to using JSON based configuration files, including configuring the pki module.
One of the primary issues for switching to the json based configuration is to be able to manage the configuration around the local CA (specifically control the CN value of its subject DN strings to make them unique per install). The goal is to have caddy on startup with the proper configuration, generate and install trust for a local CA with the properties set by the PKI module configuration.
The “configuration example” from the caddyserver documentation presents the following:
{
"certificate_authorities": {
"": {
"name": "",
"root_common_name": "",
"intermediate_common_name": "",
"install_trust": false,
"root": {
"certificate": "",
"private_key": "",
"format": ""
},
"intermediate": {
"certificate": "",
"private_key": "",
"format": ""
},
"storage": {•••}
}
}
}
I’m running into a couple of issues:
-
I’m not finding a clear example of how to properly position the PKI module into our existing json file that was generated from our original Caddyfile with the
caddy adapt
command. I’m assuming it needs to be presented as a “peer” to the “http”: module declaration in the file but have not been successful in formatting it in a way that starts up properly. Does anyone have an example of using this configuration that can be shared? -
In getting into actually using the configuration, where should CA ID be presented? Is it in the first value within the “certificate_authorities”: object? For example if we wanted CA ID to be local-test would we use the following
"certificate_authorities": {
"local-test": {
...
- what is “required” values in the pki module? In our use case we are specifically focused on programmatically setting
"root_common_name": "",
to a unique value per deployment. Do we have to set the other values beyond this or will defaults apply across them? - If configuring the root and intermediate values are required; what is required around the “root”: and “intermediate”: child object entries with regard to the certificate, private key and format values. Will they fall back to defaults being generated by caddy on startup, or is this implying I need to provide already generated private key and generated CA certificate file (which is confusing at this point because I’m not sure if I’m pursuing the right configuration approach now).
4. Error messages and/or full log output:
5. What I already tried:
I’ve iterated with positioning the pki assertion outside of the main block, within it, and I seem to break the parsing regardless of how I introduce it to the file.
I’d rather focus on what is proper form for the configuration file and its required parameters than the iterations of configuration attempted to date; this should be a predictable specific configuration pattern, I’m not seeing in the docs how to include it in a json configuration file.
6. Links to relevant resources:
(looking to pointers for other contextual references…)