Skip to content

Run as a service

Prometheus scrapes the exporter every minute, day and night, so it has to run permanently and start again after a reboot. The binary integrates with both service managers by itself: it tells systemd when it is ready (Type=notify) and runs as a native Windows service, with no wrapper such as NSSM.

Keep the connection options out of the command line: put them in a options file readable only by the service, so the token does not appear in the process list or in the unit.

  1. Install the binary. The deb, rpm and AUR packages put it in /usr/bin/cv4pve-metrics-exporter; with the zip, copy it there yourself.

  2. Create a user for the service, with no shell and no home:

    sudo useradd --system --no-create-home --shell /usr/sbin/nologin cv4pve-metrics
  3. Create the configuration folder, the settings file and the parameter file with the connection options:

    sudo install -d -m 750 -o root -g cv4pve-metrics /etc/cv4pve-metrics-exporter
    cd /etc/cv4pve-metrics-exporter
    sudo cv4pve-metrics-exporter create-settings -o settings.json # add --fast or --full to start from those
    sudo tee connection.conf > /dev/null <<'EOF'
    --host=pve1.local,pve2.local
    --api-token=metrics@pve!metrics=<uuid>
    EOF
    sudo chown root:cv4pve-metrics settings.json connection.conf
    sudo chmod 640 settings.json connection.conf

    In settings.json, set Host to * if Prometheus runs on another machine, see Listening address. In the parameter file the token needs no quotes.

  4. Create /etc/systemd/system/cv4pve-metrics-exporter.service:

    [Unit]
    Description=cv4pve-metrics-exporter - Prometheus exporter for Proxmox VE
    Wants=network-online.target
    After=network-online.target
    [Service]
    Type=notify
    User=cv4pve-metrics
    Group=cv4pve-metrics
    ExecStart=/usr/bin/cv4pve-metrics-exporter @/etc/cv4pve-metrics-exporter/connection.conf --settings-file=/etc/cv4pve-metrics-exporter/settings.json run
    Restart=on-failure
    RestartSec=10
    [Install]
    WantedBy=multi-user.target
  5. Start it, and enable it at boot:

    sudo systemctl daemon-reload
    sudo systemctl enable --now cv4pve-metrics-exporter
    systemctl status cv4pve-metrics-exporter
    curl -s http://localhost:9221/metrics/ | head

Type=notify makes systemctl start return only once the HTTP endpoint is listening, and Restart=on-failure starts it again if it stops with an error, for example when the port is taken at boot. Use absolute paths in ExecStart: the parameter file and --settings-file are not looked up in the folder of the binary.

The output goes to the journal:

journalctl -u cv4pve-metrics-exporter -f

To change the settings, edit the file and run sudo systemctl restart cv4pve-metrics-exporter: the settings are read only at start.

  1. Unzip cv4pve-metrics-exporter.exe-win-x64.zip into a folder for all users, e.g. C:\Program Files\cv4pve-metrics-exporter. The WinGet package installs per user, in a folder the service account does not use.

  2. Create the settings file and the parameter file, in an administrator PowerShell:

    $dir = 'C:\ProgramData\cv4pve-metrics-exporter'
    New-Item -ItemType Directory -Force $dir | Out-Null
    & 'C:\Program Files\cv4pve-metrics-exporter\cv4pve-metrics-exporter.exe' create-settings -o "$dir\settings.json"
    Set-Content "$dir\connection.conf" "--host=pve1.local,pve2.local`n--api-token=metrics@pve!metrics=<uuid>"

    Then restrict C:\ProgramData\cv4pve-metrics-exporter to Administrators and SYSTEM: the parameter file holds the token.

  3. Create and start the service:

    New-Service -Name cv4pve-metrics-exporter -DisplayName 'cv4pve-metrics-exporter' -StartupType Automatic -BinaryPathName '"C:\Program Files\cv4pve-metrics-exporter\cv4pve-metrics-exporter.exe" @C:\ProgramData\cv4pve-metrics-exporter\connection.conf --settings-file=C:\ProgramData\cv4pve-metrics-exporter\settings.json run'
    Start-Service cv4pve-metrics-exporter
    Invoke-WebRequest http://localhost:9221/metrics/ -UseBasicParsing | Select-Object StatusCode

    New-Service works the same in Windows PowerShell 5.1 and PowerShell 7. The quotes around the path of the executable are needed because of the space in Program Files.

The service runs as LocalSystem, which is allowed to listen on every interface: set Host to * if Prometheus runs on another machine, and open the port in Windows Firewall:

New-NetFirewallRule -DisplayName 'cv4pve-metrics-exporter' -Direction Inbound -Protocol TCP -LocalPort 9221 -Action Allow

To change the settings, edit the file and run Restart-Service cv4pve-metrics-exporter: the settings are read only at start.

Errors go to the Windows Event Log: Event Viewer → Windows Logs → Application, source cv4pve-metrics-exporter. A failed login, for example, is logged there as an error while the service keeps running and the scrape answers 503.

To remove the service:

Stop-Service cv4pve-metrics-exporter
sc.exe delete cv4pve-metrics-exporter