Setting Up Nginx Access Log Monitoring with Loki and Grafana
This guide walks through installing Nginx, configuring Promtail and Loki to collect JSON‑formatted access logs, adding GeoIP support, deploying Grafana via Docker, connecting the Loki data source, and creating a dashboard with the world‑map panel to visualize website traffic.
When a client needs to view website access statistics without using Google or Baidu analytics, a lightweight log‑analysis stack can be built using Nginx, Promtail, Loki, and Grafana.
For a small site, Loki is chosen over the full ELK stack. The architecture consists of Nginx as the web server, Promtail to ship logs, Loki as the log store, and Grafana for visualization.
Installation : Install Nginx normally. Download the binary releases of Promtail and Loki, extract them, and start each with its configuration file.
Promtail configuration (excerpt):
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://localhost:3100/loki/api/v1/push
scrape_configs:
- job_name: nginx
pipeline_stages:
- replace:
expression: '(?:[0-9]{1,3}\.){3}([0-9]{1,3})'
replace: '***'
static_configs:
- targets:
- localhost
labels:
job: nginx_access_log
host: expatsxxxxs
agent: promtail
__path__: /var/log/nginx/expatshxxxxs.access.logAfter Promtail is running, modify Nginx to output logs in JSON format. The log_format json_analytics definition includes fields such as msec , connection , remote_addr , request , status , upstream , ssl_protocol , and geoip_country_code .
log_format json_analytics escape=json '{'
"msec": "$msec",
"connection": "$connection",
"connection_requests": "$connection_requests",
"pid": "$pid",
"request_id": "$request_id",
"request_length": "$request_length",
"remote_addr": "$remote_addr",
"remote_user": "$remote_user",
"remote_port": "$remote_port",
"time_local": "$time_local",
"time_iso8601": "$time_iso8601",
"request": "$request",
"request_uri": "$request_uri",
"args": "$args",
"status": "$status",
"body_bytes_sent": "$body_bytes_sent",
"bytes_sent": "$bytes_sent",
"http_referer": "$http_referer",
"http_user_agent": "$http_user_agent",
"http_x_forwarded_for": "$http_x_forwarded_for",
"http_host": "$http_host",
"server_name": "$server_name",
"request_time": "$request_time",
"upstream": "$upstream_addr",
"upstream_connect_time": "$upstream_connect_time",
"upstream_header_time": "$upstream_header_time",
"upstream_response_time": "$upstream_response_time",
"upstream_response_length": "$upstream_response_length",
"upstream_cache_status": "$upstream_cache_status",
"ssl_protocol": "$ssl_protocol",
"ssl_cipher": "$ssl_cipher",
"scheme": "$scheme",
"request_method": "$request_method",
"server_protocol": "$server_protocol",
"pipe": "$pipe",
"gzip_ratio": "$gzip_ratio",
"http_cf_ray": "$http_cf_ray",
"geoip_country_code": "$geoip_country_code"
}';Because the geoip_country_code variable requires the GeoIP module, install the GeoIP libraries via yum -y install GeoIP GeoIP-data GeoIP-devel and recompile Nginx with --with-http_geoip_module . After recompilation, replace the binary using a kill -USR2 graceful upgrade.
Sample JSON log entries produced by the new format are shown, confirming that logs are now structured and can be parsed by Loki.
Deploy Grafana quickly with Docker:
docker run -d -p 3000:3000 grafana/grafanaLog in with the default admin/admin credentials, reset the password, then add Loki as a data source. Use the Explore view to verify that logs are being ingested.
Import a pre‑built dashboard (by ID) that visualizes request counts, response codes, and geographic information. The world‑map panel initially lacks the required plugin, so install it with:
grafana-cli plugins install grafana-worldmap-panelAfter restarting Grafana, the map appears, though external map tiles may be blocked; a reverse‑proxy can be used to serve them.
In summary, the combination of Nginx + Promtail + Loki + Grafana provides a fast, self‑hosted solution for detailed website access monitoring.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.