Task

Install Node Exporter without touching the host by hand

Ansible · 15 min · Practical

One playbook fetches the release, creates a locked-down service account, wires up systemd, and leaves you with a metrics endpoint — reproducible on every box you run it against.

Why this playbook holds up

Built around three properties that matter for anything running unattended on a server: idempotency, isolation, and portability. Every task uses a native Ansible module — no shell one-liners to babysit, no drift between runs. Run it once or run it a hundred times; the end state doesn't change.

Safe to re-run

Tasks check current state before acting, so a second run against an already-configured host changes nothing.

No distro assumptions

Works against any systemd-based Linux host — swap hosts: localhost for an inventory group and it scales the same way.

The full task list

node_exporter.yml
---
- name: Install node exporter
  hosts: localhost
  become: yes
  vars:
    node_exporter_version: "1.8.1"
  tasks:
    - name: Download and extract node exporter
      unarchive:
        src: "https://github.com/prometheus/node_exporter/releases/download/v{{ node_exporter_version }}/node_exporter-{{ node_exporter_version }}.linux-amd64.tar.gz"
        dest: /tmp
        remote_src: yes

    - name: Copy node exporter binary
      copy:
        src: "/tmp/node_exporter-{{ node_exporter_version }}.linux-amd64/node_exporter"
        dest: /usr/local/bin/node_exporter
        mode: '0755'
        remote_src: yes

    - name: Create node exporter user
      user:
        name: node_exporter
        shell: /sbin/nologin
        system: yes
        create_home: no

    - name: Create systemd service file
      copy:
        dest: /etc/systemd/system/node_exporter.service
        content: |
          [Unit]
          Description=Node Exporter
          After=network.target
          [Service]
          User=node_exporter
          ExecStart=/usr/local/bin/node_exporter
          [Install]
          WantedBy=multi-user.target

    - name: Reload systemd
      command: systemctl daemon-reload

    - name: Enable and start node exporter
      service:
        name: node_exporter
        state: started
        enabled: yes

Run order

  • fetch Download and extract the release into /tmp.

    unarchive, remote_src

  • place Move the binary to /usr/local/bin and mark it executable.

    copy, mode 0755

  • isolate Create a no-login system account to run the service as.

    user, /sbin/nologin

  • wire Write the unit file and register it with systemd.

    copy + daemon-reload

  • run Enable on boot and start the service now.

    service, enabled + started

Confirm it's actually up

Two checks are enough: is the systemd unit reporting active, and is the metrics endpoint answering. If both check out, Prometheus can scrape the host.

terminal

$ systemctl status node_exporter
● node_exporter.service - Node Exporter
   Active: active (running) since Wed 2026-07-08

$ curl -s localhost:9100/metrics | head -n 3
# HELP go_gc_duration_seconds A summary of the pause duration.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 1.7e-05

$

Lessons from running this in production