Laravel·MikroTik·Networking

Cara Menghubungkan Laravel ke MikroTik RouterOS API

Puji Ermanto
Puji Ermanto17 September 2026 · 18 mins read
Cara Menghubungkan Laravel ke MikroTik RouterOS API

بسم الله الرحمن الرحيم

Pada catatan sebelumnya saya mulai membangun fondasi web app billing ISP menggunakan Laravel dan MikroTik.

Kita sudah memisahkan data bisnis seperti pelanggan, paket internet, akun PPPoE, dan invoice dari konfigurasi jaringan yang berada di MikroTik.

Sekarang kita masuk ke bagian yang menurut saya mulai menarik dari eksperimen ini:

membuat aplikasi Laravel benar-benar berkomunikasi dengan MikroTik RouterOS.

Artikel ini merupakan Part 3 dari catatan eksperimen Laravel + MikroTik untuk ISP Billing.

Part 1
PPPoE Server MikroTik CHR

        ↓

Part 2
Fondasi Web App Billing Laravel

        ↓

Part 3
Laravel ↔ RouterOS API
        ↑
    kita di sini

Catatan: konfigurasi pada artikel ini berasal dari environment lab yang saya gunakan ketika mengembangkan aplikasi billing MikroTik. IP address, username, password, dan data lainnya disederhanakan untuk kebutuhan artikel. Jangan menyalin credential lab langsung ke environment production.


Target Part 3

Pada tahap ini kita belum membuat provisioning PPPoE secara otomatis.

Target kita lebih sederhana:

Laravel
   │
   │ RouterOS API
   ▼
MikroTik CHR
   │
   ├── menerima koneksi
   ├── memberikan informasi router
   └── memberikan data PPP

Kita ingin membuktikan beberapa hal:

✓ RouterOS API aktif

✓ Laravel dapat membuka koneksi ke MikroTik

✓ Credential disimpan melalui environment configuration

✓ Logic RouterOS tidak diletakkan langsung di controller

✓ Laravel dapat membaca informasi dari router

✓ Error koneksi dapat ditangani

✓ Fondasi siap digunakan untuk provisioning PPPoE

Kalau semua ini berhasil, pada Part berikutnya Laravel sudah mempunyai jalur komunikasi yang dapat digunakan untuk membuat dan mengelola PPP Secret.


Environment Lab yang Saya Gunakan

Untuk eksperimen ini saya menggunakan MikroTik CHR sebagai router virtual.

Secara sederhana environment-nya seperti ini:

┌──────────────────────────┐
│      Laravel Web App     │
│                          │
│ ISP Billing Application  │
└─────────────┬────────────┘
              │
              │ RouterOS API
              │
              ▼
┌──────────────────────────┐
│    MikroTik CHR Server   │
│                          │
│ API        : 8728        │
│ PPPoE      : aktif       │
│ PPP Secret : tersedia    │
└─────────────┬────────────┘
              │
              │ PPPoE
              ▼
┌──────────────────────────┐
│    MikroTik CHR Client   │
│                          │
│     testclient           │
└──────────────────────────┘

Pada Part 1 sebelumnya kita sudah membuktikan bahwa client testclient dapat terhubung ke PPPoE Server.

Sekarang Laravel akan berbicara dengan CHR Server, bukan dengan PPPoE Client.


Gambaran Hasil yang Ingin Kita Capai

Pada aplikasi billing, saya ingin mempunyai indikator sederhana untuk mengetahui apakah router dapat dijangkau oleh aplikasi.

Preview test connection Laravel ke MikroTik RouterOS API

Gambar 1. Ilustrasi preview halaman test connection Laravel ke MikroTik RouterOS API. Data pada gambar merupakan contoh environment lab.

Secara sederhana flow-nya:

Operator
   │
   │ klik Test Connection
   ▼
Laravel
   │
   │ RouterOS API
   ▼
MikroTik CHR
   │
   ├── berhasil
   │      ↓
   │   Connected
   │
   └── gagal
          ↓
       Error / Timeout

Test connection seperti ini sangat membantu sebelum kita mulai melakukan operasi yang lebih berisiko seperti membuat, men-disable, atau menghapus PPP Secret.


Pastikan RouterOS API Aktif

Sebelum Laravel dapat terhubung, kita perlu memastikan service API RouterOS tersedia.

Login ke MikroTik CHR Server melalui Winbox atau terminal, kemudian jalankan:

/ip service print

Cari service:

api

Contoh:

Flags: X - disabled

 #   NAME     PORT
 0   telnet   23
 1   ftp      21
 2   www      80
 3   ssh      22
 4   www-ssl  443
 5   api      8728
 6   winbox   8291
 7   api-ssl  8729

Untuk lab, kita dapat menggunakan API pada port:

8728

Pastikan service api tidak dalam kondisi disabled.

Jika memang disabled pada environment lab:

/ip service enable api

Kemudian periksa lagi:

/ip service print

Ilustrasi RouterOS API service aktif pada MikroTik CHR

Gambar 2. Ilustrasi pengecekan service RouterOS API pada CHR Server.


Jangan Gunakan User Admin untuk Aplikasi

Ketika pertama kali melakukan eksperimen, memang paling mudah menggunakan akun administrator.

Tetapi kebiasaan tersebut sebaiknya tidak diteruskan.

Saya lebih memilih membuat akun khusus untuk aplikasi billing.

Secara konsep:

admin
────────────────────
Digunakan administrator

api-billing
────────────────────
Digunakan Laravel

Tujuannya supaya credential aplikasi dapat dipisahkan dari credential administrator router.

Untuk environment sebenarnya, policy/group user juga harus dibatasi hanya pada permission yang memang dibutuhkan aplikasi.

Prinsipnya:

Laravel tidak membutuhkan
hak akses lebih banyak
daripada pekerjaannya.

Ini menjadi semakin penting ketika aplikasi nantinya dapat melakukan:

create PPP Secret
disable PPP Secret
enable PPP Secret
read PPP Active
read interface
read traffic

Simpan Credential Router di .env

Jangan menulis konfigurasi router langsung di controller.

Contoh yang sebaiknya dihindari:

$client = new Client([
    'host' => '192.168.1.7',
    'user' => 'admin',
    'pass' => 'password-router',
]);

Masalahnya bukan hanya kode terlihat berantakan.

Kalau repository dipublikasikan ke GitHub, credential dapat ikut ter-push.

Gunakan .env.

ROUTEROS_HOST=192.168.1.7
ROUTEROS_PORT=8728
ROUTEROS_USERNAME=api-billing
ROUTEROS_PASSWORD=ganti-dengan-password-lab
ROUTEROS_TIMEOUT=10

Kemudian tambahkan konfigurasi aplikasi.

Misalnya:

config/routeros.php

Isinya:

<?php

return [

    'host' => env('ROUTEROS_HOST'),

    'port' => (int) env('ROUTEROS_PORT', 8728),

    'username' => env('ROUTEROS_USERNAME'),

    'password' => env('ROUTEROS_PASSWORD'),

    'timeout' => (int) env('ROUTEROS_TIMEOUT', 10),

];

Dengan begitu aplikasi cukup menggunakan:

config('routeros.host');
config('routeros.port');
config('routeros.username');

tanpa mengetahui dari mana credential sebenarnya berasal.


Jangan Commit .env

Pastikan .env masuk .gitignore.

.env
.env.*
!.env.example

Untuk repository, kita cukup menyediakan .env.example.

Misalnya:

ROUTEROS_HOST=
ROUTEROS_PORT=8728
ROUTEROS_USERNAME=
ROUTEROS_PASSWORD=
ROUTEROS_TIMEOUT=10

Jangan pernah menaruh password sebenarnya di:

GitHub
GitLab
screenshot
artikel
log publik
JavaScript frontend

Kalau credential pernah terlanjur dipublikasikan, anggap credential tersebut sudah tidak aman dan lakukan rotasi.


Membuat RouterOS Client Service

Saya tidak ingin setiap controller membuat koneksi MikroTik sendiri.

Daripada seperti ini:

CustomerController
    ↓
RouterOS

