Certbot deploy hook script to upload renewed Let's Encrypt certificates to a MikroTik RouterOS device via the REST API.
Project description
mikrotik-certbot
A Certbot deploy-hook tool that uploads renewed Let’s Encrypt certificates to MikroTik RouterOS devices and applies them to services. It is idempotent and non‑destructive: imports under a versioned name, applies to targets, then prunes older unreferenced certificates.
Why not just use the built in ACME support?
- EAB authentication is broken in ROS 7.20 and lower.
- Router may not have access to the Internet
- Renewal of services like hotspot not supported by the built in ACME service.
Contents
Highlights
- Versioned, collision‑safe certificate naming (UTC
YYYYMMDDThhmm,_SEQsuffix when needed) - REST upload on RouterOS ≥ 7.17; SFTP fallback otherwise, then REST import
- Applies to
www-ssl,api-ssl, and optional Hotspot profiles - Strict gating (
MIKROTIK_DOMAINmust be inRENEWED_DOMAINS),DRY_RUNsupport
Prerequisites
- Python
3.11+anduvinstalled - Certbot on the host that renews the certificate
- MikroTik RouterOS reachable over HTTPS (REST); SFTP enabled only if supporting fallback
- A RouterOS user with access to files/certificates/services
Initial Setup (Certbot deploy hook)
- Install
uvif needed:curl -LsSf https://astral.sh/uv/install.sh | sh - Download the hook directly (no repository clone required). Replace the example URL with the raw file URL for this repo:
sudo curl -fsSL "https://raw.githubusercontent.com/karrots/mikrotik-certbot/refs/heads/main/deploy-hook.sh" -o /etc/letsencrypt/renewal-hooks/deploy/mikrotik-certbot.sh
- Edit the following variables in the downloaded
/etc/letsencrypt/renewal-hooks/deploy/mikrotik-certbot.shfile:MIKROTIK_DOMAIN: your FQDN (must appear inRENEWED_DOMAINS)ROUTER_HOST: e.g.,router.example.net:8443ROUTER_USER/ROUTER_PASS: least‑privilege credentials for RouterOS access
- Verify with a dry‑run:
sudo certbot renew --dry-run --deploy-hook /etc/letsencrypt/renewal-hooks/deploy/mikrotik-certbot.sh - If multiple hosts need certificates duplicate the
deploy-hook.shas needed.
See docs/config.md for all configuration options and behavior toggles.
Application Flow
The hook exits early unless MIKROTIK_DOMAIN is present in RENEWED_DOMAINS. It derives a versioned, collision‑safe certificate name and detects RouterOS capabilities to pick REST upload or SFTP fallback. The combined PEM (privkey + fullchain) is uploaded, then imported without removing any existing same‑name certificate first. The new certificate is applied to www-ssl, api-ssl, and any configured Hotspot profiles. After a real import completes, older unreferenced certificates are pruned, keeping the newest two.
More Documentation
- Configuration:
docs/config.md - Usage:
docs/usage.md - RouterOS Permissions:
docs/permissions.md
Developer Workflows
- Sync dev deps:
uv sync --group dev - Run:
uv run mikrotik-certbot - Lint:
uv run --group dev ruff check . - Types:
uv run --group dev mypy . - Tests:
uv run --group dev pytest - Build:
uv build
License & Authors
- License: MIT (see
LICENSE) - Author: Jonathan Karras
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mikrotik_certbot-1.0.2.tar.gz.
File metadata
- Download URL: mikrotik_certbot-1.0.2.tar.gz
- Upload date:
- Size: 64.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2dcd4e8f1b58681097361d8d54e928dabbe1f004760f2b56d9ee1eb3f8777b95
|
|
| MD5 |
61f9323b910d7074e64fd2a90c65cbf4
|
|
| BLAKE2b-256 |
59356d68d932f67c94dd43dea3da86537357fac54967d21cfe63625da5469a61
|
Provenance
The following attestation bundles were made for mikrotik_certbot-1.0.2.tar.gz:
Publisher:
publish.yml on karrots/mikrotik-certbot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mikrotik_certbot-1.0.2.tar.gz -
Subject digest:
2dcd4e8f1b58681097361d8d54e928dabbe1f004760f2b56d9ee1eb3f8777b95 - Sigstore transparency entry: 1735798572
- Sigstore integration time:
-
Permalink:
karrots/mikrotik-certbot@7d5b1782cb2705f2b75fb6b08170f670076d1e5c -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/karrots
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7d5b1782cb2705f2b75fb6b08170f670076d1e5c -
Trigger Event:
push
-
Statement type:
File details
Details for the file mikrotik_certbot-1.0.2-py3-none-any.whl.
File metadata
- Download URL: mikrotik_certbot-1.0.2-py3-none-any.whl
- Upload date:
- Size: 18.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
47436ea556f3c49c11f283a4e90894d2897ed6b9782ed243c326f4f1f1a04a03
|
|
| MD5 |
2a15f4a972348dcf2ba829fd21b94e5d
|
|
| BLAKE2b-256 |
2e4fa9ed68ee16f808105cfaaade1c4907d93a9815c0ae637a78866f0dccf9c4
|
Provenance
The following attestation bundles were made for mikrotik_certbot-1.0.2-py3-none-any.whl:
Publisher:
publish.yml on karrots/mikrotik-certbot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mikrotik_certbot-1.0.2-py3-none-any.whl -
Subject digest:
47436ea556f3c49c11f283a4e90894d2897ed6b9782ed243c326f4f1f1a04a03 - Sigstore transparency entry: 1735798654
- Sigstore integration time:
-
Permalink:
karrots/mikrotik-certbot@7d5b1782cb2705f2b75fb6b08170f670076d1e5c -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/karrots
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7d5b1782cb2705f2b75fb6b08170f670076d1e5c -
Trigger Event:
push
-
Statement type: