(in 13 lucky steps)
This guide shows how to run acme.sh in a RouterOS container on your USB drive, use Cloudflare DNS‑01, and deploy certs via SSH to RouterOS automatically.
Configure RouterOS container engine paths:
/container config
set layer-dir=usb1-part1/container-layers/ \
registry-url=https://registry.hub.docker.com \
tmpdir=usb1-part1/container-tmp \
username=yourusername
Create folders on USB for state and SSH keys:
/file add type=directory name=usb1-part1/container-volumes/acme_sh_data
/file add type=directory name=usb1-part1/container-volumes/ssh_keys
Note:
src=
paths must not start with/
.
/container mounts
add name=acme_sh_data dst=/acme.sh src=usb1-part1/container-volumes/acme_sh_data
add name=ssh_keys dst=/root/.ssh src=usb1-part1/container-volumes/ssh_keys
Add Cloudflare and RouterOS deploy‑hook vars:
/container envs
add list=ACME_ENV name=CF_Token value="0123456789abcdef012345"
add list=ACME_ENV name=CF_Email value="[email protected]"
add list=ACME_ENV name=ROUTER_OS_USERNAME value="certuser"
add list=ACME_ENV name=ROUTER_OS_HOST value="10.13.1.1"
add list=ACME_ENV name=ROUTER_OS_PORT value="22"
Attach the container to your LAN bridge:
/interface veth add name=veth13.10 address=10.13.1.10/24 gateway=10.13.1.1
/interface bridge port add bridge=bridge-LAN interface=veth13.10
Ensure
veth13.10
is in the same bridge as your LAN so it can reach Cloudflare and SSH to RouterOS.
Add the container, telling it to run in daemon mode:
/container add name=acme_sh \
remote-image=neilpang/acme.sh:latest \
hostname=acme_sh interface=veth13.10 \
mounts=acme_sh_data,ssh_keys \
envlist=ACME_ENV \
logging=yes start-on-boot=no \
root-dir=usb1-part1/container/acme_sh \
entrypoint="/entrypoint.sh" \
cmd="daemon"
/container shell [find hostname="acme_sh"]
# Inside container:
ssh-keygen -t ed25519 -f /root/.ssh/id_rsa -N ""
exit
This creates /root/.ssh/id_rsa
(private) and id_rsa.pub
(public) in the ssh_keys
volume.
Before issuing any certificates, configure acme.sh in the container to use the official Let’s Encrypt CA:
/container shell [find hostname="acme_sh"]
/entry.sh --set-default-ca --server letsencrypt
exit
# On MikroTik CLI:
/user add name=certuser password="" group=full comment="LE automation user"
/user ssh-keys import user=certuser public-key-file=usb1-part1/container-volumes/ssh_keys/id_rsa.pub
Verify with:
/user ssh-keys print
/container shell [find hostname="acme_sh"]
ssh -o StrictHostKeyChecking=no [email protected] 'echo SSH OK'
exit
You should see SSH OK
.
Temporarily update the container command to issue certs for your domains:
/container set acme_sh cmd="--issue --dns dns_cf --keylength 4096 \
-d lan.example.com \
-d gw.lan.example.com \
-d dynamic.example.com \
-d dynamic.contoso.com \
--deploy-hook routeros"
/container start acme_sh
/container log show where container=acme_sh
Watch for a successful issuance and deployment.
/container set acme_sh cmd="--cron --deploy-hook routeros"
Create a RouterOS scheduler to run daily at 03:00 and then stop the container:
/system scheduler add name="LE-Renew" start-time=03:00:00 interval=24h \
on-event="/container start acme_sh; :delay 300; /container stop acme_sh"
:delay 300
allows 5 minutes for renewal & deploy.
After an auto‑run, verify on the Router:
/certificate print detail where common-name~"lan.example.com"
/ip service print where name=www-ssl
From a LAN host, test HTTPS:
curl -v https://lan.example.com/ --insecure
Once trusted, drop --insecure
.
- The
--issue
command is a one‑time action. - Keep volumes organized under
container-volumes/
. - Ensure your SSH keys and ACME data persist on USB.
You now have a fully automated Let’s Encrypt setup running on your MikroTik, using Cloudflare DNS‑01 and a RouterOS container. 🚀
The full initial container setup isn't documented here as I had done it previously, and the documentation is available on the Web. I wanted to document the Let's Encrypt using a Cloudflare DNS-01 challenge in full since I couldn't find a complete working step-by-step guide for it.