Skip to content

Commit 072c78e

Browse files
committed
monit-nb: add module
nix-bitcoin monitoring via monit
1 parent cae0ff4 commit 072c78e

File tree

8 files changed

+206
-1
lines changed

8 files changed

+206
-1
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ NixOS modules ([src](modules/modules.nix))
9494
* [netns-isolation](modules/netns-isolation.nix): isolates applications on the network-level via network namespaces
9595
* [nodeinfo](modules/nodeinfo.nix): script which prints info about the node's services
9696
* [backups](modules/backups.nix): duplicity backups of all your node's important files
97+
* [monitoring](modules/monit-nb.nix): pro-active monitoring for nix-bitcoin
9798
* [operator](modules/operator.nix): adds non-root user `operator` who has access to client tools (e.g. `bitcoin-cli`, `lightning-cli`)
9899

99100
Security

examples/configuration.nix

+7
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,13 @@
236236
# and electrs data directory, enable
237237
# services.backups.with-bulk-data = true;
238238

239+
### Monitoring
240+
# Set this to enable monit-nb, nix-bitcoin's own monitoring service. It will
241+
# create a user `monitmail` with password $secretsDir/monitmail-password,
242+
# which you can use to connect over IMAP using the monit-nb onion service and
243+
# your favorite mail client with Tor proxy support.
244+
# services.monit-nb.enable = true;
245+
239246
### netns-isolation (EXPERIMENTAL)
240247
# Enable this module to use Network Namespace Isolation. This feature places
241248
# every service in its own network namespace and only allows truly necessary

modules/modules.nix

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
./netns-isolation.nix
3636
./nodeinfo.nix
3737
./backups.nix
38+
./monit-nb.nix
3839
];
3940

4041
disabledModules = [ "services/networking/bitcoind.nix" ];

modules/monit-nb.nix

+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
{ config, lib, pkgs, ... }:
2+
3+
with lib;
4+
let
5+
options.services.monit-nb = {
6+
enable = mkEnableOption "nix-bitcoin monitoring via monit";
7+
address = mkOption {
8+
type = types.str;
9+
default = "127.0.0.1";
10+
description = "Dovecot server address.";
11+
};
12+
port = mkOption {
13+
type = types.port;
14+
default = 143;
15+
description = "Dovecot server port.";
16+
};
17+
};
18+
19+
cfg = config.services.monit-nb;
20+
nbLib = config.nix-bitcoin.lib;
21+
secretsDir = config.nix-bitcoin.secretsDir;
22+
23+
checkStatus = pkgs.writeScriptBin "checkStatus" ''
24+
#! /bin/sh
25+
if [[ $(systemctl show --property=ActiveState $1) == *"=active"* ]];
26+
then exit 0
27+
else exit 1
28+
fi
29+
'';
30+
31+
configFile = ''
32+
set alert monitmail@localhost
33+
set daemon 120 with start delay 60
34+
set mailserver
35+
localhost
36+
37+
set httpd unixsocket /var/run/monit.sock
38+
uid root
39+
gid root
40+
permission 660
41+
# Placeholder username & password
42+
# Secured through unix socket permissions
43+
allow admin:obwjoawijerfoijsiwfj29jf2f2jd
44+
45+
check filesystem root with path /
46+
if space usage > 80% then alert
47+
if inode usage > 80% then alert
48+
49+
check system $HOST
50+
if cpu usage > 95% for 10 cycles then alert
51+
if memory usage > 75% for 5 cycles then alert
52+
if swap usage > 20% for 10 cycles then alert
53+
if loadavg (1min) > 90 for 15 cycles then alert
54+
if loadavg (5min) > 80 for 10 cycles then alert
55+
if loadavg (15min) > 70 for 8 cycles then alert
56+
57+
check program duplicity path "${pkgs.systemd}/bin/systemctl is-failed duplicity"
58+
if changed status then alert
59+
60+
check program bitcoind path "${checkStatus}/bin/checkStatus bitcoind"
61+
if changed status then alert
62+
63+
check program bitcoind-import-banlist path "${pkgs.systemd}/bin/systemctl is-failed bitcoind-import-banlist"
64+
if changed status then alert
65+
66+
${optionalString config.services.btcpayserver.enable ''
67+
check program nbxplorer path "${checkStatus}/bin/checkStatus nbxplorer"
68+
if changed status then alert
69+
''}
70+
71+
${optionalString config.services.btcpayserver.enable ''
72+
check program btcpayserver path "${checkStatus}/bin/checkStatus nbxplorer"
73+
if changed status then alert
74+
''}
75+
76+
${optionalString config.services.charge-lnd.enable ''
77+
check program charge-lnd path "${checkStatus}/bin/checkStatus charge-lnd"
78+
if changed status then alert
79+
''}
80+
81+
${optionalString config.services.clightning.enable ''
82+
check program clightning path "${checkStatus}/bin/checkStatus clightning"
83+
if changed status then alert
84+
''}
85+
86+
${optionalString config.services.electrs.enable ''
87+
check program electrs path "${checkStatus}/bin/checkStatus electrs"
88+
if changed status then alert
89+
''}
90+
91+
${optionalString config.services.joinmarket.enable ''
92+
check program joinmarket path "${checkStatus}/bin/checkStatus joinmarket"
93+
if changed status then alert
94+
''}
95+
96+
${optionalString config.services.joinmarket.yieldgenerator.enable ''
97+
check program joinmarket-yieldgenerator path "${checkStatus}/bin/checkStatus joinmarket-yieldgenerator"
98+
if changed status then alert
99+
''}
100+
101+
${optionalString config.services.joinmarket-ob-watcher.enable ''
102+
check program joinmarket-ob-watcher path "${checkStatus}/bin/checkStatus joinmarket-ob-watcher"
103+
if changed status then alert
104+
''}
105+
106+
${optionalString config.services.lightning-loop.enable ''
107+
check program lightning-loop path "${checkStatus}/bin/checkStatus lightning-loop"
108+
if changed status then alert
109+
''}
110+
111+
${optionalString config.services.lightning-pool.enable ''
112+
check program lightning-pool path "${checkStatus}/bin/checkStatus lightning-pool"
113+
if changed status then alert
114+
''}
115+
116+
${optionalString config.services.liquidd.enable ''
117+
check program liquidd path "${checkStatus}/bin/checkStatus liquidd"
118+
if changed status then alert
119+
''}
120+
121+
${optionalString config.services.lnd.enable ''
122+
check program lnd path "${checkStatus}/bin/checkStatus lnd"
123+
if changed status then alert
124+
''}
125+
126+
${optionalString config.services.clightning-rest.enable ''
127+
check program clightning-rest path "${checkStatus}/bin/checkStatus clightning-rest"
128+
if changed status then alert
129+
''}
130+
131+
${optionalString config.services.rtl.enable ''
132+
check program rtl path "${checkStatus}/bin/checkStatus rtl"
133+
if changed status then alert
134+
''}
135+
136+
${optionalString config.services.spark-wallet.enable ''
137+
check program spark-wallet path "${checkStatus}/bin/checkStatus spark-wallet"
138+
if changed status then alert
139+
''}
140+
'';
141+
142+
in {
143+
inherit options;
144+
145+
config = mkIf cfg.enable {
146+
environment.systemPackages = [ pkgs.monit ];
147+
148+
environment.etc.monitrc = {
149+
text = "${configFile}";
150+
mode = "0400";
151+
};
152+
153+
systemd.services.monit-nb = {
154+
description = "Pro-active monitoring utility for nix-bitcoin";
155+
after = [ "network.target" ];
156+
wantedBy = [ "multi-user.target" ];
157+
serviceConfig = {
158+
ExecStart = "${pkgs.monit}/bin/monit -I -c /etc/monitrc";
159+
ExecStop = "${pkgs.monit}/bin/monit -c /etc/monitrc quit";
160+
ExecReload = "${pkgs.monit}/bin/monit -c /etc/monitrc reload";
161+
KillMode = "process";
162+
Restart = "always";
163+
} // nbLib.allowLocalIPAddresses;
164+
restartTriggers = [ config.environment.etc.monitrc.source ];
165+
};
166+
167+
services.postfix.enable = true;
168+
services.dovecot2.enable = true;
169+
users.users.monitmail = {
170+
passwordFile = "${secretsDir}/monitmail-password";
171+
isNormalUser = true;
172+
};
173+
174+
nix-bitcoin.secrets.monitmail-password.user = "root";
175+
nix-bitcoin.generateSecretsCmds.monitmail = ''
176+
makePasswordSecret monitmail-password
177+
'';
178+
};
179+
}
180+

