Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Network Namespaces #187

Merged
merged 22 commits into from
Jul 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ env:
# CACHIX_SIGNING_KEY
- secure: "xXCFZ7g+k5YmCGm8R8l3bZElVmt+RD1KscG3kGr5w4HyyDPTzFetPo+sT8bUpysDU0u3HWhfVhHtpog2mhNhwVl3tQwKXea3dHKC1i6ypBg3gjDngmJRR5wo++ocYDpK8qPaU7m/jHQTNFnTA4CbmMcc05GcYx/1Ai/ZGkNwWFjdIcVeOUoiol33gykMOXIGDg2qlXudt33wP53FHbX8L4fxzodWfAuxKK4AoGprxy5eSnU7LCaXxxJmu4HwuV+Ux2U1NfE/E33cvhlUvTQCswVSZFG06mg8rwhMG1ozsDvlL2itZlu/BeUQH5y3XMMlnJIUXUazkRBibf1w/ebVjpOF+anqkqmq8tcbFEa7T+RJeVTIsvP+L8rE8fcmuZtdg9hNmgRnLmaeT0vVwD1L2UqW9HdRyujdoS0jPYuoc1W7f1JQWfAPhBPQ1SrtKyNNqcbVJ34aN7b+4vCzRpQL1JTbmjzQIWhkiKN1qMo1v/wbIydW8yka4hc4JOfdQLaAJEPI1eAC1MLotSAegMnwKWE1dzm66MuPSipksYjZrvsB28cV4aCVUffIuRhrSr1i2afRHwTpNbK9U4/576hah15ftUdR79Sfkcoi1ekSQTFGRvkRIPYtkKLYwFa3jVA41qz7+IIZCf4TsApy3XDdFx91cRub7yPq9BeZ83A+qYQ="
jobs:
- TestModules=1 STABLE=1
- TestModules=1 STABLE=1 SCENARIO=default
- TestModules=1 STABLE=1 SCENARIO=withnetns
- PKG=hwi STABLE=1
- PKG=hwi STABLE=0
- PKG=lightning-charge STABLE=1
Expand All @@ -38,7 +39,7 @@ script:
exit 1
fi
sudo chmod go+rw /dev/kvm
test/run-tests.sh exprForCI
test/run-tests.sh --scenario $SCENARIO exprForCI
else
echo "(import ./. {}).$PKG"
fi
Expand Down
18 changes: 15 additions & 3 deletions examples/configuration.nix
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,19 @@
# Enable this module to use clightning, a Lightning Network implementation
# in C.
services.clightning.enable = true;
# Enable this option to listen for incoming lightning connections. By
# default nix-bitcoin nodes offer outgoing connectivity.
# services.clightning.autolisten = true;
# Enable this option to announce our Tor Hidden Service. By default clightning
# offers outgoing functionality, but doesn't announce the Tor Hidden Service
# under which peers can reach us.
# services.clightning.announce-tor = true;

### LND
# Disable clightning and uncomment the following line in order to enable lnd,
# a lightning implementation written in Go.
# services.lnd.enable = true;
# Enable this option to announce our Tor Hidden Service. By default lnd
# offers outgoing functionality, but doesn't announce the Tor Hidden Service
# under which peers can reach us.
# services.lnd.announce-tor = true;
## WARNING
# If you use lnd, you should manually backup your wallet mnemonic
# seed. This will allow you to recover on-chain funds. You can run the
Expand Down Expand Up @@ -117,6 +122,13 @@
# `docs/usage.md`.
# services.hardware-wallets.trezor = true;

### netns-isolation (EXPERIMENTAL)
# Enable this module to use Network Namespace Isolation. This feature places
# every service in its own network namespace and only allows truly necessary
# connections between network namespaces, making sure services are isolated on
# a network-level as much as possible.
# nix-bitcoin.netns-isolation.enable = true;

# FIXME: Define your hostname.
networking.hostName = "nix-bitcoin";
time.timeZone = "UTC";
Expand Down
37 changes: 35 additions & 2 deletions modules/bitcoind.nix
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ let
${optionalString (cfg.assumevalid != null) "assumevalid=${cfg.assumevalid}"}

