Punya lebih dari satu situs di satu VPS itu enak, tapi ada satu hal yang sering kelewat: log nginx-nya jadi berserakan di banyak folder. Tiap kali mau tahu ada bot aneh yang nyerang, error 500 yang muncul tiba-tiap, atau sekadar mau ngecek apakah Googlebot beneran nge-crawl situs, kita harus buka satu-satu file log yang isinya ribuan baris teks mentah. Makanya gue akhirnya bikin sendiri dashboard monitoring log nginx yang bisa nampung semua situs sekaligus, lengkap dengan filter dan export data.
Kenapa Perlu Monitoring Log Nginx Kalau Situs Sudah Banyak
Log nginx sebenarnya sudah punya semua informasi yang kita butuhkan: siapa yang akses, dari IP mana, pakai user agent apa, ke path mana, dan hasilnya status berapa. Masalahnya bukan datanya, tapi caranya baca. File access.log yang isinya ratusan ribu baris teks polos nyaris mustahil dibaca manual, apalagi kalau situsnya lebih dari satu dan masing-masing punya folder log sendiri.
Kebutuhan gue waktu itu spesifik: pengen tahu bot AdSense beneran nge-review situs atau enggak, pengen ngecek IP yang sering muncul di error 404/403 (indikasi ada yang lagi coba nebak-nebak endpoint), dan pengen laporan traffic mingguan tanpa harus SSH terus buka tail -f.
Opsi yang Sempat Gue Coba Sebelum Bikin Sendiri
Sebelum mutusin bikin aplikasi sendiri, gue coba dulu tool-tool open source yang sudah ada. GoAccess gampang banget dipasang lewat Docker dan langsung kasih laporan HTML yang cukup informatif, tapi mode real-time-nya butuh satu container dan satu port per situs, jadi begitu situsnya banyak, jumlah container dan subdomain yang harus di-setup ikut membengkak.
Gue juga sempat coba kombinasi Grafana, Loki, dan Promtail yang memang didesain buat multi-source log monitoring. Fiturnya lengkap dan bisa satu dashboard buat semua situs, tapi setup awalnya lumayan berat untuk kebutuhan yang sebenarnya sederhana: filter tanggal, IP, dan user agent doang.
Bikin Dashboard Monitoring Log Nginx Sendiri Pakai Python dan Docker
Akhirnya gue putuskan bikin aplikasi sendiri pakai Python (Flask) dan SQLite, dikemas dalam satu container Docker saja. Aplikasi ini otomatis scan semua folder log di VPS tiap beberapa menit, parsing tiap baris log jadi data terstruktur, lalu simpan ke database SQLite biar query filter-nya cepat meskipun datanya sudah ratusan ribu baris.
Formatnya mengikuti format combined bawaan nginx, jadi kalau situs kamu masih pakai log format default nginx, tinggal pasang tanpa perlu ubah konfigurasi nginx sama sekali.
services:
log-viewer:
build: .
container_name: nginx-log-viewer
restart: unless-stopped
environment:
- LOG_ROOT=/var/log/sites
- LOG_PATH_PATTERN=${LOG_PATTERN:-*/logs/nginx/access.log*}
- AUTH_USERNAME=${AUTH_USERNAME:-admin}
- AUTH_PASSWORD=${AUTH_PASSWORD:-}
- SECRET_KEY=${SECRET_KEY:-}
volumes:
- ${LOG_SOURCE_DIR:-/home}:/var/log/sites:ro
- ./data:/data
ports:
- "127.0.0.1:8877:5000"
Kode Python Buat Parsing Log Nginx-nya
Bagian paling penting dari aplikasi ini ada di parsing log-nya. Gue pakai regex buat mecah tiap baris log format combined jadi field-field terpisah (IP, waktu, method, path, status, bytes, referer, user agent), lalu simpan ke SQLite biar nanti query filter-nya cepat walau datanya sudah ratusan ribu baris.
import re
import glob
import sqlite3
from datetime import datetime, timezone
LOG_ROOT = "/var/log/sites"
DB_PATH = "/data/logs.db"
# Format combined bawaan nginx:
# 1.2.3.4 - - [24/Jul/2026:08:01:06 +0000] "GET /path HTTP/1.1" 200 555 "referer" "user agent"
LOG_RE = re.compile(
r'^(?P<ip>S+) S+ S+ [(?P<time>[^]]+)] '
r'"(?P<method>S+) (?P<path>S+) (?P<protocol>[^"]*)" '
r'(?P<status>d+) (?P<bytes>S+) '
r'"(?P<referer>[^"]*)" "(?P<ua>[^"]*)"'
)
def parse_time(s):
# 24/Jul/2026:08:01:06 +0000
try:
dt = datetime.strptime(s, "%d/%b/%Y:%H:%M:%S %z")
return int(dt.astimezone(timezone.utc).timestamp())
except Exception:
return None
def scan_logs():
# Cari semua access.log di tiap folder situs, sesuai struktur CloudPanel
pattern = f"{LOG_ROOT}/*/logs/nginx/access.log*"
conn = sqlite3.connect(DB_PATH)
cur = conn.cursor()
for fpath in glob.glob(pattern):
site = fpath.split("/")[len(LOG_ROOT.split("/"))] # nama folder situs
with open(fpath, "r", errors="ignore") as f:
for line in f:
m = LOG_RE.match(line.strip())
if not m:
continue
ts = parse_time(m.group("time"))
if ts is None:
continue
cur.execute(
"INSERT INTO logs (site, ip, ts, method, path, status, bytes, referer, user_agent) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
(site, m.group("ip"), ts, m.group("method"), m.group("path"),
int(m.group("status")), m.group("bytes"), m.group("referer"), m.group("ua"))
)
conn.commit()
conn.close()
Ini versi inti-nya doang biar gampang dipahami alurnya. Versi lengkap yang gue pakai nambahin beberapa hal lagi: nyimpen posisi baca terakhir tiap file (biar restart container nggak baca ulang semua history dari awal), endpoint Flask buat filter multi-kolom, sampai integrasi DataTables dan export CSV yang sudah dibahas di bagian fitur di atas. Polanya sama, tinggal dikembangin dari inti regex dan SQLite ini.
Cara Deploy Dashboard Monitoring Log Nginx Sendiri dengan Docker
Kalau kamu pakai CloudPanel, struktur log tiap situsnya sudah otomatis rapi di /home/<nama-situs>/logs/nginx/access.log, jadi default konfigurasi di atas langsung nyambung tanpa perlu diubah. Kalau situs kamu sudah pakai Docker Compose sebelumnya, artinya kamu sudah punya modal dasarnya, tinggal siapkan folder khusus buat aplikasi ini.
mkdir -p ~/log-monitoring/data
cd ~/log-monitoring
nano .env
Isi .env minimal berisi lokasi log dan kredensial login. Kalau AUTH_PASSWORD dikosongin, login otomatis nonaktif, cocok kalau kamu sudah proteksi akses lewat reverse proxy.
LOG_SOURCE_DIR=/home
LOG_PATTERN=*/logs/nginx/access.log*
AUTH_USERNAME=admin
AUTH_PASSWORD=passwordkuattt123
SECRET_KEY=hasil-generate-token-acak
Generate SECRET_KEY-nya pakai perintah singkat ini biar sesi login nggak ke-reset tiap kali container restart.
python3 -c "import secrets; print(secrets.token_hex(32))"
Setelah semua file siap, jalankan seperti biasa, lalu tinggal arahkan reverse proxy dari panel yang kamu pakai ke port lokal aplikasi ini.
docker compose up -d --build
Fitur Dashboard Monitoring Log Nginx yang Gue Bikin
Beberapa fitur ini yang bikin dashboard ini lebih enak dipakai sehari-hari dibanding baca log mentah:
- Filter lengkap: site, rentang tanggal, IP, path, dan status code, semuanya bisa dikombinasikan sekaligus.
- Kombobox user agent yang sudah diklasifikasi: tinggal pilih “Google (Bot & Crawler)” buat langsung nyaring semua trafik dari Googlebot, AdsBot, sampai bot review AdSense, tanpa perlu hafal nama teknisnya satu-satu.
- Arti status code otomatis: kode 404, 500, atau 403 langsung ditampilkan artinya (Not Found, Internal Server Error, dst), jadi nggak perlu buka Google tiap ketemu kode yang lupa.
- Tabel interaktif: pencarian cepat, sorting per kolom, dan pagination, jadi tetap ringan meskipun datanya ratusan ribu baris.
- Export CSV sesuai filter aktif: bukan cuma data yang lagi tampil di layar, tapi semua baris yang cocok dengan filter, siap dianalisis lebih lanjut di Excel atau Google Sheets.
- Dashboard ringkas: grafik traffic per hari dan breakdown status code, biar langsung kelihatan kalau ada lonjakan traffic aneh atau error yang tiba-tiba naik.
Troubleshooting Dashboard Monitoring Log Nginx
Beberapa masalah yang mungkin kamu temui waktu setup dan cara ngatasinnya:
- Grafik tidak muncul di browser: cek console browser (F12), biasanya karena library chart gagal dimuat akibat ad-blocker atau firewall jaringan yang mem-block CDN. Coba akses dari jaringan lain buat mastiin.
- Data kosong padahal log-nya ada isinya: cek permission file log dengan
ls -la, kalau ownernya beda dari user container biasanya masih tetap kebaca karena container jalan sebagai root, tapi kalau tidak, sesuaikan mount volume-nya. - Situs baru tidak muncul di dropdown: tunggu satu siklus scan otomatis (default 2 menit), atau klik tombol Rescan di pojok kanan atas buat trigger index ulang manual.
- Lupa password login: ganti nilai
AUTH_PASSWORDdi file.env, lalu jalankan ulangdocker compose up -d --build.
Penutup
Dengan dashboard monitoring log nginx sendiri ini, gue nggak perlu lagi bolak-balik SSH cuma buat ngecek siapa yang lagi akses situs atau apakah ada error yang perlu diperhatikan. Semua situs kelihatan dari satu tempat, filternya fleksibel, dan datanya bisa diexport kapan saja. Kalau kamu belum kenal Portainer buat ngatur container Docker, itu juga bisa jadi pelengkap yang enak buat kelola aplikasi kayak gini tanpa harus hafal command satu-satu.
