InvoiceController
    ↓
RouterOS

PppoeController
    ↓
RouterOS

lebih baik kita mempunyai satu abstraction:

Controller
    ↓
Service
    ↓
RouterosClient
    ↓
MikroTik

Struktur sederhananya:

app/

├── Http/
│   └── Controllers/
│
├── Services/
│   └── MikroTik/
│       ├── RouterosClient.php
│       ├── PppoeProvisioningService.php
│       └── PppoeMonitoringService.php
│
└── Jobs/
    └── SyncPppoeSessions.php

Pada Part 3 ini kita fokus pada:

RouterosClient.php

Service inilah yang nantinya menjadi pintu komunikasi aplikasi dengan RouterOS.


Contoh RouterosClient

Implementasi persisnya bergantung pada RouterOS client/library yang digunakan.

Secara konsep saya ingin service tersebut mempunyai kemampuan seperti:

class RouterosClient
{
    public function testConnection(): bool
    {
        // membuka koneksi ke RouterOS
        // menjalankan query ringan
        // return true jika berhasil
    }

    public function getSystemResource(): array
    {
        // membaca /system/resource
    }

    public function getActivePppoeSessions(): array
    {
        // membaca /ppp/active
    }
}

Controller tidak perlu mengetahui detail protocol RouterOS.

Controller cukup melakukan:

$router->testConnection();

atau:

$router->getActivePppoeSessions();

Ini membuat integrasi lebih mudah dirawat ketika suatu saat library RouterOS yang digunakan berubah.


Membuat Test Connection

Sebelum provisioning, saya membuat fungsi sederhana untuk memastikan koneksi benar-benar bekerja.

Misalnya:

public function testConnection()
{
    try {

        $connected = $this->routeros->testConnection();

        return response()->json([
            'success' => $connected,
            'message' => $connected
                ? 'RouterOS connected'
                : 'RouterOS connection failed',
        ]);

    } catch (\Throwable $e) {

        report($e);

        return response()->json([
            'success' => false,
            'message' => 'Unable to connect to RouterOS',
        ], 503);
    }
}

Untuk debugging internal, detail error dapat masuk ke log.

Namun saya tidak ingin response production mengembalikan:

password
credential
stack trace
internal network detail

kepada browser.


Preview Test Connection

Saat koneksi berhasil, dashboard dapat menampilkan informasi sederhana.

Preview Laravel berhasil terhubung dengan MikroTik RouterOS

Gambar 3. Ilustrasi kondisi ketika Laravel berhasil membuka koneksi ke MikroTik CHR Server.

Misalnya:

Router

Name       : chr-lab-01
Host       : 192.168.1.x
API Port   : 8728
Status     : CONNECTED
Last Seen  : just now

Yang penting bukan tampilannya.

Yang penting adalah Laravel sudah berhasil melakukan komunikasi dua arah dengan RouterOS.


Mengambil /system resource

Setelah koneksi berhasil, jangan langsung membuat PPP Secret.

Saya lebih suka mencoba query read-only terlebih dahulu.

Salah satunya:

/system resource print

Informasi yang biasanya dapat diperoleh antara lain:

uptime
version
build-time
free-memory
total-memory
cpu
cpu-count
cpu-frequency
cpu-load
free-hdd-space
total-hdd-space
architecture-name
board-name
platform

Dari Laravel kita dapat mengubah response tersebut menjadi struktur aplikasi.

Misalnya:

{
    "status": "connected",
    "router": {
        "platform": "MikroTik",
        "board": "CHR",
        "version": "RouterOS",
        "uptime": "1h20m"
    }
}

Preview informasi RouterOS yang dibaca oleh Laravel

Gambar 4. Ilustrasi data RouterOS yang berhasil dibaca aplikasi Laravel.

Kalau /system resource sudah berhasil dibaca, kita mempunyai bukti yang jauh lebih kuat dibanding sekadar berhasil membuka socket.


Mengambil Data PPP Active

Langkah berikutnya adalah membaca session PPP yang sedang aktif.

Di MikroTik:

/ppp active print

Contohnya:

NAME         SERVICE   ADDRESS
testclient   pppoe     10.10.10.10

Data ini nantinya sangat berguna untuk monitoring.

Laravel dapat mengubahnya menjadi:

[
    {
        "username": "testclient",
        "service": "pppoe",
        "address": "10.10.10.10",
        "status": "online"
    }
]

Preview PPP Active MikroTik yang dibaca aplikasi Laravel

Gambar 5. Ilustrasi aplikasi membaca session PPPoE aktif dari MikroTik.

Di sinilah eksperimen kita mulai menyambung dengan Part 1.

Pada Part 1:

testclient
     ↓
PPPoE Server
     ↓
/ppp active

Sekarang:

testclient
     ↓
PPPoE Server
     ↓
/ppp active
     ↓
RouterOS API
     ↓
Laravel
     ↓
Dashboard

Jangan Jadikan Router sebagai Database Utama

Walaupun Laravel sekarang dapat membaca RouterOS, saya tetap tidak menjadikan MikroTik sebagai sumber seluruh data pelanggan.

Misalnya RouterOS mempunyai:

testclient

Laravel dapat mempunyai:

Customer

Nama
Nomor WhatsApp
Alamat
Paket
Tanggal pemasangan
Status billing

Kemudian:

PPPoE Account

customer_id
username
router
profile
provisioning_status
connection_status
last_seen_at

Router hanya bertanggung jawab pada kondisi jaringan.

Database Laravel tetap bertanggung jawab pada data bisnis.


Status Router Sebaiknya Disimpan

Pada aplikasi billing yang saya kerjakan, status router tidak cukup hanya:

online
offline

Saya juga ingin mengetahui kapan terakhir kali aplikasi berhasil berkomunikasi dengannya.

Contoh:

routers

name
host
status
last_seen_at
last_error

Ketika komunikasi berhasil:

status       = online
last_seen_at = now()
last_error   = null

Ketika gagal:

status       = offline
last_error   = Connection timed out

Dengan begitu dashboard dapat menampilkan:

MikroTik CHR Server

● Online

Last seen:
10 seconds ago

daripada sekadar mengandalkan operator membuka Winbox.


Menangani Timeout

Router adalah perangkat jaringan.

Artinya kita harus menganggap koneksi dapat gagal kapan saja.

Misalnya:

Router mati

Network terputus

Firewall berubah

API service disabled

Credential berubah

Port salah

Router sedang reboot

Karena itu jangan membuat request tanpa timeout.

Contoh konfigurasi:

ROUTEROS_TIMEOUT=10

Flow aplikasi:

Laravel
   │
   │ connect
   ▼
RouterOS
   │
   ├── response
   │      ↓
   │   continue
   │
   └── timeout
          ↓
       catch error
          ↓
       tulis log
          ↓
       status offline

Tanpa timeout, request operator dapat menggantung terlalu lama ketika router tidak dapat dijangkau.


Jangan Menampilkan Error Mentah ke User

Misalnya koneksi gagal dengan error internal:

Connection refused to 192.168.x.x:8728

atau exception library yang panjang.

Jangan langsung mengembalikan semuanya ke frontend.

User cukup menerima:

{
    "success": false,
    "message": "Tidak dapat terhubung ke router."
}

Sedangkan log aplikasi menyimpan informasi teknis:

router
host
exception
timestamp
operation

Dengan begitu operator mendapatkan pesan yang mudah dipahami, sementara developer masih mempunyai informasi debugging.


Hindari Memanggil Router pada Setiap Page Load

Ini bagian yang menurut saya penting.

Setelah berhasil menghubungkan Laravel ke MikroTik, godaan berikutnya adalah melakukan query router setiap kali dashboard dibuka.

Misalnya:

GET /dashboard
     ↓
query router
     ↓
query PPP active
     ↓
query interfaces
     ↓
query traffic
     ↓
render dashboard

Untuk aplikasi kecil mungkin terasa baik-baik saja.

Tetapi ketika jumlah router dan pelanggan bertambah, pola tersebut dapat menjadi masalah.

Lebih baik pisahkan proses sinkronisasi.

Scheduler / Queue
       │
       ▼
RouterOS API
       │
       ▼
Laravel Database
       │
       ▼
Dashboard

Dashboard membaca data terakhir dari database.

Job di background bertugas memperbaruinya.

Contoh:

SyncPppoeSessions
SyncRouterStatus
SyncInterfaceTraffic

Ini juga membuat dashboard tetap dapat dibuka ketika salah satu router sedang offline.


Contoh Job Monitoring

Secara sederhana:

class SyncPppoeSessions implements ShouldQueue
{
    public function handle(
        RouterosClient $router
    ): void {
        $sessions = $router->getActivePppoeSessions();

        foreach ($sessions as $session) {

            PppoeAccount::query()
                ->where('username', $session['username'])
                ->update([
                    'connection_status' => 'online',
                    'last_seen_at' => now(),
                ]);
        }
    }
}

Contoh tersebut masih sederhana.

Pada implementasi sebenarnya kita juga harus menangani akun yang sebelumnya online tetapi sudah tidak ditemukan dalam /ppp active.

Konsepnya:

Database
─────────────────
A
B
C

PPP Active
─────────────────
A
C

Hasil
─────────────────
A → ONLINE
B → OFFLINE
C → ONLINE

Bagian tersebut akan kita bahas lebih dalam pada Part monitoring.


Keamanan RouterOS API

Untuk environment production, saya tidak ingin API MikroTik terbuka bebas ke internet.

Idealnya:

Internet
   │
   X
   │
RouterOS API

Akses API hanya diperbolehkan dari:

Laravel Server
      │
      │ private network / VPN
      ▼
MikroTik Router

Beberapa hal yang perlu dipertimbangkan:

✓ firewall source address

✓ VPN / private network

✓ user API khusus

✓ least privilege

✓ credential rotation

✓ logging

✓ timeout

✓ encrypted transport jika tersedia dan sesuai environment

✓ jangan expose API management sembarangan

Untuk lab lokal, konfigurasi tentu dapat lebih sederhana.

Tetapi kita perlu memahami perbedaannya sejak awal.


Debugging Ketika Laravel Tidak Bisa Connect

Dalam proses integrasi, koneksi tidak selalu langsung berhasil.

Saya biasanya memeriksa dari lapisan paling bawah.

1. Apakah Laravel server dapat menjangkau router?

ping 192.168.1.7

Jika environment atau firewall memang tidak mengizinkan ICMP, kegagalan ping saja belum cukup untuk menyimpulkan API tidak dapat diakses.

Lanjutkan dengan pengecekan port.

2. Apakah port RouterOS API dapat dijangkau?

Contoh dari Linux/macOS:

nc -vz 192.168.1.7 8728

Jika berhasil:

Connection to 192.168.1.7 port 8728 succeeded

3. Apakah API aktif?

Di RouterOS:

/ip service print

4. Apakah credential benar?

Periksa:

ROUTEROS_USERNAME
ROUTEROS_PASSWORD

Jangan print password ke log.

5. Apakah firewall mengizinkan koneksi?

Periksa:

/ip firewall filter print

6. Apakah Laravel masih menggunakan config cache lama?

Jika .env baru diubah:

php artisan config:clear

Pada environment production yang menggunakan config cache, rebuild sesuai deployment workflow:

php artisan config:cache

Flow Debugging yang Saya Gunakan

Supaya tidak menebak-nebak:

Laravel gagal connect
        │
        ▼
Host reachable?
        │
    ┌───┴───┐
    │       │
   NO      YES
    │       │
Network     ▼
problem   Port 8728?
            │
        ┌───┴───┐
        │       │
       NO      YES
        │       │
    Firewall    ▼
    / API     Credential?
                │
            ┌───┴───┐
            │       │
           NO      YES
            │       │
        Fix user    ▼
                  Query
              /system resource
                    │
                    ▼
                 SUCCESS

Cara seperti ini lebih cepat daripada mengubah banyak konfigurasi sekaligus tanpa mengetahui sumber masalahnya.


Hasil Part 3

Setelah tahap ini selesai, arsitektur kita berubah dari:

Laravel

MikroTik

menjadi:

Laravel
   │
   │ RouterOS API
   ▼
MikroTik

Dan Laravel sekarang mempunyai kemampuan dasar:

✓ test connection

✓ membaca resource router

✓ membaca PPP Active

✓ mendeteksi kegagalan koneksi

✓ mencatat last seen router

✓ menjalankan komunikasi melalui service layer

Tetapi kita belum mengubah konfigurasi PPPoE dari Laravel.

Itu disengaja.

Saya ingin memastikan jalur komunikasinya stabil terlebih dahulu sebelum aplikasi diberikan kemampuan mengubah konfigurasi router.


Batas Part 3

Posisi kita sekarang:

Part 1
PPPoE Server MikroTik CHR             ✓

Part 2
Fondasi Web App Billing Laravel       ✓

Part 3
Laravel ↔ RouterOS API                ✓

Part 4
Provisioning PPPoE Otomatis           berikutnya

Part 5
Monitoring PPPoE Online / Offline     berikutnya

Pada Part 4 kita mulai melakukan operasi yang lebih nyata.

Laravel akan menerima data pelanggan:

Customer
+
Service Plan
+
PPPoE Account

kemudian melakukan provisioning ke MikroTik:

Laravel
   │
   │ create PPP Secret
   ▼
RouterOS
   │
   ▼
/ppp secret

Di sana kita juga akan membahas apa yang terjadi ketika:

database berhasil
router gagal

router berhasil
database gagal

username sudah ada

router offline

provisioning timeout

Karena menurut saya bagian sulit dari integrasi bukan sekadar menjalankan command MikroTik.

Bagian sulitnya adalah menjaga database aplikasi dan kondisi router tetap konsisten ketika salah satu proses gagal.


Checklist Part 3

Sebelum melanjutkan:

□ RouterOS API sudah aktif

□ Laravel dapat menjangkau router

□ Credential tidak ditulis di source code

□ Akun khusus aplikasi digunakan

□ RouterosClient dipisahkan dari controller

□ Test connection berhasil

□ /system resource dapat dibaca

□ /ppp active dapat dibaca

□ Timeout sudah ditentukan

□ Error tidak membocorkan credential

□ API RouterOS tidak diekspos sembarangan

Kalau checklist ini sudah aman, kita mempunyai fondasi yang cukup untuk masuk ke provisioning.


Kesimpulan

Menghubungkan Laravel dengan MikroTik ternyata bukan hanya persoalan membuat koneksi API berhasil.

Ada beberapa keputusan yang menurut saya lebih penting:

Laravel
────────────────────────────
menyimpan data bisnis

RouterOS
────────────────────────────
mengelola kondisi jaringan

RouterosClient
────────────────────────────
menjadi pintu komunikasi

Queue / Scheduler
────────────────────────────
melakukan sinkronisasi

Database
────────────────────────────
menyimpan kondisi terakhir

Dengan pemisahan seperti ini, aplikasi tidak terlalu bergantung pada kondisi router ketika operator membuka dashboard.

Dan ketika koneksi MikroTik sedang bermasalah, kita mempunyai tempat yang jelas untuk melakukan debugging.

Pada catatan berikutnya kita akan masuk ke bagian yang lebih menarik:

membuat provisioning PPPoE otomatis dari Laravel ke MikroTik RouterOS.

Kita akan mencoba membuat PPP Secret berdasarkan pelanggan dan paket internet dari aplikasi, sekaligus memikirkan bagaimana menangani provisioning yang gagal di tengah proses.

Sampai jumpa di catatan CodeSyariah berikutnya.

Wallahu a’lam.

CodeSyariah dispatch

Dapatkan catatan berikutnya.

Ringkasan praktis seputar build, fix, dan deployment.
Puji Ermanto

Ditulis oleh

Puji Ermanto

Senior Engineer yang membangun dan merawat web application, API, ERP, serta workflow deployment. Saat ini aktif di Wangun Teknologi Bersama dan PT. Indiga Nusa Digitama (Tokoweb.co).
Lihat portfolio