Enabling MikroTik REST API Over SSL Using Ansible
In this guide, we’ll show you how to enable the MikroTik REST API over SSL using Ansible 1. Starting from RouterOS v7.9, MikroTik officially supports SSL for the REST API 2.
We’ll break down the process into six simple steps:
- Set up a Python environment and install Ansible
- Test Ansible connectivity to the MikroTik router
- Generate a self-signed SSL certificate
- Enable the REST API with SSL
- Test the REST API with
curl
- Automate SSL certificate renewal with a script
1. Set Up Python Environment and Install Ansible
Ansible is written in Python, so we’ll begin by creating an isolated Python virtual environment. This keeps dependencies contained and avoids conflicts with system-wide Python packages.
1.1 Create and Activate a Virtual Environment
python3 -m venv .venv
source .venv/bin/activate
1.2 Install Ansible
pip install ansible
1.3 Confirm Installation
Let’s verify Ansible is working by running a test ping to localhost:
ansible localhost -m ping -e 'ansible_python3_interpreter="/usr/bin/env python3"'
Expected result:
localhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
1.4 Set Up Your Project Structure
Create directories for inventory
and playbooks
:
mkdir inventory playbooks
Also, create and config an ansible.cfg
file so Ansible knows where your inventory is:
[defaults]
inventory=./inventory
2. Configure Ansible and Test Connection to MikroTik
In this step, we define how Ansible can reach your MikroTik router — including IP address, credentials, and connection method.
2.1 Create an Inventory File
Create a file named inventory/hosts
with the following content:
[mikrotik_routers]
mikrotik.wiphoo.dev.internal ansible_host=192.168.88.1
[mikrotik_routers:vars]
ansible_connection=ansible.netcommon.network_cli
ansible_network_os=community.routeros.routeros
ansible_user=admin
ansible_password=REPLACE_THIS_WITH_YOUR_ROUTER_PASSWORD
Let’s break this down:
mikrotik.wiphoo.dev.internal
: A label for your router (can be a hostname or alias).ansible_host=192.168.88.1
: The IP address for a MikroTik device.ansible_connection
: Specifies we’re using CLI-based communication.ansible_network_os
: Tells Ansible we’re working with MikroTik’s RouterOS.ansible_user
andansible_password
: The login credentials — replace these with your actual values.
💡 You can name your host anything you like. The
mikrotik_routers
group is referenced in playbooks to target one or more MikroTik devices.
2.2 Test the Inventory File
Run the following command to verify your inventory:
ansible-inventory --list
Expected result:
{
"_meta": {
"hostvars": {
"mikrotik.wiphoo.dev.internal": {
"ansible_connection": "ansible.netcommon.network_cli",
"ansible_host": "192.168.88.1",
"ansible_network_os": "community.routeros.routeros",
"ansible_password": "REPLACE_THIS_WITH_YOUR_ROUTER_PASSWORD",
"ansible_user": "admin"
}
}
},
"all": {
"children": [
"ungrouped",
"mikrotik_routers"
]
},
"mikrotik_routers": {
"hosts": [
"mikrotik.wiphoo.dev.internal"
]
}
}
This confirms Ansible has parsed your configuration correctly and recognizes your MikroTik host.
2.3 Test the Connection with a Playbook
Now we’ll create a playbook that:
- Logs in to the router
- Executes
/system resource print
- Displays system information
- Retrieves interface facts (like IP address)
Create the file playbooks/check_routeros_connection.yaml
:
---
- name: Check RouterOS connection
hosts: mikrotik_routers
gather_facts: false
tasks:
- name: Run a command
community.routeros.command:
commands:
- /system resource print
register: system_resource_print
- name: Print its output
ansible.builtin.debug:
var: system_resource_print.stdout_lines
- name: Retrieve facts
community.routeros.facts:
- name: Retrieve IP address
ansible.builtin.debug:
msg: "First IP address: {{ ansible_net_all_ipv4_addresses[0] }}"
Run the Playbook:
ansible-playbook playbooks/check_routeros_connection.yaml --limit mikrotik.wiphoo.dev.internal
If successful, you’ll see your MikroTik system details and current IP address. This confirms that Ansible can talk to your device using CLI automation.
3. Generate a Self-Signed SSL Certificate
To enable HTTPS for the REST API, the MikroTik router needs an SSL certificate. For simplicity, we’ll generate a self-signed certificate directly on the router using Ansible.
3.1 Create the Certificate Playbook
Create a file named playbooks/create_self-signed_certificate.yaml
:
---
- name: Create self-signed SSL certificate on MikroTik
hosts: mikrotik_routers
gather_facts: false
vars:
domain_name: "{{ inventory_hostname }}"
tasks:
- name: Create certificate template
community.routeros.command:
commands:
- /certificate add name={{ domain_name }} common-name={{ domain_name }} key-usage=key-cert-sign,crl-sign
- name: Sign the certificate (self-signed)
community.routeros.command:
commands:
- /certificate sign {{ domain_name }} name={{ domain_name }}
- name: Confirm certificate is created
community.routeros.command:
commands:
- /certificate print
register: service_status
- name: Show output
ansible.builtin.debug:
var: service_status.stdout_lines
What this does:
- Adds a certificate entry with the router’s hostname as the common name.
- Self-signs the certificate.
- Prints the list of available certificates to confirm success.
3.2 Run the Playbook
ansible-playbook playbooks/create_self-signed_certificate.yaml --limit mikrotik.wiphoo.dev.internal
Expected result:
...
ok: [mikrotik.wiphoo.dev.internal] => {
"service_status.stdout_lines": [
[
"Flags: K - PRIVATE-KEY; A - AUTHORITY; T - TRUSTED",
"Columns: NAME, COMMON-NAME",
"# NAME COMMON-NAME ",
"0 KAT mikrotik.wiphoo.dev.internal mikrotik.wiphoo.dev.internal"
]
]
}
...
You should see the mikrotik.wiphoo.dev.internal
certificate with flags like KAT, which means:
K
: It has a private keyA
: It’s an authority (can sign)T
: It’s trusted This certificate will later be used to enable HTTPS on the MikroTik REST API.
4. Enable the REST API Over SSL
Now that we’ve created a valid SSL certificate on the MikroTik router, it’s time to enable the REST API using HTTPS, ensuring secure communication. We’ll also disable the insecure HTTP version to avoid exposing sensitive data.
This is critical when building automation workflows or integrations — using SSL protects the data and credentials from being intercepted.
4.1 Create the Enable the REST API Playbook
Create a file named playbooks/enable_rest_api_with_ssl_service.yaml
with the follow content:
---
- name: Enable MikroTik REST API (SSL) and Disable REST API (without SSL)
hosts: mikrotik
gather_facts: false
vars:
api_port: 443
allowed_ips: "0.0.0.0/0"
certificate: "{{ inventory_hostname }}"
tasks:
- name: Enable REST API (SSL)
community.routeros.command:
commands:
- /ip service set www-ssl disabled=no
- /ip service set www-ssl port={{ api_port }}
- /ip service set www-ssl address={{ allowed_ips }}
- /ip service set www-ssl certificate={{ certificate }}
- name: Disable REST API
community.routeros.command:
commands:
- /ip service set www disabled=yes
- name: Confirm REST API are enabled and disabled
community.routeros.command:
commands:
- /ip service print
register: service_status
- name: Show output
ansible.builtin.debug:
var: service_status.stdout_lines
Let’s break it down step-by-step:
www-ssl
is the MikroTik service that serves the REST API over HTTPS (SSL).- We set the port to
443
, which is the default for secure HTTP. - We configure it to listen on
0.0.0.0/0
, meaning it will accept requests from any IP address (adjust this for stricter security). - We assign the SSL certificate we created earlier to encrypt traffic and authenticate the server.
- We set the port to
www
is the unencrypted version of the REST API (HTTP).- We disabled it to eliminate insecure access and enforce secure communication only.
4.2 Run the Playbook
ansible-playbook playbooks/enable_rest_api_with_ssl_service.yaml --limit mikrotik.wiphoo.dev.internal
Expected result:
PLAY [Enable MikroTik REST API (SSL) and Disalbe REST API (without SSL)] ****************************************************************************************************************************
TASK [Enable REST API (SSL)] ************************************************************************************************************************************************************************
changed: [mikrotik.wiphoo.dev.internal]
TASK [Disable REST API] *****************************************************************************************************************************************************************************
changed: [mikrotik.wiphoo.dev.internal]
TASK [Confirm REST API are enabled and disabled] ****************************************************************************************************************************************************
changed: [mikrotik.wiphoo.dev.internal]
TASK [Show output] **********************************************************************************************************************************************************************************
ok: [mikrotik.wiphoo.dev.internal] => {
"service_status.stdout_lines": [
[
"Flags: X - DISABLED, I - INVALID",
"Columns: NAME, PORT, ADDRESS, CERTIFICATE, VRF, MAX-SESSIONS",
"# NAME PORT ADDRESS CERTIFICATE VRF MAX-SESSIONS",
"0 X telnet 23 main 20",
"1 X ftp 21 main 20",
"2 X www 80 main 20",
"3 ssh 22 main 20",
"4 www-ssl 443 0.0.0.0/0 mikrotik.wiphoo.dev.internal main 20",
"5 X api 8728 main 20",
"6 X winbox 8291 main 20",
"7 X api-ssl 8729 none main 20"
]
]
}
PLAY RECAP ******************************************************************************************************************************************************************************************
mikrotik.wiphoo.dev.internal : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
This confirms the success:
- The
X
mark next towww
means it’s disabled www-ssl
is enabled and bound to port443
- It is using the certificate named
mikrotik.wiphoo.dev.internal
5. Test the REST API with curl
After enabling SSL and assigning the certificate, it’s important to verify both the certificate and the API functionality.
5.1 Check the SSL Certificate with openssl
You can inspect the certificate served by the MikroTik router using the openssl
command. This helps confirm that SSL is correctly set up and that the expected certificate is being used.
Run the following command:
openssl s_client -connect 192.168.88.1:443 -servername 192.168.88.1 < /dev/null | openssl x509 -noout -text
This will output details about the SSL certificate, including:
- Common Name (CN) (should match your hostname)
- Signature Algorithm
- Validity Period (notBefore / notAfter)
- Public Key Details
- Signature Value
5.2 Call the REST API with curl
(over HTTPS)
Now, let’s confirm that the REST API is working securely over SSL. Use the curl
command with basic authentication and the -k
flag to skip certificate verification (helpful when using self-signed certificates):
curl -k -u admin:REPLACE_THIS_WITH_YOUR_ROUTER_PASSWORD http://192.168.88.1/rest/system/resource
Expected output:
{
"architecture-name": "arm",
"bad-blocks": "0",
"board-name": "hEX",
"build-time": "2025-03-11 11:59:04",
"cpu": "ARM",
"cpu-count": "2",
"cpu-load": "0",
"factory-software": "7.15.3",
"free-hdd-space": "110993408",
"free-memory": "465379328",
"platform": "MikroTik",
"total-hdd-space": "134217728",
"total-memory": "536870912",
"uptime": "1d1h38m41s",
"version": "7.18.2 (stable)",
"write-sect-since-reboot": "385",
"write-sect-total": "10238"
}
6. Automate SSL certificate renewal with a script
By default, self-signed certificates on MikroTik expire after 1 year. To ensure your REST API remains accessible over HTTPS, it’s essential to renew the certificate before it expires.
We’ll automate this renewal process using a MikroTik script that:
- Removes the old certificate
- Creates and signs a new one
- Assigns the new certificate to the www-ssl service
6.1 Create the Jinja2 Script Template
Create a new file called renew_self-signed_certificate.rsc.j2
under your Ansible playbooks/templates/
directory. This is a Jinja2 template that MikroTik will interpret as a script.
:log info \"Renew {{ domain_name }} self-signed certificate\";
/certificate remove [find name={{ domain_name }}];
/certificate add name={{ domain_name }} common-name={{ domain_name }} key-usage=key-cert-sign,crl-sign
/certificate sign {{ domain_name }};
:delay 5s;
/ip service set www-ssl certificate={{ domain_name }};
:log info \"Certificate {{ domain_name }} renewal completed\";
Let’s break it down step-by-step:
- Logs the renewal process
- Removes the old certificate by name
- Creates and signs a new certificate
- Applies it to the
www-ssl
service - Logs the renewal process is completed
6.2 Create the Ansible Playbook
Now, we’ll write a playbook named schedule_renew_self-signed_certificate.yaml
. This playbook uploads the template as a MikroTik script and schedules it to run automatically.
---
- name: Renew self-signed certificate on MikroTik
hosts: mikrotik_routers
gather_facts: false
vars:
domain_name: "{{ inventory_hostname }}"
script_name: "renew-self-signed-cert"
schedule_name: "auto-renew-self-signed-cert"
tasks:
- name: Upload certificate renewal script
community.routeros.command:
commands:
- /system script remove [find name={{ script_name }}]
- /system script add name={{ script_name }} source="{{ lookup('template', 'templates/renew_self-signed_certificate.rsc.j2') | regex_replace('\n', '\\r\\n') }}"
- name: Run the renewal script
community.routeros.command:
commands:
- /system script run {{ script_name }}
- name: Create scheduler to run script yearly
community.routeros.command:
commands:
- /system scheduler remove [find name={{ schedule_name }}]
- /system scheduler add name={{ schedule_name }} interval=51w on-event={{ script_name }}
What this doeses:
- Removes the previous version (if any) and uploads the new one from the Jinja2 template.
- Runs the script immediately, Ensures everything works now, not just next year.
- Sets up a scheduler, Configures MikroTik to run the script every 51 weeks — safely renewing before expiration.
6.3 Run the Playbook
Now that we’ve written our renewal script and scheduled it via Ansible, let’s execute the playbook to upload and schedule it on the MikroTik device.
Run the following command:
ansible-playbook playbooks/schedule_renew_self-signed_certificate.yaml --limit mikrotik.wiphoo.dev.internal
If all tasks complete without errors:
- Your MikroTik router now has a fresh certificate applied.
- A scheduler is set up to automatically renew the certificate every 51 weeks.
- You should see logs from
/log print
command in MikroTik like:
2025-04-15 01:02:31 script,info Renew mikrotik.wiphoo.dev.internal self-signed certificate
2025-04-15 01:02:35 certificate,info generated CA certificate: mikrotik.wiphoo.dev.internal
2025-04-15 01:02:40 script,info Certificate mikrotik.wiphoo.dev.internal renewal completed