Automated certificate management for MikroTik routers with cert-manager integration
Project description
Certs4MikroTik
Automated SSL/TLS certificate management and deployment for MikroTik routers using Kubernetes, cert-manager, and external-dns.
Overview
This project automates the process of:
- Creating DNS records for your MikroTik routers via external-dns
- Requesting and managing SSL/TLS certificates via cert-manager and Let's Encrypt
- Uploading certificates to MikroTik routers via their API (SSL or plain)
Features
- ✅ Automatic certificate management - Uses cert-manager to automatically request and renew certificates
- ✅ DNS automation - Creates DNS records automatically via external-dns
- ✅ SSL/TLS API support - Connects via SSL (port 8729) with certificate verification disabled
- ✅ Fallback to plain - Falls back to plain API (port 8728) if SSL is unavailable
- ✅ Kubernetes native - Runs as a CronJob in your Kubernetes cluster
- ✅ Multiple routers - Manages certificates for multiple routers from a single configuration
Prerequisites
- Kubernetes cluster
- cert-manager installed
- external-dns configured for your DNS provider
- Let's Encrypt Issuer or ClusterIssuer configured
- MikroTik routers with API access enabled (SSL recommended)
Installation
1. Install from PyPI
pip install certs4mikrotik
2. Configure your routers
Edit k8s/routers-config.yaml to include your routers:
apiVersion: v1
kind: ConfigMap
metadata:
name: mikrotik-routers-config
namespace: default
data:
routers.json: |
{
routers: [
{
name: router1,
host: 192.168.1.1,
port: 8728,
username: admin,
cert_secret: router1-tls,
password_secret: router1-credentials,
cert_name: router1-cert
}
]
}
3. Create router credentials
For each router, create a Kubernetes secret with the admin password:
kubectl create secret generic router1-credentials \
--from-literal=password='your-router-password'
4. Configure the Let's Encrypt Issuer or ClusterIssuer
Option A: Namespace-scoped Issuer (default):
kubectl apply -f k8s/issuer-example.yaml
Option B: Cluster-wide ClusterIssuer:
kubectl apply -f k8s/clusterissuer-example.yaml
kubectl apply -f k8s/cluster-role-issuers.yaml
kubectl apply -f k8s/clusterrolebinding-issuers.yaml
Update the YAML file with your email address and DNS provider credentials before applying.
5. Deploy the application
kubectl apply -f k8s/service-account.yaml
kubectl apply -f k8s/routers-config.yaml
kubectl apply -f k8s/cronjob.yaml
Configuration
Router Configuration
Each router entry in the configuration requires:
| Field | Description | Example |
|---|---|---|
name |
Router identifier (used for DNS) | router1 |
host |
Router IP address | 192.168.1.1 |
port |
Plain API port | 8728 |
ssl_port |
SSL API port (optional, default: 8729) | 8729 |
username |
API username | admin |
cert_secret |
Kubernetes secret name for TLS cert | router1-tls |
password_secret |
Kubernetes secret name for password | router1-credentials |
cert_name |
Certificate name on the router | router1-cert |
CronJob Schedule
The default schedule runs at 2 AM on Sundays and Wednesdays:
schedule: 0 2 * * 0,3
Modify this in k8s/cronjob.yaml to fit your needs.
How It Works
- CronJob triggers on the scheduled time
- DNS records created/updated via DNSEndpoint resources
- Certificates requested via cert-manager Certificate resources
- Script connects to each router:
- First tries SSL connection (port 8729) with cert verification disabled
- Falls back to plain connection (port 8728) if SSL fails
- Certificates uploaded to the router via API
- Certificates imported and marked as trusted on the router
MikroTik Router Setup
Enable API Access
For SSL API (recommended):
/ip service
set api-ssl disabled=no
For plain API (less secure):
/ip service
set api disabled=no
Create API User (Optional)
For better security, create a dedicated API user:
/user group add name=api-users policy=api,read,write,test
/user add name=certbot group=api-users password=strong-password
Usage
Using Issuer vs ClusterIssuer
By default, the script uses namespace-scoped Issuers. To use a ClusterIssuer, pass the --issuer-kind flag:
# Using default Issuer
cert2mikrotik --config routers.json --issuer letsencrypt-prod
# Using ClusterIssuer
cert2mikrotik --config routers.json --issuer letsencrypt-prod --issuer-kind ClusterIssuer
Command-line Options
--config Path to routers config JSON file (required)
--namespace Kubernetes namespace (default: default)
--issuer cert-manager Issuer name (default: letsencrypt-prod)
--issuer-kind Issuer kind: Issuer or ClusterIssuer (default: Issuer)
--domain-suffix Domain suffix for DNS names (default: .adviser.com)
--ensure-resources Create/update Certificate and DNSEndpoint resources (default: true)
--skip-resources Skip creating/updating Certificate and DNSEndpoint resources
--verbose, -v Enable verbose logging
Manual Testing
You can manually trigger a job run:
kubectl create job --from=cronjob/mikrotik-cert-upload manual-test
kubectl logs -f job/manual-test
Troubleshooting
Connection Issues
Check if the API port is accessible:
# Test SSL API
openssl s_client -connect <router-ip>:8729
# Test plain API
telnet <router-ip> 8728
View Job Logs
# List recent jobs
kubectl get jobs
# View logs
kubectl logs job/<job-name>
Certificate Issues
Check cert-manager certificate status:
kubectl get certificates
kubectl describe certificate <cert-name>
Security Considerations
- Use SSL API - Always prefer SSL API (port 8729) over plain API (port 8728)
- Restrict API access - Use firewall rules to limit API access to the Kubernetes cluster
- Use strong passwords - Store router passwords securely in Kubernetes secrets
- Certificate verification - The script disables cert verification for compatibility; consider using proper CA-signed certificates for production
- RBAC - The service account has minimal permissions required for operation
License
Apache License 2.0 - See LICENSE file for details
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Acknowledgments
This project was developed with the assistance of Claude Code, an AI-powered coding assistant by Anthropic.
Author
Created for automated MikroTik certificate management in Kubernetes environments.
Author: Meno Abels
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 certs4mikrotik-0.0.2.tar.gz.
File metadata
- Download URL: certs4mikrotik-0.0.2.tar.gz
- Upload date:
- Size: 14.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33f07c9c66df816a3354a198414ef7a15f5278970bba89225d5725bef567f809
|
|
| MD5 |
4aebbd036f6b0865f78d6d8eaea45dca
|
|
| BLAKE2b-256 |
4be48642324d76255f08b99e4d4970826358ed098ac2932793c64cacaa33a551
|
Provenance
The following attestation bundles were made for certs4mikrotik-0.0.2.tar.gz:
Publisher:
publish-to-pypi.yml on mabels/certs4mikrotik
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
certs4mikrotik-0.0.2.tar.gz -
Subject digest:
33f07c9c66df816a3354a198414ef7a15f5278970bba89225d5725bef567f809 - Sigstore transparency entry: 659141983
- Sigstore integration time:
-
Permalink:
mabels/certs4mikrotik@c6fe4faca191886472502af79af70ff36b1c3b40 -
Branch / Tag:
refs/tags/v0.0.2 - Owner: https://github.com/mabels
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@c6fe4faca191886472502af79af70ff36b1c3b40 -
Trigger Event:
push
-
Statement type:
File details
Details for the file certs4mikrotik-0.0.2-py3-none-any.whl.
File metadata
- Download URL: certs4mikrotik-0.0.2-py3-none-any.whl
- Upload date:
- Size: 13.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0170d9a2ac8c1bc61a152ae7775e3746f19819d114c26ee771fdf9a619d1bac1
|
|
| MD5 |
33e24d04b015a62e63c5f1f18819ed57
|
|
| BLAKE2b-256 |
591b4c9660d5973c18c27c2a497868ac092eed845f28d22dad1417e86a17598e
|
Provenance
The following attestation bundles were made for certs4mikrotik-0.0.2-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on mabels/certs4mikrotik
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
certs4mikrotik-0.0.2-py3-none-any.whl -
Subject digest:
0170d9a2ac8c1bc61a152ae7775e3746f19819d114c26ee771fdf9a619d1bac1 - Sigstore transparency entry: 659142004
- Sigstore integration time:
-
Permalink:
mabels/certs4mikrotik@c6fe4faca191886472502af79af70ff36b1c3b40 -
Branch / Tag:
refs/tags/v0.0.2 - Owner: https://github.com/mabels
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@c6fe4faca191886472502af79af70ff36b1c3b40 -
Trigger Event:
push
-
Statement type: