diff --git a/morph/grid/local/grid.nix b/morph/grid/local/grid.nix
index b500c485c0dc318354fba9edc7c5baeb55c76667..3f4f5243c7274bc77b3b64e6a29698ff98ba2248 100644
--- a/morph/grid/local/grid.nix
+++ b/morph/grid/local/grid.nix
@@ -38,7 +38,7 @@ import ../../lib/make-grid.nix {
       monitoringvpnIPv4 = "172.23.23.1";
       inherit vpnClientIPs;
       inherit sshUsers;
-      nodeExporterTargets = [ ];
+      nodeExporterTargets = [ "172.23.23.1" "172.23.23.11" "172.23.23.12" "172.23.23.13" ]; # TBD: derive automatically
       nginxExporterTargets = [ ];
       hardware = import ./virtual-hardware.nix ({ inherit publicIPv4; });
       stateVersion = "19.09";
diff --git a/morph/lib/make-issuer.nix b/morph/lib/make-issuer.nix
index 82b194840db0d2387b10d435dfbc0e1dd8066b26..039e426807386cafc06453a470cb4e7e4b10c674 100644
--- a/morph/lib/make-issuer.nix
+++ b/morph/lib/make-issuer.nix
@@ -55,6 +55,7 @@
     hardware
     ../../nixos/modules/issuer.nix
     ../../nixos/modules/monitoring/vpn/client.nix
+    ../../nixos/modules/monitoring/exporters/node.nix
   ];
 
   services.private-storage.sshUsers = sshUsers;
diff --git a/morph/lib/make-monitoring.nix b/morph/lib/make-monitoring.nix
index 4a2dd83c47de5a3ee140fda50dfe2e2128128a7f..b8242446926066841973cf715e05ec1b92e63ad4 100644
--- a/morph/lib/make-monitoring.nix
+++ b/morph/lib/make-monitoring.nix
@@ -52,6 +52,7 @@ rec {
     ../../nixos/modules/monitoring/vpn/server.nix
     ../../nixos/modules/monitoring/server/grafana.nix
     ../../nixos/modules/monitoring/server/prometheus.nix
+    ../../nixos/modules/monitoring/exporters/node.nix
     # Loki 0.3.0 from Nixpkgs 19.09 is too old and does not work:
     # ../../nixos/modules/monitoring/server/loki.nix
   ];
diff --git a/morph/lib/make-testing.nix b/morph/lib/make-testing.nix
index 7cd3c80aa0e237d003f07e9f95ee5eac211a5ca5..1eb39ab550b640e44de233ed6cd54d574d7e40f8 100644
--- a/morph/lib/make-testing.nix
+++ b/morph/lib/make-testing.nix
@@ -48,6 +48,7 @@
     hardware
     ../../nixos/modules/private-storage.nix
     ../../nixos/modules/monitoring/vpn/client.nix
+    ../../nixos/modules/monitoring/exporters/node.nix
   ];
 
   services.private-storage =
