[new feature] caddy trust with support for --config switch

1. Caddy version (caddy version):

$ caddy version
v2.3.0 h1:fnrqJLa3G5vfxcxmOH/+kJOcunPLhSBnjgIvjXV/QTA=

2. How I run Caddy:

a. System environment:

using systemd unit file (see below)

eeuser@elite-pi:~ $ 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
HOME_URL=“http://www.raspbian.org/
SUPPORT_URL=“RaspbianForums - Raspbian
BUG_REPORT_URL=“RaspbianBugs - Raspbian

b. Command:

systemctl start caddy

c. Service/unit/compose file:

$ cat /lib/systemd/system/caddy.service
# 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.
#
# WARNING: This service does not use the --resume flag, so if you
# use the API to make changes, they will be overwritten by the
# Caddyfile next time the service is restarted. If you intend to
# use Caddy's API to configure it, add the --resume flag to the
# caddy run command or use the caddy-api.service file instead.

[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

[Service]
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
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:

 $ sudo caddy fmt /etc/caddy/Caddyfile
{
        storage file_system {
                root /opt/caddy/storage
        }
        local_certs
        http_port 80
        https_port 443
}
https://192.167.37.127 {
        # caddy-auth-portal with local db config
        log {
                level INFO
                format console
                output file /var/log/caddy/caddy.log
        }
        # caddy auth portal login
        route /auth* {
                auth_portal {
                        path /auth
                        backends {
                                local_backend {
                                        method local
                                        path /opt/caddy/auth/user_db.json
                                        realm local
                                }
                        }
                        jwt {
                                token_name access_token
                                token_secret AnExampleSecretString123
                                token_lifetime 13200
                        }
                        ui {
                                theme basic
                                generic_template "/opt/caddy/templates/custom/generic.template"
                                login_template "/opt/caddy/templates/custom/login.template"
                                portal_template "/opt/caddy/templates/custom/portal.template"
                                register_template "/opt/caddy/templates/custom/register.template"
                                whoami_template "/opt/caddy/templates/custom/whoami.template"
                                settings_template "/opt/caddy/templates/custom/settings.template"
                                custom_css_path "/opt/caddy/css/custom.css"
                                logo_url "https://example.com/example.png"
                                links {
                                        "Elite Manager" /
                                        "Auth Portal Settings" /auth/settings
                                        "who am i check" /auth/whoami
                                        "Add MFA Authentication App" /auth/settings/mfa/add/app
                                }
                        }
                }
        }
        # grafana with modified base URL configuration for /gr running on port 3000 route with auth proxy & jwt authzn
        route /gr/* {
                #               trace tag="grafana" response_debug=yes
                jwt {
                        enable claim headers
                }
                reverse_proxy http://localhost:3000
        }
        route /version* {
                respond * "2.0.0-a" 200
        }
        # node-red dahsboard running on port 1880 route with integrated jwt and custom middleware
           route /ui/* {
                jwt {
                        enable claim headers
                }
                reverse_proxy http://localhost:1880
        }
        # elite manager running on port 1081 route
        route /* {
                jwt {
                        primary yes
                        trusted_tokens {
                                static_secret {
                                        token_name access_token
                                        token_secret AnExampleSecretString123
                                }
                        }
                        enable claim headers
                }
                reverse_proxy http://localhost:1081
        }
}

3. The problem I’m having:

I’m trying to script setup and configuration of caddy server based on a custom download that includes additional plugins (caddy-auth-portal, caddy-auth-jwt, caddy-trace).

During setup, the caddy unit file is configured to run caddy as a non priveleged user (by design), to get certificates configured properly we are attempting to use the caddy trust command as root during install/config. I think this is performing the trust install based on the default caddy CA location created upon install, rather than the custom storage file_system root declaration I’m passing in my /etc/caddy/Caddyfile.

The result is on first startup from systemctl is throwing errors indicating it cant import the root ca because the service is not running as a priveledged user.

What would be nice is to be able to run caddy trust as root, indicating the custom location for all local CA certificate files.

4. Error messages and/or full log output:

 $ sudo journalctl -xe | less
Feb 22 20:18:33 pi caddy[1008]: {"level":"info","ts":1614050313.9027066,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0x35138b0"}
Feb 22 20:18:33 pi caddy[1008]: {"level":"info","ts":1614050313.9056551,"logger":"http","msg":"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}
Feb 22 20:18:33 pi caddy[1008]: {"level":"info","ts":1614050313.905718,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
Feb 22 20:18:33 pi caddy[1008]: {"level":"info","ts":1614050313.9081674,"logger":"http.handlers.auth_portal","msg":"JWT token name found","instance_name":"portal-1","token_name":"access_token"}
Feb 22 20:18:33 pi caddy[1008]: {"level":"warn","ts":1614050313.9082112,"logger":"http.handlers.auth_portal","msg":"JWT token origin not found, using default","instance_name":"portal-1"}
Feb 22 20:18:33 pi caddy[1008]: {"level":"info","ts":1614050313.9082396,"logger":"http.handlers.auth_portal","msg":"local backend configuration","db_path":"/opt/caddy/auth/user_db.json"}
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.0570807,"logger":"http.handlers.auth_portal","msg":"created new user","user_id":"9bcc4dd5-b6b3-4f13-a09d-0a5f91db0745","user_name":"webadmin","user_email":"webadmin@localdomain.l
ocal","user_claims":{"roles":"superadmin"}}
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.0571637,"logger":"http.handlers.auth_portal","msg":"created default superadmin user for the database","user_name":"webadmin","user_secret":"BLAHDY-BLAH-BLAH"}
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.057186,"logger":"http.handlers.auth_portal","msg":"validating local backend","db_path":"/opt/caddy/auth/user_db.json"}
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.0795283,"logger":"http.handlers.auth_portal","msg":"JWT token validator provisioned","instance_name":"portal-1","access_list":[{"action":"allow","values":["anonymous","guest","*"
],"claim":"roles"}]}
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.079613,"logger":"http.handlers.auth_portal","msg":"provisioned plugin instance","instance_name":"portal-1","started_at":1614050313.9081526}
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.0809515,"logger":"http.authentication.providers.jwt","msg":"provisioned plugin instance","instance_name":"jwt-3","started_at":1614050314.0808883}
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.0814776,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["192.167.0.127"]}
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.0826998,"logger":"tls.obtain","msg":"acquiring lock","identifier":"192.167.0.127"}
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.0874429,"logger":"tls.obtain","msg":"lock acquired","identifier":"192.167.0.127"}
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.10088,"logger":"tls.obtain","msg":"certificate obtained successfully","identifier":"192.167.0.127"}
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.100936,"logger":"tls.obtain","msg":"releasing lock","identifier":"192.167.0.127"}
Feb 22 20:18:34 pi caddy[1008]: {"level":"warn","ts":1614050314.103576,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [192.167.37.127]: no OCSP server specified in certificate"}
Feb 22 20:18:34 pi caddy[1008]: {"level":"warn","ts":1614050314.189484,"logger":"pki.ca.local","msg":"installing root certificate (you might be prompted for password)","path":"storage:pki/authorities/local/root.crt"}
Feb 22 20:18:34 pi caddy[1008]: 2021/02/22 20:18:34 not NSS security databases found
Feb 22 20:18:34 pi caddy[1008]: 2021/02/22 20:18:34 define JAVA_HOME environment variable to use the Java trust
**Feb 22 20:18:34 pi sudo[1018]: pam_unix(sudo:auth): conversation failed**
**Feb 22 20:18:34 pi sudo[1018]: pam_unix(sudo:auth): auth could not identify password for [caddy]**
**Feb 22 20:18:34 pi sudo[1018]:    caddy : user NOT in sudoers ; TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/usr/bin/tee /usr/local/share/ca-certificates/Caddy_Local_Authority_-_2021_ECC_Root_237805637019721463165409701864614578005.crt**
**Feb 22 20:18:34 pi caddy[1008]: {"level":"error","ts":1614050314.2079978,"logger":"pki.ca.local","msg":"failed to install root certificate","error":"failed to execute sudo: exit status 1","certificate_file":"storage:pki/authorities/local/root.crt"}**
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.2087014,"msg":"autosaved config","file":"/home/caddy/.config/caddy/autosave.json"}
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.2088294,"msg":"serving initial configuration"}
Feb 22 20:18:34 pi caddy[1008]: {"level":"info","ts":1614050314.2096772,"logger":"tls","msg":"cleaned up storage units"}

5. What I already tried:

When attempting to pass the --config /etc/caddy/Caddyfile switch to the caddy trust command, it pretty much stats its “not supported”. --environ and --config do not work together either.

$ sudo /usr/bin/caddy trust --config /etc/caddy/Caddyfile
flag provided but not defined: -config
Usage of trust:
$ sudo /usr/bin/caddy trust --environ --config /etc/caddy/Caddyfile
flag provided but not defined: -environ
Usage of trust:
$

6. Links to relevant resources:

Since this is a feature request, you can open an issue on Github for this. Thanks!