Set up Prometheus, Node Exporter, and Grafana on Debian or Ubuntu
Step by step guide to build a monitoring stack on a Debian/Ubuntu server. Versions used below are the latest stable as of this writing (August 2026): Prometheus 3.13.1, Node Exporter 1.12.1, Grafana 13.1.1. Check the release pages before you run this in case newer versions are out.
- Prometheus releases: https://github.com/prometheus/prometheus/releases
- Node Exporter releases: https://github.com/prometheus/node_exporter/releases
- Grafana releases: https://grafana.com/grafana/download
Architecture
+----------------+ scrapes :9100 +----------------+
| Node Exporter | <---------------- | Prometheus |
| :9100 | | :9090 |
+----------------+ +--------+-------+
|
| PromQL queries :9090
v
+----------------+
| Grafana |
| :3000 |
+----------------+
|
v
Browser / userPrerequisites
- A Debian or Ubuntu server with sudo access
curlandtarinstalled- Ports 9090 (Prometheus), 9100 (Node Exporter), 3000 (Grafana) open on your firewall if you access them remotely
Part 1: Install Prometheus
Step 1: Create the prometheus system user
sudo useradd --no-create-home --shell /bin/false prometheusStep 2: Create directories
sudo mkdir -p /etc/prometheus /var/lib/prometheusStep 3: Download Prometheus
cd /tmp
curl -LO https://github.com/prometheus/prometheus/releases/download/v3.13.1/prometheus-3.13.1.linux-amd64.tar.gz
tar -xvf prometheus-3.13.1.linux-amd64.tar.gzStep 4: Install the binaries
sudo cp prometheus-3.13.1.linux-amd64/prometheus /usr/local/bin/
sudo cp prometheus-3.13.1.linux-amd64/promtool /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/prometheus /usr/local/bin/promtoolStep 5: Install console templates and set ownership
sudo cp -r prometheus-3.13.1.linux-amd64/consoles /etc/prometheus
sudo cp -r prometheus-3.13.1.linux-amd64/console_libraries /etc/prometheus
sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheusStep 6: Create the config file
sudo tee /etc/prometheus/prometheus.yml > /dev/null <<EOF
global:
scrape_interval: 10s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
EOFNode Exporter's scrape job gets added in Part 3, once it's installed.
Step 7: Create the systemd service
sudo tee /etc/systemd/system/prometheus.service > /dev/null <<EOF
[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \\
--config.file=/etc/prometheus/prometheus.yml \\
--storage.tsdb.path=/var/lib/prometheus \\
--web.console.templates=/etc/prometheus/consoles \\
--web.console.libraries=/etc/prometheus/console_libraries \\
--storage.tsdb.retention.time=365d
ExecReload=/bin/kill -HUP \$MAINPID
[Install]
WantedBy=multi-user.target
EOFExecReload is what makes systemctl reload prometheus work in Part 3. Without it systemd refuses the reload with "Job type reload is not applicable", and your only option is a full restart. Note the backslash in \$MAINPID: this heredoc is unquoted so the shell would otherwise expand the variable to nothing while writing the file.
Step 8: Start and enable Prometheus
sudo systemctl daemon-reload
sudo systemctl enable --now prometheusStep 9: Verify
sudo systemctl status prometheus
curl -s http://localhost:9090/-/healthyOpen http://<server-ip>:9090 in a browser to confirm the UI loads.
Clean up the Prometheus download
rm -rf /tmp/prometheus-3.13.1.linux-amd64*Part 2: Install Node Exporter
Step 1: Create the node_exporter system user
sudo useradd --no-create-home --shell /bin/false node_exporterStep 2: Download Node Exporter
cd /tmp
curl -LO https://github.com/prometheus/node_exporter/releases/download/v1.12.1/node_exporter-1.12.1.linux-amd64.tar.gz
tar -xvf node_exporter-1.12.1.linux-amd64.tar.gzStep 3: Install the binary
sudo cp node_exporter-1.12.1.linux-amd64/node_exporter /usr/local/bin/
sudo chown node_exporter:node_exporter /usr/local/bin/node_exporterStep 4: Create the systemd service
sudo tee /etc/systemd/system/node_exporter.service > /dev/null <<EOF
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter
[Install]
WantedBy=multi-user.target
EOFStep 5: Start and enable Node Exporter
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporterStep 6: Verify
curl -s http://localhost:9100/metrics | headClean up the Node Exporter download
rm -rf /tmp/node_exporter-1.12.1.linux-amd64*Part 3: Point Prometheus at Node Exporter
Step 1: Add the scrape job
sudo vim /etc/prometheus/prometheus.ymlAdd under scrape_configs:
- job_name: "node_exporter"
static_configs:
- targets: ['localhost:9100']Step 2: Validate the config
promtool check config /etc/prometheus/prometheus.ymlStep 3: Reload Prometheus
sudo systemctl reload prometheusStep 4: Verify the target is up
Open http://<server-ip>:9090/targets, both prometheus and node_exporter jobs should show State = UP.
Part 4: Install Grafana
Official method: APT repository, so apt-get update keeps Grafana current. Source: https://grafana.com/docs/grafana/latest/setup-grafana/installation/debian/
Step 1: Install prerequisites
sudo apt-get install -y apt-transport-https wget gnupgStep 2: Import the GPG key
sudo mkdir -p /etc/apt/keyrings
sudo wget -O /etc/apt/keyrings/grafana.asc https://apt.grafana.com/gpg-full.key
sudo chmod 644 /etc/apt/keyrings/grafana.ascStep 3: Add the stable repository
echo "deb [signed-by=/etc/apt/keyrings/grafana.asc] https://apt.grafana.com stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.listStep 4: Update package list
sudo apt-get updateStep 5: Install Grafana OSS
sudo apt-get install -y grafanaStep 6: Start and enable Grafana
sudo systemctl daemon-reload
sudo systemctl enable --now grafana-serverStep 7: Verify
sudo systemctl status grafana-serverOpen http://<server-ip>:3000. Default login is admin / admin, you'll be asked to change it on first sign-in.
Part 5: Optional Grafana config (custom domain / HTTPS)
Only needed if you're putting Grafana behind a domain name with TLS.
Step 1: Edit grafana.ini
sudo vim /etc/grafana/grafana.ini[server]
http_addr =
http_port = 3000
domain = mysite.com
root_url = https://subdomain.mysite.com:3000
cert_key = /etc/grafana/grafana.key
cert_file = /etc/grafana/grafana.crt
enforce_domain = False
protocol = httpsStep 2: Restart Grafana
sudo systemctl restart grafana-serverStep 3 (optional): Nginx reverse proxy
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
server_name your_domain www.your_domain;
location / {
proxy_set_header Host $http_host;
proxy_pass http://localhost:3000;
}
location /api/live {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $http_host;
proxy_pass http://localhost:3000;
}
}Part 6: Connect Grafana to Prometheus
Step 1: Add the data source
In Grafana: Connections > Data sources > Add data source > Prometheus.
Set URL to:
http://localhost:9090Click Save & test, you should see "Successfully queried the Prometheus API."
Step 2: Import the Node Exporter dashboard
Dashboards > New > Import, enter dashboard ID:
1860Select your Prometheus data source when prompted, click Import. This is the community "Node Exporter Full" dashboard and it covers CPU, memory, disk, and network out of the box.
Service management cheat sheet
service start status enable
--------------- -------------------- -------------------- -------------------------------
prometheus systemctl start systemctl status systemctl enable prometheus
node_exporter systemctl start systemctl status systemctl enable node_exporter
grafana-server systemctl start systemctl status systemctl enable grafana-serverReload configs without downtime:
sudo systemctl reload prometheus
sudo systemctl restart grafana-serverWhere to go next
One server is where this starts, not where it ends. The next two steps are usually alerting (Alertmanager, so a full disk pages you at 3am instead of surprising you at 9) and a second exporter for whatever the box actually runs. If that box is a website, self-hosting WordPress with Docker and Redis is the other half of the same setup.
Monitoring at larger scale is a good chunk of my work: Grafana and Prometheus observability, including a benchmarking rig that dispatched ten million requests in fifteen minutes. Happy to talk it through.
Uninstall
Remove Prometheus
sudo systemctl disable --now prometheus
sudo rm -f /usr/local/bin/prometheus /usr/local/bin/promtool
sudo rm -rf /etc/prometheus /var/lib/prometheus /etc/systemd/system/prometheus.service
sudo userdel prometheus
sudo systemctl daemon-reloadRemove Node Exporter
sudo systemctl disable --now node_exporter
sudo rm -f /usr/local/bin/node_exporter /etc/systemd/system/node_exporter.service
sudo userdel node_exporter
sudo systemctl daemon-reloadRemove Grafana
sudo systemctl stop grafana-server
sudo apt-get remove -y grafana
sudo rm -i /etc/apt/sources.list.d/grafana.list