Contents

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:

  1. Set up a Python environment and install Ansible
  2. Test Ansible connectivity to the MikroTik router
  3. Generate a self-signed SSL certificate
  4. Enable the REST API with SSL
  5. Test the REST API with curl
  6. 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 and ansible_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 key
  • A: 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.
  • 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 to www means it’s disabled
  • www-ssl is enabled and bound to port 443
  • 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