Motivation
In today’s world where every web site must be encrypted lest the browsers and security software get all upset about the lack, yet where services like Let’s Encrypt cannot succeed in doing a trustworthy domain validation check, even a home LAN user may find themselves in need of setting up a local certificate authority. There are many ways to achieve this, and RouterOS is one of them.
For this example, we will imagine a simple two-device setup:
- an Internet gateway (
gw
) router with the default MikroTik IP 192.168.88.1, serving as our new CA - a switch (
sw
) at IP 192.168.88.16 to expand the port count, which will have need of certificates minted by this CA
Extending this to more devices is trivial, to a point. With enough devices, you will want a more automated scheme than I am showing here.
I will show the method from the CLI, partly by preference, and partly because it’s easier to copy-paste from a command line example than a screenshot. I will therefore assume you have SSH access to your devices in my examples below, which has the side bonus of clarifying which device I’m talking about at any given moment. However, the core elements of what I show can be done from Winbox or Webfig as well.
Setting up the CA
The first thing we must do is establish the CA signing certificate on the gateway:
$ ssh gw
> /certificate
> add name=MyCA common-name=MyCA \
country=XX state=YY locality=Zedzed organization=MyOrg unit="Home IT" \
trusted=yes key-usage=key-cert-sign,crl-sign days-valid=3650
> sign MyCA
You can put any values you like into the location fields. I’m not aware of any software that checks these for truth, or even plausibility. No web browser will run a GPS query on the values and go, “Aha! I can infer from the ping time that the endpoint must be nearby on the Earth, yet the certificate claims to be signed by an entity on Elara, the seventh moon of Jupiter; it must be invalid!”
Of more import is the validity time. I’ve chosen 10 years in the hopes that I will have replaced this gateway before the CA signing cert becomes invalid. As we will shortly see, there are moves in the tech world to disregard long-lived certs, but the grabbies aren’t coming for the CAs yet.
That last step is also worth explaining: this CA cert is, by virtue of this command, a self-signed certificate. We need a few more steps to make our browsers trust it implicitly, as they do for the big-name CAs…
Trusting the CA Implicitly
We will need a copy of the public half of the new CA root cert, generated above on gw
:
$ ssh gw
> export-certificate file-name=MyCA.crt MyCA
> exit
$ scp gw:MyCA.crt ~/Desktop
Next, you need to install that public certificate into the local CA root trust store. On macOS and Windows, this is easy: double-click the MyCA.crt
file and walk through the resulting GUI steps. Mark it as Trusted, and you’re done.
The comparable steps on Linuxes vary, and they’re a bit more fiddly. On Red Hattish ones, the key steps are:
$ sudo mv ~/Desktop/MyCA.crt /etc/pki/ca-trust/source/anchors/
$ sudo update-ca-trust
The commands are similar for Debian and its derivatives like Ubuntu, but they differ because Linux 🙄:
$ sudo mv ~/Desktop/MyCA.crt /usr/local/share/ca-certificates
$ sudo update-ca-certificates
At this point, these client machines will trust any certificate signed by this CA. You must therefore protect the root certificate assiduously! Anyone who can get their hands on the private half can impersonate any web site on the planet, as far as any TLS client on these hosts are now concerned. It is a good idea to export a copy of the certificate for backup purposes…
> export-certificate file-name=MyCA.key passphrase=ABCD1234 MyCA
> exit
$ scp gw:MyCA.key ~/Desktop
…but I would not recommend relying entirely on that passphrase for security. I keep mine in a password manager; belt-and-bracers.
Note that you do not have a choice in supplying the passphrase. If you do not, you get the public half of the certificate only. To get the actual signing key, you must give RouterOS a passphrase, even if it’s a single character.
Minting TLS Certificates
To this point, nothing of functional import has occurred. Let’s fix that:
$ ssh gw
> /certificate
> add name=OfficeSwitchTLS common-name=officeswitch \
subject-alt-name=IP:192.168.88.16,DNS:sw16 \
country=XX state=YY locality=Zedzed organization=MyOrg unit="Home IT" \
trusted=yes key-usage=tls-server
> /certificate sign ca=MyCA OfficeSwitchTLS
> /certificate export-certificate export-passphrase=ABCD1234 \
file-name=SwTLS OfficeSwitchTLS
> exit
The common-name
field should be the device’s primary host name on the network, as configured in DNS, without the domain name.1 The subject-alt-name
value appends aliases for that name, making it optional but helpful; it lets us mint a single certificate that works for multiple possible CNAMEs/IPs. If you leave this unset, you must remember which single one of these possibilities the certificate was minted for and use that one exclusively.
The location values do not have to match those of the CA, but since both devices are in the same house in our example, they should. They differ normally when you are contracting with a third-party CA to mint and sign certificates for you.
The default lifetime for certificates is 365 days, which is currently legal as I write this, but it is scheduled to ratchet downward over the coming few years to an ultimate upper limit of 47 days. Be thankful for moderating forces; the brilliant minds behind this move wanted it to be a week!
We’ll get back to that detail below, but for now, let’s install that certificate into the switch:
$ scp gw:SwTLS.key sw:
$ ssh sw
> /certificate
> import file-name=SwTLS.key name=SwTLS trusted=yes passphrase=ABCD1234
> /ip/service/set www-ssl certificate=SwTLS
At this point, you should be able to open Webfig on that switch (presuming it was enabled prior to this) via an https://192.168.88.16
URL. It should come up without the browser complaining that this is a self-signed certificate because it was signed by a CA it was told to trust in the steps above.
(You should not have to import SwTLS.crt
separately, because the passphrase-protected private key form has the public key concatenated. However, I have not tested that with RouterOS specifically, only other software.)
There’s a shortcut when the CA and the device needing the certificate are the same. Let’s say we’ve enabled the RouterOS REST API on the gateway for some reason:
$ ssh gw
> /certificate
> add name=GatewayTLS common-name=hapax3 \
subject-alt-name=IP:192.168.88.1,DNS:gw \
country=XX state=YY locality=Zedzed organization=MyOrg unit="Home IT" \
trusted=yes key-usage=tls-server
> /certificate sign ca=MyCA GatewayTLS
> /ip/service/set api-ssl certificate=GatewayTLS
We were able to skip the export-and-import dance because the certificate was already on the device.
Nevertheless, you might still want to export the generated GatewayTLS
certificate per the instructions above for backup purposes.
Automating This, Home IT Style
Out on the wider Internet, the advent of Let’s Encrypt revolutionized certificate issuance by making it free and easy to get updated domain validation certificates on demand. Other CAs copied the method, which is why it is now all but the universal way certificates are acquired and provisioned. This in turn is why those “brilliant minds” above felt they could push the limit down to a week: as long as your systems check in every day or so, a week is far in excess of requirements.
The thing is, none of that works on private LANs, where services like Let’s Encrypt will fail at the domain validation step. We must therefore cope with a time limit made with the assumption that the certificate generation and provisioning process is automated while not being able to use the most popular automation tooling.
There are IT systems management software packages for handling this, but they’re not appropriate for home users like me.
Being a software developer, I wrote my own script for this. I offer it in the hopes that you will be able to wring sufficient utility from it that it was worth your time in trying, but you will find no warranty, and no support for it here.
License
This work is © 2025 by Warren Young and is licensed under CC BY-NC-SA 4.0
- ^ If FQDNs are important in your application, you should be using Let’s Encrypt or similar to get a domain validation check.