acme.sh for an asrock rack BMC¶
secrets
i make my secrets from my own secret store, which
only fits my setup. the docker secret create commands here are plain
swarm: use them, or however you normally make secrets.
acme.sh keeps a real certificate on my ASRock Rack BMC (the AMI MegaRAC web UI, firmware 11.02). it renews over cloudflare DNS, and a deploy hook installs every renewal on the BMC. after the first run there is nothing to do by hand. it runs as one replica, anywhere on the swarm.
compose.yml, 38 lines
before you deploy¶
-
give acme.sh an account on the BMC with Administrator privilege, and KVM and virtual media turned off
- the BMC's SSL page disables every control for anything less
- mine is a dedicated account,
acme-sh, not the built in admin
-
create the state directory on the cephfs mount:
- acme.sh keeps its CA account, the certificate, its key and the renewal settings there, and the cloudflare token once it has used it
-
create the password secret on a manager, type the password, then Ctrl-D:
- swarm secrets can't be changed, so a new password goes in a new secret,
_v3.ASROCK_BMC_PASSWORD_FILEin the compose names the one in use
- swarm secrets can't be changed, so a new password goes in a new secret,
-
set
CF_Account_IDto your cloudflare account id. it's on the right of any zone's overview page, under API- with a token, acme.sh needs the account id or the zone id to find the zone, and the account id covers every zone in the account
state considerations¶
acmeis a named bind of/mnt/docker-cephFS/acme_asrock_bmc_acme, mounted at/acme.sh, see stack conventions. it holds all of acme.sh's state, the keys and the cloudflare token included, so only root can read it- the BMC password is a swarm secret and the hook a swarm config, so neither is in the volume
network considerations¶
- nothing is published, and it joins no overlay network besides the stack's default. the container only calls out: to the CA, cloudflare and the BMC
ASROCK_BMC_URLis the BMC's IPv4 address, because my overlay networks have no IPv6
the first certificate¶
do this once, after the first deploy:
-
on the node running the task, open a shell in the container:
-
issue the certificate:
export CF_Token="<cloudflare token>" /acmebin/acme.sh --issue --server letsencrypt --dns dns_cf -d asrock-bmc.mydomain.com --home /acmebin --config-home /acme.sh- the token needs DNS edit on the zone: Zone > DNS > Edit on a user token, DNS Write on an account-owned token
- acme.sh saves the token in
/acme.sh/account.conf, and renewals read it from there --server letsencryptis saved with the certificate, so renewals stay with let's encrypt. without it acme.sh uses zerossl
-
register the hook. this also installs the certificate straight away:
/acmebin/acme.sh --deploy -d asrock-bmc.mydomain.com --ecc --deploy-hook asrock_bmc --home /acmebin --config-home /acme.sh--deploy-hooksavesLe_DeployHookin the certificate's settings, and every renewal after that runs the hook by itself- a
--deployrun by hand has to name the hook every time. renewals read the saved one
the hook¶
the hook uploads with the same call that the BMC web UI's SSL page makes. it
doesn't use redfish: on this firmware redfish ReplaceCertificate takes a
certificate and no private key, so it can't install a certificate whose key
acme.sh generated.
the hook reads the password from the file that ASROCK_BMC_PASSWORD_FILE names,
and hands it to curl as a file, never as an argument. see
secrets.
it's mounted as a swarm config at /acmebin/deploy/asrock_bmc.sh, which is
where acme.sh looks for deploy hooks. swarm configs can't be changed, so bump
the config name whenever the script changes.
asrock_bmc.sh: the deploy hook acme.sh runs after each renewal, 62 lines, 2 notes
each in the code opens a note on that line. download asrock_bmc.sh
- every call to the BMC goes through
_asrock_curl, which passes--insecureso the hook still works while the BMC is serving its self-signed factory certificate. - the hook reads
certificate-infoin the line above and writes it back unchanged in the PUT below, which is what the BMC's SSL page does straight after an upload.
how it runs¶
command: daemonruns supercronic, which runsacme.sh --cronfour times a day- the image is pinned by digest, renovate opens a PR when it changes
checking it¶
the BMC should serve the new certificate, issued by let's encrypt:
openssl s_client -connect asrock-bmc.mydomain.com:443 -servername asrock-bmc.mydomain.com </dev/null 2>/dev/null | openssl x509 -noout -issuer -dates
gatus checks the same certificate every hour, with verification on, and goes red with less than 21 days left. acme.sh renews with 30 days left, so red means about nine days of failed renewals.