G’day,
It took longer than expected to get Smokeping working, so I thought I would post a working example for others. Now it will be indexed
I notice there is no maintainer, and I guess if there was interest, I could update the module with a few of the tweaks I worked out. Or you could just copy this… I think most people have moved to prometheus blackbox
https://search.nixos.org/packages?channel=unstable&show=smokeping&from=0&size=50&sort=relevance&type=packages&query=smokeping
#
# nixos/hp/hp4/smokeping.nix
#
# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/smokeping.nix
# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/monitoring/prometheus/exporters/smokeping.nix
# https://oss.oetiker.ch/smokeping/doc/smokeping_examples.en.html
# https://oss.oetiker.ch/smokeping/probe/Curl.en.html
# https://oss.oetiker.ch/smokeping/probe/DNS.en.html
{ config, lib, pkgs, ... }:
let
targets = {
# DNS Servers - ICMP ping testing
"DNSServers" = {
title = "DNS Server Connectivity (ICMP Ping)";
menu = "DNS Servers";
targets = {
"Google_DNS_IPv4" = {
name = "Google DNS IPv4";
host = "8.8.8.8";
};
"Google_DNS_IPv6" = {
name = "Google DNS IPv6";
host = "2001:4860:4860::8888";
};
"Cloudflare_DNS_IPv4" = {
name = "Cloudflare DNS IPv4";
host = "1.1.1.1";
};
"Cloudflare_DNS_IPv6" = {
name = "Cloudflare DNS IPv6";
host = "2606:4700:4700::1111";
};
"Cloudflare_DNS_Secondary_IPv4" = {
name = "Cloudflare DNS Secondary IPv4";
host = "1.0.0.1";
};
"Cloudflare_DNS_Secondary_IPv6" = {
name = "Cloudflare DNS Secondary IPv6";
host = "2606:4700:4700::1001";
};
};
};
# Internet Connectivity
"Internet" = {
title = "Internet Connectivity Monitoring";
menu = "Internet Connectivity";
targets = {
"Google_IPv4" = {
name = "Google.com IPv4";
host = "142.250.190.78";
};
"Google_IPv6" = {
name = "Google.com IPv6";
host = "2607:f8b0:4007:811::200e";
};
"Facebook_IPv6" = {
name = "Facebook IPv6";
host = "2a03:2880:f10d:183:face:b00c:0:25de";
};
"Yahoo_IPv6" = {
name = "Yahoo IPv6";
host = "2001:4998:24:120d::1:0";
};
};
};
# Add HTTP category and targets
"HTTP" = {
title = "HTTP Site Monitoring";
menu = "HTTP Sites";
targets = {
"Google_HTTP" = {
name = "Google HTTP";
host = "google.com";
probe = "Curl";
};
"IBM_HTTP" = {
name = "IBM HTTP";
host = "ibm.com";
probe = "Curl";
};
"Yahoo_HTTP" = {
name = "Yahoo HTTP";
host = "yahoo.com";
probe = "Curl";
};
"Facebook_HTTP" = {
name = "Facebook HTTP";
host = "facebook.com";
probe = "Curl";
};
};
};
# Add DNS lookup testing
"DNSLookup" = {
title = "DNS Resolution Testing (dig queries)";
menu = "DNS Resolution";
targets = {
"Google_DNS_Lookup" = {
name = "Google DNS - google.com lookup";
host = "8.8.8.8";
probe = "DNS";
lookup = "google.com";
};
"Cloudflare_DNS_Lookup" = {
name = "Cloudflare DNS - google.com lookup";
host = "1.1.1.1";
probe = "DNS";
lookup = "google.com";
};
"Local_DNS_Lookup" = {
name = "Local DNS - google.com lookup";
host = "::1";
probe = "DNS";
lookup = "google.com";
};
};
};
};
generateTargetConfig = categoryName: category: ''
+ ${categoryName}
menu = ${category.menu}
title = ${category.title}
${lib.concatStringsSep "\n" (lib.mapAttrsToList (targetName: target: ''
++ ${targetName}
menu = ${target.name}
title = ${target.name}${lib.optionalString (target ? probe) "\nprobe = ${target.probe}"}
host = ${target.host}${lib.optionalString (target ? lookup) "\nlookup = ${target.lookup}"}
'' ) category.targets)}'';
# Generate the complete target configuration
targetConfig = ''
probe = FPing
menu = Top
title = Network Latency Grapher
remark = Welcome to the SmokePing website of Siden Network Operations. \
Here you will learn all about the latency of our network.
${lib.concatStringsSep "\n" (lib.mapAttrsToList generateTargetConfig targets)}'';
prometheusTargets = lib.flatten (lib.mapAttrsToList (categoryName: category:
lib.mapAttrsToList (targetName: target:
{
name = "${categoryName}_${targetName}";
host = target.host;
}) category.targets
) targets);
in {
# Smokeping configuration for network monitoring
# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/smokeping.nix
services.smokeping = {
enable = true;
webService = false; # Disable automatic nginx configuration to avoid conflicts
# Basic configuration
owner = "Network Operations";
ownerEmail = "ops@siden.io";
hostName = "smokeping.localhost";
# Database configuration (5 minute intervals, 20 pings per step)
# Using AVERAGE as the consolidation function (MEDIAN is not supported)
databaseConfig = ''
step = 300
pings = 20
# consfn mrhb steps total
AVERAGE 0.5 1 1008
AVERAGE 0.5 12 4320
MIN 0.5 12 4320
MAX 0.5 12 4320
AVERAGE 0.5 144 720
MAX 0.5 144 720
MIN 0.5 144 720
'';
# Probe configuration for both IPv4 and IPv6
# Modern fping handles IPv6 addresses automatically
probeConfig = ''
+ FPing
binary = ${config.security.wrapperDir}/fping
+ Curl
binary = ${pkgs.curl}/bin/curl
urlformat = http://%host%/
timeout = 10
step = 300
extraargs = --silent
follow_redirects = yes
include_redirects = no
+ DNS
binary = ${pkgs.bind.dnsutils}/bin/dig
timeout = 15
step = 300
'';
# Target configuration generated from data structure
inherit targetConfig;
# Alert configuration
alertConfig = ''
to = root@localhost
from = smokeping@localhost
+someloss
type = loss
pattern = >0%,*12*,>0%,*12*,>0%
comment = Loss of connectivity
+highloss
type = loss
pattern = >50%,*12*,>50%,*12*,>50%
comment = High loss of connectivity
+highlatency
type = rtt
pattern = >100,*12*,>100,*12*,>100
comment = High latency detected
'';
# Presentation configuration
presentationConfig = ''
+ charts
menu = Charts
title = The most interesting destinations
++ stddev
sorter = StdDev(entries=>4)
title = Top Standard Deviation
menu = Std Deviation
format = Standard Deviation %f
++ max
sorter = Max(entries=>5)
title = Top Max Roundtrip Time
menu = by Max
format = Max Roundtrip Time %f seconds
++ loss
sorter = Loss(entries=>5)
title = Top Packet Loss
menu = Loss
format = Packets Lost %f
++ median
sorter = Median(entries=>5)
title = Top Median Roundtrip Time
menu = by Median
format = Median RTT %f seconds
+ overview
width = 600
height = 50
range = 10h
+ detail
width = 600
height = 200
unison_tolerance = 2
"Last 3 Hours" 3h
"Last 30 Hours" 30h
"Last 10 Days" 10d
"Last 360 Days" 360d
'';
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
# Ensure nginx can read cache/data for static file serving
users.users.nginx.extraGroups = [ "smokeping" ];
systemd.tmpfiles.rules = [
"d /var/lib/smokeping/cache 0750 smokeping smokeping"
"d /var/lib/smokeping/data 0750 smokeping smokeping"
"Z /var/lib/smokeping 0750 smokeping smokeping"
];
# Systemd security measures for smokeping
systemd.slices.smokeping = {
description = "Smokeping network monitoring slice";
sliceConfig = {
MemoryHigh = "200M";
MemoryMax = "300M";
CPUQuota = "20%";
TasksMax = 200;
};
};
# Enhanced smokeping service configuration with security measures
# systemd-analyze security smokeping
systemd.services.smokeping = {
serviceConfig = {
# Resource limits
Slice = "smokeping.slice";
MemoryHigh = "200M";
MemoryMax = "300M";
CPUQuota = "20%";
TasksMax = 200;
# Process limits
LimitNOFILE = 1024;
LimitNPROC = 100;
# Security restrictions
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
ProtectKernelLogs = true;
PrivateDevices = true;
RestrictRealtime = true;
# RestrictSUIDSGID = true; # Disabled - smokeping needs SUID wrapper for ping
RestrictNamespaces = true;
LockPersonality = true;
# MemoryDenyWriteExecute = true; # Disabled - interferes with DNS resolution
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
# Additional security restrictions
RemoveIPC = true; # Clean up IPC objects
UMask = "0077"; # Restrict file permissions
SystemCallFilter = [ "@system-service" "~@privileged" "~@mount" "~@debug" "~@module" "~@reboot" "~@swap" "~@clock" "~@cpu-emulation" "~@obsolete" ]; # Allow raw-io for IPv6 ping
CapabilityBoundingSet = [ "CAP_NET_RAW" "CAP_NET_BIND_SERVICE" ]; # Only network capabilities needed
ProtectProc = "default"; # Allow access to process info for DNS resolution
ProcSubset = "all"; # Allow access to all process info
ProtectHostname = true; # Prevent hostname changes
ProtectClock = true; # Prevent clock changes
# File system restrictions - allow access to dig
ReadWritePaths = [
"/var/lib/smokeping"
"/var/log"
"/run"
];
ReadOnlyPaths = [
"/etc/smokeping.conf"
"/nix/store"
"${pkgs.curl}"
"${config.services.smokeping.package}"
"${config.security.wrapperDir}"
"/etc/resolv.conf"
"/etc/hosts"
"/etc/nsswitch.conf"
"/etc/ssl"
"/etc/ca-bundle.crt"
"/etc/ssl/certs"
];
# User/group restrictions
User = "smokeping";
Group = "smokeping";
SupplementaryGroups = [ "smokeping" ];
# Restart policy
Restart = "on-failure";
RestartSec = "10s";
# Nice priority (lower number = higher priority)
Nice = 10;
# Required by smokeping module
ExecStart = "${config.services.smokeping.package}/bin/smokeping --config=/etc/smokeping.conf --nodaemon";
};
# Add curl package to the service environment
path = [ pkgs.curl pkgs.bind.dnsutils ];
environment = {
# Ensure DNS resolution works
NSS_WRAPPER_PASSWD = "/etc/passwd";
NSS_WRAPPER_GROUP = "/etc/group";
LD_LIBRARY_PATH = "${pkgs.curl}/lib";
};
};
# Also secure the prometheus smokeping exporter - DISABLED
# systemd.services.prometheus-smokeping-exporter = {
# serviceConfig = {
# # Resource limits
# MemoryHigh = "512M";
# MemoryMax = "1G";
# CPUQuota = "25%";
#
# # Security restrictions
# NoNewPrivileges = true;
# ProtectSystem = "strict";
# ProtectHome = true;
# ProtectKernelTunables = true;
# ProtectKernelModules = true;
# ProtectControlGroups = true;
# ProtectKernelLogs = true;
# PrivateDevices = true;
# RestrictRealtime = true;
# RestrictSUIDSGID = true;
# RestrictNamespaces = true;
# LockPersonality = true;
# MemoryDenyWriteExecute = true;
# RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
#
# # Additional security restrictions
# RemoveIPC = true; # Clean up IPC objects
# UMask = "0077"; # Restrict file permissions
# SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" "~@mount" "~@debug" "~@module" "~@reboot" "~@swap" "~@clock" "~@cpu-emulation" "~@obsolete" "~@raw-io" ];
# CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; # Only binding capability needed
# ProtectProc = "invisible"; # Hide other processes
# ProcSubset = "pid"; # Only show own process info
# ProtectHostname = true; # Prevent hostname changes
# ProtectClock = true; # Prevent clock changes
#
# # File system restrictions
# ReadWritePaths = [
# "/var/log"
# "/run"
# ];
# ReadOnlyPaths = [
# "/nix/store"
# ];
#
# # Restart policy
# Restart = "on-failure";
# RestartSec = "10s";
#
# # Nice priority
# Nice = 15;
# };
# };
}
# Available Probes in NixOS Smokeping 2.8.2:
#
# Network/Connectivity Probes:
# - FPing: Standard ping using fping binary (IPv4/IPv6)
# - FPing6: Legacy IPv6 ping (deprecated, use FPing)
# - FPingContinuous: Continuous ping monitoring
# - RemoteFPing: Ping through remote host
# - TCPPing: TCP connection testing
# - TraceroutePing: Traceroute-based ping
#
# HTTP/Web Probes:
# - Curl: HTTP/HTTPS testing using curl binary
# - EchoPingHttp: HTTP echo ping
# - EchoPingHttps: HTTPS echo ping
# - WebProxyFilter: Web proxy testing
#
# DNS Probes:
# - DNS: DNS query testing
# - AnotherDNS: Alternative DNS testing
# - EchoPingDNS: DNS echo ping
# - CiscoRTTMonDNS: Cisco DNS monitoring
#
# SSH/Telnet Probes:
# - SSH: SSH connection testing
# - AnotherSSH: Alternative SSH testing
# - TelnetIOSPing: Cisco IOS telnet ping
# - TelnetJunOSPing: Juniper telnet ping
# - OpenSSHEOSPing: OpenSSH to Cisco IOS
# - OpenSSHJunOSPing: OpenSSH to Juniper
#
# Application Probes:
# - LDAP: LDAP connection testing
# - EchoPingLDAP: LDAP echo ping
# - Radius: RADIUS authentication testing
# - TacacsPlus: TACACS+ authentication testing
# - FTPtransfer: FTP file transfer testing
# - NFSping: NFS mount testing
# - Qstat: Quake server status
# - SipSak: SIP protocol testing
#
# Network Equipment Probes:
# - CiscoRTTMonEchoICMP: Cisco ICMP echo monitoring
# - CiscoRTTMonTcpConnect: Cisco TCP connection monitoring
# - DismanPing: DISMAN-PING-MIB SNMP ping
# - IOSPing: Cisco IOS ping
# - IRTT: In-band Round Trip Time
#
# Email Probes:
# - EchoPingSmtp: SMTP echo ping
# - SendEmail: Email sending test
#
# Other Probes:
# - EchoPingChargen: Chargen echo ping
# - EchoPingDiscard: Discard echo ping
# - EchoPingIcp: ICP echo ping
# - EchoPingWhois: Whois echo ping
# - EchoPingPlugin: Plugin-based echo ping
# - passwordchecker: Password checking
#
# Note: The HTTP probe is NOT available in NixOS smokeping 2.8.2.
# Use Curl probe for HTTP/HTTPS testing instead.
The resulting service has some security protections
[das@hp4:~/nixos/hp/hp4]$ cat /etc/systemd/system/smokeping.service
[Unit]
X-Reload-Triggers=/nix/store/df5bf4z39qizhp2i9kyh7p8fp04sl30m-X-Reload-Triggers-smokeping
[Service]
Environment="LD_LIBRARY_PATH=/nix/store/zl7h70n70g5m57iw5pa8gqkxz6y0zfcf-curl-8.12.1-bin/lib"
Environment="LOCALE_ARCHIVE=/nix/store/nqixjjil6mbzf0rdqqr2sm47w5av72f6-glibc-locales-2.40-66/lib/locale/locale-archive"
Environment="NSS_WRAPPER_GROUP=/etc/group"
Environment="NSS_WRAPPER_PASSWD=/etc/passwd"
Environment="PATH=/nix/store/zl7h70n70g5m57iw5pa8gqkxz6y0zfcf-curl-8.12.1-bin/bin:/nix/store/vi3pdc7q416gh2njxhlnc8xrnbkxxjw0-bind-9.18.33-dnsutils/bin:/nix/store/440q5scq8paszj2sdgz98hxl1rz12i88-coreutils-9.5/bin:/nix/store/lpz4m485bm2y8mann5c4xcf4p4hlls3k-findutils-4.10.0/bin:/nix/store/0mqngkz34kv5z6hz91bbbgzgrnz56c4y-gnugrep-3.11/bin:/nix/store/q5b7l0zfk7k6nadpj80niqzymaq0z9yp-gnused-4.9/bin:/nix/store/v9fckvvzbzw55xgj7pk8vfxwsx96d3qw-systemd-256.10/bin:/nix/store/zl7h70n70g5m57iw5pa8gqkxz6y0zfcf-curl-8.12.1-bin/sbin:/nix/store/vi3pdc7q416gh2njxhlnc8xrnbkxxjw0-bind-9.18.33-dnsutils/sbin:/nix/store/440q5scq8paszj2sdgz98hxl1rz12i88-coreutils-9.5/sbin:/nix/store/lpz4m485bm2y8mann5c4xcf4p4hlls3k-findutils-4.10.0/sbin:/nix/store/0mqngkz34kv5z6hz91bbbgzgrnz56c4y-gnugrep-3.11/sbin:/nix/store/q5b7l0zfk7k6nadpj80niqzymaq0z9yp-gnused-4.9/sbin:/nix/store/v9fckvvzbzw55xgj7pk8vfxwsx96d3qw-systemd-256.10/sbin"
Environment="TZDIR=/nix/store/d4prd3ravga8vikbr625apnspk477p1q-tzdata-2025b/share/zoneinfo"
CPUQuota=20%
CapabilityBoundingSet=CAP_NET_RAW
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
ExecStart=/nix/store/fljhb3x3kxx4aqjbdmjmc7w1zx6dcdr2-smokeping-2.8.2/bin/smokeping --config=/etc/smokeping.conf --nodaemon
ExecStartPre=/nix/store/cfnfd8vmrsn1dd3grhny3imrppxsigj6-unit-script-smokeping-pre-start/bin/smokeping-pre-start
Group=smokeping
LimitNOFILE=1024
LimitNPROC=100
LockPersonality=true
MemoryHigh=200M
MemoryMax=300M
Nice=10
NoNewPrivileges=true
PrivateDevices=true
ProcSubset=all
ProtectClock=true
ProtectControlGroups=true
ProtectHome=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectProc=default
ProtectSystem=strict
ReadOnlyPaths=/etc/smokeping.conf
ReadOnlyPaths=/nix/store
ReadOnlyPaths=/nix/store/zl7h70n70g5m57iw5pa8gqkxz6y0zfcf-curl-8.12.1-bin
ReadOnlyPaths=/nix/store/fljhb3x3kxx4aqjbdmjmc7w1zx6dcdr2-smokeping-2.8.2
ReadOnlyPaths=/run/wrappers/bin
ReadOnlyPaths=/etc/resolv.conf
ReadOnlyPaths=/etc/hosts
ReadOnlyPaths=/etc/nsswitch.conf
ReadOnlyPaths=/etc/ssl
ReadOnlyPaths=/etc/ca-bundle.crt
ReadOnlyPaths=/etc/ssl/certs
ReadWritePaths=/var/lib/smokeping
ReadWritePaths=/var/log
ReadWritePaths=/run
RemoveIPC=true
Restart=on-failure
RestartSec=10s
RestrictAddressFamilies=AF_INET
RestrictAddressFamilies=AF_INET6
RestrictNamespaces=true
RestrictRealtime=true
Slice=smokeping.slice
SupplementaryGroups=smokeping
SystemCallFilter=@system-service
SystemCallFilter=~@privileged
SystemCallFilter=~@mount
SystemCallFilter=~@debug
SystemCallFilter=~@module
SystemCallFilter=~@reboot
SystemCallFilter=~@swap
SystemCallFilter=~@clock
SystemCallFilter=~@cpu-emulation
SystemCallFilter=~@obsolete
TasksMax=200
UMask=0077
User=smokeping
[das@hp4:~/nixos/hp/hp4]$
Kind regards,
Dave