One of the useful approach to monitor several servers is to use grafana and prometheus. Here you can see the architecture of this approach:
+----------------+
| node_exporter 1|--+
+----------------+ |
+----------------+ | scrapes +--------------+ queries +-------------+
| node_exporter 2|--+------------> | Prometheus | ----------> | Grafana |
+----------------+ | | (stores time | | (dashboards |
+----------------+ | | series data)| | & alerts) |
| node_exporter 3|--+ +--------------+ +-------------+
+----------------+
node_exporters 1/2/3 are small agents which are installed directly on different machines. They generate stats about the servers. prometheus is the main tool which collects the status from node_exporters, aggregate and store the stats and it also has its own query language to query the data afterwards. Grafana is used to create dashboards and graphs from different data sources such as prometheus. What we see in grafana, we can also see it in Prometheus dashboard but it’s ugly and text based. That’s why we install and use grafana. In this way, not only we can see things beautifully, but also we can connect different other data sources to grafana and have them all in on panel.
So the first step is to install node_exporter on different machines securely.
Visiting node exporter download page, we need to download the one that is suitable for our server, for example, if you use Linux machine,
_node_exporter-
wget https://github.com/prometheus/node_exporter/releases/download/v1.12.1/node_exporter-1.12.1.linux-amd64.tar.gz
tar xvfz node_exporter-1.12.1.linux-amd64.tar.gz
We make sure the hash is the exact match with the one on the dowload page:
sha256sum node_exporter-1.12.1.linux-amd64.tar.gz
# output b51d8a76aa2a9156a55d501aca6276fae09e262259a5e4e831d2c2222f084e63
# output is the exact match
extracting the tar file
tar -xvzf node_exporter-1.12.1.linux-amd64.tar.gz
cd node_exporter-1.12.1.linux-amd64
make sure the binary is working on your machine
./node_exporter --version
Now we will create a separate user without login for the node_exporter
sudo useradd --shell /usr/sbin/nologin pro_node_exporter
we create a /etc/node_exporter directory, move the binary to /usr/local/bin . From now on, we will work in /etc/node_exporter directory.
The binary and other related config files (we will create later), all belong to the new user we created.
# create the directory
sudo mkdir /etc/node_exporter
# move the binary
sudo mv node_exporter /usr/local/bin/node_exporter
# change the ownership of the binary
sudo chown pro_node_exporter:pro_node_exporter /usr/local/bin/node_exporter
We need to issue a certificate for connection (self-signed) and also create HTTP auth for our node exporter.
We will pass some config file to openssl to tell how to create a certificate. (Replace server IP address with
# content of the /etc/node_exporter/openssl.conf
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
CN = node-exporter
[v3_req]
subjectAltName = @alt_names
[alt_names]
IP.1 = <IP-ADDRESS>
Now we can issue a certificate by passing the config file:
sudo openssl req -x509 -nodes -days 825 -newkey rsa:2048 -keyout /etc/node_exporter/node_exporter.key -out /etc/node_exporter/node_exporter.crt -config /etc/node_exporter/openssl.conf
# now change the ownership of the key and crt file to the new user
sudo chown pro_node_exporter:pro_node_exporter /etc/node_exporter/node_exporter.key /etc/node_exporter/node_exporter.crt
# change the permission only to the owner
sudo chmod 600 /etc/node_exporter/node_exporter.key
sudo chmod 600 /etc/node_exporter/node_exporter.crt
We need to create a hash for HTTP auth for node_exporter (so that only those who have the password can see the metrics).
# install htpasswd if you don't have it: sudo apt install -y apache2-utils
# create the hash, it will ask for a password
htpasswd -nBC 10 "" | tr -d ':\n'
# I used this password: thisismypassword
# the result is something like: $2y$10$SIoEkqfqSvxK7jv3eD6FFOUgQOGIqhCMQCL7YQ//lDZ4CKaoDeU7a
Now create a config file /etc/node_exporter/web-config.yml and paste the followings:
tls_server_config:
cert_file: /etc/node_exporter/node_exporter.crt
key_file: /etc/node_exporter/node_exporter.key
basic_auth_users:
prometheus: $2y$10$SIoEkqfqSvxK7jv3eD6FFOUgQOGIqhCMQCL7YQ//lDZ4CKaoDeU7a
Note that the username we chose is prometheus but you are free to choose whatever you want. Then, change the ownership of the web-config.yml file:
sudo chown pro_node_exporter:pro_node_exporter web-config.yml
sudo chmod 600 /etc/node_exporter/web-config.yml
Now it’s time to run the node_exporter binary as a service in our Linux machine to make sure it’s always working whenever we start the machine. We need to create a file
called /etc/systemd/system/node_exporter.service and add the following content:
[Unit]
Description=Prometheus Node Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=pro_node_exporter
Group=pro_node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter --web.config.file=/etc/node_exporter/web-config.yml
[Install]
WantedBy=multi-user.target
Let’s reload the daemon, enable the service in every boot and check the status to make sure it’s active.
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
sudo systemctl restart node_exporter
sudo service node_exporter status
If it’s all good, we can see the service by using the following curl:
# -k is used because we have a self-signed certificate
curl -k -u prometheus:thisismypassword https://localhost:9100/metrics
# we must see a bunch of text on the screen
We should be able to also visit the page (in browser) by going to: https://<YOUR-SERVER-PUBLIC-IP>:9100/metrics (we will get certificate browser error at first).
NOTE: We can install the node_exporter on whatever number of machine we want, in the very same way I just explained. After each installation, we need to keep the 1) public URL to visit the metric, 2) username and password we used for HTTP AUTH, 3) the generated hash for HTTP AUTH
Having all that installed, we can move on and install Grafana and Prometheus on one machine that is less busy and has enough disk or we can rent a VPS (small one) and install the tools there. Then, we will (securely) connect all the node_exporters to our dashboard.
It’s easier to install Grafana and Pormetheus in docker. It’s also possible to install it on the server directly but I don’t see any advantage!
Things that we want to do are:
We created 3 scripts as follows:
generate-cert.sh: will generate certificate for connecting to Grafana panel securely.prometheus.yml: this is the configuration file we pass to Prometheus. We put all the information of the node_exporters here.docker-compose.yml: this is our final docker file to run everything with docker compose.first create a directory like monitoring for example so that we put everything in it.
Here is what we have in generate-cert.sh:
#!/bin/bash
# Generates a self-signed TLS certificate for Grafana.
# Replace CN / SAN with your actual server IP or hostname if you have one.
set -e
CERT_DIR="./certs"
DAYS_VALID=825 # ~2.25 years, common self-signed cert lifetime
CN="grafana.local" # change to your domain or server IP
mkdir -p "$CERT_DIR"
openssl req -x509 -nodes -newkey rsa:2048 \
-keyout "$CERT_DIR/grafana.key" \
-out "$CERT_DIR/grafana.crt" \
-days $DAYS_VALID \
-subj "/CN=$CN" \
-addext "subjectAltName=DNS:$CN,IP:127.0.0.1"
# Grafana's container runs as UID 472 (non-root), not as whoever runs this
# script. 644 lets that user read the key when it's bind-mounted read-only.
# (Fine for a self-signed key used only by this local Grafana container;
# don't reuse this key/cert for anything more sensitive.)
chmod 644 "$CERT_DIR/grafana.key"
chmod 644 "$CERT_DIR/grafana.crt"
echo "Certificate generated in $CERT_DIR/"
echo " - grafana.crt"
echo " - grafana.key"
Here is the content of the prometheus.yml file:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# repeat this block for each server you installed node_exporter
# for example, if you have 10 servers, you need 10 blocks like this
- job_name: 'srv-detection'
scheme: https
tls_config:
insecure_skip_verify: true
basic_auth:
username: prometheus # here is your username for this node
password: thisismypassword # here is the password you set on this node
static_configs:
- targets: ['37.27.67.243:9100'] # <-- IP:PORT of the server
labels:
instance: 'srv-detection' # <-- put a nice name here and we show this on grafana
And here is the docker-compose.yml file:
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=30d'
ports:
# bind it to localhost to make not exposed on Internet
# Access it via: ssh -L 9090:localhost:9090 user@IP-ADDR
- "127.0.0.1:9090:9090"
restart: unless-stopped
networks:
- monitoring
grafana:
image: grafana/grafana:latest
container_name: grafana
volumes:
- grafana_data:/var/lib/grafana
- ./certs:/etc/grafana/certs:ro
environment:
# --- Auth ---
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin@123
- GF_AUTH_ANONYMOUS_ENABLED=false
- GF_AUTH_DISABLE_LOGIN_FORM=false
# --- HTTPS ---
- GF_SERVER_PROTOCOL=https
- GF_SERVER_CERT_FILE=/etc/grafana/certs/grafana.crt
- GF_SERVER_CERT_KEY=/etc/grafana/certs/grafana.key
- GF_SERVER_DOMAIN=localhost
ports:
# This one IS meant to be reachable (dashboard), over HTTPS.
- "3000:3000"
restart: unless-stopped
networks:
- monitoring
depends_on:
- prometheus
networks:
monitoring:
driver: bridge
volumes:
prometheus_data:
grafana_data:
The docker compose file will create a network bridge so that grafana and prometheus can connect to each other internally.
Now that we have all 3 scripts, first run generate-cert.sh to generate the certificates. and then just simply run
docker compose up -d to start the docker. Now we can visit https://<IP-ADDRESS>:3000 to see the grafana panel.
NOTES:
GF_SECURITY_ADMIN_PASSWORD to something secure.ssh -L 9090:localhost:9090 user@<server-ip> and then visit http://localhost:9090 in you browser.http://prometheus:9090 not http://localhost:9090. This is due to the fact that localhost inside the grafana docker means the grafana docker itself.sudo usermod -aG docker $USER so that you never run docker with sudo.The final step is to launch grafana panel (https://<server-IP>:3000) and start creating dashboards and panels to monitor servers.