modules/nodeinfo.nix

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ let
3434
liquidd = mkInfo "";
3535
joinmarket-ob-watcher = mkInfo "";
3636
rtl = mkInfo "";
37+
monit-nb = mkInfo "";
3738
# Only add sshd when it has an onion service
3839
sshd = name: cfg: mkIfOnionPort "sshd" (onionPort: ''
3940
add_service("sshd", """set_onion_address(info, "sshd", ${onionPort})""")

modules/presets/enable-tor.nix

+1
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,6 @@ in {
4949
spark-wallet.enable = defaultTrue;
5050
joinmarket-ob-watcher.enable = defaultTrue;
5151
rtl.enable = defaultTrue;
52+
monit-nb.enable = defaultTrue;
5253
};
5354
}

test/tests.nix

+4-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ let
2323
nix-bitcoin.secretsDir = "/secrets";
2424
nix-bitcoin.generateSecrets = true;
2525
nix-bitcoin.operator.enable = true;
26-
environment.systemPackages = with pkgs; [ jq ];
26+
environment.systemPackages = with pkgs; [ jq mailutils ];
2727
}
2828
];
2929

@@ -116,6 +116,8 @@ let
116116

117117
tests.backups = cfg.backups.enable;
118118

119+
tests.monit-nb = cfg.monit-nb.enable;
120+
119121
# To test that unused secrets are made inaccessible by 'setup-secrets'
120122
systemd.services.setup-secrets.preStart = mkIfTest "security" ''
121123
install -D -o nobody -g nogroup -m777 <(:) /secrets/dummy
@@ -179,6 +181,7 @@ let
179181
services.joinmarket.enable = true;
180182
services.joinmarket-ob-watcher.enable = true;
181183
services.backups.enable = true;
184+
services.monit-nb.enable = true;
182185

183186
nix-bitcoin.nodeinfo.enable = true;
184187

test/tests.py

+11
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,17 @@ def _():
262262
info = json.loads(json_info)
263263
assert info["bitcoind"]["local_address"]
264264

265+
@test("monit-nb")
266+
def _():
267+
assert_running("monit-nb")
268+
machine.wait_until_succeeds(
269+
log_has_string("monit-nb", "Monit 5.29.0 started")
270+
)
271+
assert_matches(
272+
"runuser -u monitmail -- mail -H",
273+
"monit alert",
274+
)
275+
265276
@test("secure-node")
266277
def _():
267278
assert_running("onion-addresses")

0 commit comments

Comments
 (0)