# Connection options
${optionalString cfg.listen "bind=${cfg.bind}"}
${optionalString (cfg.port != null) "port=${toString cfg.port}"}
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
listen=${if cfg.listen then "1" else "0"}
Expand All @@ -30,6 +31,8 @@ let
(rpcUser: "rpcauth=${rpcUser.name}:${rpcUser.passwordHMAC}")
(attrValues cfg.rpc.users)
}
${lib.concatMapStrings (rpcbind: "rpcbind=${rpcbind}\n") cfg.rpcbind}
${lib.concatMapStrings (rpcallowip: "rpcallowip=${rpcallowip}\n") cfg.rpcallowip}
${optionalString (cfg.rpcuser != null) "rpcuser=${cfg.rpcuser}"}
${optionalString (cfg.rpcpassword != null) "rpcpassword=${cfg.rpcpassword}"}

Expand Down Expand Up @@ -68,6 +71,13 @@ in {
default = "/var/lib/bitcoind";
description = "The data directory for bitcoind.";
};
bind = mkOption {
type = types.str;
default = "127.0.0.1";
description = ''
Bind to given address and always listen on it.
'';
};
user = mkOption {
type = types.str;
default = "bitcoin";
Expand Down Expand Up @@ -117,6 +127,20 @@ in {
'';
};
};
rpcbind = mkOption {
type = types.listOf types.str;
default = [ "127.0.0.1" ];
description = ''
Bind to given address to listen for JSON-RPC connections.
'';
};
rpcallowip = mkOption {
type = types.listOf types.str;
default = [ "127.0.0.1" ];
description = ''
Allow JSON-RPC connections from specified source.
'';
};
rpcuser = mkOption {
type = types.nullOr types.str;
default = "bitcoinrpc";
Expand Down Expand Up @@ -233,11 +257,20 @@ in {
};
cli = mkOption {
type = types.package;
default = cfg.cli-nonetns-exec;
description = "Binary to connect with the bitcoind instance.";
};
# Needed because bitcoind-import-banlist already executes inside
# nb-bitcoind, hence it doesn't need netns-exec prefixed.
cli-nonetns-exec = mkOption {
readOnly = true;
type = types.package;
default = pkgs.writeScriptBin "bitcoin-cli" ''
exec ${cfg.package}/bin/bitcoin-cli -datadir='${cfg.dataDir}' "$@"
'';
description = "Binary to connect with the bitcoind instance.";
description = ''
Binary to connect with the bitcoind instance without netns-exec.
'';
};
enforceTor = nix-bitcoin-services.enforceTor;
};
Expand Down Expand Up @@ -297,7 +330,7 @@ in {
bindsTo = [ "bitcoind.service" ];
after = [ "bitcoind.service" ];
script = ''
cd ${cfg.cli}/bin
cd ${cfg.cli-nonetns-exec}/bin
# Poll until bitcoind accepts commands. This can take a long time.
while ! ./bitcoin-cli getnetworkinfo &> /dev/null; do
sleep 1
Expand Down
28 changes: 18 additions & 10 deletions modules/clightning.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ with lib;
let
cfg = config.services.clightning;
inherit (config) nix-bitcoin-services;
onion-chef-service = (if cfg.announce-tor then [ "onion-chef.service" ] else []);
configFile = pkgs.writeText "config" ''
autolisten=${if cfg.autolisten then "true" else "false"}
network=bitcoin
bitcoin-datadir=${config.services.bitcoind.dataDir}
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
always-use-proxy=${if cfg.always-use-proxy then "true" else "false"}
${optionalString (cfg.bind-addr != null) "bind-addr=${cfg.bind-addr}"}
bitcoin-rpcuser=${cfg.bitcoin-rpcuser}
${optionalString (cfg.bitcoin-rpcconnect != null) "bitcoin-rpcconnect=${cfg.bitcoin-rpcconnect}"}
bitcoin-rpcuser=${config.services.bitcoind.rpcuser}
rpc-file-mode=0660
'';
in {
Expand All @@ -28,7 +29,8 @@ in {
type = types.bool;
default = false;
description = ''
If enabled, the clightning service will listen.
Bind (and maybe announce) on IPv4 and IPv6 interfaces if no addr,
bind-addr or announce-addr options are specified.
'';
};
proxy = mkOption {
Expand All @@ -48,11 +50,15 @@ in {
default = null;
description = "Set an IP address or UNIX domain socket to listen to";
};
bitcoin-rpcuser = mkOption {
type = types.str;
description = ''
Bitcoin RPC user
'';
announce-tor = mkOption {
type = types.bool;
default = false;
description = "Announce clightning Tor Hidden Service";
};
bitcoin-rpcconnect = mkOption {
type = types.nullOr types.str;
default = null;
description = "The bitcoind RPC host to connect to.";
};
dataDir = mkOption {
type = types.path;
Expand Down Expand Up @@ -93,19 +99,21 @@ in {
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
];

services.onion-chef.access.clightning = if cfg.announce-tor then [ "clightning" ] else [];
systemd.services.clightning = {
description = "Run clightningd";
path = [ pkgs.nix-bitcoin.bitcoind ];
wantedBy = [ "multi-user.target" ];
requires = [ "bitcoind.service" ];
after = [ "bitcoind.service" ];
requires = [ "bitcoind.service" ] ++ onion-chef-service;
after = [ "bitcoind.service" ] ++ onion-chef-service;
preStart = ''
cp ${configFile} ${cfg.dataDir}/config
chown -R '${cfg.user}:${cfg.group}' '${cfg.dataDir}'
# The RPC socket has to be removed otherwise we might have stale sockets
rm -f ${cfg.dataDir}/bitcoin/lightning-rpc
chmod 600 ${cfg.dataDir}/config
echo "bitcoin-rpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword)" >> '${cfg.dataDir}/config'
${optionalString cfg.announce-tor "echo announce-addr=$(cat /var/lib/onion-chef/clightning/clightning) >> '${cfg.dataDir}/config'"}
'';
serviceConfig = nix-bitcoin-services.defaultHardening // {
ExecStart = "${pkgs.nix-bitcoin.clightning}/bin/lightningd --lightning-dir=${cfg.dataDir}";
Expand Down
18 changes: 17 additions & 1 deletion modules/electrs.nix
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ in {
default = "/var/lib/electrs";
description = "The data directory for electrs.";
};
# Needed until electrs tls proxy is removed
host = mkOption {
type = types.str;
default = "localhost";
description = ''
The host on which incoming connections arrive.
'';
};
user = mkOption {
type = types.str;
default = "electrs";
Expand Down Expand Up @@ -44,6 +52,13 @@ in {
default = 50001;
description = "RPC port.";
};
daemonrpc = mkOption {
type = types.str;
default = "127.0.0.1:8332";
description = ''
Bitcoin daemon JSONRPC 'addr:port' to connect
'';
};
extraArgs = mkOption {
type = types.separatedString " ";
default = "";
Expand Down Expand Up @@ -97,7 +112,8 @@ in {
"--jsonrpc-import --index-batch-size=10"
} \
--db-dir '${cfg.dataDir}' --daemon-dir '${config.services.bitcoind.dataDir}' \
--electrum-rpc-addr=${toString cfg.address}:${toString cfg.port} ${cfg.extraArgs}
--electrum-rpc-addr=${toString cfg.address}:${toString cfg.port} \
--daemon-rpc-addr=${toString cfg.daemonrpc} ${cfg.extraArgs}
'';
User = cfg.user;
Group = cfg.group;
Expand Down
19 changes: 16 additions & 3 deletions modules/lightning-charge.nix
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ in {
default = "/var/lib/lightning-charge";
description = "The data directory for lightning-charge.";
};
host = mkOption {
type = types.str;
default = "127.0.0.1";
description = "http server listen address";
};
extraArgs = mkOption {
type = types.separatedString " ";
default = "";
description = "Extra command line arguments passed to lightning-charge.";
};
enforceTor = nix-bitcoin-services.enforceTor;
};

config = mkIf cfg.enable {
Expand Down Expand Up @@ -60,13 +71,15 @@ in {
# Needed to access clightning.dataDir in preStart
PermissionsStartOnly = "true";
EnvironmentFile = "${config.nix-bitcoin.secretsDir}/lightning-charge-env";
ExecStart = "${pkgs.nix-bitcoin.lightning-charge}/bin/charged -l ${config.services.clightning.dataDir}/bitcoin -d ${cfg.dataDir}/lightning-charge.db";
ExecStart = "${pkgs.nix-bitcoin.lightning-charge}/bin/charged -l ${config.services.clightning.dataDir}/bitcoin -d ${cfg.dataDir}/lightning-charge.db -i ${cfg.host} ${cfg.extraArgs}";
User = user;
Restart = "on-failure";
RestartSec = "10s";
ReadWritePaths = "${cfg.dataDir}";
} // nix-bitcoin-services.nodejs
// nix-bitcoin-services.allowTor;
} // (if cfg.enforceTor
then nix-bitcoin-services.allowTor
else nix-bitcoin-services.allowAnyIP)
// nix-bitcoin-services.nodejs;
};
nix-bitcoin.secrets.lightning-charge-env.user = user;
};
Expand Down
35 changes: 33 additions & 2 deletions modules/liquid.nix
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ let
${optionalString (cfg.validatepegin != null) "validatepegin=${if cfg.validatepegin then "1" else "0"}"}

# Connection options
${optionalString cfg.listen "bind=${cfg.bind}"}
${optionalString (cfg.port != null) "port=${toString cfg.port}"}
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
listen=${if cfg.listen then "1" else "0"}
Expand All @@ -25,8 +26,11 @@ let
(rpcUser: "rpcauth=${rpcUser.name}:${rpcUser.passwordHMAC}")
(attrValues cfg.rpc.users)
}
${lib.concatMapStrings (rpcbind: "rpcbind=${rpcbind}\n") cfg.rpcbind}
${lib.concatMapStrings (rpcallowip: "rpcallowip=${rpcallowip}\n") cfg.rpcallowip}
${optionalString (cfg.rpcuser != null) "rpcuser=${cfg.rpcuser}"}
${optionalString (cfg.rpcpassword != null) "rpcpassword=${cfg.rpcpassword}"}
${optionalString (cfg.mainchainrpchost != null) "mainchainrpchost=${cfg.mainchainrpchost}"}

# Extra config options (from liquidd nixos service)
${cfg.extraConfig}
Expand Down Expand Up @@ -80,6 +84,13 @@ in {
default = "/var/lib/liquidd";
description = "The data directory for liquidd.";
};
bind = mkOption {
type = types.str;
default = "127.0.0.1";
description = ''
Bind to given address and always listen on it.
'';
};

user = mkOption {
type = types.str;
Expand Down Expand Up @@ -111,6 +122,20 @@ in {
};
};

rpcbind = mkOption {
type = types.listOf types.str;
default = [ "127.0.0.1" ];
description = ''
Bind to given address to listen for JSON-RPC connections.
'';
};
rpcallowip = mkOption {
type = types.listOf types.str;
default = [ "127.0.0.1" ];
description = ''
Allow JSON-RPC connections from specified source.
'';
};
rpcuser = mkOption {
type = types.nullOr types.str;
default = null;
Expand All @@ -121,6 +146,14 @@ in {
default = null;
description = "Password for JSON-RPC connections";
};
mainchainrpchost = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
The address which the daemon will try to connect to the trusted
mainchain daemon to validate peg-ins.
'';
};

testnet = mkOption {
type = types.bool;
Expand Down Expand Up @@ -177,14 +210,12 @@ in {
'';
};
cli = mkOption {
readOnly = true;
default = pkgs.writeScriptBin "elements-cli" ''
exec ${pkgs.nix-bitcoin.elementsd}/bin/elements-cli -datadir='${cfg.dataDir}' "$@"
'';
description = "Binary to connect with the liquidd instance.";
};
swap-cli = mkOption {
readOnly = true;
default = pkgs.writeScriptBin "liquidswap-cli" ''
exec ${pkgs.nix-bitcoin.liquid-swap}/bin/liquidswap-cli -c '${cfg.dataDir}/elements.conf' "$@"
'';
Expand Down
Loading