6.4 KiB
Using ACME with step-ca
Let’s assume you’ve installed
step-ca
(e.g., using brew install step
), have it running at https://ca.internal
,
and you’ve bootstrapped your ACME client
system(s) (or at
least installed your root
certificate at
~/.step/certs/root_ca.crt
).
Enabling ACME
To enable ACME, simply add an ACME provisioner to your step-ca
configuration
by running:
$ step ca provisioner add my-acme-provisioner --type ACME
NOTE: The above command will add a new provisioner of type
ACME
and namemy-acme-provisioner
. The name is used to identify the provisioner (e.g. you cannot have twoACME
provisioners with the same name).
Now restart or SIGHUP step-ca
to pick up the new configuration.
That’s it.
Configuring Clients
To configure an ACME client to connect to step-ca
you need to:
- Point the client at the right ACME directory URL
- Tell the client to trust your CA’s root certificate
Once certificates are issued, you’ll also need to ensure they’re renewed before they expire.
Pointing Clients at the right ACME Directory URL
Most ACME clients connect to Let’s Encrypt by default. To connect to step-ca
you need to point the client at the right ACME directory
URL.
A single instance of step-ca
can have multiple ACME provisioners, each with
their own ACME directory URL that looks like:
https://{ca-host}/acme/{provisioner-name}/directory
We just added an ACME provisioner named “acme”. Its ACME directory URL is:
https://ca.internal/acme/acme/directory
Telling clients to trust your CA’s root certificate
Communication between an ACME client and server always uses
HTTPS. By default, client’s
will validate the server’s HTTPS certificate using the public root certificates
in your system’s default
trust store.
That’s fine when you’re connecting to Let’s Encrypt: it’s a public CA and its
root certificate is in your system’s default trust store already. Your internal
root certificate isn’t, so HTTPS connections from ACME clients to step-ca
will
fail.
There are two ways to address this problem:
- Explicitly configure your ACME client to trust
step-ca
's root certificate, or - Add
step-ca
's root certificate to your system’s default trust store (e.g., usingstep certificate install
)
If you’re using your CA for TLS in production, explicitly configuring your ACME client to only trust your root certificate is a better option. We’ll demonstrate this method with several clients below.
If you’re simulating Let’s Encrypt in pre-production, installing your root certificate is a more faithful simulation of production. Once your root certificate is installed, no additional client configuration is necessary.
Caution: adding a root certificate to your system’s trust store is a global operation. Certificates issued by your CA will be trusted everywhere, including in web browsers.
Example using certbot
certbot
is the grandaddy of ACME clients. Built
and supported by the EFF, it’s the standard-bearer for
production-grade command-line ACME.
To get a certificate from step-ca
using certbot
you need to:
- Point
certbot
at your ACME directory URL using the--
server flag. - Tell
certbot
to trust your root certificate using theREQUESTS_CA_BUNDLE
environment variable.
For example:
$ sudo REQUESTS_CA_BUNDLE=$(step path)/certs/root_ca.crt \
certbot certonly -n --standalone -d foo.internal \
--server https://ca.internal/acme/acme/directory
sudo
is required in certbot
's standalone
mode so it can listen on
port 80 to complete the http-01
challenge. If you already have a webserver
running you can use webroot
mode instead. With the
appropriate plugin
certbot
also supports the dns-01
challenge for most popular DNS providers.
Deeper integrations with nginx
and apache can even configure
your server to use HTTPS automatically (we'll set this up ourselves later). All
of this works with step-ca
.
You can renew all of the certificates you've installed using cerbot
by running:
$ sudo REQUESTS_CA_BUNDLE=$(step path)/certs/root_ca.crt certbot renew
You can automate renewal with a simple cron
entry:
*/15 * * * * root REQUESTS_CA_BUNDLE=$(step path)/certs/root_ca.crt certbot -q renew
The certbot
packages for some Linux distributions will create a cron
entry
or systemd
timer
like this for you. This entry won't work with step-ca
because it doesn't set
the REQUESTS_CA_BUNDLE
environment
variable. You'll need to
manually tweak it to do so.
More subtly, certbot
's default renewal job is tuned for Let's Encrypt's 90
day certificate lifetimes: it's run every 12 hours, with actual renewals
occurring for certificates within 30 days of expiry. By default, step-ca
issues certificates with much shorter 24 hour lifetimes. The cron
entry
above accounts for this by running certbot renew
every 15 minutes. You'll
also want to configure your domain to only renew certificates when they're
within a few hours of expiry by adding a line like:
renew_before_expiry = 8 hours
to the top of your renewal configuration (e.g., in /etc/letsencrypt/renewal/foo.internal.conf
).
Feedback
step-ca
should work with any ACMEv2
(RFC8555) compliant client that supports
the http-01 or dns-01 challenge.
Post feedback on our GitHub Discussions tab, or create a bug report issue.