Monitoring with Prometheus and Grafana
Author: OMchik33
A complete guide to setting up monitoring for the Remnawave panel using Prometheus, Grafana, and Node Exporter, as well as secure access to metrics via an SSH tunnel and Nginx.
📦 Setting up docker-compose.yml on the Remnawave server
Section titled “📦 Setting up docker-compose.yml on the Remnawave server”Make sure that port 3001 is open in the Remnawave docker-compose.yml file, through which metrics are provided:
ports: - '127.0.0.1:3001:3001'Example configuration (for installation using the eGames script)
remnawave: image: remnawave/backend:latest container_name: remnawave hostname: remnawave restart: always env_file: - .env ports: - '127.0.0.1:3000:3000' - '127.0.0.1:3001:3001' networks: - remnawave-network depends_on: remnawave-db: condition: service_healthy remnawave-redis: condition: service_healthy logging: driver: 'json-file' options: max-size: '30m' max-file: '5'🔐 Setting up an SSH tunnel
Section titled “🔐 Setting up an SSH tunnel”-
Generate a key, do not set a password:
Terminal window ssh-keygen -t ed25519 -f ~/.ssh/remna_tunnel_key -
Add the public key to the
~/.ssh/authorized_keysfile on the Remnawave server. ReplaceAAAAC3...with the content ofremna_tunnel_key.pub, which starts withAAAAC3:Terminal window from="MONITORING_SERVER_IP",no-pty,no-agent-forwarding,no-X11-forwarding,command="/bin/false" ssh-ed25519 AAAAC3... remna_tunnel_key -
Install
autossh(continue on the monitoring server):Terminal window sudo apt install autossh -
Create a systemd service file at
/etc/systemd/system/remna-tunnel.service. Replaceremnauser@REMNA_SERVER_IPwith the SSH login and address of the Remnawave panel server.[Unit]Description=SSH tunnel to Remnawave for Prometheus and Node ExporterAfter=network.target[Service]User=rootEnvironment="AUTOSSH_GATETIME=0"ExecStart=/usr/bin/autossh -N \-o "ServerAliveInterval 60" \-o "ServerAliveCountMax 3" \-i /root/.ssh/remna_tunnel_key \-L 9001:localhost:3001 \-L 9002:localhost:9100 \remnauser@REMNA_SERVER_IPRestart=always[Install]WantedBy=multi-user.target -
On the first server (where autossh is running), it’s important to add the second server’s key to
known_hosts, where12.345.678.91is the IP address of the Remnawave panel, to avoid a host authenticity verification error. Otherwise, the service will simply not connect to the panel server.Terminal window ssh-keyscan -H 12.345.678.91 >> ~/.ssh/known_hosts -
Start the service:
Terminal window sudo systemctl daemon-reexecsudo systemctl enable remna-tunnelsudo systemctl start remna-tunnel -
Check if the service started successfully:
Terminal window sudo systemctl status remna-tunnel
Now Remnawave and Node Exporter metrics are available at http://localhost:9001/metrics and http://localhost:9002/metrics on the monitoring server.
📈 Installing Prometheus and Grafana
Section titled “📈 Installing Prometheus and Grafana”-
Create directories:
Terminal window mkdir -p /opt/monitoring/{grafana,prometheus} -
Create the file
/opt/monitoring/docker-compose.ymlservices:prometheus:image: prom/prometheus:latestcontainer_name: prometheusrestart: unless-stoppedvolumes:- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml- prometheus-data:/prometheuscommand:- '--config.file=/etc/prometheus/prometheus.yml'- '--storage.tsdb.path=/prometheus'- '--web.console.libraries=/etc/prometheus/console_libraries'- '--web.console.templates=/etc/prometheus/consoles'- '--web.external-url=https://sub.mydomain.com/prometheus/'- '--web.route-prefix=/'network_mode: hostgrafana:image: grafana/grafana:latestcontainer_name: grafanarestart: unless-stoppedvolumes:- grafana-data:/var/lib/grafana- ./grafana/provisioning:/etc/grafana/provisioningenvironment:- GF_SERVER_DOMAIN=mydomain.com- GF_SERVER_ROOT_URL=https://sub.mydomain.com/grafana- GF_SERVER_SERVE_FROM_SUB_PATH=true- GF_SERVER_HTTP_PORT=3000- GF_SERVER_PROTOCOL=http- GF_SECURITY_ADMIN_USER=admin- GF_SECURITY_ADMIN_PASSWORD=admin- GF_ANALYTICS_REPORTING_ENABLED=falsenetwork_mode: hostxray-checker:image: kutovoys/xray-checkerenvironment:- "SUBSCRIPTION_URL=https://podpiska.mydomain.com/6f5g46df46g45f54"- "PROXY_STATUS_CHECK_URL=http://google.com/generate_204"- "PROXY_CHECK_INTERVAL=60"network_mode: hostvolumes:prometheus-data:grafana-data:
Here sub.mydomain.com is the domain address attached to the monitoring VPS where Grafana and Prometheus are installed.
https://podpiska.mydomain.com/6f5g46df46g45f54 is the subscription; create a separate user for this role.
⚙️ Configuring Prometheus
Section titled “⚙️ Configuring Prometheus”-
File
/opt/monitoring/prometheus/prometheus.yml.usernameandpasswordare from the Remnawave.envfile (section### PROMETHEUS ###)global:scrape_interval: 15sscrape_configs:# For proper operation of the Grafana dashboards listed in the links below,# use job_name: integrations/node_exporter.- job_name: 'node_exporter'static_configs:- targets: ['127.0.0.1:9002']labels:cluster: "test"instance: "127.0.0.1:9002"- job_name: 'remnawave_exporter'static_configs:- targets: ['127.0.0.1:9001']basic_auth:username: "XXXXXXXXXXXXXXX"password: "XXXXXXXXXXXXXXX"- job_name: "xray-checker"metrics_path: "/metrics"static_configs:- targets: ["localhost:2112"]scrape_interval: 1m -
Start all containers:
Terminal window cd /opt/monitoring && docker compose up -d
🌐 Setting up Nginx and SSL
Section titled “🌐 Setting up Nginx and SSL”-
Install nginx (local installation, not in a Docker container):
Terminal window apt install nginx -
Obtain SSL certificates; the 3rd level domain should already be configured to the IP address of the monitoring server:
Terminal window sudo apt install certbot python3-certbot-nginxsudo certbot --nginx -d sub.mydomain.com -
Add auto-renewal of certificates to crontab:
Terminal window 0 5 * * * root certbot renew --quiet -
Configure the nginx config file
Terminal window nano /etc/nginx/sites-available/default
Example nginx configuration
# Check by cookiemap $http_cookie $auth_cookie { default 0; "~*fd4gd54fg2dfg4241=1" 1;}
# Check by GET parametermap $arg_fd4gd54fg2dfg4241 $auth_query { default 0; "1" 1;}
# General authorization flagmap "$auth_cookie$auth_query" $authorized { "~1" 1; default 0;}
# Set cookie if parameter existsmap $arg_fd4gd54fg2dfg4241 $set_cookie_header { "1" "fd4gd54fg2dfg4241=1; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=31536000"; default "";}
# HTTP redirect to HTTPSserver { listen 80; server_name sub.mydomain.com; return 301 https://$server_name$request_uri;}
# HTTPS server blockserver { listen 443 ssl http2; server_name sub.mydomain.com;
# SSL configuration ssl_certificate /etc/letsencrypt/live/sub.mydomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/sub.mydomain.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on;
# Set the cookie if the user logs in via a link add_header Set-Cookie $set_cookie_header;
# Redirect from the main domain directly to the desired public dashboard in Grafana location = / { return 301 /grafana/public-dashboards/f5g4df4g5df4gd5f4g63d4834379e; }
# Grafana configuration location /grafana { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $server_name;
# WebSocket support proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade;
# Remove Authorization header proxy_set_header Authorization ""; }
# Grafana Live WebSocket location /grafana/api/live/ { proxy_pass http://localhost:3000/api/live/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }
# Prometheus location /prometheus/ { if ($authorized = 0) { return 404; }
proxy_pass http://localhost:9090/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $server_name; proxy_set_header Authorization ""; }
# Xray Checker location /checker/ { if ($authorized = 0) { return 404; }
proxy_pass http://localhost:2112/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $server_name; }}Here sub.mydomain.com is the domain address attached to the test VPS where Grafana and Prometheus are installed.
fd4gd54fg2dfg4241 is a unique cookie value, YOU NEED to replace it with your own.
/grafana/public-dashboards/f5g4df4g5df4gd5f4g63d4834379e; is a unique link to a public Dashboard in Grafana. You will get it after completing all the instructions and building the necessary Dashboard yourself. After that, you can get the link for external connection, insert it here and restart nginx. The link in the nginx config is set so that users are immediately redirected to the public Dashboard when they go to sub.mydomain.com.
-
Edit
/etc/nginx/nginx.conf, add there:# Map for Grafana WebSocket connectionsmap $http_upgrade $connection_upgrade {default upgrade;'' close;} -
Apply nginx configuration
nginx -t && systemctl restart nginx
Example of a default nginx.conf with the necessary map added
Open an example
user www-data;worker_processes auto;pid /run/nginx.pid;error_log /var/log/nginx/error.log;include /etc/nginx/modules-enabled/*.conf;
events { worker_connections 768; # multi_accept on;}
http {
## # Basic Settings ##
sendfile on; tcp_nopush on; types_hash_max_size 2048; # server_tokens off;
# server_names_hash_bucket_size 64; # server_name_in_redirect off;
include /etc/nginx/mime.types; default_type application/octet-stream;
# Map for Grafana WebSocket connections map $http_upgrade $connection_upgrade { default upgrade; '' close; } ## # SSL Settings ##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on;
## # Logging Settings ##
access_log /var/log/nginx/access.log;
## # Gzip Settings ##
gzip on;
# gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/jav>
## # Virtual Host Configs ##
include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*;}🧠 Node Exporter
Section titled “🧠 Node Exporter”-
Install on the server with Remnawave:
Terminal window . <(wget -qO- https://raw.githubusercontent.com/g7AzaZLO/NodeExporter-autoinstaller/main/NodeExporter-auto-install.sh) -
You can install it on other nodes and add it to
prometheus.yml:- job_name: 'external_nodes'static_configs:- targets: ['1.2.3.4:9100']
Node Exporter is available on the monitoring server at localhost:9002 (via SSH tunnel).
Here 1.2.3.4 is the address of another node where we also installed Node Exporter.
Or use SSH tunnels similar to this guide.
📊 Checking and configuring Grafana
Section titled “📊 Checking and configuring Grafana”Authentication in Grafana
Section titled “Authentication in Grafana”- Go to:
https://sub.mydomain.com/grafana - Login:
admin / admin, then change the password - Add a data source: Prometheus
- URL:
http://localhost:9090
- URL:
- Go to Explore → Metrics → Grafana Drilldown → Metrics
After all the manipulations, we have added a new data source to Grafana - Prometheus. Now you need to create a new Dashboard yourself, adding the necessary visualizations and connecting the required data sources from Prometheus to them.
Checking the health of data sources (metrics) in Prometheus
Section titled “Checking the health of data sources (metrics) in Prometheus”-
Go to the link
https://sub.mydomain.com/prometheus/graph?fd4gd54fg2dfg4241=1 -
Open the
Status-Target Healthmenu and make sure that each data source isUP. -
Open Prometheus
https://sub.mydomain.com/prometheus/graph?fd4gd54fg2dfg4241=1 -
Open Grafana
https://sub.mydomain.com/grafana/ -
Open xray checker
https://sub.mydomain.com/checker/?fd4gd54fg2dfg4241=1