diff --git a/nixos/modules/monitoring/exporters/node.nix b/nixos/modules/monitoring/exporters/node.nix
new file mode 100644
index 0000000000000000000000000000000000000000..519e04d1bf3e8bcd4ae54fc66c82ea3ae57ce34f
--- /dev/null
+++ b/nixos/modules/monitoring/exporters/node.nix
@@ -0,0 +1,75 @@
+# Prometheus common node exporter config
+#
+# Scope: Export platform data like CPU, memory, disk space etc. to be
+#        polled by Prometheus server
+# Usage: Import this to every server you want to include in the central
+#        monitoring system
+# See https://nixos.org/manual/nixos/stable/#module-services-prometheus-exporters
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  mountsFileSystemType = fsType: {} != filterAttrs (n: v: v.fsType == fsType) config.fileSystems;
+
+in {
+  config.networking.firewall.allowedTCPPorts = [ 9100 ];
+
+  config.services.prometheus.exporters.node = {
+    enable = true;
+    openFirewall = true;
+    port = 9100;
+    # extraFlags = [ "--collector.disable-defaults" ]; # not in nixpkgs 19.09
+    # Thanks https://github.com/mayflower/nixexprs/blob/master/modules/monitoring/default.nix
+    enabledCollectors = [
+      "arp"
+      "bcache"
+      "conntrack"
+      "filefd"
+      "logind"
+      "netclass"
+      "netdev"
+      "netstat"
+      #"rapl" # not in nixpkgs 19.09
+      "sockstat"
+      #"softnet" # not in nixpkgs 19.09
+      "stat"
+      "systemd"
+      # "textfile"
+      # "textfile.directory /run/prometheus-node-exporter"
+      #"thermal_zone" # not in nixpkgs 19.09
+      "time"
+      #"udp_queues" # not in nixpkgs 19.09
+      "uname"
+      "vmstat"
+    ] ++ optionals (!config.boot.isContainer) [
+      "cpu"
+      "cpufreq"
+      "diskstats"
+      "edac"
+      "entropy"
+      "filesystem"
+      "hwmon"
+      "interrupts"
+      "ksmd"
+      "loadavg"
+      "meminfo"
+      "pressure"
+      "timex"
+    ] ++ (
+      optionals (config.services.nfs.server.enable) [ "nfsd" ]
+    ) ++ (
+      optionals ("" != config.boot.initrd.mdadmConf) [ "mdadm" ]
+    ) ++ (
+      optionals ({} != config.networking.bonds) [ "bonding" ]
+    ) ++ (
+      optionals (mountsFileSystemType "nfs") [ "nfs" ]
+    ) ++ (
+      optionals (mountsFileSystemType "xfs") [ "xfs" ]
+    ) ++ (
+      optionals (mountsFileSystemType "zfs" || elem "zfs" config.boot.supportedFilesystems) [ "zfs" ]
+    );
+  };
+}
+
diff --git a/nixos/modules/monitoring/server/grafana-config/resources-overview.json b/nixos/modules/monitoring/server/grafana-config/resources-overview.json
index 70519e5bf77c9a3dc5973e1a88ca62c7030f6018..02db119b250b386c6b26bcb070d8894c066db61c 100644
--- a/nixos/modules/monitoring/server/grafana-config/resources-overview.json
+++ b/nixos/modules/monitoring/server/grafana-config/resources-overview.json
@@ -494,14 +494,14 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "max by (instance) (rate(node_network_transmit_bytes_total{device!=\"lo\"}[5m]) / node_network_speed_bytes)",
+          "expr": "max by (instance) (rate(node_network_transmit_bytes_total{device!~\"lo|monitoringvpn\"}[5m]) / node_network_speed_bytes)",
           "interval": "",
           "intervalFactor": 4,
           "legendFormat": "{{instance}} out",
           "refId": "A"
         },
         {
-          "expr": "- max by (instance) (rate(node_network_receive_bytes_total{device!=\"lo\"}[5m]) / node_network_speed_bytes)",
+          "expr": "- max by (instance) (rate(node_network_receive_bytes_total{device!~\"lo|monitoringvpn\"}[5m]) / node_network_speed_bytes)",
           "interval": "",
           "intervalFactor": 4,
           "legendFormat": "{{instance}} in",
@@ -602,28 +602,28 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "rate(node_network_reveive_packets_total{device!=\"lo\"}[5m])",
+          "expr": "rate(node_network_receive_packets_total{device!~\"lo|monitoringvpn\"}[5m])",
           "interval": "",
           "intervalFactor": 4,
           "legendFormat": "{{instance}} {{device}}",
           "refId": "A"
         },
         {
-          "expr": "rate(node_network_reveive_errs_total{device!=\"lo\"}[5m])",
+          "expr": "rate(node_network_receive_errs_total{device!~\"lo|monitoringvpn\"}[5m])",
           "interval": "",
           "intervalFactor": 4,
           "legendFormat": "{{instance}} {{device}}",
           "refId": "B"
         },
         {
-          "expr": "- rate(node_network_transmit_packets_total{device!=\"lo\"}[5m])",
+          "expr": "- rate(node_network_transmit_packets_total{device!~\"lo|monitoringvpn\"}[5m])",
           "interval": "",
           "intervalFactor": 4,
           "legendFormat": "{{instance}} {{device}}",
           "refId": "C"
         },
         {
-          "expr": "- rate(node_network_transmit_errs_total{device!=\"lo\"}[5m])",
+          "expr": "- rate(node_network_transmit_errs_total{device!~\"lo|monitoringvpn\"}[5m])",
           "interval": "",
           "intervalFactor": 4,
           "legendFormat": "{{instance}} {{device}}",
@@ -1291,4 +1291,4 @@
   "title": "Resources overview",
   "uid": "ResSatUse",
   "version": 1
-}
\ No newline at end of file
+}