160 lines
3.6 KiB
Markdown
160 lines
3.6 KiB
Markdown
# Step CA
|
|
|
|
An internal CA and ACME Provider.
|
|
|
|
## Brief
|
|
|
|
Guide to setup a internal Certificate Authority and ACME Provider
|
|
for issuing trusted TLS certs for internal sites.
|
|
This is useful for both traefik certificateResolver or kubernetes ClusterIssuer.
|
|
Step can do more, but lets configure the basics.
|
|
|
|
- by `rskntroot` on `2025-06-18`
|
|
|
|
## Assumptions
|
|
|
|
- An Internal DNS server is configured and accessible.
|
|
- Debian is your choice for the ACME/CA server install.
|
|
|
|
## Install
|
|
|
|
``` bash
|
|
sudo -i
|
|
```
|
|
|
|
``` bash
|
|
apt-get update && apt-get install -y --no-install-recommends curl vim gpg ca-certificates
|
|
curl -fsSL https://packages.smallstep.com/keys/apt/repo-signing-key.gpg -o /etc/apt/trusted.gpg.d/smallstep.asc && \
|
|
echo 'deb [signed-by=/etc/apt/trusted.gpg.d/smallstep.asc] https://packages.smallstep.com/stable/debian debs main' \
|
|
| tee /etc/apt/sources.list.d/smallstep.list
|
|
apt-get update && apt-get -y install step-cli step-ca
|
|
```
|
|
|
|
!!! note "For more install instructions see smallstep [installation guide](https://smallstep.com/docs/step-ca/installation/)."
|
|
|
|
## Config Setup
|
|
|
|
``` bash
|
|
echo 'some-password' > secret
|
|
```
|
|
|
|
=== "Config"
|
|
|
|
``` bash
|
|
step ca init \
|
|
--deployment-type standalone \
|
|
--name ${CA_NAME} \
|
|
--dns=${CA_DNS_NAMES} \
|
|
--address "0.0.0.0:5001" \
|
|
--provisioner ${CA_EMAIL} \
|
|
--password-file ./secret
|
|
```
|
|
|
|
=== "Example"
|
|
|
|
``` bash
|
|
step ca init \
|
|
--deployment-type standalone \
|
|
--name rskio \
|
|
--dns=rskio.com,rskntr.com \
|
|
--address "0.0.0.0:5001" \
|
|
--provisioner dev@rskio.com \
|
|
--password-file ./secret
|
|
```
|
|
|
|
``` bash
|
|
step ca provisioner add dev --type ACME
|
|
mv secret /root/.step/config/.
|
|
```
|
|
|
|
## Service
|
|
|
|
``` bash
|
|
vi /root/.step/step.service
|
|
```
|
|
|
|
paste the following and save with `[ESC] [:] [x] [ENTER]`
|
|
|
|
``` toml
|
|
[Unit]
|
|
Description=Step CA & ACME Provider
|
|
After=network-online.target
|
|
Requires=network-online.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
RemainAfterExit=yes
|
|
ExecStart=/usr/bin/step-ca /root/.step/config/ca.json --password-file /root/.step/config/secret
|
|
User=root
|
|
|
|
Restart=always
|
|
RestartSec=60
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
``` bash
|
|
ln -s /root/.step/step.service /etc/systemd/system/.
|
|
systemctl daemon-reload
|
|
systemctl enable --now step.service
|
|
systemctl status step.service
|
|
```
|
|
|
|
``` bash
|
|
ss -pnlt | grep 5001
|
|
curl -k https://localhost:5001/acme/dev/directory
|
|
```
|
|
|
|
you should see your service logs showing it is listening on port `:5001` and see the contents of the webpage from `curl`
|
|
|
|
## Certificates
|
|
|
|
### Trust
|
|
|
|
``` bash
|
|
cat ~/.step/certs/root_ca.crt
|
|
cat ~/.step/certs/intermediate_ca.crt
|
|
```
|
|
|
|
save and install the files into the trusted certificates on your endpoint and enable trust for ssl signing.
|
|
|
|
you should now be able to browse to your sites without warning
|
|
|
|
### ClusterIssuer
|
|
|
|
``` bash
|
|
cat .step/certs/root_ca.crt | base64 -w0
|
|
```
|
|
|
|
use above output under `spec.acme.caBundle`
|
|
|
|
``` yaml
|
|
apiVersion: cert-manager.io/v1
|
|
kind: ClusterIssuer
|
|
metadata:
|
|
name: dev-step-issuer
|
|
spec:
|
|
acme:
|
|
email: ${SOME_EMAIL}
|
|
server: https://${CA_DOMAIN}/acme/dev/directory
|
|
privateKeySecretRef:
|
|
name: dev-step-issuer-account-key
|
|
caBundle: ${CA_ROOT_PEM}
|
|
solvers:
|
|
- selector: {}
|
|
http01:
|
|
ingress:
|
|
class: traefik
|
|
```
|
|
|
|
## FAQs
|
|
|
|
> Why didnt you containerize this?
|
|
|
|
Because I have multiple kubernetes clusters.
|
|
Running this on a separate machine means that I don't have to install a `rootCA.pem` for each cluster instance.
|
|
You might say "yeah, but you can specify the rootCA as an input to step CA"--but who wants to key files and
|
|
setup CA for each kuberenetes install?
|
|
So yeah, maybe I'll do it in the future.
|