Compare commits
108 Commits
master
...
moneta-ove
Author | SHA1 | Date | |
---|---|---|---|
|
ed567d67f2 | ||
|
9538c63a76 | ||
|
479e21a122 | ||
|
475af2d6cb | ||
|
addfa8ec6b | ||
|
ae733d887e | ||
|
6cbd0d93ae | ||
|
85310b533a | ||
|
bc2f66d4f1 | ||
|
519ae31202 | ||
|
a1023696e6 | ||
|
34fe8675bd | ||
|
a3bdecb10b | ||
|
397d2bab9b | ||
|
0e4af28df0 | ||
|
6291d4fbea | ||
|
690a8f6256 | ||
|
2af642f56a | ||
|
56c2abd91a | ||
|
86dc7e2669 | ||
|
c948af2e18 | ||
|
5634f08873 | ||
|
b76728a1ec | ||
|
84fc4d48d3 | ||
|
b4d7e1aa8f | ||
|
b35d08d3f2 | ||
|
4d76eb9183 | ||
|
dc0710f3f4 | ||
|
dfeff7b17b | ||
|
9019a17bfc | ||
|
aae4b6bfc5 | ||
|
9e30d2728b | ||
|
c6d85c6fe3 | ||
|
a51f7b419e | ||
|
da612fe84f | ||
|
4b5b4eac58 | ||
|
8d476cfeaf | ||
|
700b6d8c90 | ||
|
1b4c5749f6 | ||
|
a6ab131e7d | ||
|
314020b246 | ||
|
00cceca861 | ||
|
e4b8e14d3a | ||
|
d1ef2a6e1e | ||
|
74c8593407 | ||
|
109dccca27 | ||
|
a9c1995ed9 | ||
|
9e456ea3a9 | ||
|
77d58162e7 | ||
|
142cbcfb37 | ||
|
c9b1e59f20 | ||
|
62515a5696 | ||
|
932e4c93bc | ||
|
84382e3338 | ||
|
d1b3a4617d | ||
|
81166a012e | ||
|
875fac6862 | ||
|
5cafafd027 | ||
|
d9fdc49e9a | ||
|
8b091eb661 | ||
|
c5493717b7 | ||
|
81350a03c9 | ||
|
4a533d90ea | ||
|
1800ed7cb3 | ||
|
a333989ca8 | ||
|
313e374774 | ||
|
0447c5bacb | ||
|
0de16095e1 | ||
|
d332177d3e | ||
|
1b5e51b7fe | ||
|
565deb770a | ||
|
a576fa3afe | ||
|
edbaeb9813 | ||
|
90e942e5ae | ||
|
8eaa4cce30 | ||
|
47a09ec214 | ||
|
b0dfa69e84 | ||
|
d428755399 | ||
|
a12b701e75 | ||
|
450de19803 | ||
|
5f1bb2a8fc | ||
|
a87a59a86b | ||
|
b616d7ac1b | ||
|
73d2fbb448 | ||
|
3c816b862c | ||
|
1d3f49f8da | ||
|
b840548d40 | ||
|
dcca4fb262 | ||
|
b412de3ad7 | ||
|
a174dc8093 | ||
|
57b76d4461 | ||
|
7c16fc5865 | ||
|
a7357c1176 | ||
|
67949a002a | ||
|
49303be2e0 | ||
|
46f17fe313 | ||
|
277510c7ee | ||
|
9d074e1985 | ||
|
c88acbb1bb | ||
|
13a835e88f | ||
|
3549725b51 | ||
|
61c539d5b6 | ||
|
9fc05e384c | ||
|
cf836b5d3b | ||
|
d3b7e8c432 | ||
|
34f6eb90d7 | ||
|
261f7a043f | ||
|
09c765368f |
@ -9,7 +9,7 @@ task:
|
|||||||
|
|
||||||
container:
|
container:
|
||||||
# Defined in https://github.com/nix-community/docker-nixpkgs
|
# Defined in https://github.com/nix-community/docker-nixpkgs
|
||||||
image: nixpkgs/nix-flakes:nixos-22.05
|
image: nixpkgs/nix-flakes:nixos-22.11
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
- name: modules_test
|
- name: modules_test
|
||||||
@ -30,11 +30,12 @@ task:
|
|||||||
# This script is run as root
|
# This script is run as root
|
||||||
build_script:
|
build_script:
|
||||||
- echo "sandbox = true" >> /etc/nix/nix.conf
|
- echo "sandbox = true" >> /etc/nix/nix.conf
|
||||||
- nix shell --inputs-from . nixpkgs#{bash,coreutils,gawk,cachix} -c ./test/ci/build.sh
|
- nix shell --inputs-from . nixpkgs#{bash,coreutils,cachix} -c ./test/ci/build.sh $scenario
|
||||||
|
|
||||||
- name: flake
|
- name: flake
|
||||||
build_script:
|
build_script:
|
||||||
- nix flake check
|
- nix flake check
|
||||||
|
- ./test/nixos-search/ci-test.sh
|
||||||
|
|
||||||
- name: shellcheck
|
- name: shellcheck
|
||||||
build_script:
|
build_script:
|
||||||
|
@ -53,6 +53,8 @@ Hint: To show a table of contents, click the button (![Github TOC button](docs/i
|
|||||||
top left corner of the documents.
|
top left corner of the documents.
|
||||||
|
|
||||||
<!-- TODO-EXTERNAL: -->
|
<!-- TODO-EXTERNAL: -->
|
||||||
|
<!-- Change query to `nix-bitcoin` when upstream search has been fixed -->
|
||||||
|
* [NixOS options search](https://search.nixos.org/flakes?channel=unstable&sort=relevance&type=options&query=bitcoin)
|
||||||
* [Hardware requirements](docs/hardware.md)
|
* [Hardware requirements](docs/hardware.md)
|
||||||
* [Installation](docs/install.md)
|
* [Installation](docs/install.md)
|
||||||
* [Configuration and maintenance](docs/configuration.md)
|
* [Configuration and maintenance](docs/configuration.md)
|
||||||
@ -118,6 +120,10 @@ The nix-bitcoin security fund is a 2 of 3 bitcoin multisig address open for dona
|
|||||||
security researchers who discover vulnerabilities in nix-bitcoin or its upstream dependencies.\
|
security researchers who discover vulnerabilities in nix-bitcoin or its upstream dependencies.\
|
||||||
See [Security Fund](./SECURITY.md#nix-bitcoin-security-fund) for details.
|
See [Security Fund](./SECURITY.md#nix-bitcoin-security-fund) for details.
|
||||||
|
|
||||||
|
Developing
|
||||||
|
---
|
||||||
|
See [dev/README](./dev/README.md).
|
||||||
|
|
||||||
Troubleshooting
|
Troubleshooting
|
||||||
---
|
---
|
||||||
If you are having problems with nix-bitcoin check the [FAQ](docs/faq.md) or submit an issue.\
|
If you are having problems with nix-bitcoin check the [FAQ](docs/faq.md) or submit an issue.\
|
||||||
|
104
dev/README.md
Normal file
104
dev/README.md
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
This directory contains docs and helper scripts for developing and debugging:
|
||||||
|
|
||||||
|
- [`dev.sh`](./dev.sh): misc dev helpers
|
||||||
|
- [`dev-features.sh`](./dev-features.sh): helpers for developing specific
|
||||||
|
nix-bitcoin features, like services
|
||||||
|
- [`topics`](./topics) features specific topics
|
||||||
|
- [`dev-scenarios.nix`](./dev-scenarios.nix): extra test scenarios used in the above scripts
|
||||||
|
|
||||||
|
See also: [test/README.md](../test/README.md)
|
||||||
|
|
||||||
|
## Run a dev shell
|
||||||
|
|
||||||
|
There are two ways to run a dev shell:
|
||||||
|
|
||||||
|
### 1. Run command `nix develop`
|
||||||
|
|
||||||
|
This starts a shell with [`test/run-tests.sh`](../test/run-tests.sh) and
|
||||||
|
the scripts in dir [`helper`](../helper) added to `PATH`.
|
||||||
|
|
||||||
|
### 2. Setup and start the `direnv` dev env
|
||||||
|
|
||||||
|
This is an opinionated, [direnv](https://direnv.net/)-based dev env, optimized for developer experience.
|
||||||
|
|
||||||
|
[`dev-env/create.sh`](./dev-env/create.sh) creates a git repo with the following contents:
|
||||||
|
- Dir `src` which contains the nix-bitcoin repo
|
||||||
|
- Dir `bin` for helper scripts
|
||||||
|
- File `scenarios.nix` for custom test scenarios
|
||||||
|
- File `.envrc` that defines a [direnv](https://direnv.net/) environment,
|
||||||
|
mainly for adding nix-bitcoin and helper scripts to `PATH`
|
||||||
|
|
||||||
|
#### Installation
|
||||||
|
|
||||||
|
1. [Install direnv](https://direnv.net/docs/installation.html).\
|
||||||
|
If you use NixOS (and Bash as the default shell), just add the following to your system config:
|
||||||
|
```nix
|
||||||
|
environment.systemPackages = [ pkgs.direnv ];
|
||||||
|
programs.bash.interactiveShellInit = ''
|
||||||
|
eval "$(direnv hook bash)"
|
||||||
|
'';
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Create the dev env:
|
||||||
|
```bash
|
||||||
|
# Set up a dev environment in dir ~/dev/nix-bitcoin.
|
||||||
|
# The dir is created automatically.
|
||||||
|
./dev-env/create.sh ~/dev/nix-bitcoin
|
||||||
|
|
||||||
|
cd ~/dev/nix-bitcoin
|
||||||
|
|
||||||
|
# Enable direnv
|
||||||
|
direnv allow
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Optional: Editor integration
|
||||||
|
- Add envrc support to your editor
|
||||||
|
- Setup your editor so you can easily execute lines or paragraphs from a shell script
|
||||||
|
file in a shell.\
|
||||||
|
This simplifies using dev helper scripts like [`./dev.sh`](./dev.sh).
|
||||||
|
|
||||||
|
#### Explore the dev env
|
||||||
|
```bash
|
||||||
|
# The direnv is automatically activated when visiting any subdir of ~/dev/nix-bitcoin
|
||||||
|
cd ~/dev/nix-bitcoin
|
||||||
|
|
||||||
|
ls -al . bin lib
|
||||||
|
|
||||||
|
# The direnv config file
|
||||||
|
cat .envrc
|
||||||
|
|
||||||
|
# You can use this file to define extra scenarios
|
||||||
|
cat scenarios.nix
|
||||||
|
|
||||||
|
# Binary `dev-run-tests` runs nix-bitcoin's `run-tests.sh` with extra scenarios from ./scenarios.nix
|
||||||
|
# Example:
|
||||||
|
# Run command `nodeinfo` in `myscenario` (defined in ./scenarios.nix) via a container
|
||||||
|
dev-run-tests -s myscenario container --run c nodeinfo
|
||||||
|
|
||||||
|
# Equivalent (shorthand)
|
||||||
|
te -s myscenario container --run c nodeinfo
|
||||||
|
|
||||||
|
# Run the tests for `myscenario` in a VM
|
||||||
|
te -s myscenario
|
||||||
|
|
||||||
|
# Start an interactive shell inside a VM
|
||||||
|
te -s myscenario vm
|
||||||
|
```
|
||||||
|
|
||||||
|
See also: [test/README.md](../test/README.md)
|
||||||
|
|
||||||
|
## Adding a new service
|
||||||
|
|
||||||
|
It's easiest to use an existing service as a template:
|
||||||
|
- [electrs.nix](../modules/electrs.nix): a basic service
|
||||||
|
- [clightning.nix](../modules/clightning.nix): simple, but covers a few more features.\
|
||||||
|
(A `cli` binary and a runtime-composed config to include secrets.)
|
||||||
|
- [rtl.nix](../modules/rtl.nix): includes a custom package, defined in [pkgs/rtl](../pkgs/rtl).\
|
||||||
|
Most other services use packages that are already included in nixpkgs.
|
||||||
|
|
||||||
|
## Switching to a new NixOS release
|
||||||
|
|
||||||
|
- [flake.nix](../flake.nix): update `nixpkgs.url`
|
||||||
|
- [cirrus.yml](../.cirrus.yml): update toplevel container -> image attribute
|
||||||
|
- [examples/configuration.nix](../examples/configuration.nix): update `system.stateVersion`
|
||||||
|
- Treewide: check if any `TODO-EXTERNAL` comments can be resolved
|
65
dev/dev-env/create.sh
Executable file
65
dev/dev-env/create.sh
Executable file
@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
destDir=${1:-nix-bitcoin}
|
||||||
|
|
||||||
|
scriptDir=$(cd "${BASH_SOURCE[0]%/*}" && pwd)
|
||||||
|
|
||||||
|
mkdir -p "$destDir/"{bin,lib}
|
||||||
|
cd "$destDir"
|
||||||
|
|
||||||
|
if [[ ! -e src ]]; then
|
||||||
|
echo "Cloning fort-nix/nix-bitcoin"
|
||||||
|
git clone https://github.com/fort-nix/nix-bitcoin src
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo 'export root=$PWD
|
||||||
|
export src=$root/src
|
||||||
|
PATH_add bin
|
||||||
|
PATH_add src/helper' > .envrc
|
||||||
|
|
||||||
|
if [[ ! -e scenarios.nix ]]; then
|
||||||
|
cp "$scriptDir/template-scenarios.nix" scenarios.nix
|
||||||
|
fi
|
||||||
|
|
||||||
|
install -m 755 <(
|
||||||
|
echo '#!/usr/bin/env bash'
|
||||||
|
echo 'exec run-tests.sh --extra-scenarios "$root/scenarios.nix" "$@"'
|
||||||
|
) bin/dev-run-tests
|
||||||
|
|
||||||
|
install -m 755 <(
|
||||||
|
echo '#!/usr/bin/env bash'
|
||||||
|
echo 'exec $root/src/test/run-tests.sh --out-link-prefix /tmp/nix-bitcoin/test "$@"'
|
||||||
|
) bin/run-tests.sh
|
||||||
|
|
||||||
|
ln -sfn dev-run-tests bin/te
|
||||||
|
|
||||||
|
## nix-bitcoin-firejail
|
||||||
|
|
||||||
|
echo '# Add your shell config files here that should be accessible in the sandbox
|
||||||
|
whitelist ${HOME}/.bashrc
|
||||||
|
read-only ${HOME}/.bashrc' > lib/nix-bitcoin-firejail.conf
|
||||||
|
|
||||||
|
install -m 755 <(
|
||||||
|
echo '#!/usr/bin/env bash'
|
||||||
|
echo '# A sandbox for running shells/binaries in an isolated environment:'
|
||||||
|
echo '# - The sandbox user is the calling user, with all capabilities dropped'
|
||||||
|
echo '# and with no way to gain new privileges (e.g. via `sudo`).'
|
||||||
|
echo '# - $HOME is bind-mounted to a dir that only contains shell config files and files required by direnv.'
|
||||||
|
echo '#'
|
||||||
|
echo '# You can modify the firejail env by editing `lib/nix-bitcoin-firejail.conf` in your dev env dir.'
|
||||||
|
echo 'exec firejail --profile="$root/lib/nix-bitcoin-firejail.conf" --profile="$root/src/dev/dev-env/nix-bitcoin-firejail.conf" "$@"'
|
||||||
|
) bin/nix-bitcoin-firejail
|
||||||
|
|
||||||
|
echo "1" > lib/dev-env-version
|
||||||
|
|
||||||
|
## git
|
||||||
|
|
||||||
|
echo '/src' > .gitignore
|
||||||
|
|
||||||
|
if [[ ! -e .git ]]; then
|
||||||
|
git init
|
||||||
|
git add .
|
||||||
|
git commit -a -m init
|
||||||
|
fi
|
16
dev/dev-env/dev-shell.nix
Normal file
16
dev/dev-env/dev-shell.nix
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
pkgs:
|
||||||
|
|
||||||
|
pkgs.mkShell {
|
||||||
|
shellHook = ''
|
||||||
|
# A known rev from the master branch to test whether `nix develop`
|
||||||
|
# is called inside the nix-bitcoin repo
|
||||||
|
rev=5cafafd02777919c10e559b5686237fdefe920c2
|
||||||
|
if git cat-file -e $rev &>/dev/null; then
|
||||||
|
root=$(git rev-parse --show-toplevel)
|
||||||
|
export PATH=$root/test:$root/helper:$PATH
|
||||||
|
else
|
||||||
|
echo 'Error: `nix develop` must be called inside the nix-bitcoin repo.'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
}
|
25
dev/dev-env/nix-bitcoin-firejail.conf
Normal file
25
dev/dev-env/nix-bitcoin-firejail.conf
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
include default.local
|
||||||
|
include globals.local
|
||||||
|
|
||||||
|
include disable-common.inc
|
||||||
|
include disable-programs.inc
|
||||||
|
|
||||||
|
caps.drop all
|
||||||
|
netfilter
|
||||||
|
noinput
|
||||||
|
nonewprivs
|
||||||
|
noroot
|
||||||
|
notv
|
||||||
|
novideo
|
||||||
|
protocol unix,inet,inet6
|
||||||
|
seccomp
|
||||||
|
|
||||||
|
## Enable features
|
||||||
|
|
||||||
|
allow-debuggers
|
||||||
|
|
||||||
|
# Enable direnv configs
|
||||||
|
whitelist ${HOME}/.config/direnv
|
||||||
|
read-only ${HOME}/.config/direnv
|
||||||
|
whitelist ${HOME}/.local/share/direnv
|
||||||
|
read-only ${HOME}/.local/share/direnv
|
20
dev/dev-env/template-scenarios.nix
Normal file
20
dev/dev-env/template-scenarios.nix
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{ pkgs, lib, scenarios, nix-bitcoin }:
|
||||||
|
with lib;
|
||||||
|
rec {
|
||||||
|
# For more examples, see `scenarios` and `exampleScenarios` in ./src/test/tests.nix
|
||||||
|
|
||||||
|
template = { config, pkgs, lib, ... }: {
|
||||||
|
imports = [
|
||||||
|
(nix-bitcoin + "/modules/presets/secure-node.nix")
|
||||||
|
scenarios.netnsBase
|
||||||
|
scenarios.regtestBase
|
||||||
|
];
|
||||||
|
test.container.enableWAN = true;
|
||||||
|
test.container.exposeLocalhost = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
myscenario = { config, pkgs, lib, ... }: {
|
||||||
|
services.clightning.enable = true;
|
||||||
|
nix-bitcoin.nodeinfo.enable = true;
|
||||||
|
};
|
||||||
|
}
|
299
dev/dev-features.sh
Normal file
299
dev/dev-features.sh
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
# shellcheck disable=SC2086,SC2154
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# Run tests
|
||||||
|
# See ../test/README.md for a tutorial
|
||||||
|
# and ../test/run-tests.sh for a complete documentation
|
||||||
|
|
||||||
|
# Start a shell in a container
|
||||||
|
run-tests.sh -s electrs container
|
||||||
|
|
||||||
|
# Run a command in a container.
|
||||||
|
# The container is deleted afterwards.
|
||||||
|
run-tests.sh -s electrs container --run c journalctl -u electrs
|
||||||
|
|
||||||
|
# Run a bash command
|
||||||
|
run-tests.sh -s bitcoind container --run c bash -c "sleep 1; journalctl -u bitcoind"
|
||||||
|
|
||||||
|
run-tests.sh -s '{
|
||||||
|
imports = [ scenarios.regtestBase ];
|
||||||
|
services.electrs.enable = true;
|
||||||
|
}' container --run c journalctl -u electrs
|
||||||
|
|
||||||
|
run-tests.sh -s "{
|
||||||
|
services.electrs.enable = true;
|
||||||
|
nix-bitcoin.nodeinfo.enable = true;
|
||||||
|
}" container --run c nodeinfo
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# Get generic node infos
|
||||||
|
|
||||||
|
# Start container shell
|
||||||
|
run-tests.sh -s bitcoind container
|
||||||
|
|
||||||
|
# Run commands inside the shell:
|
||||||
|
|
||||||
|
# The node's services
|
||||||
|
c systemctl status
|
||||||
|
|
||||||
|
# Failed units
|
||||||
|
c systemctl list-units --failed
|
||||||
|
|
||||||
|
# Analyze container boot performance
|
||||||
|
c systemd-analyze critical-chain
|
||||||
|
|
||||||
|
# Listening TCP sockets
|
||||||
|
c netstat -nltp
|
||||||
|
# Listening sockets
|
||||||
|
c netstat -nlp
|
||||||
|
|
||||||
|
# The container root filesystem
|
||||||
|
ls -al /var/lib/nixos-containers/nb-test
|
||||||
|
|
||||||
|
# The container root filesystem on NixOS systems with stateVersion < 22.05
|
||||||
|
ls -al /var/lib/containers/nb-test
|
||||||
|
|
||||||
|
# Start a shell in the context of a service process.
|
||||||
|
# Must be run inside the container (enter with cmd `c`).
|
||||||
|
enter_service() {
|
||||||
|
local name=$1
|
||||||
|
nsenter --all -t "$(systemctl show -p MainPID --value "$name")" \
|
||||||
|
--setuid "$(id -u "$name")" --setgid "$(id -g "$name")" bash
|
||||||
|
}
|
||||||
|
enter_service clightning
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# bitcoind
|
||||||
|
run-tests.sh -s bitcoind container
|
||||||
|
|
||||||
|
c systemctl status bitcoind
|
||||||
|
c systemctl cat bitcoind
|
||||||
|
c journalctl --output=short-precise -u bitcoind
|
||||||
|
ls -al /var/lib/nixos-containers/nb-test/var/lib/bitcoind
|
||||||
|
c bitcoin-cli getpeerinfo
|
||||||
|
c bitcoin-cli getnetworkinfo
|
||||||
|
c bitcoin-cli getblockchaininfo
|
||||||
|
|
||||||
|
run-tests.sh -s '{
|
||||||
|
imports = [ scenarios.regtestBase ];
|
||||||
|
services.bitcoind.enable = true;
|
||||||
|
}' container
|
||||||
|
|
||||||
|
address=$(c bitcoin-cli getnewaddress)
|
||||||
|
echo $address
|
||||||
|
c bitcoin-cli generatetoaddress 10 $address
|
||||||
|
|
||||||
|
# Run bitcoind with network access
|
||||||
|
run-tests.sh -s "{
|
||||||
|
test.container.enableWAN = true;
|
||||||
|
services.bitcoind.enable = true;
|
||||||
|
}" container --run c journalctl -u bitcoind -f
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# clightning
|
||||||
|
run-tests.sh -s clightning container
|
||||||
|
|
||||||
|
c systemctl status clightning
|
||||||
|
c journalctl --output=short-precise -u clightning
|
||||||
|
c lightning-cli getinfo
|
||||||
|
|
||||||
|
# Plugins
|
||||||
|
run-tests.sh -s "{
|
||||||
|
services.clightning.enable = true;
|
||||||
|
test.features.clightningPlugins = true;
|
||||||
|
}" container
|
||||||
|
|
||||||
|
c lightning-cli plugin list
|
||||||
|
|
||||||
|
# Show plugin config
|
||||||
|
nix eval --raw .#makeTest --apply '
|
||||||
|
makeTest: let
|
||||||
|
config = (makeTest {
|
||||||
|
config = {
|
||||||
|
services.clightning.enable = true;
|
||||||
|
test.features.clightningPlugins = true;
|
||||||
|
};
|
||||||
|
}).nodes.machine;
|
||||||
|
in
|
||||||
|
config.services.clightning.extraConfig
|
||||||
|
'
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# clightning-rest
|
||||||
|
run-tests.sh -s clightning-rest container
|
||||||
|
|
||||||
|
c systemctl status clightning-rest
|
||||||
|
c journalctl -u clightning-rest
|
||||||
|
c systemctl status clightning-rest-migrate-datadir
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# spark-wallet
|
||||||
|
|
||||||
|
run-tests.sh -s "{
|
||||||
|
services.spark-wallet.enable = true;
|
||||||
|
test.container.exposeLocalhost = true;
|
||||||
|
}" container
|
||||||
|
|
||||||
|
c systemctl status spark-wallet
|
||||||
|
c journalctl -u spark-wallet
|
||||||
|
|
||||||
|
sparkAuth=$(c cat /secrets/spark-wallet-login | grep -ohP '(?<=login=).*')
|
||||||
|
curl -v http://$sparkAuth@$ip:9737
|
||||||
|
# Open in browser
|
||||||
|
runuser -u "$(logname)" -- xdg-open http://$sparkAuth@$ip:9737
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# electrs
|
||||||
|
|
||||||
|
run-tests.sh -s "{
|
||||||
|
imports = [ scenarios.regtestBase ];
|
||||||
|
services.electrs.enable = true;
|
||||||
|
}" container
|
||||||
|
|
||||||
|
c systemctl status electrs
|
||||||
|
c systemctl cat electrs
|
||||||
|
c journalctl --output=short-precise -u electrs
|
||||||
|
|
||||||
|
electrs_rpc() {
|
||||||
|
echo "$1" | c nc 127.0.0.1 50001 | head -1 | jq
|
||||||
|
}
|
||||||
|
electrs_rpc '{"method": "server.version", "id": 0, "params": ["electrum/3.3.8", "1.4"]}'
|
||||||
|
electrs_rpc '{"method": "blockchain.headers.subscribe", "id": 0}'
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# fulcrum
|
||||||
|
|
||||||
|
run-tests.sh -s "{
|
||||||
|
imports = [ scenarios.regtestBase ];
|
||||||
|
services.fulcrum.enable = true;
|
||||||
|
}" container
|
||||||
|
|
||||||
|
c systemctl status fulcrum
|
||||||
|
c systemctl cat fulcrum
|
||||||
|
c journalctl --output=short-precise -u fulcrum
|
||||||
|
|
||||||
|
fulcrum_rpc() {
|
||||||
|
echo "$1" | c nc 127.0.0.1 50002 | head -1 | jq
|
||||||
|
}
|
||||||
|
fulcrum_rpc '{"method": "server.version", "id": 0, "params": ["electrum/3.3.8", "1.4"]}'
|
||||||
|
fulcrum_rpc '{"method": "blockchain.headers.subscribe", "id": 0}'
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# lnd
|
||||||
|
run-tests.sh -s lnd container
|
||||||
|
c systemctl status lnd
|
||||||
|
c journalctl -u lnd
|
||||||
|
c lncli getinfo
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# lightning-loop
|
||||||
|
run-tests.sh -s lightning-loop container
|
||||||
|
c systemctl status lightning-loop
|
||||||
|
c journalctl -u lightning-loop
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# btcpayserver
|
||||||
|
# https://docs.btcpayserver.org/Development/GreenFieldExample/
|
||||||
|
|
||||||
|
run-tests.sh -s btcpayserver-regtest container
|
||||||
|
|
||||||
|
c systemctl status btcpayserver
|
||||||
|
c journalctl -u btcpayserver
|
||||||
|
c systemctl cat btcpayserver
|
||||||
|
|
||||||
|
c systemctl status nbxplorer
|
||||||
|
c journalctl -u nbxplorer
|
||||||
|
|
||||||
|
## Access the API
|
||||||
|
request() {
|
||||||
|
local type=$1
|
||||||
|
local method=$2
|
||||||
|
local body=$3
|
||||||
|
shift; shift; shift
|
||||||
|
curl -sSL -H "Content-Type: application/json" -X $type --user "a@a.a:aaaaaa" \
|
||||||
|
-d "$body" "$@" "$ip:23000/api/v1/$method" | jq
|
||||||
|
}
|
||||||
|
post() {
|
||||||
|
local method=$1
|
||||||
|
local body=$2
|
||||||
|
shift; shift
|
||||||
|
request post "$method" "$body" "$@"
|
||||||
|
}
|
||||||
|
get() {
|
||||||
|
local method=$1
|
||||||
|
request get "$method"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create new user
|
||||||
|
post users '{"email": "a@a.a", "password": "aaaaaa", "isAdministrator": true}'
|
||||||
|
|
||||||
|
# Login with:
|
||||||
|
# user: a@a.a
|
||||||
|
# password: aaaaaa
|
||||||
|
runuser -u "$(logname)" -- xdg-open http://$ip:23000
|
||||||
|
|
||||||
|
# create store
|
||||||
|
post stores '{"name": "a", "defaultPaymentMethod": "BTC_LightningNetwork"}'
|
||||||
|
post stores '{"name": "a", "defaultPaymentMethod": "BTC"}'
|
||||||
|
|
||||||
|
store=$(get stores | jq -r .[].id)
|
||||||
|
echo $store
|
||||||
|
get stores/$store
|
||||||
|
get stores/$store/payment-methods
|
||||||
|
get stores/$store/payment-methods/LightningNetwork
|
||||||
|
|
||||||
|
# Connect to internal lightning node (internal API, doesn't work)
|
||||||
|
# Lightning must be manually setup via the webinterface.
|
||||||
|
post stores/$store/lightning/BTC/setup "" --data-raw 'LightningNodeType=Internal&ConnectionString=&command=save'
|
||||||
|
|
||||||
|
nix run --inputs-from . nixpkgs#lynx -- --dump http://$ip:23000/embed/$store/BTC/ln
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# liquid
|
||||||
|
run-tests.sh -s liquid container
|
||||||
|
|
||||||
|
c systemctl status liquidd
|
||||||
|
c elements-cli getpeerinfo
|
||||||
|
c elements-cli getnetworkinfo
|
||||||
|
c liquidswap-cli --help
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# tor
|
||||||
|
run-tests.sh container
|
||||||
|
|
||||||
|
c cat /var/lib/tor/state
|
||||||
|
c ls -al /var/lib/tor/onion/
|
||||||
|
c ls -al /var/lib/tor/onion/bitcoind
|
||||||
|
c ls -al /var/lib/tor/onion/clightning-rest
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# joinmarket
|
||||||
|
run-tests.sh -s joinmarket container
|
||||||
|
|
||||||
|
c systemctl status joinmarket
|
||||||
|
c journalctl -u joinmarket
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# joinmarket-ob-watcher
|
||||||
|
|
||||||
|
# This starts a container with WAN access, so that jm-ob-watcher
|
||||||
|
# can connect to the joinmarket IRC servers over Tor
|
||||||
|
run-tests.sh -s jm-ob-watcher container
|
||||||
|
|
||||||
|
c systemctl status joinmarket-ob-watcher
|
||||||
|
c journalctl -u joinmarket-ob-watcher
|
||||||
|
|
||||||
|
# Manually wait for string 'started http server, visit http://127.0.0.1:62601/'
|
||||||
|
# This can take >10 minutes when the Tor network is under heavy load.
|
||||||
|
# While connecting, errors like `We failed to connect and handshake with ANY directories...`
|
||||||
|
# may be shown.
|
||||||
|
c journalctl -f -u joinmarket-ob-watcher
|
||||||
|
|
||||||
|
# Check webinterface
|
||||||
|
c curl localhost:62601
|
||||||
|
nix run --inputs-from . nixpkgs#lynx -- --dump $ip:62601
|
||||||
|
c curl -s localhost:62601 | grep -i "orders found"
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# rtl
|
||||||
|
# see ./topics/rtl.sh
|
45
dev/dev-scenarios.nix
Normal file
45
dev/dev-scenarios.nix
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Extra scenarios for developing and debugging
|
||||||
|
|
||||||
|
{ lib, scenarios }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
{
|
||||||
|
btcpayserver-regtest = {
|
||||||
|
imports = [ scenarios.regtestBase ];
|
||||||
|
services.btcpayserver.enable = true;
|
||||||
|
test.container.exposeLocalhost = true;
|
||||||
|
# services.btcpayserver.lbtc = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
# A node with internet access to test joinmarket-ob-watcher
|
||||||
|
jm-ob-watcher = {
|
||||||
|
services.joinmarket-ob-watcher.enable = true;
|
||||||
|
# Don't download blocks
|
||||||
|
services.bitcoind.extraConfig = ''
|
||||||
|
connect = 0;
|
||||||
|
'';
|
||||||
|
test.container.exposeLocalhost = true;
|
||||||
|
test.container.enableWAN = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
rtl-dev = { config, pkgs, lib, ... }: {
|
||||||
|
imports = [
|
||||||
|
# scenarios.netnsBase
|
||||||
|
# scenarios.regtestBase
|
||||||
|
];
|
||||||
|
services.rtl = {
|
||||||
|
enable = true;
|
||||||
|
nodes.clightning = {
|
||||||
|
enable = true;
|
||||||
|
extraConfig.Settings.themeColor = "INDIGO";
|
||||||
|
};
|
||||||
|
# nodes.lnd.enable = false;
|
||||||
|
# services.rtl.nodes.reverseOrder = true;
|
||||||
|
nightTheme = true;
|
||||||
|
extraCurrency = "CHF";
|
||||||
|
};
|
||||||
|
test.container.exposeLocalhost = true;
|
||||||
|
nix-bitcoin.nodeinfo.enable = true;
|
||||||
|
# test.container.enableWAN = true;
|
||||||
|
};
|
||||||
|
}
|
128
dev/dev.sh
Normal file
128
dev/dev.sh
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# Access nix-bitcoin flake packages
|
||||||
|
|
||||||
|
function nb() {
|
||||||
|
nix build --no-link --print-out-paths --print-build-logs "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# A package defined by nix-bitcoin
|
||||||
|
nb .#joinmarket
|
||||||
|
# Equivalent
|
||||||
|
nb .#modulesPkgs.joinmarket
|
||||||
|
|
||||||
|
# A nix-bitcoin python package
|
||||||
|
nb .#nbPython3Packages.pyln-client
|
||||||
|
|
||||||
|
# A pinned package from nixpkgs(-unstable)
|
||||||
|
nb .#pinned.electrs
|
||||||
|
# Equivalent
|
||||||
|
nb .#modulesPkgs.electrs
|
||||||
|
|
||||||
|
## Eval packages
|
||||||
|
# Check version
|
||||||
|
nix eval .#joinmarket.version
|
||||||
|
|
||||||
|
# Eval derivation. --raw is needed due to a Nix bug (https://github.com/NixOS/nix/issues/5731)
|
||||||
|
nix eval --raw .#joinmarket; echo
|
||||||
|
|
||||||
|
# Check the version of a package in the nixpkgs(-unstable) inputs of the nix-bitcoin flake
|
||||||
|
nix eval --inputs-from . nixpkgs#electrs.version
|
||||||
|
nix eval --inputs-from . nixpkgs-unstable#electrs.version
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# Inspect test systems
|
||||||
|
|
||||||
|
# Build a test system
|
||||||
|
nix build -o /tmp/system --print-build-logs "$(nix eval --raw .#tests.default --apply '
|
||||||
|
test: test.nodes.machine.system.build.toplevel.drvPath
|
||||||
|
')"
|
||||||
|
readlink /tmp/system
|
||||||
|
# Inspect system files
|
||||||
|
cat /tmp/system/activate
|
||||||
|
cat /tmp/system/etc/system/bitcoind.service
|
||||||
|
|
||||||
|
# Evaluate a config value
|
||||||
|
nix eval .#tests.default --apply '
|
||||||
|
test: test.nodes.machine.services.bitcoind.rpc.port
|
||||||
|
'
|
||||||
|
|
||||||
|
# Evaluate a config value in a custom test
|
||||||
|
nix eval .#makeTest --apply '
|
||||||
|
makeTest: let
|
||||||
|
config = (makeTest {
|
||||||
|
config = {
|
||||||
|
services.electrs.port = 10000;
|
||||||
|
};
|
||||||
|
}).nodes.machine;
|
||||||
|
in
|
||||||
|
config.services.electrs.port
|
||||||
|
'
|
||||||
|
|
||||||
|
# Evaluate a config value in a scenario defined in a file
|
||||||
|
nix eval --impure .#getTest --apply '
|
||||||
|
getTest: let
|
||||||
|
config = (getTest {
|
||||||
|
name = "default";
|
||||||
|
extraScenariosFile = builtins.getEnv("root") + "/scenarios.nix";
|
||||||
|
}).nodes.machine;
|
||||||
|
in
|
||||||
|
config.services.bitcoind.port
|
||||||
|
'
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# Manually run a nix-bitcoin container, without the test framework.
|
||||||
|
# This allows sharing directories with the container host via option `bindMounts.`
|
||||||
|
|
||||||
|
read -rd '' src <<'EOF' || :
|
||||||
|
let
|
||||||
|
nix-bitcoin = builtins.getFlake "git+file://${toString ../.}";
|
||||||
|
in
|
||||||
|
nix-bitcoin.inputs.extra-container.lib.buildContainers {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
inherit (nix-bitcoin.inputs) nixpkgs;
|
||||||
|
# legacyInstallDirs = true;
|
||||||
|
config = {
|
||||||
|
containers.nb-adhoc = {
|
||||||
|
# bindMounts."/shared" = { hostPath = "/my/hostpath"; isReadOnly = false; };
|
||||||
|
extra.addressPrefix = "10.200.255";
|
||||||
|
config = {
|
||||||
|
imports = [ nix-bitcoin.nixosModules.default ];
|
||||||
|
services.bitcoind.enable = true;
|
||||||
|
nix-bitcoin.generateSecrets = true;
|
||||||
|
nix-bitcoin.nodeinfo.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
nix run --impure --expr "$src"
|
||||||
|
|
||||||
|
# Run command in container
|
||||||
|
nix shell --impure --expr "$src" -c container --run c nodeinfo
|
||||||
|
# TODO-EXTERNAL: Use this instead when https://github.com/NixOS/nix/issues/7444 is fixed
|
||||||
|
# nix run --impure --expr "$src" -- --run c nodeinfo
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# Show build logs from a CI test run
|
||||||
|
#
|
||||||
|
# If a specific test derivation was already built successfully, the test is not rerun
|
||||||
|
# and the CI logs don't show the test output.
|
||||||
|
|
||||||
|
# To view the test output:
|
||||||
|
# 1. Get the test store path at the end of the CI logs
|
||||||
|
# 2.
|
||||||
|
fetch_build_log() {
|
||||||
|
local log=$1
|
||||||
|
nix cat-store --store https://nix-bitcoin.cachix.org "$log/output.xml" |
|
||||||
|
nix shell --inputs-from . nixpkgs#html-tidy -c tidy -xml -i - > /tmp/build-output.xml
|
||||||
|
echo
|
||||||
|
echo "Fetched log to /tmp/build-output.xml"
|
||||||
|
}
|
||||||
|
# Set this to your store path
|
||||||
|
fetch_build_log /nix/store/0cdjhvg84jsp47f3357812zjmj2wmz94-vm-test-run-nix-bitcoin-default
|
||||||
|
|
||||||
|
# Show runtime
|
||||||
|
grep "script finished in" /tmp/build-output.xml
|
||||||
|
|
||||||
|
# View XML with node folding
|
||||||
|
firefox /tmp/build-output.xml
|
47
dev/topics/rtl.sh
Normal file
47
dev/topics/rtl.sh
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# shellcheck disable=SC2154
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# Docs
|
||||||
|
# https://github.com/Ride-The-Lightning/RTL
|
||||||
|
# config options: https://github.com/Ride-The-Lightning/RTL/blob/master/.github/docs/Application_configurations.md
|
||||||
|
# https://github.com/Ride-The-Lightning/c-lightning-REST
|
||||||
|
# local src: ~/s/RTL/
|
||||||
|
|
||||||
|
# Browse API docs (in container shell)
|
||||||
|
runuser -u "$(logname)" -- xdg-open "http://$ip:4001/api-docs/"
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# Debug the service
|
||||||
|
run-tests.sh -s rtl-dev container
|
||||||
|
|
||||||
|
c systemctl status rtl
|
||||||
|
c journalctl -u rtl
|
||||||
|
c cat /var/lib/rtl/RTL-Config.json
|
||||||
|
|
||||||
|
c systemctl status clightning-rest
|
||||||
|
|
||||||
|
# Open webinterface. Password: a
|
||||||
|
runuser -u "$(logname)" -- xdg-open "http://$ip:3000"
|
||||||
|
|
||||||
|
#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
|
||||||
|
# Build RTL manually
|
||||||
|
# [[~/s/RTL/dockerfiles/Dockerfile][dockerfile]]
|
||||||
|
# [[~/s/RTL/package.json][package.json]]
|
||||||
|
|
||||||
|
rtl_src=~/s/RTL
|
||||||
|
git clone https://github.com/Ride-The-Lightning/RTL "$rtl_src"
|
||||||
|
|
||||||
|
nix build -o /tmp/nix-bitcoin-dev/nodejs --inputs-from . nixpkgs#nodejs-16_x
|
||||||
|
# Start a shell in a sandbox
|
||||||
|
env --chdir "$rtl_src" nix-bitcoin-firejail --whitelist="$rtl_src" --whitelist=/tmp/nix-bitcoin-dev/nodejs
|
||||||
|
PATH=/tmp/nix-bitcoin-dev/nodejs/bin:"$PATH"
|
||||||
|
|
||||||
|
# Install
|
||||||
|
npm ci --omit=dev --omit=optional --no-update-notifier --ignore-scripts
|
||||||
|
# If the above fails, try: (details: https://github.com/Ride-The-Lightning/RTL/issues/1182)
|
||||||
|
npm ci --omit=dev --omit=optional --no-update-notifier --ignore-scripts --legacy-peer-deps
|
||||||
|
|
||||||
|
|
||||||
|
# Run
|
||||||
|
node rtl --help
|
||||||
|
|
||||||
|
git clean -xdf # Cleanup repo
|
@ -135,7 +135,7 @@ You can use the same approach to allow connections to other services.
|
|||||||
## Example: bitcoind
|
## Example: bitcoind
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# 1. Stop bitcoind on your nodes
|
# 1. Stop bitcoind on your node
|
||||||
ssh root@nix-bitcoin-node 'systemctl stop bitcoind'
|
ssh root@nix-bitcoin-node 'systemctl stop bitcoind'
|
||||||
# Also stop bitcoind on the node that you'll be copying data from
|
# Also stop bitcoind on the node that you'll be copying data from
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ This is borrowed from the [NixOS manual](https://nixos.org/nixos/manual/index.ht
|
|||||||
ls /sys/firmware/efi
|
ls /sys/firmware/efi
|
||||||
```
|
```
|
||||||
|
|
||||||
If the file exists exists, you should continue the installation for UEFI otherwise for Legacy Boot.
|
If the file exists you should continue the installation for UEFI otherwise for Legacy Boot.
|
||||||
|
|
||||||
4. Option 1: Partition and format for UEFI
|
4. Option 1: Partition and format for UEFI
|
||||||
|
|
||||||
|
@ -51,41 +51,11 @@ the node:
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Tests
|
### Tests
|
||||||
The internal test suite is also useful for exploring features.\
|
The [nix-bitcoin test suite](../test/README.md) is also useful for exploring features.
|
||||||
The following `run-tests.sh` commands leave no traces (outside of `/nix/store`) on
|
|
||||||
the host system.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/fort-nix/nix-bitcoin
|
|
||||||
cd nix-bitcoin/test
|
|
||||||
|
|
||||||
# Run a node in a VM. No tests are executed.
|
|
||||||
./run-tests.sh vm
|
|
||||||
systemctl status bitcoind
|
|
||||||
|
|
||||||
# Run a Python test shell inside a VM node
|
|
||||||
./run-tests.sh debug
|
|
||||||
print(succeed("systemctl status bitcoind"))
|
|
||||||
run_test("bitcoind")
|
|
||||||
|
|
||||||
# Run a node in a container. Requires systemd and root privileges.
|
|
||||||
./run-tests.sh container
|
|
||||||
c systemctl status bitcoind
|
|
||||||
|
|
||||||
# Explore a single feature
|
|
||||||
./run-tests.sh --scenario electrs container
|
|
||||||
|
|
||||||
# Run a command in a container
|
|
||||||
./run-tests.sh --scenario '{
|
|
||||||
services.clightning.enable = true;
|
|
||||||
nix-bitcoin.nodeinfo.enable = true;
|
|
||||||
}' container --run c nodeinfo
|
|
||||||
```
|
|
||||||
See [`run-tests.sh`](../test/run-tests.sh) for a complete documentation.
|
|
||||||
|
|
||||||
### Real-world example
|
### Real-world example
|
||||||
Check the [server repo](https://github.com/fort-nix/nixbitcoin.org) for https://nixbitcoin.org
|
Check the [server repo](https://github.com/fort-nix/nixbitcoin.org) for https://nixbitcoin.org
|
||||||
to see the configuration of a nix-bitcoin node that's used in production.
|
to see the configuration of a Flakes-based nix-bitcoin node that's used in production.
|
||||||
|
|
||||||
The commands in `shell.nix` allow you to locally run the node in a VM or container.
|
The commands in `shell.nix` allow you to locally run the node in a VM or container.
|
||||||
|
|
||||||
|
@ -287,10 +287,10 @@
|
|||||||
# this value at the release version of the first install of this system.
|
# this value at the release version of the first install of this system.
|
||||||
# Before changing this value read the documentation for this option
|
# Before changing this value read the documentation for this option
|
||||||
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
||||||
system.stateVersion = "22.05"; # Did you read the comment?
|
system.stateVersion = "22.11"; # Did you read the comment?
|
||||||
|
|
||||||
# The nix-bitcoin release version that your config is compatible with.
|
# The nix-bitcoin release version that your config is compatible with.
|
||||||
# When upgrading to a backwards-incompatible release, nix-bitcoin will display an
|
# When upgrading to a backwards-incompatible release, nix-bitcoin will display an
|
||||||
# an error and provide instructions for migrating your config to the new release.
|
# an error and provide instructions for migrating your config to the new release.
|
||||||
nix-bitcoin.configVersion = "0.0.70";
|
nix-bitcoin.configVersion = "0.0.85";
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,11 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
if [[ ! -v NIX_BITCOIN_EXAMPLES_DIR ]]; then
|
|
||||||
echo "Running script in nix shell env..."
|
|
||||||
cd "${BASH_SOURCE[0]%/*}"
|
|
||||||
exec nix-shell --run "./${BASH_SOURCE[0]##*/} $*"
|
|
||||||
else
|
|
||||||
cd "$NIX_BITCOIN_EXAMPLES_DIR"
|
|
||||||
fi
|
|
||||||
|
|
||||||
tmpDir=$(mktemp -d /tmp/nix-bitcoin-minimal-container.XXX)
|
tmpDir=$(mktemp -d /tmp/nix-bitcoin-minimal-container.XXX)
|
||||||
trap 'rm -rf $tmpDir' EXIT
|
trap 'rm -rf $tmpDir' EXIT
|
||||||
|
|
||||||
|
cd "${BASH_SOURCE[0]%/*}"
|
||||||
|
|
||||||
# Modify importable-configuration.nix to use the local <nix-bitcoin>
|
# Modify importable-configuration.nix to use the local <nix-bitcoin>
|
||||||
# source instead of fetchTarball
|
# source instead of fetchTarball
|
||||||
<importable-configuration.nix sed '
|
<importable-configuration.nix sed '
|
||||||
@ -31,4 +25,4 @@ cat > "$tmpDir/configuration.nix" <<EOF
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
"${BASH_SOURCE[0]%/*}/deploy-container.sh" "$tmpDir/configuration.nix" "$@"
|
./deploy-container.sh "$tmpDir/configuration.nix" "$@"
|
||||||
|
@ -8,23 +8,21 @@ set -euo pipefail
|
|||||||
# Run with option `--interactive` or `-i` to start a shell for interacting with
|
# Run with option `--interactive` or `-i` to start a shell for interacting with
|
||||||
# the node.
|
# the node.
|
||||||
|
|
||||||
if [[ ! -v NIX_BITCOIN_EXAMPLES_DIR ]]; then
|
if [[ $EUID != 0 ]]; then
|
||||||
echo "Running script in nix shell env..."
|
# NixOS containers require root permissions
|
||||||
cd "${BASH_SOURCE[0]%/*}"
|
exec sudo "${BASH_SOURCE[0]}" "$@"
|
||||||
exec nix-shell --run "./${BASH_SOURCE[0]##*/} $*"
|
|
||||||
else
|
|
||||||
cd "$NIX_BITCOIN_EXAMPLES_DIR"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $(sysctl -n net.ipv4.ip_forward || sudo sysctl -n net.ipv4.ip_forward) != 1 ]]; then
|
if [[ $(sysctl -n net.ipv4.ip_forward) != 1 ]]; then
|
||||||
echo "Error: IP forwarding (net.ipv4.ip_forward) is not enabled."
|
echo "Error: IP forwarding (net.ipv4.ip_forward) is not enabled."
|
||||||
echo "Needed for container WAN access."
|
echo "Needed for container WAN access."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $EUID != 0 ]]; then
|
if [[ ! -v DEPLOY_CONTAINER_NIX_SHELL ]]; then
|
||||||
# NixOS containers require root permissions
|
echo "Running script in nix shell env..."
|
||||||
exec sudo "PATH=$PATH" "NIX_PATH=$NIX_PATH" "NIX_BITCOIN_EXAMPLES_DIR=$NIX_BITCOIN_EXAMPLES_DIR" "${BASH_SOURCE[0]}" "$@"
|
cd "${BASH_SOURCE[0]%/*}"
|
||||||
|
DEPLOY_CONTAINER_NIX_SHELL=1 exec nix-shell --run "./${BASH_SOURCE[0]##*/} $*"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
interactive=
|
interactive=
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
# Import the secure-node preset, an opinionated config to enhance security
|
# Import the secure-node preset, an opinionated config to enhance security
|
||||||
# and privacy.
|
# and privacy.
|
||||||
#
|
#
|
||||||
# "${nix-bitcoin}/modules/presets/secure-node.nix"
|
# (nix-bitcoin + "/modules/presets/secure-node.nix")
|
||||||
|
|
||||||
{
|
{
|
||||||
# Automatically generate all secrets required by services.
|
# Automatically generate all secrets required by services.
|
||||||
|
@ -13,13 +13,13 @@ rec {
|
|||||||
QEMU_OPTS="-smp $(nproc) -m 1500" ${vm}/bin/run-*-vm
|
QEMU_OPTS="-smp $(nproc) -m 1500" ${vm}/bin/run-*-vm
|
||||||
'';
|
'';
|
||||||
|
|
||||||
vm = (import "${nixpkgs}/nixos" {
|
vm = (import (nixpkgs + "/nixos") {
|
||||||
inherit system;
|
inherit system;
|
||||||
configuration = { config, lib, modulesPath, ... }: {
|
configuration = { config, lib, modulesPath, ... }: {
|
||||||
imports = [
|
imports = [
|
||||||
nix-bitcoin.nixosModules.default
|
nix-bitcoin.nixosModules.default
|
||||||
"${nix-bitcoin}/modules/presets/secure-node.nix"
|
(nix-bitcoin + "/modules/presets/secure-node.nix")
|
||||||
"${modulesPath}/virtualisation/qemu-vm.nix"
|
(modulesPath + "/virtualisation/qemu-vm.nix")
|
||||||
];
|
];
|
||||||
|
|
||||||
virtualisation.graphics = false;
|
virtualisation.graphics = false;
|
||||||
@ -29,6 +29,9 @@ rec {
|
|||||||
# For faster startup in offline VMs
|
# For faster startup in offline VMs
|
||||||
services.clightning.extraConfig = "disable-dns";
|
services.clightning.extraConfig = "disable-dns";
|
||||||
|
|
||||||
|
# Avoid lengthy build of the nixos manual
|
||||||
|
documentation.nixos.enable = false;
|
||||||
|
|
||||||
nixpkgs.pkgs = pkgs;
|
nixpkgs.pkgs = pkgs;
|
||||||
services.getty.autologinUser = "root";
|
services.getty.autologinUser = "root";
|
||||||
nix.nixPath = [ "nixpkgs=${nixpkgs}" ];
|
nix.nixPath = [ "nixpkgs=${nixpkgs}" ];
|
||||||
@ -40,6 +43,7 @@ rec {
|
|||||||
- nodeinfo
|
- nodeinfo
|
||||||
- systemctl status bitcoind
|
- systemctl status bitcoind
|
||||||
- systemctl status clightning
|
- systemctl status clightning
|
||||||
|
- lightning-cli getinfo
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# Power off VM when the user exits the shell
|
# Power off VM when the user exits the shell
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
# Disable the hardened preset to improve VM performance
|
# Disable the hardened preset to improve VM performance
|
||||||
disabledModules = [ <nix-bitcoin/modules/presets/hardened.nix> ];
|
disabledModules = [ <nix-bitcoin/modules/presets/hardened.nix> ];
|
||||||
|
|
||||||
imports = [ "${modulesPath}/virtualisation/qemu-vm.nix" ];
|
imports = [ (modulesPath + "/virtualisation/qemu-vm.nix") ];
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
virtualisation.graphics = false;
|
virtualisation.graphics = false;
|
||||||
|
48
flake.lock
48
flake.lock
@ -1,12 +1,35 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"extra-container": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": [
|
||||||
|
"flake-utils"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1671802034,
|
||||||
|
"narHash": "sha256-mkv2u5nQJEV3KlWiopkt/gMz0OM4nmEXSfzkSw6welQ=",
|
||||||
|
"owner": "erikarvstedt",
|
||||||
|
"repo": "extra-container",
|
||||||
|
"rev": "e34f0cca15f6f0f2e598dad0b329196d0dab6d4f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "erikarvstedt",
|
||||||
|
"repo": "extra-container",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1659877975,
|
"lastModified": 1667395993,
|
||||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -17,27 +40,27 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1662099760,
|
"lastModified": 1674407282,
|
||||||
"narHash": "sha256-MdZLCTJPeHi/9fg6R9fiunyDwP3XHJqDd51zWWz9px0=",
|
"narHash": "sha256-2qwc8mrPINSFdWffPK+ji6nQ9aGnnZyHSItVcYDZDlk=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "67e45078141102f45eff1589a831aeaa3182b41e",
|
"rev": "ab1254087f4cdf4af74b552d7fc95175d9bdbb49",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixos-22.05",
|
"ref": "nixos-22.11",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgsUnstable": {
|
"nixpkgs-unstable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1662096612,
|
"lastModified": 1674487464,
|
||||||
"narHash": "sha256-R+Q8l5JuyJryRPdiIaYpO5O3A55rT+/pItBrKcy7LM4=",
|
"narHash": "sha256-Jgq50e4S4JVCYpWLqrabBzDp/1mfaxHCh8/OOorHTy0=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "21de2b973f9fee595a7a1ac4693efff791245c34",
|
"rev": "3954218cf613eba8e0dcefa9abe337d26bc48fd0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -49,9 +72,10 @@
|
|||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"extra-container": "extra-container",
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"nixpkgsUnstable": "nixpkgsUnstable"
|
"nixpkgs-unstable": "nixpkgs-unstable"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
36
flake.nix
36
flake.nix
@ -5,27 +5,42 @@
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.05";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11";
|
||||||
nixpkgsUnstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
extra-container = {
|
||||||
|
url = "github:erikarvstedt/extra-container";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.flake-utils.follows = "flake-utils";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, nixpkgsUnstable, flake-utils }:
|
outputs = { self, nixpkgs, nixpkgs-unstable, flake-utils, ... }:
|
||||||
let
|
let
|
||||||
supportedSystems = [
|
supportedSystems = [
|
||||||
"x86_64-linux"
|
"x86_64-linux"
|
||||||
"i686-linux"
|
|
||||||
"aarch64-linux"
|
"aarch64-linux"
|
||||||
"armv7l-linux"
|
# On these 32-bit platforms, Python pkg `pymemcache` 4.0.0 (required by
|
||||||
|
# `joinmarket`) is broken:
|
||||||
|
# "i686-linux"
|
||||||
|
# "armv7l-linux"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
test = import ./test/tests.nix nixpkgs.lib;
|
||||||
in {
|
in {
|
||||||
lib = {
|
lib = {
|
||||||
mkNbPkgs = {
|
mkNbPkgs = {
|
||||||
system
|
system
|
||||||
, pkgs ? nixpkgs.legacyPackages.${system}
|
, pkgs ? nixpkgs.legacyPackages.${system}
|
||||||
, pkgsUnstable ? nixpkgsUnstable.legacyPackages.${system}
|
, pkgsUnstable ? nixpkgs-unstable.legacyPackages.${system}
|
||||||
}:
|
}:
|
||||||
import ./pkgs { inherit pkgs pkgsUnstable; };
|
import ./pkgs { inherit pkgs pkgsUnstable; };
|
||||||
|
|
||||||
|
test = {
|
||||||
|
inherit (test) scenarios;
|
||||||
|
};
|
||||||
|
|
||||||
|
inherit supportedSystems;
|
||||||
};
|
};
|
||||||
|
|
||||||
overlays.default = final: prev: let
|
overlays.default = final: prev: let
|
||||||
@ -91,7 +106,12 @@
|
|||||||
# Allow accessing the whole nested `nbPkgs` attrset (including `modulesPkgs`)
|
# Allow accessing the whole nested `nbPkgs` attrset (including `modulesPkgs`)
|
||||||
# via this flake.
|
# via this flake.
|
||||||
# `packages` is not allowed to contain nested pkgs attrsets.
|
# `packages` is not allowed to contain nested pkgs attrsets.
|
||||||
legacyPackages = nbPkgs;
|
legacyPackages =
|
||||||
|
nbPkgs //
|
||||||
|
(test.pkgs self pkgs) //
|
||||||
|
{
|
||||||
|
extra-container = self.inputs.extra-container.packages.${system}.default;
|
||||||
|
};
|
||||||
|
|
||||||
apps = rec {
|
apps = rec {
|
||||||
default = vm;
|
default = vm;
|
||||||
@ -102,6 +122,8 @@
|
|||||||
program = toString packages.runVM;
|
program = toString packages.runVM;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
devShells.default = import ./dev/dev-env/dev-shell.nix pkgs;
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
12
helper/start-bash-session.sh
Normal file
12
helper/start-bash-session.sh
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Start an interactive bash session in the current bash environment.
|
||||||
|
# This is helpful for debugging bash scripts like pkg update scripts,
|
||||||
|
# by adding `source <path-to>/start-bash-session.sh` at the location to
|
||||||
|
# be inspected.
|
||||||
|
|
||||||
|
|
||||||
|
# BASH_ENVIRONMENT contains definitions of read-only variables like 'BASHOPTS' that
|
||||||
|
# cause warnings on evaluation. Suppress these warnings while sourcing.
|
||||||
|
#
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
BASH_ENVIRONMENT=<(declare -p; declare -pf) \
|
||||||
|
bash --rcfile <(echo 'source $BASH_ENVIRONMENT 2>/dev/null')
|
@ -12,6 +12,19 @@ set -euo pipefail
|
|||||||
# pinned to stable.
|
# pinned to stable.
|
||||||
# All other pkgs are pinned to unstable.
|
# All other pkgs are pinned to unstable.
|
||||||
|
|
||||||
|
forceRun=
|
||||||
|
nixosVersion=
|
||||||
|
for arg in "$@"; do
|
||||||
|
case $arg in
|
||||||
|
-f)
|
||||||
|
forceRun=1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
nixosVersion=$arg
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
# cd to script dir
|
# cd to script dir
|
||||||
cd "${BASH_SOURCE[0]%/*}"
|
cd "${BASH_SOURCE[0]%/*}"
|
||||||
|
|
||||||
@ -21,7 +34,7 @@ if [[ $(nix flake 2>&1) != *"requires a sub-command"* ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ${1:-} != -f ]] && ! git diff --quiet ../flake.{nix,lock}; then
|
if [[ $forceRun ]] && ! git diff --quiet ../flake.{nix,lock}; then
|
||||||
echo "error: flake.nix/flake.lock have changes. Run with option -f to ignore."
|
echo "error: flake.nix/flake.lock have changes. Run with option -f to ignore."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@ -36,6 +49,9 @@ versions=$(nix eval --json -f update-flake.nix versions)
|
|||||||
# versions=$(echo "$versions" | sed 's|1|0|g')
|
# versions=$(echo "$versions" | sed 's|1|0|g')
|
||||||
|
|
||||||
echo "Updating main flake"
|
echo "Updating main flake"
|
||||||
|
if [[ $nixosVersion ]]; then
|
||||||
|
sed -Ei "s|(nixpkgs.url = .*nixos-)[^\"]+|\1$nixosVersion|" ../flake.nix
|
||||||
|
fi
|
||||||
nix flake update ..
|
nix flake update ..
|
||||||
|
|
||||||
echo
|
echo
|
||||||
|
@ -6,7 +6,7 @@ let
|
|||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Enable backups of node data.
|
Enable backups of node data.
|
||||||
This uses the NixOS duplicity service.
|
This uses the NixOS duplicity service.
|
||||||
To further configure the backup, you can set NixOS options `services.duplicity.*`.
|
To further configure the backup, you can set NixOS options `services.duplicity.*`.
|
||||||
@ -16,34 +16,34 @@ let
|
|||||||
with-bulk-data = mkOption {
|
with-bulk-data = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Whether to also backup Bitcoin blockchain and other bulk data.
|
Whether to also backup Bitcoin blockchain and other bulk data.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
destination = mkOption {
|
destination = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "file:///var/lib/localBackups";
|
default = "file:///var/lib/localBackups";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Where to back up to.
|
Where to back up to.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
frequency = mkOption {
|
frequency = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Run backup with the given frequency. If null, do not run automatically.
|
Run backup with the given frequency. If null, do not run automatically.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
postgresqlDatabases = mkOption {
|
postgresqlDatabases = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [];
|
default = [];
|
||||||
description = "List of database names to backup.";
|
description = mdDoc "List of database names to backup.";
|
||||||
};
|
};
|
||||||
extraFiles = mkOption {
|
extraFiles = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [];
|
default = [];
|
||||||
example = [ "/var/lib/nginx" ];
|
example = [ "/var/lib/nginx" ];
|
||||||
description = "Additional files to be appended to filelist.";
|
description = mdDoc "Additional files to be appended to filelist.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,19 +8,19 @@ let
|
|||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
description = "Address to listen for peer connections.";
|
description = mdDoc "Address to listen for peer connections.";
|
||||||
};
|
};
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 8333;
|
default = 8333;
|
||||||
description = "Port to listen for peer connections.";
|
description = mdDoc "Port to listen for peer connections.";
|
||||||
};
|
};
|
||||||
onionPort = mkOption {
|
onionPort = mkOption {
|
||||||
type = types.nullOr types.port;
|
type = types.nullOr types.port;
|
||||||
# When the bitcoind onion service is enabled, add an onion-tagged socket
|
# When the bitcoind onion service is enabled, add an onion-tagged socket
|
||||||
# to distinguish local connections from Tor connections
|
# to distinguish local connections from Tor connections
|
||||||
default = if (config.nix-bitcoin.onionServices.bitcoind.enable or false) then 8334 else null;
|
default = if (config.nix-bitcoin.onionServices.bitcoind.enable or false) then 8334 else null;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Port to listen for Tor peer connections.
|
Port to listen for Tor peer connections.
|
||||||
If set, inbound connections to this port are tagged as onion peers.
|
If set, inbound connections to this port are tagged as onion peers.
|
||||||
'';
|
'';
|
||||||
@ -28,15 +28,15 @@ let
|
|||||||
listen = mkOption {
|
listen = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Listen for peer connections at `address:port`
|
Listen for peer connections at `address:port`
|
||||||
and `address:onionPort` (if `onionPort` is set).
|
and `address:onionPort` (if {option}`onionPort` is set).
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
listenWhitelisted = mkOption {
|
listenWhitelisted = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Listen for peer connections at `address:whitelistedPort`.
|
Listen for peer connections at `address:whitelistedPort`.
|
||||||
Peers connected through this socket are automatically whitelisted.
|
Peers connected through this socket are automatically whitelisted.
|
||||||
'';
|
'';
|
||||||
@ -44,12 +44,12 @@ let
|
|||||||
whitelistedPort = mkOption {
|
whitelistedPort = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 8335;
|
default = 8335;
|
||||||
description = "See `listenWhitelisted`.";
|
description = mdDoc "See `listenWhitelisted`.";
|
||||||
};
|
};
|
||||||
getPublicAddressCmd = mkOption {
|
getPublicAddressCmd = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "";
|
default = "";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Bash expression which outputs the public service address to announce to peers.
|
Bash expression which outputs the public service address to announce to peers.
|
||||||
If left empty, no address is announced.
|
If left empty, no address is announced.
|
||||||
'';
|
'';
|
||||||
@ -58,7 +58,7 @@ let
|
|||||||
type = types.package;
|
type = types.package;
|
||||||
default = config.nix-bitcoin.pkgs.bitcoind;
|
default = config.nix-bitcoin.pkgs.bitcoind;
|
||||||
defaultText = "config.nix-bitcoin.pkgs.bitcoind";
|
defaultText = "config.nix-bitcoin.pkgs.bitcoind";
|
||||||
description = "The package providing bitcoin binaries.";
|
description = mdDoc "The package providing bitcoin binaries.";
|
||||||
};
|
};
|
||||||
extraConfig = mkOption {
|
extraConfig = mkOption {
|
||||||
type = types.lines;
|
type = types.lines;
|
||||||
@ -67,41 +67,41 @@ let
|
|||||||
par=16
|
par=16
|
||||||
logips=1
|
logips=1
|
||||||
'';
|
'';
|
||||||
description = "Extra lines appended to <filename>bitcoin.conf</filename>.";
|
description = mdDoc "Extra lines appended to {file}`bitcoin.conf`.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/bitcoind";
|
default = "/var/lib/bitcoind";
|
||||||
description = "The data directory for bitcoind.";
|
description = mdDoc "The data directory for bitcoind.";
|
||||||
};
|
};
|
||||||
rpc = {
|
rpc = {
|
||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Address to listen for JSON-RPC connections.
|
Address to listen for JSON-RPC connections.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 8332;
|
default = 8332;
|
||||||
description = "Port to listen for JSON-RPC connections.";
|
description = mdDoc "Port to listen for JSON-RPC connections.";
|
||||||
};
|
};
|
||||||
threads = mkOption {
|
threads = mkOption {
|
||||||
type = types.nullOr types.ints.u16;
|
type = types.nullOr types.ints.u16;
|
||||||
default = null;
|
default = null;
|
||||||
description = "The number of threads to service RPC calls.";
|
description = mdDoc "The number of threads to service RPC calls.";
|
||||||
};
|
};
|
||||||
allowip = mkOption {
|
allowip = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [ "127.0.0.1" ];
|
default = [ "127.0.0.1" ];
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Allow JSON-RPC connections from specified sources.
|
Allow JSON-RPC connections from specified sources.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
users = mkOption {
|
users = mkOption {
|
||||||
default = {};
|
default = {};
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Allowed users for JSON-RPC connections.
|
Allowed users for JSON-RPC connections.
|
||||||
'';
|
'';
|
||||||
example = {
|
example = {
|
||||||
@ -116,16 +116,16 @@ let
|
|||||||
type = types.str;
|
type = types.str;
|
||||||
default = name;
|
default = name;
|
||||||
example = "alice";
|
example = "alice";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Username for JSON-RPC connections.
|
Username for JSON-RPC connections.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
passwordHMAC = mkOption {
|
passwordHMAC = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
example = "f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae";
|
example = "f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Password HMAC-SHA-256 for JSON-RPC connections. Must be a string of the
|
Password HMAC-SHA-256 for JSON-RPC connections. Must be a string of the
|
||||||
format `salt-hex$hmac-hex`.
|
format `<SALT-HEX>$<HMAC-HEX>`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
passwordHMACFromFile = mkOption {
|
passwordHMACFromFile = mkOption {
|
||||||
@ -136,7 +136,7 @@ let
|
|||||||
rpcwhitelist = mkOption {
|
rpcwhitelist = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [];
|
default = [];
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
List of allowed rpc calls for each user.
|
List of allowed rpc calls for each user.
|
||||||
If empty list, rpcwhitelist is disabled for that user.
|
If empty list, rpcwhitelist is disabled for that user.
|
||||||
'';
|
'';
|
||||||
@ -148,7 +148,7 @@ let
|
|||||||
regtest = mkOption {
|
regtest = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = "Enable regtest mode.";
|
description = mdDoc "Enable regtest mode.";
|
||||||
};
|
};
|
||||||
network = mkOption {
|
network = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
@ -161,12 +161,12 @@ let
|
|||||||
proxy = mkOption {
|
proxy = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||||
description = "Connect through SOCKS5 proxy";
|
description = mdDoc "Connect through SOCKS5 proxy";
|
||||||
};
|
};
|
||||||
i2p = mkOption {
|
i2p = mkOption {
|
||||||
type = types.enum [ false true "only-outgoing" ];
|
type = types.enum [ false true "only-outgoing" ];
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Enable peer connections via i2p.
|
Enable peer connections via i2p.
|
||||||
With `only-outgoing`, incoming i2p connections are disabled.
|
With `only-outgoing`, incoming i2p connections are disabled.
|
||||||
'';
|
'';
|
||||||
@ -174,7 +174,7 @@ let
|
|||||||
dataDirReadableByGroup = mkOption {
|
dataDirReadableByGroup = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
If enabled, data dir content is readable by the bitcoind service group.
|
If enabled, data dir content is readable by the bitcoind service group.
|
||||||
Warning: This disables bitcoind's wallet support.
|
Warning: This disables bitcoind's wallet support.
|
||||||
'';
|
'';
|
||||||
@ -182,7 +182,7 @@ let
|
|||||||
sysperms = mkOption {
|
sysperms = mkOption {
|
||||||
type = types.nullOr types.bool;
|
type = types.nullOr types.bool;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Create new files with system default permissions, instead of umask 077
|
Create new files with system default permissions, instead of umask 077
|
||||||
(only effective with disabled wallet functionality)
|
(only effective with disabled wallet functionality)
|
||||||
'';
|
'';
|
||||||
@ -190,7 +190,7 @@ let
|
|||||||
disablewallet = mkOption {
|
disablewallet = mkOption {
|
||||||
type = types.nullOr types.bool;
|
type = types.nullOr types.bool;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Do not load the wallet and disable wallet RPC calls
|
Do not load the wallet and disable wallet RPC calls
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -198,13 +198,13 @@ let
|
|||||||
type = types.nullOr (types.ints.between 4 16384);
|
type = types.nullOr (types.ints.between 4 16384);
|
||||||
default = null;
|
default = null;
|
||||||
example = 4000;
|
example = 4000;
|
||||||
description = "Override the default database cache size in MiB.";
|
description = mdDoc "Override the default database cache size in MiB.";
|
||||||
};
|
};
|
||||||
prune = mkOption {
|
prune = mkOption {
|
||||||
type = types.ints.unsigned;
|
type = types.ints.unsigned;
|
||||||
default = 0;
|
default = 0;
|
||||||
example = 10000;
|
example = 10000;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Automatically prune block files to stay under the specified target size in MiB.
|
Automatically prune block files to stay under the specified target size in MiB.
|
||||||
Value 0 disables pruning.
|
Value 0 disables pruning.
|
||||||
'';
|
'';
|
||||||
@ -212,25 +212,25 @@ let
|
|||||||
txindex = mkOption {
|
txindex = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = "Enable the transaction index.";
|
description = mdDoc "Enable the transaction index.";
|
||||||
};
|
};
|
||||||
zmqpubrawblock = mkOption {
|
zmqpubrawblock = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
example = "tcp://127.0.0.1:28332";
|
example = "tcp://127.0.0.1:28332";
|
||||||
description = "ZMQ address for zmqpubrawblock notifications";
|
description = mdDoc "ZMQ address for zmqpubrawblock notifications";
|
||||||
};
|
};
|
||||||
zmqpubrawtx = mkOption {
|
zmqpubrawtx = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
example = "tcp://127.0.0.1:28333";
|
example = "tcp://127.0.0.1:28333";
|
||||||
description = "ZMQ address for zmqpubrawtx notifications";
|
description = mdDoc "ZMQ address for zmqpubrawtx notifications";
|
||||||
};
|
};
|
||||||
assumevalid = mkOption {
|
assumevalid = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
example = "00000000000000000000e5abc3a74fe27dc0ead9c70ea1deb456f11c15fd7bc6";
|
example = "00000000000000000000e5abc3a74fe27dc0ead9c70ea1deb456f11c15fd7bc6";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
If this block is in the chain assume that it and its ancestors are
|
If this block is in the chain assume that it and its ancestors are
|
||||||
valid and potentially skip their script verification.
|
valid and potentially skip their script verification.
|
||||||
'';
|
'';
|
||||||
@ -239,37 +239,37 @@ let
|
|||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [];
|
default = [];
|
||||||
example = [ "ecoc5q34tmbq54wl.onion" ];
|
example = [ "ecoc5q34tmbq54wl.onion" ];
|
||||||
description = "Add nodes to connect to and attempt to keep the connections open";
|
description = mdDoc "Add nodes to connect to and attempt to keep the connections open";
|
||||||
};
|
};
|
||||||
discover = mkOption {
|
discover = mkOption {
|
||||||
type = types.nullOr types.bool;
|
type = types.nullOr types.bool;
|
||||||
default = null;
|
default = null;
|
||||||
description = "Discover own IP addresses";
|
description = mdDoc "Discover own IP addresses";
|
||||||
};
|
};
|
||||||
addresstype = mkOption {
|
addresstype = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
example = "bech32";
|
example = "bech32";
|
||||||
description = "The type of addresses to use";
|
description = mdDoc "The type of addresses to use";
|
||||||
};
|
};
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "bitcoin";
|
default = "bitcoin";
|
||||||
description = "The user as which to run bitcoind.";
|
description = mdDoc "The user as which to run bitcoind.";
|
||||||
};
|
};
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.user;
|
default = cfg.user;
|
||||||
description = "The group as which to run bitcoind.";
|
description = mdDoc "The group as which to run bitcoind.";
|
||||||
};
|
};
|
||||||
cli = mkOption {
|
cli = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
type = types.package;
|
type = types.package;
|
||||||
default = pkgs.writeScriptBin "bitcoin-cli" ''
|
default = pkgs.writers.writeBashBin "bitcoin-cli" ''
|
||||||
exec ${cfg.package}/bin/bitcoin-cli -datadir='${cfg.dataDir}' "$@"
|
exec ${cfg.package}/bin/bitcoin-cli -datadir='${cfg.dataDir}' "$@"
|
||||||
'';
|
'';
|
||||||
defaultText = "(See source)";
|
defaultText = "(See source)";
|
||||||
description = "Binary to connect with the bitcoind instance.";
|
description = mdDoc "Binary to connect with the bitcoind instance.";
|
||||||
};
|
};
|
||||||
tor = nbLib.tor;
|
tor = nbLib.tor;
|
||||||
};
|
};
|
||||||
@ -367,9 +367,10 @@ in {
|
|||||||
proto.sam.enable = true;
|
proto.sam.enable = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
# Commented out to avoid trying to chown the nfs-mounted directory
|
||||||
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
|
# systemd.tmpfiles.rules = [
|
||||||
];
|
# "d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
|
||||||
|
# ];
|
||||||
|
|
||||||
systemd.services.bitcoind = {
|
systemd.services.bitcoind = {
|
||||||
# Use `wants` instead of `requires` so that bitcoind and all dependent services
|
# Use `wants` instead of `requires` so that bitcoind and all dependent services
|
||||||
@ -380,7 +381,7 @@ in {
|
|||||||
# TODO-EXTERNAL: Instead of `wants`, use a future systemd dependency type
|
# TODO-EXTERNAL: Instead of `wants`, use a future systemd dependency type
|
||||||
# that propagates initial start failures but no restarts
|
# that propagates initial start failures but no restarts
|
||||||
wants = [ "nix-bitcoin-secrets.target" ];
|
wants = [ "nix-bitcoin-secrets.target" ];
|
||||||
after = [ "network.target" "nix-bitcoin-secrets.target" ];
|
after = [ "network-online.target" "nix-bitcoin-secrets.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
preStart = let
|
preStart = let
|
||||||
@ -412,17 +413,17 @@ in {
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
# Enable RPC access for group
|
# Enable RPC access for group
|
||||||
postStart = ''
|
# postStart = ''
|
||||||
chmod g=r '${cfg.dataDir}/${optionalString cfg.regtest "regtest/"}.cookie'
|
# chmod g=r '${cfg.dataDir}/${optionalString cfg.regtest "regtest/"}.cookie'
|
||||||
'';
|
# '';
|
||||||
|
|
||||||
serviceConfig = nbLib.defaultHardening // {
|
serviceConfig = nbLib.defaultHardening // {
|
||||||
Type = "notify";
|
Type = "notify";
|
||||||
NotifyAccess = "all";
|
NotifyAccess = "all";
|
||||||
User = cfg.user;
|
User = cfg.user;
|
||||||
Group = cfg.group;
|
Group = cfg.group;
|
||||||
TimeoutStartSec = "10min";
|
TimeoutStartSec = "30min";
|
||||||
TimeoutStopSec = "10min";
|
TimeoutStopSec = "30min";
|
||||||
ExecStart = "${cfg.package}/bin/bitcoind -datadir='${cfg.dataDir}'";
|
ExecStart = "${cfg.package}/bin/bitcoind -datadir='${cfg.dataDir}'";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
UMask = mkIf cfg.dataDirReadableByGroup "0027";
|
UMask = mkIf cfg.dataDirReadableByGroup "0027";
|
||||||
|
@ -8,12 +8,12 @@ let
|
|||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
description = "Address to listen on.";
|
description = mdDoc "Address to listen on.";
|
||||||
};
|
};
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 23000;
|
default = 23000;
|
||||||
description = "Port to listen on.";
|
description = mdDoc "Port to listen on.";
|
||||||
};
|
};
|
||||||
package = mkOption {
|
package = mkOption {
|
||||||
type = types.package;
|
type = types.package;
|
||||||
@ -22,38 +22,38 @@ let
|
|||||||
else
|
else
|
||||||
config.nix-bitcoin.pkgs.btcpayserver;
|
config.nix-bitcoin.pkgs.btcpayserver;
|
||||||
defaultText = "(See source)";
|
defaultText = "(See source)";
|
||||||
description = "The package providing btcpayserver binaries.";
|
description = mdDoc "The package providing btcpayserver binaries.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/btcpayserver";
|
default = "/var/lib/btcpayserver";
|
||||||
description = "The data directory for btcpayserver.";
|
description = mdDoc "The data directory for btcpayserver.";
|
||||||
};
|
};
|
||||||
lightningBackend = mkOption {
|
lightningBackend = mkOption {
|
||||||
type = types.nullOr (types.enum [ "clightning" "lnd" ]);
|
type = types.nullOr (types.enum [ "clightning" "lnd" ]);
|
||||||
default = null;
|
default = null;
|
||||||
description = "The lightning node implementation to use.";
|
description = mdDoc "The lightning node implementation to use.";
|
||||||
};
|
};
|
||||||
lbtc = mkOption {
|
lbtc = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = "Enable liquid support in btcpayserver.";
|
description = mdDoc "Enable liquid support in btcpayserver.";
|
||||||
};
|
};
|
||||||
rootpath = mkOption {
|
rootpath = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
example = "btcpayserver";
|
example = "btcpayserver";
|
||||||
description = "The prefix for root-relative btcpayserver URLs.";
|
description = mdDoc "The prefix for root-relative btcpayserver URLs.";
|
||||||
};
|
};
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "btcpayserver";
|
default = "btcpayserver";
|
||||||
description = "The user as which to run btcpayserver.";
|
description = mdDoc "The user as which to run btcpayserver.";
|
||||||
};
|
};
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.btcpayserver.user;
|
default = cfg.btcpayserver.user;
|
||||||
description = "The group as which to run btcpayserver.";
|
description = mdDoc "The group as which to run btcpayserver.";
|
||||||
};
|
};
|
||||||
tor.enforce = nbLib.tor.enforce;
|
tor.enforce = nbLib.tor.enforce;
|
||||||
};
|
};
|
||||||
@ -63,7 +63,7 @@ let
|
|||||||
# This option is only used by netns-isolation
|
# This option is only used by netns-isolation
|
||||||
internal = true;
|
internal = true;
|
||||||
default = cfg.btcpayserver.enable;
|
default = cfg.btcpayserver.enable;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
nbxplorer is always enabled when btcpayserver is enabled.
|
nbxplorer is always enabled when btcpayserver is enabled.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -71,32 +71,32 @@ let
|
|||||||
type = types.package;
|
type = types.package;
|
||||||
default = config.nix-bitcoin.pkgs.nbxplorer;
|
default = config.nix-bitcoin.pkgs.nbxplorer;
|
||||||
defaultText = "config.nix-bitcoin.pkgs.nbxplorer";
|
defaultText = "config.nix-bitcoin.pkgs.nbxplorer";
|
||||||
description = "The package providing nbxplorer binaries.";
|
description = mdDoc "The package providing nbxplorer binaries.";
|
||||||
};
|
};
|
||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
description = "Address to listen on.";
|
description = mdDoc "Address to listen on.";
|
||||||
};
|
};
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 24444;
|
default = 24444;
|
||||||
description = "Port to listen on.";
|
description = mdDoc "Port to listen on.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/nbxplorer";
|
default = "/var/lib/nbxplorer";
|
||||||
description = "The data directory for nbxplorer.";
|
description = mdDoc "The data directory for nbxplorer.";
|
||||||
};
|
};
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "nbxplorer";
|
default = "nbxplorer";
|
||||||
description = "The user as which to run nbxplorer.";
|
description = mdDoc "The user as which to run nbxplorer.";
|
||||||
};
|
};
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.nbxplorer.user;
|
default = cfg.nbxplorer.user;
|
||||||
description = "The group as which to run nbxplorer.";
|
description = mdDoc "The group as which to run nbxplorer.";
|
||||||
};
|
};
|
||||||
tor.enforce = nbLib.tor.enforce;
|
tor.enforce = nbLib.tor.enforce;
|
||||||
};
|
};
|
||||||
@ -193,14 +193,14 @@ in {
|
|||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = "10s";
|
RestartSec = "10s";
|
||||||
ReadWritePaths = [ cfg.nbxplorer.dataDir ];
|
ReadWritePaths = [ cfg.nbxplorer.dataDir ];
|
||||||
MemoryDenyWriteExecute = "false";
|
MemoryDenyWriteExecute = false;
|
||||||
} // nbLib.allowedIPAddresses cfg.nbxplorer.tor.enforce;
|
} // nbLib.allowedIPAddresses cfg.nbxplorer.tor.enforce;
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.btcpayserver = let
|
systemd.services.btcpayserver = let
|
||||||
nbExplorerUrl = "http://${nbLib.addressWithPort cfg.nbxplorer.address cfg.nbxplorer.port}/";
|
nbExplorerUrl = "http://${nbLib.addressWithPort cfg.nbxplorer.address cfg.nbxplorer.port}/";
|
||||||
nbExplorerCookie = "${cfg.nbxplorer.dataDir}/${bitcoind.makeNetworkName "Main" "RegTest"}/.cookie";
|
nbExplorerCookie = "${cfg.nbxplorer.dataDir}/${bitcoind.makeNetworkName "Main" "RegTest"}/.cookie";
|
||||||
configFile = builtins.toFile "config" (''
|
configFile = builtins.toFile "btcpayserver-config" (''
|
||||||
network=${bitcoind.network}
|
network=${bitcoind.network}
|
||||||
bind=${cfg.btcpayserver.address}
|
bind=${cfg.btcpayserver.address}
|
||||||
port=${toString cfg.btcpayserver.port}
|
port=${toString cfg.btcpayserver.port}
|
||||||
@ -212,41 +212,34 @@ in {
|
|||||||
rootpath=${cfg.btcpayserver.rootpath}
|
rootpath=${cfg.btcpayserver.rootpath}
|
||||||
'' + optionalString (cfg.btcpayserver.lightningBackend == "clightning") ''
|
'' + optionalString (cfg.btcpayserver.lightningBackend == "clightning") ''
|
||||||
btclightning=type=clightning;server=unix:///${cfg.clightning.dataDir}/${bitcoind.makeNetworkName "bitcoin" "regtest"}/lightning-rpc
|
btclightning=type=clightning;server=unix:///${cfg.clightning.dataDir}/${bitcoind.makeNetworkName "bitcoin" "regtest"}/lightning-rpc
|
||||||
'' + optionalString cfg.btcpayserver.lbtc ''
|
'' + optionalString (cfg.btcpayserver.lightningBackend == "lnd")
|
||||||
|
(
|
||||||
|
"btclightning=type=lnd-rest;" +
|
||||||
|
"server=https://${cfg.lnd.restAddress}:${toString cfg.lnd.restPort}/;" +
|
||||||
|
"macaroonfilepath=/run/lnd/btcpayserver.macaroon;" +
|
||||||
|
"certfilepath=${config.services.lnd.certPath}" +
|
||||||
|
"\n"
|
||||||
|
)
|
||||||
|
+ optionalString cfg.btcpayserver.lbtc ''
|
||||||
chains=btc,lbtc
|
chains=btc,lbtc
|
||||||
lbtcexplorerurl=${nbExplorerUrl}
|
lbtcexplorerurl=${nbExplorerUrl}
|
||||||
lbtcexplorercookiefile=${nbExplorerCookie}
|
lbtcexplorercookiefile=${nbExplorerCookie}
|
||||||
'');
|
'');
|
||||||
lndConfig =
|
|
||||||
"btclightning=type=lnd-rest;" +
|
|
||||||
"server=https://${cfg.lnd.restAddress}:${toString cfg.lnd.restPort}/;" +
|
|
||||||
"macaroonfilepath=/run/lnd/btcpayserver.macaroon;" +
|
|
||||||
"certthumbprint=";
|
|
||||||
in let self = {
|
in let self = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
requires = [ "nbxplorer.service" "postgresql.service" ]
|
requires = [ "nbxplorer.service" "postgresql.service" ]
|
||||||
++ optional (cfg.btcpayserver.lightningBackend != null) "${cfg.btcpayserver.lightningBackend}.service";
|
++ optional (cfg.btcpayserver.lightningBackend != null) "${cfg.btcpayserver.lightningBackend}.service";
|
||||||
after = self.requires;
|
after = self.requires;
|
||||||
preStart = ''
|
|
||||||
install -m 600 ${configFile} '${cfg.btcpayserver.dataDir}/settings.config'
|
|
||||||
${optionalString (cfg.btcpayserver.lightningBackend == "lnd") ''
|
|
||||||
{
|
|
||||||
echo -n "${lndConfig}"
|
|
||||||
${pkgs.openssl}/bin/openssl x509 -noout -fingerprint -sha256 -in ${config.services.lnd.certPath} \
|
|
||||||
| sed -e 's/.*=//;s/://g'
|
|
||||||
} >> '${cfg.btcpayserver.dataDir}/settings.config'
|
|
||||||
''}
|
|
||||||
'';
|
|
||||||
serviceConfig = nbLib.defaultHardening // {
|
serviceConfig = nbLib.defaultHardening // {
|
||||||
ExecStart = ''
|
ExecStart = ''
|
||||||
${cfg.btcpayserver.package}/bin/btcpayserver --conf='${cfg.btcpayserver.dataDir}/settings.config' \
|
${cfg.btcpayserver.package}/bin/btcpayserver --conf=${configFile} \
|
||||||
--datadir='${cfg.btcpayserver.dataDir}'
|
--datadir='${cfg.btcpayserver.dataDir}'
|
||||||
'';
|
'';
|
||||||
User = cfg.btcpayserver.user;
|
User = cfg.btcpayserver.user;
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = "10s";
|
RestartSec = "10s";
|
||||||
ReadWritePaths = [ cfg.btcpayserver.dataDir ];
|
ReadWritePaths = [ cfg.btcpayserver.dataDir ];
|
||||||
MemoryDenyWriteExecute = "false";
|
MemoryDenyWriteExecute = false;
|
||||||
} // nbLib.allowedIPAddresses cfg.btcpayserver.tor.enforce;
|
} // nbLib.allowedIPAddresses cfg.btcpayserver.tor.enforce;
|
||||||
}; in self;
|
}; in self;
|
||||||
|
|
||||||
|
@ -9,18 +9,17 @@ let
|
|||||||
type = listOf str;
|
type = listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
example = [ "--verbose" "--dry-run" ];
|
example = [ "--verbose" "--dry-run" ];
|
||||||
description = "Extra flags to pass to the charge-lnd command.";
|
description = mdDoc "Extra flags to pass to the charge-lnd command.";
|
||||||
};
|
};
|
||||||
|
|
||||||
interval = mkOption {
|
interval = mkOption {
|
||||||
type = str;
|
type = str;
|
||||||
default = "*-*-* 04:00:00";
|
default = "*-*-* 04:00:00";
|
||||||
example = "hourly";
|
example = "hourly";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Systemd calendar expression when to adjust fees.
|
Systemd calendar expression when to adjust fees.
|
||||||
|
|
||||||
See <citerefentry><refentrytitle>systemd.time</refentrytitle>
|
See {man}`systemd.time(7)` for possible values.
|
||||||
<manvolnum>7</manvolnum></citerefentry> for possible values.
|
|
||||||
|
|
||||||
Default is once a day.
|
Default is once a day.
|
||||||
'';
|
'';
|
||||||
@ -29,7 +28,7 @@ let
|
|||||||
randomDelay = mkOption {
|
randomDelay = mkOption {
|
||||||
type = str;
|
type = str;
|
||||||
default = "1h";
|
default = "1h";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Random delay to add to scheduled time.
|
Random delay to add to scheduled time.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -55,7 +54,7 @@ let
|
|||||||
[default]
|
[default]
|
||||||
strategy = ignore
|
strategy = ignore
|
||||||
'';
|
'';
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Policy definitions in INI format.
|
Policy definitions in INI format.
|
||||||
|
|
||||||
See https://github.com/accumulator/charge-lnd/blob/master/README.md#usage
|
See https://github.com/accumulator/charge-lnd/blob/master/README.md#usage
|
||||||
@ -126,7 +125,6 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
systemd.timers.charge-lnd = {
|
systemd.timers.charge-lnd = {
|
||||||
description = "Adjust LND routing fees";
|
|
||||||
wantedBy = [ "timers.target" ];
|
wantedBy = [ "timers.target" ];
|
||||||
timerConfig = {
|
timerConfig = {
|
||||||
OnCalendar = cfg.interval;
|
OnCalendar = cfg.interval;
|
||||||
|
@ -7,7 +7,7 @@ let cfg = config.services.clightning.plugins.clboss; in
|
|||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Whether to enable CLBOSS (clightning plugin).
|
Whether to enable CLBOSS (clightning plugin).
|
||||||
See also: https://github.com/ZmnSCPxj/clboss#operating
|
See also: https://github.com/ZmnSCPxj/clboss#operating
|
||||||
'';
|
'';
|
||||||
@ -15,36 +15,36 @@ let cfg = config.services.clightning.plugins.clboss; in
|
|||||||
min-onchain = mkOption {
|
min-onchain = mkOption {
|
||||||
type = types.ints.positive;
|
type = types.ints.positive;
|
||||||
default = 30000;
|
default = 30000;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Target amount (in satoshi) that CLBOSS will leave on-chain.
|
Target amount (in satoshi) that CLBOSS will leave on-chain.
|
||||||
clboss will only open new channels if this amount is smaller than
|
clboss will only open new channels if the funds in your clightning wallet are
|
||||||
the funds in your clightning wallet.
|
larger than this amount.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
min-channel = mkOption {
|
min-channel = mkOption {
|
||||||
type = types.ints.positive;
|
type = types.ints.positive;
|
||||||
default = 500000;
|
default = 500000;
|
||||||
description = "The minimum size (in satoshi) of channels created by CLBOSS.";
|
description = mdDoc "The minimum size (in satoshi) of channels created by CLBOSS.";
|
||||||
};
|
};
|
||||||
max-channel = mkOption {
|
max-channel = mkOption {
|
||||||
type = types.ints.positive;
|
type = types.ints.positive;
|
||||||
default = 16777215;
|
default = 16777215;
|
||||||
description = "The maximum size (in satoshi) of channels created by CLBOSS.";
|
description = mdDoc "The maximum size (in satoshi) of channels created by CLBOSS.";
|
||||||
};
|
};
|
||||||
zerobasefee = mkOption {
|
zerobasefee = mkOption {
|
||||||
type = types.enum [ "require" "allow" "disallow" ];
|
type = types.enum [ "require" "allow" "disallow" ];
|
||||||
default = "allow";
|
default = "allow";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
require: set `base_fee` to 0.
|
`require`: set `base_fee` to 0.
|
||||||
allow: set `base_fee` according to the CLBOSS heuristics, which may include value 0.
|
`allow`: set `base_fee` according to the CLBOSS heuristics, which may include value 0.
|
||||||
disallow: set `base_fee` to according to the CLBOSS heuristics, with a minimum value of 1.
|
`disallow`: set `base_fee` to according to the CLBOSS heuristics, with a minimum value of 1.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
package = mkOption {
|
package = mkOption {
|
||||||
type = types.package;
|
type = types.package;
|
||||||
default = config.nix-bitcoin.pkgs.clboss;
|
default = config.nix-bitcoin.pkgs.clboss;
|
||||||
defaultText = "config.nix-bitcoin.pkgs.clboss";
|
defaultText = "config.nix-bitcoin.pkgs.clboss";
|
||||||
description = "The package providing clboss binaries.";
|
description = mdDoc "The package providing clboss binaries.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ let
|
|||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Enable feeaduster (clightning plugin).
|
Enable feeaduster (clightning plugin).
|
||||||
This plugin auto-updates channel fees to keep channels balanced.
|
This plugin auto-updates channel fees to keep channels balanced.
|
||||||
|
|
||||||
@ -18,17 +18,17 @@ let
|
|||||||
fuzz = mkOption {
|
fuzz = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = true;
|
default = true;
|
||||||
description = "Enable update threshold randomization and hysteresis.";
|
description = mdDoc "Enable update threshold randomization and hysteresis.";
|
||||||
};
|
};
|
||||||
adjustOnForward = mkOption {
|
adjustOnForward = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = "Automatically update fees on forward events.";
|
description = mdDoc "Automatically update fees on forward events.";
|
||||||
};
|
};
|
||||||
method = mkOption {
|
method = mkOption {
|
||||||
type = types.enum [ "soft" "default" "hard" ];
|
type = types.enum [ "soft" "default" "hard" ];
|
||||||
default = "default";
|
default = "default";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Adjustment method to calculate channel fees.
|
Adjustment method to calculate channel fees.
|
||||||
`soft`: less difference when adjusting fees.
|
`soft`: less difference when adjusting fees.
|
||||||
`hard`: greater difference when adjusting fees.
|
`hard`: greater difference when adjusting fees.
|
||||||
@ -37,7 +37,7 @@ let
|
|||||||
adjustDaily = mkOption {
|
adjustDaily = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = true;
|
default = true;
|
||||||
description = "Automatically update fees daily.";
|
description = mdDoc "Automatically update fees daily.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,22 +8,22 @@ let cfg = config.services.clightning.plugins.summary; in
|
|||||||
currency = mkOption {
|
currency = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "USD";
|
default = "USD";
|
||||||
description = "The currency to look up on btcaverage.";
|
description = mdDoc "The currency to look up on btcaverage.";
|
||||||
};
|
};
|
||||||
currencyPrefix = mkOption {
|
currencyPrefix = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "USD $";
|
default = "USD $";
|
||||||
description = "The prefix to use for the currency.";
|
description = mdDoc "The prefix to use for the currency.";
|
||||||
};
|
};
|
||||||
availabilityInterval = mkOption {
|
availabilityInterval = mkOption {
|
||||||
type = types.int;
|
type = types.int;
|
||||||
default = 300;
|
default = 300;
|
||||||
description = "How often in seconds the availability should be calculated.";
|
description = mdDoc "How often in seconds the availability should be calculated.";
|
||||||
};
|
};
|
||||||
availabilityWindow = mkOption {
|
availabilityWindow = mkOption {
|
||||||
type = types.int;
|
type = types.int;
|
||||||
default = 72;
|
default = 72;
|
||||||
description = "How many hours the availability should be averaged over.";
|
description = mdDoc "How many hours the availability should be averaged over.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ let
|
|||||||
mkOption {
|
mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
description = "Endpoint for ${name}";
|
description = mdDoc "Endpoint for ${name}";
|
||||||
};
|
};
|
||||||
|
|
||||||
setEndpoint = ep:
|
setEndpoint = ep:
|
||||||
|
@ -6,7 +6,7 @@ let
|
|||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Enable live replication of the clightning database.
|
Enable live replication of the clightning database.
|
||||||
This prevents losing off-chain funds when the primary wallet file becomes
|
This prevents losing off-chain funds when the primary wallet file becomes
|
||||||
inaccessible.
|
inaccessible.
|
||||||
@ -26,7 +26,7 @@ let
|
|||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
example = "user@10.0.0.1:directory";
|
example = "user@10.0.0.1:directory";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
The SSH destination for which a SSHFS will be mounted.
|
The SSH destination for which a SSHFS will be mounted.
|
||||||
`directory` is relative to the home of `user`.
|
`directory` is relative to the home of `user`.
|
||||||
|
|
||||||
@ -40,12 +40,12 @@ let
|
|||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 22;
|
default = 22;
|
||||||
description = "SSH port of the remote server.";
|
description = mdDoc "SSH port of the remote server.";
|
||||||
};
|
};
|
||||||
sshOptions = mkOption {
|
sshOptions = mkOption {
|
||||||
type = with types; listOf str;
|
type = with types; listOf str;
|
||||||
default = [ "reconnect" "ServerAliveInterval=50" ];
|
default = [ "reconnect" "ServerAliveInterval=50" ];
|
||||||
description = "SSH options used for mounting the SSHFS.";
|
description = mdDoc "SSH options used for mounting the SSHFS.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
local = {
|
local = {
|
||||||
@ -53,7 +53,7 @@ let
|
|||||||
type = types.nullOr types.path;
|
type = types.nullOr types.path;
|
||||||
default = null;
|
default = null;
|
||||||
example = "/var/backup/clightning";
|
example = "/var/backup/clightning";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
This option can be specified instead of `sshfs.destination` to enable
|
This option can be specified instead of `sshfs.destination` to enable
|
||||||
replication to a local directory.
|
replication to a local directory.
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ let
|
|||||||
setupDirectory = mkOption {
|
setupDirectory = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = true;
|
default = true;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Create `local.directory` if it doesn't exist and set write permissions
|
Create `local.directory` if it doesn't exist and set write permissions
|
||||||
for the `clightning` user.
|
for the `clightning` user.
|
||||||
'';
|
'';
|
||||||
@ -78,10 +78,10 @@ let
|
|||||||
encrypt = mkOption {
|
encrypt = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Whether to encrypt the replicated database with gocryptfs.
|
Whether to encrypt the replicated database with gocryptfs.
|
||||||
The encryption password is automatically generated and stored
|
The encryption password is automatically generated and stored
|
||||||
in file `$secretsDir/clightning-replication-password`.
|
in file {file}`$secretsDir/clightning-replication-password`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -7,17 +7,17 @@ let
|
|||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 3001;
|
default = 3001;
|
||||||
description = "REST server port.";
|
description = mdDoc "REST server port.";
|
||||||
};
|
};
|
||||||
docPort = mkOption {
|
docPort = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 4001;
|
default = 4001;
|
||||||
description = "Swagger API documentation server port.";
|
description = mdDoc "Swagger API documentation server port.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/clightning-rest";
|
default = "/var/lib/clightning-rest";
|
||||||
description = "The data directory for clightning-rest.";
|
description = mdDoc "The data directory for clightning-rest.";
|
||||||
};
|
};
|
||||||
extraConfig = mkOption {
|
extraConfig = mkOption {
|
||||||
type = types.attrs;
|
type = types.attrs;
|
||||||
@ -25,7 +25,7 @@ let
|
|||||||
example = {
|
example = {
|
||||||
DOMAIN = "mynode.org";
|
DOMAIN = "mynode.org";
|
||||||
};
|
};
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Extra config options.
|
Extra config options.
|
||||||
See: https://github.com/Ride-The-Lightning/c-lightning-REST#option-1-via-config-file-cl-rest-configjson
|
See: https://github.com/Ride-The-Lightning/c-lightning-REST#option-1-via-config-file-cl-rest-configjson
|
||||||
'';
|
'';
|
||||||
@ -34,7 +34,7 @@ let
|
|||||||
group = mkOption {
|
group = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = clightning.group;
|
default = clightning.group;
|
||||||
description = "The group under which clightning-rest is run.";
|
description = mdDoc "The group under which clightning-rest is run.";
|
||||||
};
|
};
|
||||||
# Rest server address.
|
# Rest server address.
|
||||||
# Not configurable. The server always listens on all interfaces:
|
# Not configurable. The server always listens on all interfaces:
|
||||||
|
@ -7,24 +7,24 @@ let
|
|||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
description = "Address to listen for peer connections.";
|
description = mdDoc "Address to listen for peer connections.";
|
||||||
};
|
};
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 9735;
|
default = 9735;
|
||||||
description = "Port to listen for peer connections.";
|
description = mdDoc "Port to listen for peer connections.";
|
||||||
};
|
};
|
||||||
proxy = mkOption {
|
proxy = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Socks proxy for connecting to Tor nodes (or for all connections if option always-use-proxy is set).
|
Socks proxy for connecting to Tor nodes (or for all connections if option always-use-proxy is set).
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
always-use-proxy = mkOption {
|
always-use-proxy = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = cfg.tor.proxy;
|
default = cfg.tor.proxy;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Always use the proxy, even to connect to normal IP addresses.
|
Always use the proxy, even to connect to normal IP addresses.
|
||||||
You can still connect to Unix domain sockets manually.
|
You can still connect to Unix domain sockets manually.
|
||||||
This also disables all DNS lookups, to avoid leaking address information.
|
This also disables all DNS lookups, to avoid leaking address information.
|
||||||
@ -33,18 +33,18 @@ let
|
|||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/clightning";
|
default = "/var/lib/clightning";
|
||||||
description = "The data directory for clightning.";
|
description = mdDoc "The data directory for clightning.";
|
||||||
};
|
};
|
||||||
networkDir = mkOption {
|
networkDir = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = "${cfg.dataDir}/${network}";
|
default = "${cfg.dataDir}/${network}";
|
||||||
description = "The network data directory.";
|
description = mdDoc "The network data directory.";
|
||||||
};
|
};
|
||||||
wallet = mkOption {
|
wallet = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
example = "sqlite3:///var/lib/clightning/bitcoin/lightningd.sqlite3";
|
example = "sqlite3:///var/lib/clightning/bitcoin/lightningd.sqlite3";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Wallet data scheme (sqlite3 or postgres) and location/connection
|
Wallet data scheme (sqlite3 or postgres) and location/connection
|
||||||
parameters, as fully qualified data source name.
|
parameters, as fully qualified data source name.
|
||||||
'';
|
'';
|
||||||
@ -55,42 +55,42 @@ let
|
|||||||
example = ''
|
example = ''
|
||||||
alias=mynode
|
alias=mynode
|
||||||
'';
|
'';
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Extra lines appended to the configuration file.
|
Extra lines appended to the configuration file.
|
||||||
|
|
||||||
See all available options at
|
See all available options at
|
||||||
https://github.com/ElementsProject/lightning/blob/master/doc/lightningd-config.5.md
|
https://github.com/ElementsProject/lightning/blob/master/doc/lightningd-config.5.md
|
||||||
or by running `lightningd --help`.
|
or by running {command}`lightningd --help`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "clightning";
|
default = "clightning";
|
||||||
description = "The user as which to run clightning.";
|
description = mdDoc "The user as which to run clightning.";
|
||||||
};
|
};
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.user;
|
default = cfg.user;
|
||||||
description = "The group as which to run clightning.";
|
description = mdDoc "The group as which to run clightning.";
|
||||||
};
|
};
|
||||||
package = mkOption {
|
package = mkOption {
|
||||||
type = types.package;
|
type = types.package;
|
||||||
default = nbPkgs.clightning;
|
default = nbPkgs.clightning;
|
||||||
defaultText = "config.nix-bitcoin.pkgs.clightning";
|
defaultText = "config.nix-bitcoin.pkgs.clightning";
|
||||||
description = "The package providing clightning binaries.";
|
description = mdDoc "The package providing clightning binaries.";
|
||||||
};
|
};
|
||||||
cli = mkOption {
|
cli = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = pkgs.writeScriptBin "lightning-cli" ''
|
default = pkgs.writers.writeBashBin "lightning-cli" ''
|
||||||
${cfg.package}/bin/lightning-cli --lightning-dir='${cfg.dataDir}' "$@"
|
${cfg.package}/bin/lightning-cli --lightning-dir='${cfg.dataDir}' "$@"
|
||||||
'';
|
'';
|
||||||
defaultText = "(See source)";
|
defaultText = "(See source)";
|
||||||
description = "Binary to connect with the clightning instance.";
|
description = mdDoc "Binary to connect with the clightning instance.";
|
||||||
};
|
};
|
||||||
getPublicAddressCmd = mkOption {
|
getPublicAddressCmd = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "";
|
default = "";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Bash expression which outputs the public service address to announce to peers.
|
Bash expression which outputs the public service address to announce to peers.
|
||||||
If left empty, no address is announced.
|
If left empty, no address is announced.
|
||||||
'';
|
'';
|
||||||
@ -102,19 +102,26 @@ let
|
|||||||
nbLib = config.nix-bitcoin.lib;
|
nbLib = config.nix-bitcoin.lib;
|
||||||
nbPkgs = config.nix-bitcoin.pkgs;
|
nbPkgs = config.nix-bitcoin.pkgs;
|
||||||
|
|
||||||
network = config.services.bitcoind.makeNetworkName "bitcoin" "regtest";
|
inherit (config.services) bitcoind;
|
||||||
|
|
||||||
|
network = bitcoind.makeNetworkName "bitcoin" "regtest";
|
||||||
configFile = pkgs.writeText "config" ''
|
configFile = pkgs.writeText "config" ''
|
||||||
network=${network}
|
network=${network}
|
||||||
bitcoin-datadir=${config.services.bitcoind.dataDir}
|
bitcoin-datadir=${bitcoind.dataDir}
|
||||||
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
|
${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"}
|
||||||
always-use-proxy=${boolToString cfg.always-use-proxy}
|
always-use-proxy=${boolToString cfg.always-use-proxy}
|
||||||
bind-addr=${cfg.address}:${toString cfg.port}
|
bind-addr=${cfg.address}:${toString cfg.port}
|
||||||
bitcoin-rpcconnect=${nbLib.address config.services.bitcoind.rpc.address}
|
bitcoin-rpcconnect=${nbLib.address bitcoind.rpc.address}
|
||||||
bitcoin-rpcport=${toString config.services.bitcoind.rpc.port}
|
bitcoin-rpcport=${toString bitcoind.rpc.port}
|
||||||
bitcoin-rpcuser=${config.services.bitcoind.rpc.users.public.name}
|
bitcoin-rpcuser=${bitcoind.rpc.users.public.name}
|
||||||
rpc-file-mode=0660
|
rpc-file-mode=0660
|
||||||
log-timestamps=false
|
log-timestamps=false
|
||||||
${optionalString (cfg.wallet != null) "wallet=${cfg.wallet}"}
|
${optionalString (cfg.wallet != null) "wallet=${cfg.wallet}"}
|
||||||
|
${ # TODO-EXTERNAL: When updating from a version of clightning before 22.11
|
||||||
|
# to version 22.11.1, then the database upgrade needs to be allowed
|
||||||
|
# explicitly. Remove this when it's unlikely that this module is used
|
||||||
|
# with a clightning version 22.11.1 package.
|
||||||
|
optionalString (cfg.package.version == "22.11.1") "database-upgrade=true"}
|
||||||
${cfg.extraConfig}
|
${cfg.extraConfig}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
@ -7,37 +7,37 @@ let
|
|||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
description = "Address to listen for RPC connections.";
|
description = mdDoc "Address to listen for RPC connections.";
|
||||||
};
|
};
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 50001;
|
default = 50001;
|
||||||
description = "Port to listen for RPC connections.";
|
description = mdDoc "Port to listen for RPC connections.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/electrs";
|
default = "/var/lib/electrs";
|
||||||
description = "The data directory for electrs.";
|
description = mdDoc "The data directory for electrs.";
|
||||||
};
|
};
|
||||||
monitoringPort = mkOption {
|
monitoringPort = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 4224;
|
default = 4224;
|
||||||
description = "Prometheus monitoring port.";
|
description = mdDoc "Prometheus monitoring port.";
|
||||||
};
|
};
|
||||||
extraArgs = mkOption {
|
extraArgs = mkOption {
|
||||||
type = types.separatedString " ";
|
type = types.separatedString " ";
|
||||||
default = "";
|
default = "";
|
||||||
description = "Extra command line arguments passed to electrs.";
|
description = mdDoc "Extra command line arguments passed to electrs.";
|
||||||
};
|
};
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "electrs";
|
default = "electrs";
|
||||||
description = "The user as which to run electrs.";
|
description = mdDoc "The user as which to run electrs.";
|
||||||
};
|
};
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.user;
|
default = cfg.user;
|
||||||
description = "The group as which to run electrs.";
|
description = mdDoc "The group as which to run electrs.";
|
||||||
};
|
};
|
||||||
tor.enforce = nbLib.tor.enforce;
|
tor.enforce = nbLib.tor.enforce;
|
||||||
};
|
};
|
||||||
@ -61,9 +61,10 @@ in {
|
|||||||
listenWhitelisted = true;
|
listenWhitelisted = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
# Commented out to allow nfs mounts
|
||||||
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
|
# systemd.tmpfiles.rules = [
|
||||||
];
|
# "d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
|
||||||
|
# ];
|
||||||
|
|
||||||
systemd.services.electrs = {
|
systemd.services.electrs = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
@ -6,7 +6,7 @@ let
|
|||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Enable fulcrum, an Electrum server implemented in C++.
|
Enable fulcrum, an Electrum server implemented in C++.
|
||||||
|
|
||||||
Compared to electrs, fulcrum has a 3x larger database size but
|
Compared to electrs, fulcrum has a 3x larger database size but
|
||||||
@ -17,23 +17,23 @@ let
|
|||||||
|
|
||||||
This module disables peering (a distributed list of electrum servers that can
|
This module disables peering (a distributed list of electrum servers that can
|
||||||
be queried by clients), but you can manually enable it via option
|
be queried by clients), but you can manually enable it via option
|
||||||
`extraConfig`.
|
{option}`extraConfig`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
description = "Address to listen for RPC connections.";
|
description = mdDoc "Address to listen for RPC connections.";
|
||||||
};
|
};
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 50001;
|
default = 50001;
|
||||||
description = "Port to listen for RPC connections.";
|
description = mdDoc "Port to listen for RPC connections.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/fulcrum";
|
default = "/var/lib/fulcrum";
|
||||||
description = "The data directory for fulcrum.";
|
description = mdDoc "The data directory for fulcrum.";
|
||||||
};
|
};
|
||||||
extraConfig = mkOption {
|
extraConfig = mkOption {
|
||||||
type = types.lines;
|
type = types.lines;
|
||||||
@ -41,7 +41,7 @@ let
|
|||||||
example = ''
|
example = ''
|
||||||
peering = true
|
peering = true
|
||||||
'';
|
'';
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Extra lines appended to the configuration file.
|
Extra lines appended to the configuration file.
|
||||||
|
|
||||||
See all available options at
|
See all available options at
|
||||||
@ -51,12 +51,12 @@ let
|
|||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "fulcrum";
|
default = "fulcrum";
|
||||||
description = "The user as which to run fulcrum.";
|
description = mdDoc "The user as which to run fulcrum.";
|
||||||
};
|
};
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.user;
|
default = cfg.user;
|
||||||
description = "The group as which to run fulcrum.";
|
description = mdDoc "The group as which to run fulcrum.";
|
||||||
};
|
};
|
||||||
tor.enforce = nbLib.tor.enforce;
|
tor.enforce = nbLib.tor.enforce;
|
||||||
};
|
};
|
||||||
@ -126,6 +126,7 @@ in {
|
|||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = "10s";
|
RestartSec = "10s";
|
||||||
ReadWritePaths = cfg.dataDir;
|
ReadWritePaths = cfg.dataDir;
|
||||||
|
ProcSubset = "all"; # Fulcrum requires read access to /proc/meminfo
|
||||||
} // nbLib.allowedIPAddresses cfg.tor.enforce;
|
} // nbLib.allowedIPAddresses cfg.tor.enforce;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,21 +6,21 @@ let
|
|||||||
ledger = mkOption {
|
ledger = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
If enabled, the ledger udev rules will be installed.
|
If enabled, the ledger udev rules will be installed.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
trezor = mkOption {
|
trezor = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
If enabled, the trezor udev rules will be installed.
|
If enabled, the trezor udev rules will be installed.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "hardware-wallets";
|
default = "hardware-wallets";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Group the hardware wallet udev rules apply to.
|
Group the hardware wallet udev rules apply to.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
@ -7,27 +7,27 @@ let
|
|||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
description = "HTTP server address.";
|
description = mdDoc "HTTP server address.";
|
||||||
};
|
};
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 62601;
|
default = 62601;
|
||||||
description = "HTTP server port.";
|
description = mdDoc "HTTP server port.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = "/var/lib/joinmarket-ob-watcher";
|
default = "/var/lib/joinmarket-ob-watcher";
|
||||||
description = "The data directory for JoinMarket orderbook watcher.";
|
description = mdDoc "The data directory for JoinMarket orderbook watcher.";
|
||||||
};
|
};
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "joinmarket-ob-watcher";
|
default = "joinmarket-ob-watcher";
|
||||||
description = "The user as which to run JoinMarket.";
|
description = mdDoc "The user as which to run JoinMarket.";
|
||||||
};
|
};
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.user;
|
default = cfg.user;
|
||||||
description = "The group as which to run JoinMarket.";
|
description = mdDoc "The group as which to run JoinMarket.";
|
||||||
};
|
};
|
||||||
# This option is only used by netns-isolation.
|
# This option is only used by netns-isolation.
|
||||||
# Tor is always enabled.
|
# Tor is always enabled.
|
||||||
|
@ -7,7 +7,7 @@ let
|
|||||||
payjoinAddress = mkOption {
|
payjoinAddress = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
The address where payjoin onion connections are forwarded to.
|
The address where payjoin onion connections are forwarded to.
|
||||||
This address is never used directly, it only serves as the internal endpoint
|
This address is never used directly, it only serves as the internal endpoint
|
||||||
for the payjoin onion service.
|
for the payjoin onion service.
|
||||||
@ -18,12 +18,12 @@ let
|
|||||||
payjoinPort = mkOption {
|
payjoinPort = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 64180; # A random private port
|
default = 64180; # A random private port
|
||||||
description = "The port corresponding to option `payjoinAddress`.";
|
description = mdDoc "The port corresponding to option {option}`payjoinAddress`.";
|
||||||
};
|
};
|
||||||
messagingAddress = mkOption {
|
messagingAddress = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
The address where messaging onion connections are forwarded to.
|
The address where messaging onion connections are forwarded to.
|
||||||
This address is never used directly, it only serves as the internal endpoint
|
This address is never used directly, it only serves as the internal endpoint
|
||||||
for the messaging onion service.
|
for the messaging onion service.
|
||||||
@ -33,29 +33,29 @@ let
|
|||||||
messagingPort = mkOption {
|
messagingPort = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 64181; # payjoinPort + 1
|
default = 64181; # payjoinPort + 1
|
||||||
description = "The port corresponding to option `messagingAddress`.";
|
description = mdDoc "The port corresponding to option {option}`messagingAddress`.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/joinmarket";
|
default = "/var/lib/joinmarket";
|
||||||
description = "The data directory for JoinMarket.";
|
description = mdDoc "The data directory for JoinMarket.";
|
||||||
};
|
};
|
||||||
rpcWalletFile = mkOption {
|
rpcWalletFile = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = "jm_wallet";
|
default = "jm_wallet";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Name of the watch-only bitcoind wallet the JoinMarket addresses are imported to.
|
Name of the watch-only bitcoind wallet the JoinMarket addresses are imported to.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "joinmarket";
|
default = "joinmarket";
|
||||||
description = "The user as which to run JoinMarket.";
|
description = mdDoc "The user as which to run JoinMarket.";
|
||||||
};
|
};
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.user;
|
default = cfg.user;
|
||||||
description = "The group as which to run JoinMarket.";
|
description = mdDoc "The group as which to run JoinMarket.";
|
||||||
};
|
};
|
||||||
cli = mkOption {
|
cli = mkOption {
|
||||||
default = cli;
|
default = cli;
|
||||||
@ -77,57 +77,57 @@ let
|
|||||||
ordertype = mkOption {
|
ordertype = mkOption {
|
||||||
type = types.enum [ "reloffer" "absoffer" ];
|
type = types.enum [ "reloffer" "absoffer" ];
|
||||||
default = "reloffer";
|
default = "reloffer";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Which fee type to actually use
|
Which fee type to actually use.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
cjfee_a = mkOption {
|
cjfee_a = mkOption {
|
||||||
type = types.ints.unsigned;
|
type = types.ints.unsigned;
|
||||||
default = 500;
|
default = 500;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Absolute offer fee you wish to receive for coinjoins (cj) in Satoshis
|
Absolute offer fee you wish to receive for coinjoins (cj) in Satoshis.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
cjfee_r = mkOption {
|
cjfee_r = mkOption {
|
||||||
type = types.float;
|
type = types.float;
|
||||||
default = 0.00002;
|
default = 0.00002;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Relative offer fee you wish to receive based on a cj's amount
|
Relative offer fee you wish to receive based on a cj's amount.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
cjfee_factor = mkOption {
|
cjfee_factor = mkOption {
|
||||||
type = types.float;
|
type = types.float;
|
||||||
default = 0.1;
|
default = 0.1;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Variance around the average cj fee
|
Variance around the average cj fee.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
txfee = mkOption {
|
txfee = mkOption {
|
||||||
type = types.ints.unsigned;
|
type = types.ints.unsigned;
|
||||||
default = 100;
|
default = 100;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
The average transaction fee you're adding to coinjoin transactions
|
The average transaction fee you're adding to coinjoin transactions.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
txfee_contribution_factor = mkOption {
|
txfee_contribution_factor = mkOption {
|
||||||
type = types.float;
|
type = types.float;
|
||||||
default = 0.3;
|
default = 0.3;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Variance around the average tx fee
|
Variance around the average tx fee.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
minsize = mkOption {
|
minsize = mkOption {
|
||||||
type = types.ints.unsigned;
|
type = types.ints.unsigned;
|
||||||
default = 100000;
|
default = 100000;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Minimum size of your cj offer in Satoshis. Lower cj amounts will be disregarded.
|
Minimum size of your cj offer in Satoshis. Lower cj amounts will be disregarded.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
size_factor = mkOption {
|
size_factor = mkOption {
|
||||||
type = types.float;
|
type = types.float;
|
||||||
default = 0.1;
|
default = 0.1;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Variance around all offer sizes
|
Variance around all offer sizes.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -7,56 +7,56 @@ let
|
|||||||
rpcAddress = mkOption {
|
rpcAddress = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "localhost";
|
default = "localhost";
|
||||||
description = "Address to listen for gRPC connections.";
|
description = mdDoc "Address to listen for gRPC connections.";
|
||||||
};
|
};
|
||||||
rpcPort = mkOption {
|
rpcPort = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 11010;
|
default = 11010;
|
||||||
description = "Port to listen for gRPC connections.";
|
description = mdDoc "Port to listen for gRPC connections.";
|
||||||
};
|
};
|
||||||
restAddress = mkOption {
|
restAddress = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.rpcAddress;
|
default = cfg.rpcAddress;
|
||||||
description = "Address to listen for REST connections.";
|
description = mdDoc "Address to listen for REST connections.";
|
||||||
};
|
};
|
||||||
restPort = mkOption {
|
restPort = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 8081;
|
default = 8081;
|
||||||
description = "Port to listen for REST connections.";
|
description = mdDoc "Port to listen for REST connections.";
|
||||||
};
|
};
|
||||||
package = mkOption {
|
package = mkOption {
|
||||||
type = types.package;
|
type = types.package;
|
||||||
default = config.nix-bitcoin.pkgs.lightning-loop;
|
default = config.nix-bitcoin.pkgs.lightning-loop;
|
||||||
defaultText = "config.nix-bitcoin.pkgs.lightning-loop";
|
defaultText = "config.nix-bitcoin.pkgs.lightning-loop";
|
||||||
description = "The package providing lightning-loop binaries.";
|
description = mdDoc "The package providing lightning-loop binaries.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/lightning-loop";
|
default = "/var/lib/lightning-loop";
|
||||||
description = "The data directory for lightning-loop.";
|
description = mdDoc "The data directory for lightning-loop.";
|
||||||
};
|
};
|
||||||
proxy = mkOption {
|
proxy = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||||
description = "host:port of SOCKS5 proxy for connnecting to the loop server.";
|
description = mdDoc "`host:port` of SOCKS5 proxy for connnecting to the loop server.";
|
||||||
};
|
};
|
||||||
certificate = {
|
certificate = {
|
||||||
extraIPs = mkOption {
|
extraIPs = mkOption {
|
||||||
type = with types; listOf str;
|
type = with types; listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
example = [ "60.100.0.1" ];
|
example = [ "60.100.0.1" ];
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Extra `subjectAltName` IPs added to the certificate.
|
Extra `subjectAltName` IPs added to the certificate.
|
||||||
This works the same as loop option `tlsextraip`.
|
This works the same as loop option {option}`tlsextraip`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
extraDomains = mkOption {
|
extraDomains = mkOption {
|
||||||
type = with types; listOf str;
|
type = with types; listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
example = [ "example.com" ];
|
example = [ "example.com" ];
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Extra `subjectAltName` domain names added to the certificate.
|
Extra `subjectAltName` domain names added to the certificate.
|
||||||
This works the same as loop option `tlsextradomain`.
|
This works the same as loop option {option}`tlsextradomain`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -66,21 +66,21 @@ let
|
|||||||
example = ''
|
example = ''
|
||||||
debuglevel=trace
|
debuglevel=trace
|
||||||
'';
|
'';
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Extra lines appended to the configuration file.
|
Extra lines appended to the configuration file.
|
||||||
See here for all available options:
|
See here for all available options:
|
||||||
https://github.com/lightninglabs/loop/blob/11ab596080e9d36f1df43edbeba0702b25aa7457/loopd/config.go#L119
|
https://github.com/lightninglabs/loop/blob/11ab596080e9d36f1df43edbeba0702b25aa7457/loopd/config.go#L119
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
cli = mkOption {
|
cli = mkOption {
|
||||||
default = pkgs.writeScriptBin "loop" ''
|
default = pkgs.writers.writeBashBin "loop" ''
|
||||||
${cfg.package}/bin/loop \
|
${cfg.package}/bin/loop \
|
||||||
--rpcserver ${nbLib.addressWithPort cfg.rpcAddress cfg.rpcPort} \
|
--rpcserver ${nbLib.addressWithPort cfg.rpcAddress cfg.rpcPort} \
|
||||||
--macaroonpath '${cfg.dataDir}/${network}/loop.macaroon' \
|
--macaroonpath '${cfg.dataDir}/${network}/loop.macaroon' \
|
||||||
--tlscertpath '${secretsDir}/loop-cert' "$@"
|
--tlscertpath '${secretsDir}/loop-cert' "$@"
|
||||||
'';
|
'';
|
||||||
defaultText = "(See source)";
|
defaultText = "(See source)";
|
||||||
description = "Binary to connect with the lightning-loop instance.";
|
description = mdDoc "Binary to connect with the lightning-loop instance.";
|
||||||
};
|
};
|
||||||
tor = nbLib.tor;
|
tor = nbLib.tor;
|
||||||
};
|
};
|
||||||
|
@ -7,38 +7,38 @@ let
|
|||||||
rpcAddress = mkOption {
|
rpcAddress = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "localhost";
|
default = "localhost";
|
||||||
description = "Address to listen for gRPC connections.";
|
description = mdDoc "Address to listen for gRPC connections.";
|
||||||
};
|
};
|
||||||
rpcPort = mkOption {
|
rpcPort = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 12010;
|
default = 12010;
|
||||||
description = "Port to listen for gRPC connections.";
|
description = mdDoc "Port to listen for gRPC connections.";
|
||||||
};
|
};
|
||||||
restAddress = mkOption {
|
restAddress = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.rpcAddress;
|
default = cfg.rpcAddress;
|
||||||
description = "Address to listen for REST connections.";
|
description = mdDoc "Address to listen for REST connections.";
|
||||||
};
|
};
|
||||||
restPort = mkOption {
|
restPort = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 8281;
|
default = 8281;
|
||||||
description = "Port to listen for REST connections.";
|
description = mdDoc "Port to listen for REST connections.";
|
||||||
};
|
};
|
||||||
package = mkOption {
|
package = mkOption {
|
||||||
type = types.package;
|
type = types.package;
|
||||||
default = config.nix-bitcoin.pkgs.lightning-pool;
|
default = config.nix-bitcoin.pkgs.lightning-pool;
|
||||||
defaultText = "config.nix-bitcoin.pkgs.lightning-pool";
|
defaultText = "config.nix-bitcoin.pkgs.lightning-pool";
|
||||||
description = "The package providing lightning-pool binaries.";
|
description = mdDoc "The package providing lightning-pool binaries.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/lightning-pool";
|
default = "/var/lib/lightning-pool";
|
||||||
description = "The data directory for lightning-pool.";
|
description = mdDoc "The data directory for lightning-pool.";
|
||||||
};
|
};
|
||||||
proxy = mkOption {
|
proxy = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||||
description = "host:port of SOCKS5 proxy for connnecting to the pool auction server.";
|
description = mdDoc "host:port of SOCKS5 proxy for connnecting to the pool auction server.";
|
||||||
};
|
};
|
||||||
extraConfig = mkOption {
|
extraConfig = mkOption {
|
||||||
type = types.lines;
|
type = types.lines;
|
||||||
@ -46,17 +46,17 @@ let
|
|||||||
example = ''
|
example = ''
|
||||||
debuglevel=trace
|
debuglevel=trace
|
||||||
'';
|
'';
|
||||||
description = "Extra lines appended to the configuration file.";
|
description = mdDoc "Extra lines appended to the configuration file.";
|
||||||
};
|
};
|
||||||
cli = mkOption {
|
cli = mkOption {
|
||||||
default = pkgs.writeScriptBin "pool" ''
|
default = pkgs.writers.writeBashBin "pool" ''
|
||||||
exec ${cfg.package}/bin/pool \
|
exec ${cfg.package}/bin/pool \
|
||||||
--rpcserver ${nbLib.addressWithPort cfg.rpcAddress cfg.rpcPort} \
|
--rpcserver ${nbLib.addressWithPort cfg.rpcAddress cfg.rpcPort} \
|
||||||
--network ${network} \
|
--network ${network} \
|
||||||
--basedir '${cfg.dataDir}' "$@"
|
--basedir '${cfg.dataDir}' "$@"
|
||||||
'';
|
'';
|
||||||
defaultText = "(See source)";
|
defaultText = "(See source)";
|
||||||
description = "Binary to connect with the lightning-pool instance.";
|
description = mdDoc "Binary to connect with the lightning-pool instance.";
|
||||||
};
|
};
|
||||||
tor = nbLib.tor;
|
tor = nbLib.tor;
|
||||||
};
|
};
|
||||||
|
@ -8,19 +8,19 @@ let
|
|||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
description = "Address to listen for peer connections.";
|
description = mdDoc "Address to listen for peer connections.";
|
||||||
};
|
};
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 7042;
|
default = 7042;
|
||||||
description = "Override the default port on which to listen for connections.";
|
description = mdDoc "Override the default port on which to listen for connections.";
|
||||||
};
|
};
|
||||||
onionPort = mkOption {
|
onionPort = mkOption {
|
||||||
type = types.nullOr types.port;
|
type = types.nullOr types.port;
|
||||||
# When the liquidd onion service is enabled, add an onion-tagged socket
|
# When the liquidd onion service is enabled, add an onion-tagged socket
|
||||||
# to distinguish local connections from Tor connections
|
# to distinguish local connections from Tor connections
|
||||||
default = if (config.nix-bitcoin.onionServices.liquidd.enable or false) then 7043 else null;
|
default = if (config.nix-bitcoin.onionServices.liquidd.enable or false) then 7043 else null;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Port to listen for Tor peer connections.
|
Port to listen for Tor peer connections.
|
||||||
If set, inbound connections to this port are tagged as onion peers.
|
If set, inbound connections to this port are tagged as onion peers.
|
||||||
'';
|
'';
|
||||||
@ -28,15 +28,15 @@ let
|
|||||||
listen = mkOption {
|
listen = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Listen for peer connections at `address:port`
|
Listen for peer connections at `address:port`
|
||||||
and `address:onionPort` (if `onionPort` is set).
|
and `address:onionPort` (if {option}`onionPort` is set).
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
listenWhitelisted = mkOption {
|
listenWhitelisted = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Listen for peer connections at `address:whitelistedPort`.
|
Listen for peer connections at `address:whitelistedPort`.
|
||||||
Peers connected through this socket are automatically whitelisted.
|
Peers connected through this socket are automatically whitelisted.
|
||||||
'';
|
'';
|
||||||
@ -44,7 +44,7 @@ let
|
|||||||
whitelistedPort = mkOption {
|
whitelistedPort = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 7044;
|
default = 7044;
|
||||||
description = "See `listenWhitelisted`.";
|
description = mdDoc "See {option}`listenWhitelisted`.";
|
||||||
};
|
};
|
||||||
extraConfig = mkOption {
|
extraConfig = mkOption {
|
||||||
type = types.lines;
|
type = types.lines;
|
||||||
@ -54,23 +54,23 @@ let
|
|||||||
rpcthreads=16
|
rpcthreads=16
|
||||||
logips=1
|
logips=1
|
||||||
'';
|
'';
|
||||||
description = "Extra lines appended to <filename>elements.conf</filename>.";
|
description = mdDoc "Extra lines appended to {file}`elements.conf`.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/liquidd";
|
default = "/var/lib/liquidd";
|
||||||
description = "The data directory for liquidd.";
|
description = mdDoc "The data directory for liquidd.";
|
||||||
};
|
};
|
||||||
rpc = {
|
rpc = {
|
||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
description = "Address to listen for JSON-RPC connections.";
|
description = mdDoc "Address to listen for JSON-RPC connections.";
|
||||||
};
|
};
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 7041;
|
default = 7041;
|
||||||
description = "Port to listen for JSON-RPC connections.";
|
description = mdDoc "Port to listen for JSON-RPC connections.";
|
||||||
};
|
};
|
||||||
users = mkOption {
|
users = mkOption {
|
||||||
default = {};
|
default = {};
|
||||||
@ -79,7 +79,7 @@ let
|
|||||||
bob.passwordHMAC = "b2dd077cb54591a2f3139e69a897ac$4e71f08d48b4347cf8eff3815c0e25ae2e9a4340474079f55705f40574f4ec99";
|
bob.passwordHMAC = "b2dd077cb54591a2f3139e69a897ac$4e71f08d48b4347cf8eff3815c0e25ae2e9a4340474079f55705f40574f4ec99";
|
||||||
};
|
};
|
||||||
type = with types; attrsOf (submodule rpcUserOpts);
|
type = with types; attrsOf (submodule rpcUserOpts);
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
RPC user information for JSON-RPC connections.
|
RPC user information for JSON-RPC connections.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -87,25 +87,25 @@ let
|
|||||||
rpcallowip = mkOption {
|
rpcallowip = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [ "127.0.0.1" ];
|
default = [ "127.0.0.1" ];
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Allow JSON-RPC connections from specified source.
|
Allow JSON-RPC connections from specified source.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
rpcuser = mkOption {
|
rpcuser = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "liquidrpc";
|
default = "liquidrpc";
|
||||||
description = "Username for JSON-RPC connections";
|
description = mdDoc "Username for JSON-RPC connections";
|
||||||
};
|
};
|
||||||
proxy = mkOption {
|
proxy = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||||
description = "Connect through SOCKS5 proxy";
|
description = mdDoc "Connect through SOCKS5 proxy";
|
||||||
};
|
};
|
||||||
dbCache = mkOption {
|
dbCache = mkOption {
|
||||||
type = types.nullOr (types.ints.between 4 16384);
|
type = types.nullOr (types.ints.between 4 16384);
|
||||||
default = null;
|
default = null;
|
||||||
example = 4000;
|
example = 4000;
|
||||||
description = "Override the default database cache size in megabytes.";
|
description = mdDoc "Override the default database cache size in megabytes.";
|
||||||
};
|
};
|
||||||
prune = mkOption {
|
prune = mkOption {
|
||||||
type = types.nullOr (types.coercedTo
|
type = types.nullOr (types.coercedTo
|
||||||
@ -115,13 +115,13 @@ let
|
|||||||
);
|
);
|
||||||
default = null;
|
default = null;
|
||||||
example = 10000;
|
example = 10000;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Reduce storage requirements by enabling pruning (deleting) of old
|
Reduce storage requirements by enabling pruning (deleting) of old
|
||||||
blocks. This allows the pruneblockchain RPC to be called to delete
|
blocks. This allows the pruneblockchain RPC to be called to delete
|
||||||
specific blocks, and enables automatic pruning of old blocks if a
|
specific blocks, and enables automatic pruning of old blocks if a
|
||||||
target size in MiB is provided. This mode is incompatible with -txindex
|
target size in MiB is provided. This mode is incompatible with -txindex
|
||||||
and -rescan. Warning: Reverting this setting requires re-downloading
|
and -rescan. Warning: Reverting this setting requires re-downloading
|
||||||
the entire blockchain. ("disable" = disable pruning blocks, "manual"
|
the entire blockchain. (`disable` = disable pruning blocks, `manual`
|
||||||
= allow manual pruning via RPC, >=550 = automatically prune block files
|
= allow manual pruning via RPC, >=550 = automatically prune block files
|
||||||
to stay under the specified target size in MiB)
|
to stay under the specified target size in MiB)
|
||||||
'';
|
'';
|
||||||
@ -129,34 +129,34 @@ let
|
|||||||
validatepegin = mkOption {
|
validatepegin = mkOption {
|
||||||
type = types.nullOr types.bool;
|
type = types.nullOr types.bool;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Validate pegin claims. All functionaries must run this.
|
Validate pegin claims. All functionaries must run this.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "liquid";
|
default = "liquid";
|
||||||
description = "The user as which to run liquidd.";
|
description = mdDoc "The user as which to run liquidd.";
|
||||||
};
|
};
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.user;
|
default = cfg.user;
|
||||||
description = "The group as which to run liquidd.";
|
description = mdDoc "The group as which to run liquidd.";
|
||||||
};
|
};
|
||||||
cli = mkOption {
|
cli = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = pkgs.writeScriptBin "elements-cli" ''
|
default = pkgs.writers.writeBashBin "elements-cli" ''
|
||||||
${nbPkgs.elementsd}/bin/elements-cli -datadir='${cfg.dataDir}' "$@"
|
${nbPkgs.elementsd}/bin/elements-cli -datadir='${cfg.dataDir}' "$@"
|
||||||
'';
|
'';
|
||||||
defaultText = "(See source)";
|
defaultText = "(See source)";
|
||||||
description = "Binary to connect with the liquidd instance.";
|
description = mdDoc "Binary to connect with the liquidd instance.";
|
||||||
};
|
};
|
||||||
swapCli = mkOption {
|
swapCli = mkOption {
|
||||||
default = pkgs.writeScriptBin "liquidswap-cli" ''
|
default = pkgs.writers.writeBashBin "liquidswap-cli" ''
|
||||||
${nbPkgs.liquid-swap}/bin/liquidswap-cli -c '${cfg.dataDir}/elements.conf' "$@"
|
${nbPkgs.liquid-swap}/bin/liquidswap-cli -c '${cfg.dataDir}/elements.conf' "$@"
|
||||||
'';
|
'';
|
||||||
defaultText = "(See source)";
|
defaultText = "(See source)";
|
||||||
description = "Binary for managing liquid swaps.";
|
description = mdDoc "Binary for managing liquid swaps.";
|
||||||
};
|
};
|
||||||
tor = nbLib.tor;
|
tor = nbLib.tor;
|
||||||
};
|
};
|
||||||
@ -215,16 +215,16 @@ let
|
|||||||
name = mkOption {
|
name = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
example = "alice";
|
example = "alice";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Username for JSON-RPC connections.
|
Username for JSON-RPC connections.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
passwordHMAC = mkOption {
|
passwordHMAC = mkOption {
|
||||||
type = with types; uniq (strMatching "[0-9a-f]+\\$[0-9a-f]{64}");
|
type = with types; uniq (strMatching "[0-9a-f]+\\$[0-9a-f]{64}");
|
||||||
example = "f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae";
|
example = "f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Password HMAC-SHA-256 for JSON-RPC connections. Must be a string of the
|
Password HMAC-SHA-256 for JSON-RPC connections. Must be a string of the
|
||||||
format `salt-hex$hmac-hex`.
|
format `<SALT-HEX>$<HMAC-HEX>`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -270,8 +270,8 @@ in {
|
|||||||
NotifyAccess = "all";
|
NotifyAccess = "all";
|
||||||
User = cfg.user;
|
User = cfg.user;
|
||||||
Group = cfg.group;
|
Group = cfg.group;
|
||||||
TimeoutStartSec = "10min";
|
TimeoutStartSec = "2h";
|
||||||
TimeoutStopSec = "10min";
|
TimeoutStopSec = "2h";
|
||||||
ExecStart = "${nbPkgs.elementsd}/bin/elementsd -datadir='${cfg.dataDir}'";
|
ExecStart = "${nbPkgs.elementsd}/bin/elementsd -datadir='${cfg.dataDir}'";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
ReadWritePaths = [ cfg.dataDir ];
|
ReadWritePaths = [ cfg.dataDir ];
|
||||||
|
@ -7,47 +7,47 @@ let
|
|||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "localhost";
|
default = "localhost";
|
||||||
description = "Address to listen for peer connections";
|
description = mdDoc "Address to listen for peer connections";
|
||||||
};
|
};
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 9735;
|
default = 9735;
|
||||||
description = "Port to listen for peer connections";
|
description = mdDoc "Port to listen for peer connections";
|
||||||
};
|
};
|
||||||
rpcAddress = mkOption {
|
rpcAddress = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "localhost";
|
default = "localhost";
|
||||||
description = "Address to listen for RPC connections.";
|
description = mdDoc "Address to listen for RPC connections.";
|
||||||
};
|
};
|
||||||
rpcPort = mkOption {
|
rpcPort = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 10009;
|
default = 10009;
|
||||||
description = "Port to listen for gRPC connections.";
|
description = mdDoc "Port to listen for gRPC connections.";
|
||||||
};
|
};
|
||||||
restAddress = mkOption {
|
restAddress = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "localhost";
|
default = "localhost";
|
||||||
description = "Address to listen for REST connections.";
|
description = mdDoc "Address to listen for REST connections.";
|
||||||
};
|
};
|
||||||
restPort = mkOption {
|
restPort = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 8080;
|
default = 8080;
|
||||||
description = "Port to listen for REST connections.";
|
description = mdDoc "Port to listen for REST connections.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/lnd";
|
default = "/var/lib/lnd";
|
||||||
description = "The data directory for LND.";
|
description = mdDoc "The data directory for LND.";
|
||||||
};
|
};
|
||||||
networkDir = mkOption {
|
networkDir = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = "${cfg.dataDir}/chain/bitcoin/${bitcoind.network}";
|
default = "${cfg.dataDir}/chain/bitcoin/${bitcoind.network}";
|
||||||
description = "The network data directory.";
|
description = mdDoc "The network data directory.";
|
||||||
};
|
};
|
||||||
tor-socks = mkOption {
|
tor-socks = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
default = if cfg.tor.proxy then config.nix-bitcoin.torClientAddressWithPort else null;
|
||||||
description = "Socks proxy for connecting to Tor nodes";
|
description = mdDoc "Socks proxy for connecting to Tor nodes";
|
||||||
};
|
};
|
||||||
macaroons = mkOption {
|
macaroons = mkOption {
|
||||||
default = {};
|
default = {};
|
||||||
@ -55,18 +55,18 @@ let
|
|||||||
options = {
|
options = {
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
description = "User who owns the macaroon.";
|
description = mdDoc "User who owns the macaroon.";
|
||||||
};
|
};
|
||||||
permissions = mkOption {
|
permissions = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
example = ''
|
example = ''
|
||||||
{"entity":"info","action":"read"},{"entity":"onchain","action":"read"}
|
{"entity":"info","action":"read"},{"entity":"onchain","action":"read"}
|
||||||
'';
|
'';
|
||||||
description = "List of granted macaroon permissions.";
|
description = mdDoc "List of granted macaroon permissions.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Extra macaroon definitions.
|
Extra macaroon definitions.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -75,18 +75,18 @@ let
|
|||||||
type = with types; listOf str;
|
type = with types; listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
example = [ "60.100.0.1" ];
|
example = [ "60.100.0.1" ];
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Extra `subjectAltName` IPs added to the certificate.
|
Extra `subjectAltName` IPs added to the certificate.
|
||||||
This works the same as lnd option `tlsextraip`.
|
This works the same as lnd option {option}`tlsextraip`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
extraDomains = mkOption {
|
extraDomains = mkOption {
|
||||||
type = with types; listOf str;
|
type = with types; listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
example = [ "example.com" ];
|
example = [ "example.com" ];
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Extra `subjectAltName` domain names added to the certificate.
|
Extra `subjectAltName` domain names added to the certificate.
|
||||||
This works the same as lnd option `tlsextradomain`.
|
This works the same as lnd option {option}`tlsextradomain`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -96,8 +96,8 @@ let
|
|||||||
example = ''
|
example = ''
|
||||||
autopilot.active=1
|
autopilot.active=1
|
||||||
'';
|
'';
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Extra lines appended to `lnd.conf`.
|
Extra lines appended to {file}`lnd.conf`.
|
||||||
See here for all available options:
|
See here for all available options:
|
||||||
https://github.com/lightningnetwork/lnd/blob/master/sample-lnd.conf
|
https://github.com/lightningnetwork/lnd/blob/master/sample-lnd.conf
|
||||||
'';
|
'';
|
||||||
@ -106,10 +106,10 @@ let
|
|||||||
type = types.package;
|
type = types.package;
|
||||||
default = config.nix-bitcoin.pkgs.lnd;
|
default = config.nix-bitcoin.pkgs.lnd;
|
||||||
defaultText = "config.nix-bitcoin.pkgs.lnd";
|
defaultText = "config.nix-bitcoin.pkgs.lnd";
|
||||||
description = "The package providing lnd binaries.";
|
description = mdDoc "The package providing lnd binaries.";
|
||||||
};
|
};
|
||||||
cli = mkOption {
|
cli = mkOption {
|
||||||
default = pkgs.writeScriptBin "lncli"
|
default = pkgs.writers.writeBashBin "lncli"
|
||||||
# Switch user because lnd makes datadir contents readable by user only
|
# Switch user because lnd makes datadir contents readable by user only
|
||||||
''
|
''
|
||||||
${runAsUser} ${cfg.user} ${cfg.package}/bin/lncli \
|
${runAsUser} ${cfg.user} ${cfg.package}/bin/lncli \
|
||||||
@ -118,12 +118,12 @@ let
|
|||||||
--macaroonpath '${networkDir}/admin.macaroon' "$@"
|
--macaroonpath '${networkDir}/admin.macaroon' "$@"
|
||||||
'';
|
'';
|
||||||
defaultText = "(See source)";
|
defaultText = "(See source)";
|
||||||
description = "Binary to connect with the lnd instance.";
|
description = mdDoc "Binary to connect with the lnd instance.";
|
||||||
};
|
};
|
||||||
getPublicAddressCmd = mkOption {
|
getPublicAddressCmd = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "";
|
default = "";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Bash expression which outputs the public service address to announce to peers.
|
Bash expression which outputs the public service address to announce to peers.
|
||||||
If left empty, no address is announced.
|
If left empty, no address is announced.
|
||||||
'';
|
'';
|
||||||
@ -131,17 +131,17 @@ let
|
|||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "lnd";
|
default = "lnd";
|
||||||
description = "The user as which to run LND.";
|
description = mdDoc "The user as which to run LND.";
|
||||||
};
|
};
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.user;
|
default = cfg.user;
|
||||||
description = "The group as which to run LND.";
|
description = mdDoc "The group as which to run LND.";
|
||||||
};
|
};
|
||||||
certPath = mkOption {
|
certPath = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = "${secretsDir}/lnd-cert";
|
default = "${secretsDir}/lnd-cert";
|
||||||
description = "LND TLS certificate path.";
|
description = mdDoc "LND TLS certificate path.";
|
||||||
};
|
};
|
||||||
tor = nbLib.tor;
|
tor = nbLib.tor;
|
||||||
};
|
};
|
||||||
@ -174,19 +174,26 @@ let
|
|||||||
${optionalString (cfg.tor-socks != null) "tor.socks=${cfg.tor-socks}"}
|
${optionalString (cfg.tor-socks != null) "tor.socks=${cfg.tor-socks}"}
|
||||||
|
|
||||||
bitcoind.rpchost=${bitcoindRpcAddress}:${toString bitcoind.rpc.port}
|
bitcoind.rpchost=${bitcoindRpcAddress}:${toString bitcoind.rpc.port}
|
||||||
bitcoind.rpcuser=${bitcoind.rpc.users.public.name}
|
bitcoind.rpcuser=${bitcoind.rpc.users.${rpcUser}.name}
|
||||||
bitcoind.zmqpubrawblock=${bitcoind.zmqpubrawblock}
|
bitcoind.zmqpubrawblock=${zmqHandleSpecialAddress bitcoind.zmqpubrawblock}
|
||||||
bitcoind.zmqpubrawtx=${bitcoind.zmqpubrawtx}
|
bitcoind.zmqpubrawtx=${zmqHandleSpecialAddress bitcoind.zmqpubrawtx}
|
||||||
|
|
||||||
wallet-unlock-password-file=${secretsDir}/lnd-wallet-password
|
wallet-unlock-password-file=${secretsDir}/lnd-wallet-password
|
||||||
|
|
||||||
${cfg.extraConfig}
|
${cfg.extraConfig}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
zmqHandleSpecialAddress = builtins.replaceStrings [ "0.0.0.0" "[::]" ] [ "127.0.0.1" "[::1]" ];
|
||||||
|
|
||||||
|
isPruned = bitcoind.prune > 0;
|
||||||
|
# When bitcoind pruning is enabled, lnd requires non-public RPC commands `getpeerinfo`, `getnodeaddresses`
|
||||||
|
# to fetch missing blocks from peers (implemented in btcsuite/btcwallet/chain/pruned_block_dispatcher.go)
|
||||||
|
rpcUser = if isPruned then "lnd" else "public";
|
||||||
in {
|
in {
|
||||||
|
|
||||||
inherit options;
|
inherit options;
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable (mkMerge [ {
|
||||||
assertions = [
|
assertions = [
|
||||||
{ assertion =
|
{ assertion =
|
||||||
!(config.services ? clightning)
|
!(config.services ? clightning)
|
||||||
@ -207,8 +214,8 @@ in {
|
|||||||
# under high bitcoind rpc load
|
# under high bitcoind rpc load
|
||||||
rpc.threads = 16;
|
rpc.threads = 16;
|
||||||
|
|
||||||
zmqpubrawblock = "tcp://${bitcoindRpcAddress}:28332";
|
zmqpubrawblock = mkDefault "tcp://${bitcoindRpcAddress}:28332";
|
||||||
zmqpubrawtx = "tcp://${bitcoindRpcAddress}:28333";
|
zmqpubrawtx = mkDefault "tcp://${bitcoindRpcAddress}:28333";
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = [ cfg.package (hiPrio cfg.cli) ];
|
environment.systemPackages = [ cfg.package (hiPrio cfg.cli) ];
|
||||||
@ -226,7 +233,7 @@ in {
|
|||||||
preStart = ''
|
preStart = ''
|
||||||
install -m600 ${configFile} '${cfg.dataDir}/lnd.conf'
|
install -m600 ${configFile} '${cfg.dataDir}/lnd.conf'
|
||||||
{
|
{
|
||||||
echo "bitcoind.rpcpass=$(cat ${secretsDir}/bitcoin-rpcpassword-public)"
|
echo "bitcoind.rpcpass=$(cat ${secretsDir}/bitcoin-rpcpassword-${rpcUser})"
|
||||||
${optionalString (cfg.getPublicAddressCmd != "") ''
|
${optionalString (cfg.getPublicAddressCmd != "") ''
|
||||||
echo "externalip=$(${cfg.getPublicAddressCmd})"
|
echo "externalip=$(${cfg.getPublicAddressCmd})"
|
||||||
''}
|
''}
|
||||||
@ -304,5 +311,22 @@ in {
|
|||||||
makePasswordSecret lnd-wallet-password
|
makePasswordSecret lnd-wallet-password
|
||||||
makeCert lnd '${nbLib.mkCertExtraAltNames cfg.certificate}'
|
makeCert lnd '${nbLib.mkCertExtraAltNames cfg.certificate}'
|
||||||
'';
|
'';
|
||||||
};
|
}
|
||||||
|
|
||||||
|
(mkIf isPruned {
|
||||||
|
services.bitcoind.rpc.users.lnd = {
|
||||||
|
passwordHMACFromFile = true;
|
||||||
|
rpcwhitelist = bitcoind.rpc.users.public.rpcwhitelist ++ [
|
||||||
|
"getpeerinfo"
|
||||||
|
"getnodeaddresses"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
nix-bitcoin.secrets = {
|
||||||
|
bitcoin-rpcpassword-lnd.user = cfg.user;
|
||||||
|
bitcoin-HMAC-lnd.user = bitcoind.user;
|
||||||
|
};
|
||||||
|
nix-bitcoin.generateSecretsCmds.lndBitcoinRPC = ''
|
||||||
|
makeBitcoinRPCPassword lnd
|
||||||
|
'';
|
||||||
|
}) ]);
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,13 @@ let
|
|||||||
services.lnd.lndconnectOnion.enable = mkOption {
|
services.lnd.lndconnectOnion.enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Create an onion service for the lnd REST server.
|
Create an onion service for the lnd REST server.
|
||||||
Add a `lndconnect-onion` binary to the system environment.
|
Add a `lndconnect-onion` binary to the system environment.
|
||||||
See: https://github.com/LN-Zap/lndconnect
|
See: https://github.com/LN-Zap/lndconnect
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
```
|
```bash
|
||||||
# Print QR code
|
# Print QR code
|
||||||
lndconnect-onion
|
lndconnect-onion
|
||||||
|
|
||||||
@ -25,13 +25,13 @@ let
|
|||||||
services.clightning-rest.lndconnectOnion.enable = mkOption {
|
services.clightning-rest.lndconnectOnion.enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Create an onion service for clightning-rest.
|
Create an onion service for clightning-rest.
|
||||||
Add a `lndconnect-onion-clightning` binary to the system environment.
|
Add a `lndconnect-onion-clightning` binary to the system environment.
|
||||||
See: https://github.com/LN-Zap/lndconnect
|
See: https://github.com/LN-Zap/lndconnect
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
```
|
```bash
|
||||||
# Print QR code
|
# Print QR code
|
||||||
lndconnect-onion-clightning
|
lndconnect-onion-clightning
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ let
|
|||||||
addressblock = mkOption {
|
addressblock = mkOption {
|
||||||
type = types.ints.u8;
|
type = types.ints.u8;
|
||||||
default = 1;
|
default = 1;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
The address block N in 169.254.N.0/24, used as the prefix for netns addresses.
|
The address block N in 169.254.N.0/24, used as the prefix for netns addresses.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -20,7 +20,7 @@ let
|
|||||||
id = mkOption {
|
id = mkOption {
|
||||||
# TODO: Assert uniqueness
|
# TODO: Assert uniqueness
|
||||||
type = types.ints.between 11 255;
|
type = types.ints.between 11 255;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
id for the netns, used for the IP address host part and
|
id for the netns, used for the IP address host part and
|
||||||
for naming the interfaces. Must be unique. Must be greater than 10.
|
for naming the interfaces. Must be unique. Must be greater than 10.
|
||||||
'';
|
'';
|
||||||
@ -35,7 +35,7 @@ let
|
|||||||
|
|
||||||
allowedUser = mkOption {
|
allowedUser = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
User that is allowed to execute commands in the service network namespaces.
|
User that is allowed to execute commands in the service network namespaces.
|
||||||
The user's group is also authorized.
|
The user's group is also authorized.
|
||||||
'';
|
'';
|
||||||
@ -45,13 +45,13 @@ let
|
|||||||
netns = mkOption {
|
netns = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = netns;
|
default = netns;
|
||||||
description = "Exposes netns parameters.";
|
description = mdDoc "Exposes netns parameters.";
|
||||||
};
|
};
|
||||||
|
|
||||||
bridgeIp = mkOption {
|
bridgeIp = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = bridgeIp;
|
default = bridgeIp;
|
||||||
description = "IP of the netns bridge interface.";
|
description = mdDoc "IP of the netns bridge interface.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -215,9 +215,11 @@ in {
|
|||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in foldl (services: n:
|
in
|
||||||
services // (makeNetnsServices n netns.${n})
|
foldl (services: n:
|
||||||
) {} (builtins.attrNames netns));
|
services // (makeNetnsServices n netns.${n})
|
||||||
|
) {} (builtins.attrNames netns)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Service-specific config
|
# Service-specific config
|
||||||
@ -297,6 +299,7 @@ in {
|
|||||||
id = 31;
|
id = 31;
|
||||||
connections = [ "bitcoind" ];
|
connections = [ "bitcoind" ];
|
||||||
};
|
};
|
||||||
|
# id = 32 reserved for the upcoming mempool module
|
||||||
};
|
};
|
||||||
|
|
||||||
services.bitcoind = {
|
services.bitcoind = {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{ config, pkgs, lib, ... }:
|
{ config, options, pkgs, lib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
{
|
{
|
||||||
@ -8,11 +8,23 @@ with lib;
|
|||||||
type = types.attrs;
|
type = types.attrs;
|
||||||
default = (import ../pkgs { inherit pkgs; }).modulesPkgs;
|
default = (import ../pkgs { inherit pkgs; }).modulesPkgs;
|
||||||
defaultText = "nix-bitcoin/pkgs.modulesPkgs";
|
defaultText = "nix-bitcoin/pkgs.modulesPkgs";
|
||||||
|
apply = base:
|
||||||
|
let
|
||||||
|
final = foldl (prev: overlay:
|
||||||
|
prev // (overlay prev final)
|
||||||
|
) base options.nix-bitcoin.pkgOverlays.definitions;
|
||||||
|
in
|
||||||
|
final;
|
||||||
|
};
|
||||||
|
|
||||||
|
pkgOverlays = mkOption {
|
||||||
|
internal = true;
|
||||||
|
type = with types; functionTo attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
lib = mkOption {
|
lib = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = import ../pkgs/lib.nix lib pkgs;
|
default = import ../pkgs/lib.nix lib pkgs config;
|
||||||
defaultText = "nix-bitcoin/pkgs/lib.nix";
|
defaultText = "nix-bitcoin/pkgs/lib.nix";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -27,7 +39,7 @@ with lib;
|
|||||||
# Related issue: https://github.com/NixOS/nixpkgs/issues/94236
|
# Related issue: https://github.com/NixOS/nixpkgs/issues/94236
|
||||||
torify = mkOption {
|
torify = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = pkgs.writeScriptBin "torify" ''
|
default = pkgs.writers.writeBashBin "torify" ''
|
||||||
${pkgs.tor}/bin/torify \
|
${pkgs.tor}/bin/torify \
|
||||||
--address ${config.services.tor.client.socksListenAddress.addr} \
|
--address ${config.services.tor.client.socksListenAddress.addr} \
|
||||||
"$@"
|
"$@"
|
||||||
@ -39,8 +51,7 @@ with lib;
|
|||||||
runAsUserCmd = mkOption {
|
runAsUserCmd = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = if config.security.doas.enable
|
default = if config.security.doas.enable
|
||||||
# TODO-EXTERNAL: Use absolute path until https://github.com/NixOS/nixpkgs/pull/133622 is available.
|
then "doas -u"
|
||||||
then "/run/wrappers/bin/doas -u"
|
|
||||||
else "sudo -u";
|
else "sudo -u";
|
||||||
defaultText = "(See source)";
|
defaultText = "(See source)";
|
||||||
};
|
};
|
||||||
|
@ -17,17 +17,17 @@ let
|
|||||||
type = types.attrs;
|
type = types.attrs;
|
||||||
default = {};
|
default = {};
|
||||||
defaultText = "(See source)";
|
defaultText = "(See source)";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Nodeinfo service definitions.
|
Nodeinfo service definitions.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
nodeinfoLib = mkOption {
|
lib = mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = nodeinfoLib;
|
default = nodeinfoLib;
|
||||||
defaultText = "(See source)";
|
defaultText = "(See source)";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Helper functions for defining nodeinfo services.
|
Helper functions for defining nodeinfo services.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -73,9 +73,10 @@ let
|
|||||||
return
|
return
|
||||||
info["onion_address"] = f"{onion_address}:{port}"
|
info["onion_address"] = f"{onion_address}:{port}"
|
||||||
|
|
||||||
def add_service(service, make_info):
|
def add_service(service, make_info, systemd_service = None):
|
||||||
if not is_active(service):
|
systemd_service = systemd_service or service
|
||||||
infos[service] = "service is not running"
|
if not is_active(systemd_service):
|
||||||
|
infos[service] = f"'{systemd_service}.service' is not running"
|
||||||
else:
|
else:
|
||||||
info = OrderedDict()
|
info = OrderedDict()
|
||||||
exec(make_info, globals(), locals())
|
exec(make_info, globals(), locals())
|
||||||
@ -96,14 +97,19 @@ let
|
|||||||
) (builtins.attrNames cfg.services);
|
) (builtins.attrNames cfg.services);
|
||||||
|
|
||||||
nodeinfoLib = rec {
|
nodeinfoLib = rec {
|
||||||
mkInfo = extraCode: name: cfg: ''
|
mkInfo = extraCode: name: cfg:
|
||||||
|
mkInfoLong {
|
||||||
|
inherit extraCode name cfg;
|
||||||
|
};
|
||||||
|
|
||||||
|
mkInfoLong = { extraCode ? "", name, cfg, systemdServiceName ? name }: ''
|
||||||
add_service("${name}", """
|
add_service("${name}", """
|
||||||
info["local_address"] = "${nbLib.addressWithPort cfg.address cfg.port}"
|
info["local_address"] = "${nbLib.addressWithPort cfg.address cfg.port}"
|
||||||
'' + mkIfOnionPort name (onionPort: ''
|
'' + mkIfOnionPort name (onionPort: ''
|
||||||
set_onion_address(info, "${name}", ${onionPort})
|
set_onion_address(info, "${name}", ${onionPort})
|
||||||
'') + extraCode + ''
|
'') + extraCode + ''
|
||||||
|
|
||||||
""")
|
""", "${systemdServiceName}")
|
||||||
'';
|
'';
|
||||||
|
|
||||||
mkIfOnionPort = name: fn:
|
mkIfOnionPort = name: fn:
|
||||||
|
@ -12,23 +12,25 @@ let
|
|||||||
access = mkOption {
|
access = mkOption {
|
||||||
type = with types; attrsOf (listOf str);
|
type = with types; attrsOf (listOf str);
|
||||||
default = {};
|
default = {};
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
This option controls who is allowed to access onion addresses.
|
This option controls who is allowed to access onion addresses.
|
||||||
For example, the following allows user 'myuser' to access bitcoind
|
For example, the following allows user 'myuser' to access bitcoind
|
||||||
and clightning onion addresses:
|
and clightning onion addresses:
|
||||||
|
```nix
|
||||||
{
|
{
|
||||||
"myuser" = [ "bitcoind" "clightning" ];
|
"myuser" = [ "bitcoind" "clightning" ];
|
||||||
};
|
};
|
||||||
|
```
|
||||||
The onion hostnames can then be read from
|
The onion hostnames can then be read from
|
||||||
/var/lib/onion-addresses/myuser.
|
{file}`/var/lib/onion-addresses/myuser`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
services = mkOption {
|
services = mkOption {
|
||||||
type = with types; listOf str;
|
type = with types; listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Services that can access their onion address via file
|
Services that can access their onion address via file
|
||||||
`/var/lib/onion-addresses/$service`
|
{file}`/var/lib/onion-addresses/<service>`
|
||||||
The file is readable only by the service user.
|
The file is readable only by the service user.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -53,8 +55,8 @@ in {
|
|||||||
RemainAfterExit = true;
|
RemainAfterExit = true;
|
||||||
StateDirectory = "onion-addresses";
|
StateDirectory = "onion-addresses";
|
||||||
StateDirectoryMode = "771";
|
StateDirectoryMode = "771";
|
||||||
PrivateNetwork = "true"; # This service needs no network access
|
PrivateNetwork = true; # This service needs no network access
|
||||||
PrivateUsers = "false";
|
PrivateUsers = false;
|
||||||
CapabilityBoundingSet = "CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_IPC_OWNER";
|
CapabilityBoundingSet = "CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_IPC_OWNER";
|
||||||
};
|
};
|
||||||
script = ''
|
script = ''
|
||||||
|
@ -16,24 +16,24 @@ let
|
|||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = config.public;
|
default = config.public;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Create an onion service for the given service.
|
Create an onion service for the given service.
|
||||||
The service must define options 'address' and 'onionPort' (or `port`).
|
The service must define options {option}'address' and {option}'onionPort' (or `port`).
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
public = mkOption {
|
public = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Make the onion address accessible to the service.
|
Make the onion address accessible to the service.
|
||||||
If enabled, the onion service is automatically enabled.
|
If enabled, the onion service is automatically enabled.
|
||||||
Only available for services that define option `getPublicAddressCmd`.
|
Only available for services that define option {option}`getPublicAddressCmd`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
externalPort = mkOption {
|
externalPort = mkOption {
|
||||||
type = types.nullOr types.port;
|
type = types.nullOr types.port;
|
||||||
default = null;
|
default = null;
|
||||||
description = "Override the external port of the onion service.";
|
description = mdDoc "Override the external port of the onion service.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ let
|
|||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Whether to define a user named `operator` for convenient interactive access
|
Whether to define a user named `operator` for convenient interactive access
|
||||||
to nix-bitcoin features (like `bitcoin-cli`).
|
to nix-bitcoin features (like `bitcoin-cli`).
|
||||||
|
|
||||||
@ -18,17 +18,17 @@ let
|
|||||||
name = mkOption {
|
name = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "operator";
|
default = "operator";
|
||||||
description = "Name of the operator user.";
|
description = mdDoc "Name of the operator user.";
|
||||||
};
|
};
|
||||||
groups = mkOption {
|
groups = mkOption {
|
||||||
type = with types; listOf str;
|
type = with types; listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
description = "Extra groups of the operatur user.";
|
description = mdDoc "Extra groups of the operatur user.";
|
||||||
};
|
};
|
||||||
allowRunAsUsers = mkOption {
|
allowRunAsUsers = mkOption {
|
||||||
type = with types; listOf str;
|
type = with types; listOf str;
|
||||||
default = [];
|
default = [];
|
||||||
description = "Users as which the operator is allowed to run commands.";
|
description = mdDoc "Users as which the operator is allowed to run commands.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,7 +5,9 @@ let
|
|||||||
secretsDir = config.nix-bitcoin.secretsDir;
|
secretsDir = config.nix-bitcoin.secretsDir;
|
||||||
in {
|
in {
|
||||||
services.bitcoind = {
|
services.bitcoind = {
|
||||||
# Make the local bitcoin-cli work with the remote node
|
# Make the local bitcoin-cli work with the remote node.
|
||||||
|
# Without this, bitcoin-cli would try to use the .cookie file in the local
|
||||||
|
# bitcoind data dir for authorization, which doesn't exist.
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
rpcuser=${cfg.rpc.users.privileged.name}
|
rpcuser=${cfg.rpc.users.privileged.name}
|
||||||
'';
|
'';
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
{
|
{ modulesPath, ... }: {
|
||||||
imports = [
|
imports = [
|
||||||
# Source: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/hardened.nix
|
# Source:
|
||||||
<nixpkgs/nixos/modules/profiles/hardened.nix>
|
# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/hardened.nix
|
||||||
|
(modulesPath + "/profiles/hardened.nix")
|
||||||
];
|
];
|
||||||
|
|
||||||
## Reset some options set by the hardened profile
|
## Reset some options set by the hardened profile
|
||||||
|
@ -7,33 +7,33 @@ let
|
|||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "127.0.0.1";
|
default = "127.0.0.1";
|
||||||
description = "HTTP server address.";
|
description = mdDoc "HTTP server address.";
|
||||||
};
|
};
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 3000;
|
default = 3000;
|
||||||
description = "HTTP server port.";
|
description = mdDoc "HTTP server port.";
|
||||||
};
|
};
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/var/lib/rtl";
|
default = "/var/lib/rtl";
|
||||||
description = "The data directory for RTL.";
|
description = mdDoc "The data directory for RTL.";
|
||||||
};
|
};
|
||||||
nodes = {
|
nodes = {
|
||||||
clightning = {
|
clightning = {
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = "Enable the clightning node interface.";
|
description = mdDoc "Enable the clightning node interface.";
|
||||||
};
|
};
|
||||||
extraConfig = mkOption {
|
extraConfig = mkOption {
|
||||||
type = types.attrs;
|
type = with types; attrsOf anything;
|
||||||
default = {};
|
default = {};
|
||||||
example = {
|
example = {
|
||||||
Settings.userPersona = "MERCHANT";
|
Settings.userPersona = "MERCHANT";
|
||||||
Settings.logLevel = "DEBUG";
|
Settings.logLevel = "DEBUG";
|
||||||
};
|
};
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Extra clightning node configuration.
|
Extra clightning node configuration.
|
||||||
See here for all available options:
|
See here for all available options:
|
||||||
https://github.com/Ride-The-Lightning/RTL/blob/master/.github/docs/Application_configurations.md
|
https://github.com/Ride-The-Lightning/RTL/blob/master/.github/docs/Application_configurations.md
|
||||||
@ -44,21 +44,21 @@ let
|
|||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = "Enable the lnd node interface.";
|
description = mdDoc "Enable the lnd node interface.";
|
||||||
};
|
};
|
||||||
loop = mkOption {
|
loop = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = "Enable swaps with lightning-loop.";
|
description = mdDoc "Enable swaps with lightning-loop.";
|
||||||
};
|
};
|
||||||
extraConfig = mkOption {
|
extraConfig = mkOption {
|
||||||
type = types.attrs;
|
type = with types; attrsOf anything;
|
||||||
default = {};
|
default = {};
|
||||||
example = {
|
example = {
|
||||||
Settings.userPersona = "MERCHANT";
|
Settings.userPersona = "MERCHANT";
|
||||||
Settings.logLevel = "DEBUG";
|
Settings.logLevel = "DEBUG";
|
||||||
};
|
};
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Extra lnd node configuration.
|
Extra lnd node configuration.
|
||||||
See here for all available options:
|
See here for all available options:
|
||||||
https://github.com/Ride-The-Lightning/RTL/blob/master/.github/docs/Application_configurations.md
|
https://github.com/Ride-The-Lightning/RTL/blob/master/.github/docs/Application_configurations.md
|
||||||
@ -68,7 +68,7 @@ let
|
|||||||
reverseOrder = mkOption {
|
reverseOrder = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Reverse the order of nodes shown in the UI.
|
Reverse the order of nodes shown in the UI.
|
||||||
By default, clightning is shown before lnd.
|
By default, clightning is shown before lnd.
|
||||||
'';
|
'';
|
||||||
@ -77,28 +77,28 @@ let
|
|||||||
nightTheme = mkOption {
|
nightTheme = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = "Enable the Night UI Theme.";
|
description = mdDoc "Enable the Night UI Theme.";
|
||||||
};
|
};
|
||||||
extraCurrency = mkOption {
|
extraCurrency = mkOption {
|
||||||
type = with types; nullOr str;
|
type = with types; nullOr str;
|
||||||
default = null;
|
default = null;
|
||||||
example = "USD";
|
example = "USD";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Currency code (ISO 4217) of the extra currency used for displaying balances.
|
Currency code (ISO 4217) of the extra currency used for displaying balances.
|
||||||
When set, this option enables online currency rate fetching.
|
When set, this option enables online currency rate fetching.
|
||||||
Warning: Rate fetching requires outgoing clearnet connections, so option
|
Warning: Rate fetching requires outgoing clearnet connections, so option
|
||||||
`tor.enforce` is automatically disabled.
|
{option}`tor.enforce` is automatically disabled.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "rtl";
|
default = "rtl";
|
||||||
description = "The user as which to run RTL.";
|
description = mdDoc "The user as which to run RTL.";
|
||||||
};
|
};
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.user;
|
default = cfg.user;
|
||||||
description = "The group as which to run RTL.";
|
description = mdDoc "The group as which to run RTL.";
|
||||||
};
|
};
|
||||||
tor.enforce = nbLib.tor.enforce;
|
tor.enforce = nbLib.tor.enforce;
|
||||||
};
|
};
|
||||||
|
@ -6,14 +6,14 @@ let
|
|||||||
secretsDir = mkOption {
|
secretsDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
default = "/etc/nix-bitcoin-secrets";
|
default = "/etc/nix-bitcoin-secrets";
|
||||||
description = "Directory to store secrets";
|
description = mdDoc "Directory to store secrets";
|
||||||
};
|
};
|
||||||
|
|
||||||
setupSecrets = mkOption {
|
setupSecrets = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Set permissions for existing secrets in `nix-bitcoin.secretsDir`
|
Set permissions for existing secrets in {option}`nix-bitcoin.secretsDir`
|
||||||
before services are started.
|
before services are started.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -21,16 +21,16 @@ let
|
|||||||
generateSecrets = mkOption {
|
generateSecrets = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Automatically generate all required secrets before services are started.
|
Automatically generate all required secrets before services are started.
|
||||||
Note: Make sure to create a backup of the generated secrets.
|
Note: Make sure to create a backup of the generated secrets.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
generateSecretsCmds = mkOption {
|
generateSecretsCmds = mkOption {
|
||||||
type = types.attrsOf types.str;
|
type = types.attrsOf types.lines;
|
||||||
default = {};
|
default = {};
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Bash expressions for generating secrets.
|
Bash expressions for generating secrets.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -38,7 +38,7 @@ let
|
|||||||
# Currently, this is used only by ../deployment/nixops.nix
|
# Currently, this is used only by ../deployment/nixops.nix
|
||||||
deployment.secretsDir = mkOption {
|
deployment.secretsDir = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Directory of local secrets that are transferred to the nix-bitcoin node on deployment
|
Directory of local secrets that are transferred to the nix-bitcoin node on deployment
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
@ -6,16 +6,16 @@ with lib;
|
|||||||
nix-bitcoin.security.dbusHideProcessInformation = mkOption {
|
nix-bitcoin.security.dbusHideProcessInformation = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Only allow users with group 'proc' to retrieve systemd unit information like
|
Only allow users with group `proc` to retrieve systemd unit information like
|
||||||
cgroup paths (i.e. (sub)process command lines) via D-Bus.
|
cgroup paths (i.e. (sub)process command lines) via D-Bus.
|
||||||
|
|
||||||
This mitigates a systemd security issue where (sub)process command lines can
|
This mitigates a systemd security issue where (sub)process command lines can
|
||||||
be retrieved by services even when their access to /proc is restricted
|
be retrieved by services even when their access to /proc is restricted
|
||||||
(via ProtectProc).
|
(via ProtectProc).
|
||||||
|
|
||||||
This option works by restricting the D-Bus method 'GetUnitProcesses', which
|
This option works by restricting the D-Bus method `GetUnitProcesses`, which
|
||||||
is also used internally by `systemctl status`.
|
is also used internally by {command}`systemctl status`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -7,22 +7,22 @@ let
|
|||||||
address = mkOption {
|
address = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "localhost";
|
default = "localhost";
|
||||||
description = "http(s) server address.";
|
description = mdDoc "http(s) server address.";
|
||||||
};
|
};
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 9737;
|
default = 9737;
|
||||||
description = "http(s) server port.";
|
description = mdDoc "http(s) server port.";
|
||||||
};
|
};
|
||||||
extraArgs = mkOption {
|
extraArgs = mkOption {
|
||||||
type = types.separatedString " ";
|
type = types.separatedString " ";
|
||||||
default = "";
|
default = "";
|
||||||
description = "Extra command line arguments passed to spark-wallet.";
|
description = mdDoc "Extra command line arguments passed to spark-wallet.";
|
||||||
};
|
};
|
||||||
getPublicAddressCmd = mkOption {
|
getPublicAddressCmd = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "";
|
default = "";
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Bash expression which outputs the public service address.
|
Bash expression which outputs the public service address.
|
||||||
If set, spark-wallet prints a QR code to the systemd journal which
|
If set, spark-wallet prints a QR code to the systemd journal which
|
||||||
encodes an URL for accessing the web interface.
|
encodes an URL for accessing the web interface.
|
||||||
@ -31,12 +31,12 @@ let
|
|||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "spark-wallet";
|
default = "spark-wallet";
|
||||||
description = "The user as which to run spark-wallet.";
|
description = mdDoc "The user as which to run spark-wallet.";
|
||||||
};
|
};
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.user;
|
default = cfg.user;
|
||||||
description = "The group as which to run spark-wallet.";
|
description = mdDoc "The group as which to run spark-wallet.";
|
||||||
};
|
};
|
||||||
tor = nbLib.tor;
|
tor = nbLib.tor;
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,7 @@ let
|
|||||||
nix-bitcoin.configVersion = mkOption {
|
nix-bitcoin.configVersion = mkOption {
|
||||||
type = with types; nullOr str;
|
type = with types; nullOr str;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Set this option to the nix-bitcoin release version that your config is
|
Set this option to the nix-bitcoin release version that your config is
|
||||||
compatible with.
|
compatible with.
|
||||||
|
|
||||||
@ -231,6 +231,15 @@ let
|
|||||||
The `lndconnect-rest-onion` binary has been renamed to `lndconnect-onion`.
|
The `lndconnect-rest-onion` binary has been renamed to `lndconnect-onion`.
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
version = "0.0.85";
|
||||||
|
condition = config.services.fulcrum.enable;
|
||||||
|
message = ''
|
||||||
|
Fulcrum 1.9.0 has changed its database format.
|
||||||
|
The database update happens automatically and instantly on deployment,
|
||||||
|
but you can't switch back to an older Fulcrum version afterwards.
|
||||||
|
'';
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
mkOnionServiceChange = service: {
|
mkOnionServiceChange = service: {
|
||||||
|
@ -6,8 +6,8 @@ let
|
|||||||
src = pkgs.fetchFromGitHub {
|
src = pkgs.fetchFromGitHub {
|
||||||
owner = "lightningd";
|
owner = "lightningd";
|
||||||
repo = "plugins";
|
repo = "plugins";
|
||||||
rev = "59bad754cb338872c622ad716e8ed0063edf4052";
|
rev = "e625369423b00c70b23641662f62ccd898286edc";
|
||||||
sha256 = "19nnmv2jvb0xmcha79dij399avasn2x521n9qg11lqj8xnzadm6a";
|
sha256 = "04f30xlfr7pgdmdgka87x7sc9j82wc4zv7fbiqrjsc83dkmly81i";
|
||||||
};
|
};
|
||||||
|
|
||||||
version = builtins.substring 0 7 src.rev;
|
version = builtins.substring 0 7 src.rev;
|
||||||
@ -31,8 +31,8 @@ let
|
|||||||
description = "Lightning node exporter for the prometheus timeseries server";
|
description = "Lightning node exporter for the prometheus timeseries server";
|
||||||
extraPkgs = [ prometheus_client ];
|
extraPkgs = [ prometheus_client ];
|
||||||
patchRequirements =
|
patchRequirements =
|
||||||
"--replace prometheus-client==0.6.0 prometheus-client==0.13.1"
|
"--replace prometheus-client==0.6.0 prometheus-client==0.15.0"
|
||||||
+ " --replace pyln-client~=0.9.3 pyln-client~=0.11.1";
|
+ " --replace pyln-client~=0.9.3 pyln-client~=22.11rc1";
|
||||||
};
|
};
|
||||||
rebalance = {
|
rebalance = {
|
||||||
description = "Keeps your channels balanced";
|
description = "Keeps your channels balanced";
|
||||||
@ -80,7 +80,7 @@ let
|
|||||||
inherit (plugin) description;
|
inherit (plugin) description;
|
||||||
homepage = "https://github.com/lightningd/plugins";
|
homepage = "https://github.com/lightningd/plugins";
|
||||||
license = licenses.bsd3;
|
license = licenses.bsd3;
|
||||||
maintainers = with maintainers; [ nixbitcoin earvstedt ];
|
maintainers = with maintainers; [ nixbitcoin erikarvstedt ];
|
||||||
platforms = platforms.unix;
|
platforms = platforms.unix;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -49,7 +49,7 @@ let self = stdenvNoCC.mkDerivation {
|
|||||||
description = "REST API for C-Lightning";
|
description = "REST API for C-Lightning";
|
||||||
homepage = "https://github.com/Ride-The-Lightning/c-lightning-REST";
|
homepage = "https://github.com/Ride-The-Lightning/c-lightning-REST";
|
||||||
license = licenses.mit;
|
license = licenses.mit;
|
||||||
maintainers = with maintainers; [ nixbitcoin earvstedt ];
|
maintainers = with maintainers; [ nixbitcoin erikarvstedt ];
|
||||||
platforms = platforms.unix;
|
platforms = platforms.unix;
|
||||||
};
|
};
|
||||||
}; in self
|
}; in self
|
||||||
|
@ -13,7 +13,7 @@ let self = {
|
|||||||
clightning-rest = pkgs.callPackage ./clightning-rest { inherit (self) fetchNodeModules; };
|
clightning-rest = pkgs.callPackage ./clightning-rest { inherit (self) fetchNodeModules; };
|
||||||
clboss = pkgs.callPackage ./clboss { };
|
clboss = pkgs.callPackage ./clboss { };
|
||||||
clightning-plugins = pkgs.recurseIntoAttrs (import ./clightning-plugins pkgs self.nbPython3Packages);
|
clightning-plugins = pkgs.recurseIntoAttrs (import ./clightning-plugins pkgs self.nbPython3Packages);
|
||||||
joinmarket = pkgs.callPackage ./joinmarket { nbPythonPackageOverrides = import ./python-packages self; };
|
joinmarket = pkgs.callPackage ./joinmarket { inherit (self) nbPython3PackagesJoinmarket; };
|
||||||
lndinit = pkgs.callPackage ./lndinit { };
|
lndinit = pkgs.callPackage ./lndinit { };
|
||||||
liquid-swap = pkgs.python3Packages.callPackage ./liquid-swap { };
|
liquid-swap = pkgs.python3Packages.callPackage ./liquid-swap { };
|
||||||
rtl = pkgs.callPackage ./rtl { inherit (self) fetchNodeModules; };
|
rtl = pkgs.callPackage ./rtl { inherit (self) fetchNodeModules; };
|
||||||
@ -21,9 +21,10 @@ let self = {
|
|||||||
secp256k1 = pkgs.callPackage ./secp256k1 { };
|
secp256k1 = pkgs.callPackage ./secp256k1 { };
|
||||||
spark-wallet = pkgs.callPackage ./spark-wallet { };
|
spark-wallet = pkgs.callPackage ./spark-wallet { };
|
||||||
|
|
||||||
nbPython3Packages = (pkgs.python3.override {
|
pyPkgs = import ./python-packages self pkgs.python3;
|
||||||
packageOverrides = import ./python-packages self;
|
inherit (self.pyPkgs)
|
||||||
}).pkgs;
|
nbPython3Packages
|
||||||
|
nbPython3PackagesJoinmarket;
|
||||||
|
|
||||||
fetchNodeModules = pkgs.callPackage ./build-support/fetch-node-modules.nix { };
|
fetchNodeModules = pkgs.callPackage ./build-support/fetch-node-modules.nix { };
|
||||||
|
|
||||||
|
@ -1,23 +1,13 @@
|
|||||||
{ stdenv, lib, fetchurl, python3, nbPythonPackageOverrides, pkgs }:
|
{ stdenv, lib, fetchurl, python3, nbPython3PackagesJoinmarket }:
|
||||||
|
|
||||||
let
|
let
|
||||||
version = "0.9.7";
|
version = "0.9.8";
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://github.com/JoinMarket-Org/joinmarket-clientserver/archive/v${version}.tar.gz";
|
url = "https://github.com/JoinMarket-Org/joinmarket-clientserver/archive/v${version}.tar.gz";
|
||||||
sha256 = "13bfr8ha6bka8wiai8m79ki43dn2r311lrfffr39ni2wy1v12l93";
|
sha256 = "1ab4smpyx966iiiip3g11bcslya37qhac1kgkbmsmlsdkpilw9di";
|
||||||
};
|
};
|
||||||
|
|
||||||
pyPkgs = (python3.override {
|
runtimePackages = with nbPython3PackagesJoinmarket; [
|
||||||
packageOverrides = (self: super: let
|
|
||||||
overrides = nbPythonPackageOverrides self super;
|
|
||||||
in
|
|
||||||
overrides // {
|
|
||||||
cryptography = overrides.cryptography_3_3_2;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}).pkgs;
|
|
||||||
|
|
||||||
runtimePackages = with pyPkgs; [
|
|
||||||
joinmarketbase
|
joinmarketbase
|
||||||
joinmarketclient
|
joinmarketclient
|
||||||
joinmarketbitcoin
|
joinmarketbitcoin
|
||||||
|
44
pkgs/lib.nix
44
pkgs/lib.nix
@ -1,4 +1,4 @@
|
|||||||
lib: pkgs:
|
lib: pkgs: config:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
@ -7,33 +7,33 @@ with lib;
|
|||||||
let self = {
|
let self = {
|
||||||
# These settings roughly follow systemd's "strict" security profile
|
# These settings roughly follow systemd's "strict" security profile
|
||||||
defaultHardening = {
|
defaultHardening = {
|
||||||
PrivateTmp = "true";
|
PrivateTmp = true;
|
||||||
ProtectSystem = "strict";
|
ProtectSystem = "strict";
|
||||||
ProtectHome = "true";
|
ProtectHome = true;
|
||||||
NoNewPrivileges = "true";
|
NoNewPrivileges = true;
|
||||||
PrivateDevices = "true";
|
PrivateDevices = true;
|
||||||
MemoryDenyWriteExecute = "true";
|
MemoryDenyWriteExecute = true;
|
||||||
ProtectKernelTunables = "true";
|
ProtectKernelTunables = true;
|
||||||
ProtectKernelModules = "true";
|
ProtectKernelModules = true;
|
||||||
ProtectKernelLogs = "true";
|
ProtectKernelLogs = true;
|
||||||
ProtectClock = "true";
|
ProtectClock = true;
|
||||||
ProtectProc = "invisible";
|
ProtectProc = "invisible";
|
||||||
ProcSubset = "pid";
|
ProcSubset = "pid";
|
||||||
ProtectControlGroups = "true";
|
ProtectControlGroups = true;
|
||||||
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||||
RestrictNamespaces = "true";
|
RestrictNamespaces = true;
|
||||||
LockPersonality = "true";
|
LockPersonality = true;
|
||||||
IPAddressDeny = "any";
|
IPAddressDeny = "any";
|
||||||
PrivateUsers = "true";
|
PrivateUsers = true;
|
||||||
RestrictSUIDSGID = "true";
|
RestrictSUIDSGID = true;
|
||||||
RemoveIPC = "true";
|
RemoveIPC = true;
|
||||||
RestrictRealtime = "true";
|
RestrictRealtime = true;
|
||||||
ProtectHostname = "true";
|
ProtectHostname = true;
|
||||||
CapabilityBoundingSet = "";
|
CapabilityBoundingSet = "";
|
||||||
# @system-service whitelist and docker seccomp blacklist (except for "clone"
|
# @system-service whitelist and docker seccomp blacklist (except for "clone"
|
||||||
# which is a core requirement for systemd services)
|
# which is a core requirement for systemd services)
|
||||||
# @system-service is defined in src/shared/seccomp-util.c (systemd source)
|
# @system-service is defined in src/shared/seccomp-util.c (systemd source)
|
||||||
SystemCallFilter = [ "@system-service" "~add_key kcmp keyctl mbind move_pages name_to_handle_at personality process_vm_readv process_vm_writev request_key set_mempolicy setns unshare userfaultfd" ];
|
SystemCallFilter = [ "@system-service" "~add_key kcmp keyctl mbind move_pages name_to_handle_at personality process_vm_readv process_vm_writev request_key setns unshare userfaultfd" ];
|
||||||
SystemCallArchitectures = "native";
|
SystemCallArchitectures = "native";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ let self = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
# nodejs applications require memory write execute for JIT compilation
|
# nodejs applications require memory write execute for JIT compilation
|
||||||
nodejs = { MemoryDenyWriteExecute = "false"; };
|
nodejs = { MemoryDenyWriteExecute = false; };
|
||||||
|
|
||||||
# Allow takes precedence over Deny.
|
# Allow takes precedence over Deny.
|
||||||
allowLocalIPAddresses = {
|
allowLocalIPAddresses = {
|
||||||
@ -115,4 +115,8 @@ let self = {
|
|||||||
(map (ip: "IP:${ip}") cert.extraIPs)
|
(map (ip: "IP:${ip}") cert.extraIPs)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test = {
|
||||||
|
mkIfTest = test: mkIf (config.tests.${test} or false);
|
||||||
|
};
|
||||||
|
|
||||||
}; in self
|
}; in self
|
||||||
|
@ -19,6 +19,6 @@ buildGoModule rec {
|
|||||||
description = "Wallet initializer utility for lnd";
|
description = "Wallet initializer utility for lnd";
|
||||||
homepage = "https://github.com/lightninglabs/lndinit";
|
homepage = "https://github.com/lightninglabs/lndinit";
|
||||||
license = licenses.mit;
|
license = licenses.mit;
|
||||||
maintainers = with maintainers; [ earvstedt ];
|
maintainers = with maintainers; [ erikarvstedt ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -16,5 +16,5 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
nixpkgs = fetch lockedInputs.nixpkgs;
|
nixpkgs = fetch lockedInputs.nixpkgs;
|
||||||
nixpkgs-unstable = fetch lockedInputs.nixpkgsUnstable;
|
nixpkgs-unstable = fetch lockedInputs.nixpkgs-unstable;
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@ pkgs: pkgsUnstable:
|
|||||||
inherit (pkgs)
|
inherit (pkgs)
|
||||||
bitcoin
|
bitcoin
|
||||||
bitcoind
|
bitcoind
|
||||||
electrs
|
|
||||||
elementsd
|
elementsd
|
||||||
extra-container
|
extra-container
|
||||||
|
lightning-loop
|
||||||
lightning-pool
|
lightning-pool
|
||||||
lndconnect
|
lndconnect
|
||||||
nbxplorer;
|
nbxplorer;
|
||||||
@ -15,9 +15,9 @@ pkgs: pkgsUnstable:
|
|||||||
btcpayserver
|
btcpayserver
|
||||||
charge-lnd
|
charge-lnd
|
||||||
clightning
|
clightning
|
||||||
|
electrs
|
||||||
fulcrum
|
fulcrum
|
||||||
hwi
|
hwi
|
||||||
lightning-loop
|
|
||||||
lnd;
|
lnd;
|
||||||
|
|
||||||
inherit pkgs pkgsUnstable;
|
inherit pkgs pkgsUnstable;
|
||||||
|
@ -1,51 +1,66 @@
|
|||||||
nbPkgs: self: super:
|
nbPkgs: python3:
|
||||||
let
|
rec {
|
||||||
inherit (self) callPackage;
|
pyPkgsOverrides = self: super: let
|
||||||
|
inherit (self) callPackage;
|
||||||
|
clightningPkg = pkg: callPackage pkg { inherit (nbPkgs.pinned) clightning; };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
coincurve = callPackage ./coincurve {};
|
||||||
|
txzmq = callPackage ./txzmq {};
|
||||||
|
|
||||||
joinmarketPkg = pkg: callPackage pkg { inherit (nbPkgs.joinmarket) version src; };
|
pyln-client = clightningPkg ./pyln-client;
|
||||||
clightningPkg = pkg: callPackage pkg { inherit (nbPkgs.pinned) clightning; };
|
pyln-proto = clightningPkg ./pyln-proto;
|
||||||
|
pyln-bolt7 = clightningPkg ./pyln-bolt7;
|
||||||
|
pylightning = clightningPkg ./pylightning;
|
||||||
|
|
||||||
unstable = (import ../nixpkgs-pinned.nix).nixpkgs-unstable;
|
# Packages only used by joinmarket
|
||||||
in {
|
bencoderpyx = callPackage ./bencoderpyx {};
|
||||||
bencoderpyx = callPackage ./bencoderpyx {};
|
chromalog = callPackage ./chromalog {};
|
||||||
chromalog = callPackage ./chromalog {};
|
python-bitcointx = callPackage ./python-bitcointx {
|
||||||
coincurve = callPackage ./coincurve {};
|
inherit (nbPkgs) secp256k1;
|
||||||
python-bitcointx = callPackage ./python-bitcointx { inherit (nbPkgs) secp256k1; };
|
openssl = super.pkgs.openssl_1_1;
|
||||||
runes = callPackage ./runes {};
|
};
|
||||||
sha256 = callPackage ./sha256 {};
|
runes = callPackage ./runes {};
|
||||||
txzmq = callPackage ./txzmq {};
|
sha256 = callPackage ./sha256 {};
|
||||||
urldecode = callPackage ./urldecode {};
|
urldecode = callPackage ./urldecode {};
|
||||||
|
};
|
||||||
|
|
||||||
joinmarketbase = joinmarketPkg ./jmbase;
|
# Joinmarket requires a custom package set because it uses older versions of Python pkgs
|
||||||
joinmarketclient = joinmarketPkg ./jmclient;
|
pyPkgsOverridesJoinmarket = self: super: let
|
||||||
joinmarketbitcoin = joinmarketPkg ./jmbitcoin;
|
inherit (self) callPackage;
|
||||||
joinmarketdaemon = joinmarketPkg ./jmdaemon;
|
joinmarketPkg = pkg: callPackage pkg { inherit (nbPkgs.joinmarket) version src; };
|
||||||
|
in
|
||||||
|
(pyPkgsOverrides self super) // {
|
||||||
|
joinmarketbase = joinmarketPkg ./jmbase;
|
||||||
|
joinmarketclient = joinmarketPkg ./jmclient;
|
||||||
|
joinmarketbitcoin = joinmarketPkg ./jmbitcoin;
|
||||||
|
joinmarketdaemon = joinmarketPkg ./jmdaemon;
|
||||||
|
|
||||||
pyln-client = clightningPkg ./pyln-client;
|
## Specific versions of packages that already exist in nixpkgs
|
||||||
pyln-proto = clightningPkg ./pyln-proto;
|
|
||||||
pyln-bolt7 = clightningPkg ./pyln-bolt7;
|
|
||||||
pylightning = clightningPkg ./pylightning;
|
|
||||||
|
|
||||||
# Don't mark `klein` as broken.
|
# cryptography 3.3.2, required by joinmarketdaemon
|
||||||
# `klein` is fixed by using werkzeug 2.1.0 (see below)
|
cryptography = callPackage ./specific-versions/cryptography {
|
||||||
klein = super.klein.overrideAttrs (old: {
|
openssl = super.pkgs.openssl_1_1;
|
||||||
meta = builtins.removeAttrs old.meta [ "broken" ];
|
cryptography_vectors = callPackage ./specific-versions/cryptography/vectors.nix {};
|
||||||
});
|
};
|
||||||
|
|
||||||
## Specific versions of packages that already exist in nixpkgs
|
# autobahn 20.12.3, required by joinmarketclient
|
||||||
|
autobahn = callPackage ./specific-versions/autobahn.nix {};
|
||||||
|
|
||||||
# cryptography 3.3.2, required by joinmarketdaemon
|
# pyopenssl 20.0.1, required by joinmarketdaemon
|
||||||
# Used in the private python package set for joinmarket (../joinmarket/default.nix)
|
pyopenssl = callPackage ./specific-versions/pyopenssl.nix {
|
||||||
cryptography_3_3_2 = callPackage ./specific-versions/cryptography {
|
openssl = super.pkgs.openssl_1_1;
|
||||||
cryptography_vectors = callPackage ./specific-versions/cryptography/vectors.nix {};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
# autobahn 20.12.3, required by joinmarketclient
|
# twisted 22.4.0, compatible with pyopenssl 20.0.1
|
||||||
autobahn = callPackage ./specific-versions/autobahn.nix {};
|
twisted = callPackage ./specific-versions/twisted.nix {};
|
||||||
|
};
|
||||||
|
|
||||||
# werkzeug 2.1.0, required by jmclient (via pkg `klein`)
|
nbPython3Packages = (python3.override {
|
||||||
werkzeug = callPackage ./specific-versions/werkzeug.nix {};
|
packageOverrides = pyPkgsOverrides;
|
||||||
|
}).pkgs;
|
||||||
|
|
||||||
# pyopenssl 20.0.1, required by joinmarketdaemon
|
nbPython3PackagesJoinmarket = (python3.override {
|
||||||
pyopenssl = callPackage ./specific-versions/pyopenssl.nix {};
|
packageOverrides = pyPkgsOverridesJoinmarket;
|
||||||
|
}).pkgs;
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,9 @@ buildPythonPackage rec {
|
|||||||
|
|
||||||
patchPhase = ''
|
patchPhase = ''
|
||||||
substituteInPlace setup.py \
|
substituteInPlace setup.py \
|
||||||
--replace "'klein==20.6.0'" "'klein==21.8.0'"
|
--replace "'klein==20.6.0'" "'klein>=20.6.0'"
|
||||||
substituteInPlace setup.py \
|
substituteInPlace setup.py \
|
||||||
--replace "'pyjwt==2.1.0'" "'pyjwt==2.4.0'"
|
--replace "'pyjwt==2.4.0'" "'pyjwt==2.5.0'"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
|
@ -16,13 +16,5 @@ buildPythonPackage rec {
|
|||||||
|
|
||||||
checkInputs = [ pytestCheckHook ];
|
checkInputs = [ pytestCheckHook ];
|
||||||
|
|
||||||
# TODO-EXTERNAL:
|
|
||||||
# This patch is a variant (fixed relative path) of
|
|
||||||
# https://github.com/ElementsProject/lightning/pull/5574. This is already
|
|
||||||
# fixed upstream. Remove this after the next clightning release.
|
|
||||||
patches = [
|
|
||||||
./msat-null.patch
|
|
||||||
];
|
|
||||||
|
|
||||||
postUnpack = "sourceRoot=$sourceRoot/contrib/${pname}";
|
postUnpack = "sourceRoot=$sourceRoot/contrib/${pname}";
|
||||||
}
|
}
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
diff --git a/pyln/client/lightning.py b/pyln/client/lightning.py
|
|
||||||
index 38fc7563f..0013b89a3 100644
|
|
||||||
--- a/pyln/client/lightning.py
|
|
||||||
+++ b/pyln/client/lightning.py
|
|
||||||
@@ -455,6 +455,11 @@ class LightningRpc(UnixDomainSocketRpc):
|
|
||||||
if k.endswith('msat'):
|
|
||||||
if isinstance(v, list):
|
|
||||||
obj[k] = [Millisatoshi(e) for e in v]
|
|
||||||
+ # FIXME: Deprecated "listconfigs" gives two 'null' fields:
|
|
||||||
+ # "lease-fee-base-msat": null,
|
|
||||||
+ # "channel-fee-max-base-msat": null,
|
|
||||||
+ elif v is None:
|
|
||||||
+ obj[k] = None
|
|
||||||
else:
|
|
||||||
obj[k] = Millisatoshi(v)
|
|
||||||
else:
|
|
@ -27,4 +27,8 @@ buildPythonPackage rec {
|
|||||||
checkInputs = [ pytestCheckHook ];
|
checkInputs = [ pytestCheckHook ];
|
||||||
|
|
||||||
postUnpack = "sourceRoot=$sourceRoot/contrib/pyln-proto";
|
postUnpack = "sourceRoot=$sourceRoot/contrib/pyln-proto";
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
sed -i 's|cryptography = "^36.0.1"|cryptography = "^38.0.0"|' pyproject.toml
|
||||||
|
'';
|
||||||
}
|
}
|
||||||
|
173
pkgs/python-packages/specific-versions/twisted.nix
Normal file
173
pkgs/python-packages/specific-versions/twisted.nix
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
{ lib
|
||||||
|
, stdenv
|
||||||
|
, buildPythonPackage
|
||||||
|
, pythonOlder
|
||||||
|
, fetchPypi
|
||||||
|
, python
|
||||||
|
, appdirs
|
||||||
|
, attrs
|
||||||
|
, automat
|
||||||
|
, bcrypt
|
||||||
|
, constantly
|
||||||
|
, contextvars
|
||||||
|
, cryptography
|
||||||
|
, git
|
||||||
|
, glibcLocales
|
||||||
|
, h2
|
||||||
|
, hyperlink
|
||||||
|
, idna
|
||||||
|
, incremental
|
||||||
|
, priority
|
||||||
|
, pyasn1
|
||||||
|
, pyhamcrest
|
||||||
|
, pynacl
|
||||||
|
, pyopenssl
|
||||||
|
, pyserial
|
||||||
|
, service-identity
|
||||||
|
, setuptools
|
||||||
|
, typing-extensions
|
||||||
|
, zope_interface
|
||||||
|
|
||||||
|
# for passthru.tests
|
||||||
|
, cassandra-driver
|
||||||
|
, klein
|
||||||
|
, magic-wormhole
|
||||||
|
, scrapy
|
||||||
|
, treq
|
||||||
|
, txaio
|
||||||
|
, txamqp
|
||||||
|
, txrequests
|
||||||
|
, txtorcon
|
||||||
|
, thrift
|
||||||
|
, nixosTests
|
||||||
|
}:
|
||||||
|
|
||||||
|
buildPythonPackage rec {
|
||||||
|
pname = "twisted";
|
||||||
|
version = "22.4.0";
|
||||||
|
format = "setuptools";
|
||||||
|
|
||||||
|
disabled = pythonOlder "3.6";
|
||||||
|
|
||||||
|
src = fetchPypi {
|
||||||
|
pname = "Twisted";
|
||||||
|
inherit version;
|
||||||
|
extension = "tar.gz";
|
||||||
|
sha256 = "sha256-oEeZD1ffrh4L0rffJSbU8W3NyEN3TcEIt4xS8qXxNoA=";
|
||||||
|
};
|
||||||
|
|
||||||
|
__darwinAllowLocalNetworking = true;
|
||||||
|
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
attrs
|
||||||
|
automat
|
||||||
|
constantly
|
||||||
|
hyperlink
|
||||||
|
incremental
|
||||||
|
setuptools
|
||||||
|
typing-extensions
|
||||||
|
zope_interface
|
||||||
|
];
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
echo 'ListingTests.test_localeIndependent.skip = "Timezone issue"'>> src/twisted/conch/test/test_cftp.py
|
||||||
|
echo 'ListingTests.test_newFile.skip = "Timezone issue"'>> src/twisted/conch/test/test_cftp.py
|
||||||
|
echo 'ListingTests.test_newSingleDigitDayOfMonth.skip = "Timezone issue"'>> src/twisted/conch/test/test_cftp.py
|
||||||
|
echo 'ListingTests.test_oldFile.skip = "Timezone issue"'>> src/twisted/conch/test/test_cftp.py
|
||||||
|
echo 'ListingTests.test_oldSingleDigitDayOfMonth.skip = "Timezone issue"'>> src/twisted/conch/test/test_cftp.py
|
||||||
|
|
||||||
|
echo 'PTYProcessTestsBuilder_AsyncioSelectorReactorTests.test_openFileDescriptors.skip = "invalid syntax"'>> src/twisted/internet/test/test_process.py
|
||||||
|
echo 'PTYProcessTestsBuilder_SelectReactorTests.test_openFileDescriptors.skip = "invalid syntax"'>> src/twisted/internet/test/test_process.py
|
||||||
|
|
||||||
|
echo 'UNIXTestsBuilder_AsyncioSelectorReactorTests.test_sendFileDescriptorTriggersPauseProducing.skip = "sendFileDescriptor producer was not paused"'>> src/twisted/internet/test/test_unix.py
|
||||||
|
echo 'UNIXTestsBuilder_SelectReactorTests.test_sendFileDescriptorTriggersPauseProducing.skip = "sendFileDescriptor producer was not paused"'>> src/twisted/internet/test/test_unix.py
|
||||||
|
|
||||||
|
echo 'FileObserverTests.test_getTimezoneOffsetEastOfUTC.skip = "mktime argument out of range"'>> src/twisted/test/test_log.py
|
||||||
|
echo 'FileObserverTests.test_getTimezoneOffsetWestOfUTC.skip = "mktime argument out of range"'>> src/twisted/test/test_log.py
|
||||||
|
echo 'FileObserverTests.test_getTimezoneOffsetWithoutDaylightSavingTime.skip = "tuple differs, values not"'>> src/twisted/test/test_log.py
|
||||||
|
|
||||||
|
echo 'MulticastTests.test_joinLeave.skip = "No such device"'>> src/twisted/test/test_udp.py
|
||||||
|
echo 'MulticastTests.test_loopback.skip = "No such device"'>> src/twisted/test/test_udp.py
|
||||||
|
echo 'MulticastTests.test_multicast.skip = "Reactor was unclean"'>> src/twisted/test/test_udp.py
|
||||||
|
echo 'MulticastTests.test_multiListen.skip = "No such device"'>> src/twisted/test/test_udp.py
|
||||||
|
|
||||||
|
echo 'DomishExpatStreamTests.test_namespaceWithWhitespace.skip = "syntax error: line 1, column 0"'>> src/twisted/words/test/test_domish.py
|
||||||
|
|
||||||
|
# not packaged
|
||||||
|
substituteInPlace src/twisted/test/test_failure.py \
|
||||||
|
--replace "from cython_test_exception_raiser import raiser # type: ignore[import]" "raiser = None"
|
||||||
|
'' + lib.optionalString stdenv.isLinux ''
|
||||||
|
echo 'PTYProcessTestsBuilder_EPollReactorTests.test_openFileDescriptors.skip = "invalid syntax"'>> src/twisted/internet/test/test_process.py
|
||||||
|
echo 'PTYProcessTestsBuilder_PollReactorTests.test_openFileDescriptors.skip = "invalid syntax"'>> src/twisted/internet/test/test_process.py
|
||||||
|
echo 'UNIXTestsBuilder_EPollReactorTests.test_sendFileDescriptorTriggersPauseProducing.skip = "sendFileDescriptor producer was not paused"'>> src/twisted/internet/test/test_unix.py
|
||||||
|
echo 'UNIXTestsBuilder_PollReactorTests.test_sendFileDescriptorTriggersPauseProducing.skip = "sendFileDescriptor producer was not paused"'>> src/twisted/internet/test/test_unix.py
|
||||||
|
|
||||||
|
# Patch t.p._inotify to point to libc. Without this,
|
||||||
|
# twisted.python.runtime.platform.supportsINotify() == False
|
||||||
|
substituteInPlace src/twisted/python/_inotify.py --replace \
|
||||||
|
"ctypes.util.find_library(\"c\")" "'${stdenv.cc.libc}/lib/libc.so.6'"
|
||||||
|
'' + lib.optionalString (stdenv.isAarch64 && stdenv.isDarwin) ''
|
||||||
|
echo 'AbortConnectionTests_AsyncioSelectorReactorTests.test_fullWriteBufferAfterByteExchange.skip = "Timeout after 120 seconds"' >> src/twisted/internet/test/test_tcp.py
|
||||||
|
echo 'AbortConnectionTests_AsyncioSelectorReactorTests.test_resumeProducingAbort.skip = "Timeout after 120 seconds"' >> src/twisted/internet/test/test_tcp.py
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Generate Twisted's plug-in cache. Twisted users must do it as well. See
|
||||||
|
# http://twistedmatrix.com/documents/current/core/howto/plugin.html#auto3
|
||||||
|
# and http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=477103 for details.
|
||||||
|
postFixup = ''
|
||||||
|
$out/bin/twistd --help > /dev/null
|
||||||
|
'';
|
||||||
|
|
||||||
|
checkInputs = [
|
||||||
|
git
|
||||||
|
glibcLocales
|
||||||
|
pyhamcrest
|
||||||
|
]
|
||||||
|
++ passthru.optional-dependencies.conch
|
||||||
|
# not supported on aarch64-darwin: https://github.com/pyca/pyopenssl/issues/873
|
||||||
|
++ lib.optionals (!(stdenv.isDarwin && stdenv.isAarch64)) passthru.optional-dependencies.tls;
|
||||||
|
|
||||||
|
checkPhase = ''
|
||||||
|
export SOURCE_DATE_EPOCH=315532800
|
||||||
|
export PATH=$out/bin:$PATH
|
||||||
|
# race conditions when running in paralell
|
||||||
|
${python.interpreter} -m twisted.trial twisted
|
||||||
|
'';
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
optional-dependencies = rec {
|
||||||
|
conch = [ appdirs bcrypt cryptography pyasn1 ];
|
||||||
|
conch_nacl = conch ++ [ pynacl ];
|
||||||
|
contextvars = lib.optionals (pythonOlder "3.7") [ contextvars ];
|
||||||
|
http2 = [ h2 priority ];
|
||||||
|
serial = [ pyserial ];
|
||||||
|
tls = [ idna pyopenssl service-identity ];
|
||||||
|
};
|
||||||
|
|
||||||
|
tests = {
|
||||||
|
inherit
|
||||||
|
cassandra-driver
|
||||||
|
klein
|
||||||
|
magic-wormhole
|
||||||
|
scrapy
|
||||||
|
treq
|
||||||
|
txaio
|
||||||
|
txamqp
|
||||||
|
txrequests
|
||||||
|
txtorcon
|
||||||
|
thrift;
|
||||||
|
inherit (nixosTests) buildbot matrix-synapse;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
homepage = "https://github.com/twisted/twisted";
|
||||||
|
description = "Twisted, an event-driven networking engine written in Python";
|
||||||
|
longDescription = ''
|
||||||
|
Twisted is an event-driven networking engine written in Python
|
||||||
|
and licensed under the MIT license.
|
||||||
|
'';
|
||||||
|
license = licenses.mit;
|
||||||
|
maintainers = with maintainers; [ SuperSandro2000 ];
|
||||||
|
};
|
||||||
|
}
|
@ -1,68 +0,0 @@
|
|||||||
{ lib
|
|
||||||
, stdenv
|
|
||||||
, buildPythonPackage
|
|
||||||
, pythonOlder
|
|
||||||
, fetchPypi
|
|
||||||
, watchdog
|
|
||||||
, dataclasses
|
|
||||||
, ephemeral-port-reserve
|
|
||||||
, pytest-timeout
|
|
||||||
, pytest-xprocess
|
|
||||||
, pytestCheckHook
|
|
||||||
}:
|
|
||||||
|
|
||||||
buildPythonPackage rec {
|
|
||||||
pname = "werkzeug";
|
|
||||||
version = "2.1.0";
|
|
||||||
format = "setuptools";
|
|
||||||
|
|
||||||
disabled = pythonOlder "3.7";
|
|
||||||
|
|
||||||
src = fetchPypi {
|
|
||||||
pname = "Werkzeug";
|
|
||||||
inherit version;
|
|
||||||
sha256 = "sha256-m1VGaj6Z4TsfBoamYRfTm9qFqZIWbgp5rt/PNYYyj3o=";
|
|
||||||
};
|
|
||||||
|
|
||||||
propagatedBuildInputs = lib.optionals (!stdenv.isDarwin) [
|
|
||||||
# watchdog requires macos-sdk 10.13+
|
|
||||||
watchdog
|
|
||||||
] ++ lib.optionals (pythonOlder "3.7") [
|
|
||||||
dataclasses
|
|
||||||
];
|
|
||||||
|
|
||||||
checkInputs = [
|
|
||||||
ephemeral-port-reserve
|
|
||||||
pytest-timeout
|
|
||||||
pytest-xprocess
|
|
||||||
pytestCheckHook
|
|
||||||
];
|
|
||||||
|
|
||||||
disabledTests = lib.optionals stdenv.isDarwin [
|
|
||||||
"test_get_machine_id"
|
|
||||||
];
|
|
||||||
|
|
||||||
disabledTestPaths = [
|
|
||||||
# ConnectionRefusedError: [Errno 111] Connection refused
|
|
||||||
"tests/test_serving.py"
|
|
||||||
];
|
|
||||||
|
|
||||||
pytestFlagsArray = [
|
|
||||||
# don't run tests that are marked with filterwarnings, they fail with
|
|
||||||
# warnings._OptionError: unknown warning category: 'pytest.PytestUnraisableExceptionWarning'
|
|
||||||
"-m 'not filterwarnings'"
|
|
||||||
];
|
|
||||||
|
|
||||||
meta = with lib; {
|
|
||||||
homepage = "https://palletsprojects.com/p/werkzeug/";
|
|
||||||
description = "The comprehensive WSGI web application library";
|
|
||||||
longDescription = ''
|
|
||||||
Werkzeug is a comprehensive WSGI web application library. It
|
|
||||||
began as a simple collection of various utilities for WSGI
|
|
||||||
applications and has become one of the most advanced WSGI
|
|
||||||
utility libraries.
|
|
||||||
'';
|
|
||||||
license = licenses.bsd3;
|
|
||||||
maintainers = with maintainers; [ ];
|
|
||||||
};
|
|
||||||
}
|
|
@ -10,22 +10,11 @@
|
|||||||
}:
|
}:
|
||||||
let self = stdenvNoCC.mkDerivation {
|
let self = stdenvNoCC.mkDerivation {
|
||||||
pname = "rtl";
|
pname = "rtl";
|
||||||
version = "0.13.1";
|
version = "0.13.4";
|
||||||
|
|
||||||
src = applyPatches {
|
src = fetchurl {
|
||||||
src = fetchurl {
|
url = "https://github.com/Ride-The-Lightning/RTL/archive/refs/tags/v${self.version}.tar.gz";
|
||||||
url = "https://github.com/Ride-The-Lightning/RTL/archive/refs/tags/v${self.version}.tar.gz";
|
hash = "sha256-WVldNnmCB7Gi/U3dUDTYF58i480eXkstRnEg+1QCeMM=";
|
||||||
hash = "sha256-k40xwDDJxny1nPN2xz60WfbinxMNM0QPdglibO2anZw=";
|
|
||||||
};
|
|
||||||
|
|
||||||
patches = [
|
|
||||||
# Move non-runtime deps to `devDependencies`
|
|
||||||
# https://github.com/Ride-The-Lightning/RTL/pull/1070
|
|
||||||
(fetchpatch {
|
|
||||||
url = "https://github.com/Ride-The-Lightning/RTL/pull/1070.patch";
|
|
||||||
sha256 = "sha256-esDkYI27SNzj2AhYHS9XqlW0r2mr+o0K4A6PUE2kbWU=";
|
|
||||||
})
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
passthru = {
|
passthru = {
|
||||||
@ -34,7 +23,10 @@ let self = stdenvNoCC.mkDerivation {
|
|||||||
|
|
||||||
nodeModules = fetchNodeModules {
|
nodeModules = fetchNodeModules {
|
||||||
inherit (self) src nodejs;
|
inherit (self) src nodejs;
|
||||||
hash = "sha256-bYZ6snfXhDZ3MMga45EHVrPZxC0/Q0e3AgCgMBire64=";
|
# TODO-EXTERNAL: Remove `npmFlags` when no longer required
|
||||||
|
# See: https://github.com/Ride-The-Lightning/RTL/issues/1182
|
||||||
|
npmFlags = "--legacy-peer-deps";
|
||||||
|
hash = "sha256-AG7930RGLxbPp1ErTGuYvUvPur9ppEmg91Taz7Ube6w=";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -68,7 +60,7 @@ let self = stdenvNoCC.mkDerivation {
|
|||||||
description = "A web interface for LND, c-lightning and Eclair";
|
description = "A web interface for LND, c-lightning and Eclair";
|
||||||
homepage = "https://github.com/Ride-The-Lightning/RTL";
|
homepage = "https://github.com/Ride-The-Lightning/RTL";
|
||||||
license = licenses.mit;
|
license = licenses.mit;
|
||||||
maintainers = with maintainers; [ nixbitcoin earvstedt ];
|
maintainers = with maintainers; [ nixbitcoin erikarvstedt ];
|
||||||
platforms = platforms.unix;
|
platforms = platforms.unix;
|
||||||
};
|
};
|
||||||
}; in self
|
}; in self
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
. "${BASH_SOURCE[0]%/*}/../../helper/run-in-nix-env" "gnupg wget gnused" "$@"
|
. "${BASH_SOURCE[0]%/*}/../../helper/run-in-nix-env" "gnupg wget gnused" "$@"
|
||||||
|
|
||||||
version="0.13.1"
|
version="0.13.4"
|
||||||
repo=https://github.com/Ride-The-Lightning/RTL
|
repo=https://github.com/Ride-The-Lightning/RTL
|
||||||
|
|
||||||
scriptDir=$(cd "${BASH_SOURCE[0]%/*}" && pwd)
|
scriptDir=$(cd "${BASH_SOURCE[0]%/*}" && pwd)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
}, system ? builtins.currentSystem, nodejs ? pkgs."nodejs-14_x"}:
|
}, system ? builtins.currentSystem, nodejs ? pkgs."nodejs-14_x"}:
|
||||||
|
|
||||||
let
|
let
|
||||||
nodeEnv = import "${toString pkgs.path}/pkgs/development/node-packages/node-env.nix" {
|
nodeEnv = import (pkgs.path + "/pkgs/development/node-packages/node-env.nix") {
|
||||||
inherit (pkgs) stdenv lib python2 runCommand writeTextFile writeShellScript;
|
inherit (pkgs) stdenv lib python2 runCommand writeTextFile writeShellScript;
|
||||||
inherit pkgs nodejs;
|
inherit pkgs nodejs;
|
||||||
libtool = if pkgs.stdenv.isDarwin then pkgs.darwin.cctools else null;
|
libtool = if pkgs.stdenv.isDarwin then pkgs.darwin.cctools else null;
|
||||||
|
@ -10,7 +10,7 @@ nodePackages.package.override {
|
|||||||
description = "A minimalistic wallet GUI for c-lightning";
|
description = "A minimalistic wallet GUI for c-lightning";
|
||||||
homepage = "https://github.com/shesek/spark-wallet";
|
homepage = "https://github.com/shesek/spark-wallet";
|
||||||
license = licenses.mit;
|
license = licenses.mit;
|
||||||
maintainers = with maintainers; [ nixbitcoin earvstedt ];
|
maintainers = with maintainers; [ nixbitcoin erikarvstedt ];
|
||||||
platforms = platforms.unix;
|
platforms = platforms.unix;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
84
test/README.md
Normal file
84
test/README.md
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
The [`run-tests.sh`](./run-tests.sh) command is most convenient and versatile way to run tests.\
|
||||||
|
It leave no traces (outside of `/nix/store`) on the host system.
|
||||||
|
|
||||||
|
`run-tests.sh` requires Nix >= 2.10.
|
||||||
|
|
||||||
|
### Summary
|
||||||
|
```bash
|
||||||
|
./run-tests.sh [--scenario|-s <scenario>] [build|vm|debug|container]
|
||||||
|
```
|
||||||
|
|
||||||
|
See the top of [run-tests.sh](../test/run-tests.sh) for a complete documentation.\
|
||||||
|
Test scenarios are defined in [tests.nix](./tests.nix) and [tests.py](tests.py).
|
||||||
|
|
||||||
|
### Tutorial
|
||||||
|
#### Running tests
|
||||||
|
```bash
|
||||||
|
# Run the basic set of tests. These tests are also run on the GitHub CI server.
|
||||||
|
./run-tests.sh
|
||||||
|
|
||||||
|
# Run the test for scenario `regtest`.
|
||||||
|
# The test is run via the Nix build system. Successful runs are cached.
|
||||||
|
./run-tests.sh -s regtest build
|
||||||
|
./run-tests.sh -s regtest # Shorthand, equivalent
|
||||||
|
|
||||||
|
# To test a single service, use its name as a scenario.
|
||||||
|
./run-tests.sh -s clightning
|
||||||
|
|
||||||
|
# When no scenario is specified, scenario `default` is used.
|
||||||
|
./run-tests.sh build
|
||||||
|
```
|
||||||
|
#### Debugging
|
||||||
|
```bash
|
||||||
|
# Start a shell is inside a test VM. No tests are executed.
|
||||||
|
./run-tests.sh -s bitcoind vm
|
||||||
|
systemctl status bitcoind
|
||||||
|
|
||||||
|
# Run a Python NixOS test shell inside a VM.
|
||||||
|
# See https://nixos.org/manual/nixos/stable/#ssec-machine-objects for available commands.
|
||||||
|
./run-tests.sh debug
|
||||||
|
print(succeed("systemctl status bitcoind"))
|
||||||
|
run_test("bitcoind")
|
||||||
|
|
||||||
|
# Start a shell in a container node. Requires systemd and root privileges.
|
||||||
|
./run-tests.sh container
|
||||||
|
|
||||||
|
# In the container shell: Run command in container (with prefix `c`)
|
||||||
|
c systemctl status bitcoind
|
||||||
|
|
||||||
|
# Explore a single feature
|
||||||
|
./run-tests.sh -s electrs container
|
||||||
|
|
||||||
|
# Run a command in a container.
|
||||||
|
# The container is deleted afterwards.
|
||||||
|
./run-tests.sh -s clightning container --run c lightning-cli getinfo
|
||||||
|
|
||||||
|
# Define a custom scenario
|
||||||
|
./run-tests.sh --scenario '{
|
||||||
|
services.clightning.enable = true;
|
||||||
|
nix-bitcoin.nodeinfo.enable = true;
|
||||||
|
}' container --run c nodeinfo
|
||||||
|
```
|
||||||
|
|
||||||
|
# Running tests with Flakes
|
||||||
|
|
||||||
|
Tests can also be accessed via the nix-bitcoin flake:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build test
|
||||||
|
nix build --no-link ..#tests.default
|
||||||
|
|
||||||
|
# Run a node in a VM. No tests are executed.
|
||||||
|
nix run ..#tests.default.vm
|
||||||
|
|
||||||
|
# Run a Python test shell inside a VM node
|
||||||
|
nix run ..#tests.default.run -- --debug
|
||||||
|
|
||||||
|
# Run a node in a container. Requires extra-container, systemd and root privileges
|
||||||
|
nix run ..#tests.default.container
|
||||||
|
nix run ..#tests.default.containerLegacy # For NixOS with `system.stateVersion` <22.05
|
||||||
|
|
||||||
|
# Run a command in a container
|
||||||
|
nix run ..#tests.default.container -- --run c nodeinfo
|
||||||
|
nix run ..#tests.default.containerLegacy -- --run c nodeinfo # For NixOS with `system.stateVersion` <22.05
|
||||||
|
```
|
@ -1,12 +1,14 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# This script can also be run locally for testing:
|
# This script can also be run locally for testing:
|
||||||
# scenario=default ./build.sh
|
# ./build.sh <scenario>
|
||||||
#
|
#
|
||||||
# When variable CIRRUS_CI is unset, this script leaves no persistent traces on the host system.
|
# When variable CIRRUS_CI is unset, this script leaves no persistent traces on the host system.
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
scenario=$1
|
||||||
|
|
||||||
if [[ -v CIRRUS_CI ]]; then
|
if [[ -v CIRRUS_CI ]]; then
|
||||||
if [[ ! -e /dev/kvm ]]; then
|
if [[ ! -e /dev/kvm ]]; then
|
||||||
>&2 echo "No KVM available on VM host."
|
>&2 echo "No KVM available on VM host."
|
||||||
@ -16,5 +18,5 @@ if [[ -v CIRRUS_CI ]]; then
|
|||||||
chmod o+rw /dev/kvm
|
chmod o+rw /dev/kvm
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC2154
|
cd "${BASH_SOURCE[0]%/*}"
|
||||||
"${BASH_SOURCE[0]%/*}/../run-tests.sh" --ci --scenario "$scenario"
|
exec ./build-to-cachix.sh --expr "(builtins.getFlake (toString ../..)).legacyPackages.\${builtins.currentSystem}.tests.$scenario"
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
# You can run this test via `run-tests.sh -s clightningReplication`
|
# You can run this test via `run-tests.sh -s clightning-replication`
|
||||||
|
|
||||||
let
|
makeTestVM: pkgs:
|
||||||
nixpkgs = (import ../pkgs/nixpkgs-pinned.nix).nixpkgs;
|
|
||||||
in
|
|
||||||
import "${nixpkgs}/nixos/tests/make-test-python.nix" ({ pkgs, ... }:
|
|
||||||
with pkgs.lib;
|
with pkgs.lib;
|
||||||
let
|
let
|
||||||
keyDir = "${nixpkgs}/nixos/tests/initrd-network-ssh";
|
keyDir = pkgs.path + "/nixos/tests/initrd-network-ssh";
|
||||||
keys = {
|
keys = {
|
||||||
server = "${keyDir}/ssh_host_ed25519_key";
|
server = keyDir + "/ssh_host_ed25519_key";
|
||||||
client = "${keyDir}/id_ed25519";
|
client = keyDir + "/id_ed25519";
|
||||||
serverPub = readFile "${keys.server}.pub";
|
serverPub = readFile (keys.server + ".pub");
|
||||||
clientPub = readFile "${keys.client}.pub";
|
clientPub = readFile (keys.client + ".pub");
|
||||||
};
|
};
|
||||||
|
|
||||||
clientBaseConfig = {
|
clientBaseConfig = {
|
||||||
imports = [ ../modules/modules.nix ];
|
imports = [ ../modules/modules.nix ];
|
||||||
|
|
||||||
|
nixpkgs.pkgs = pkgs;
|
||||||
|
|
||||||
nix-bitcoin.generateSecrets = true;
|
nix-bitcoin.generateSecrets = true;
|
||||||
|
|
||||||
services.clightning = {
|
services.clightning = {
|
||||||
@ -29,7 +28,7 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
makeTestVM {
|
||||||
name = "clightning-replication";
|
name = "clightning-replication";
|
||||||
|
|
||||||
nodes = let nodes = {
|
nodes = let nodes = {
|
||||||
@ -57,7 +56,9 @@ in
|
|||||||
services.clightning.replication.encrypt = true;
|
services.clightning.replication.encrypt = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
server = { ... }: {
|
server = {
|
||||||
|
nixpkgs.pkgs = pkgs;
|
||||||
|
|
||||||
environment.etc."ssh-host-key" = {
|
environment.etc."ssh-host-key" = {
|
||||||
source = keys.server;
|
source = keys.server;
|
||||||
mode = "400";
|
mode = "400";
|
||||||
@ -131,8 +132,8 @@ in
|
|||||||
# A gocryptfs has been created
|
# A gocryptfs has been created
|
||||||
client.succeed("ls /var/backup/clightning/lightningd-db/gocryptfs.conf")
|
client.succeed("ls /var/backup/clightning/lightningd-db/gocryptfs.conf")
|
||||||
|
|
||||||
server.wait_for_unit("sshd.service")
|
|
||||||
switch_to_system("replicationRemote")
|
switch_to_system("replicationRemote")
|
||||||
|
server.wait_for_unit("sshd.service")
|
||||||
with subtest("remote replication"):
|
with subtest("remote replication"):
|
||||||
replica_db = "/var/cache/clightning-replication/sshfs/lightningd.sqlite3"
|
replica_db = "/var/cache/clightning-replication/sshfs/lightningd.sqlite3"
|
||||||
client.succeed(f"runuser -u clightning -- ls {replica_db}")
|
client.succeed(f"runuser -u clightning -- ls {replica_db}")
|
||||||
@ -150,4 +151,4 @@ in
|
|||||||
# A gocryptfs has been created on the server
|
# A gocryptfs has been created on the server
|
||||||
server.succeed("ls /var/backup/nb-replication/writable/lightningd-db/gocryptfs.conf")
|
server.succeed("ls /var/backup/nb-replication/writable/lightningd-db/gocryptfs.conf")
|
||||||
'';
|
'';
|
||||||
})
|
}
|
||||||
|
@ -14,7 +14,7 @@ atExit() {
|
|||||||
trap "atExit" EXIT
|
trap "atExit" EXIT
|
||||||
|
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
rsync -a --delete --exclude='.git*' "$scriptDir/../" "$tmp/src"
|
rsync -a --delete "$scriptDir/../" "$tmp/src"
|
||||||
echo "Copied src"
|
echo "Copied src"
|
||||||
|
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
# Create and maintain a minimal git repo at the root of the copied src
|
|
||||||
(
|
|
||||||
# shellcheck disable=SC2154,SC2164
|
|
||||||
cd "$scriptDir/.."
|
|
||||||
amend=(--amend)
|
|
||||||
|
|
||||||
if [[ ! -e .git ]] || ! git rev-parse HEAD 2>/dev/null; then
|
|
||||||
git init
|
|
||||||
amend=()
|
|
||||||
fi
|
|
||||||
git add .
|
|
||||||
if ! git diff --quiet --cached; then
|
|
||||||
git commit -a "${amend[@]}" -m -
|
|
||||||
fi
|
|
||||||
) >/dev/null
|
|
@ -53,17 +53,10 @@
|
|||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
if [[ $EUID != 0 ]]; then
|
# These vars are set by ../run-tests.sh
|
||||||
# NixOS containers require root permissions.
|
: "${container:=}"
|
||||||
# By using sudo here and not at the user's call-site extra-container can detect if it is running
|
: "${scriptDir:=}"
|
||||||
# inside an existing shell session (by checking an internal environment variable).
|
|
||||||
#
|
|
||||||
# shellcheck disable=SC2154
|
|
||||||
exec sudo scenario="$scenario" scriptDir="$scriptDir" NIX_PATH="$NIX_PATH" PATH="$PATH" \
|
|
||||||
scenarioOverridesFile="${scenarioOverridesFile:-}" "$scriptDir/lib/make-container.sh" "$@"
|
|
||||||
fi
|
|
||||||
|
|
||||||
export containerName=nb-test
|
|
||||||
containerCommand=shell
|
containerCommand=shell
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
@ -79,14 +72,17 @@ while [[ $# -gt 0 ]]; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
containerBin=$(type -P extra-container) || true
|
containerBin=$(type -P extra-container) || true
|
||||||
if [[ ! ($containerBin && $(realpath "$containerBin") == *extra-container-0.10*) ]]; then
|
if [[ ! ($containerBin && $(realpath "$containerBin") == *extra-container-0.11*) ]]; then
|
||||||
echo "Building extra-container. Skip this step by adding extra-container 0.10 to PATH."
|
echo
|
||||||
nix-build --out-link /tmp/extra-container "$scriptDir"/../pkgs \
|
echo "Building extra-container. Skip this step by adding extra-container 0.11 to PATH."
|
||||||
-A pinned.extra-container >/dev/null
|
nix build --out-link /tmp/extra-container "$scriptDir"/..#extra-container
|
||||||
|
# When this script is run as root, e.g. when run in an extra-container shell,
|
||||||
|
# chown the gcroot symlink to the regular (login) user so that the symlink can be
|
||||||
|
# overwritten when this script is run without root.
|
||||||
|
if [[ $EUID == 0 ]]; then
|
||||||
|
chown "$(logname):" --no-dereference /tmp/extra-container
|
||||||
|
fi
|
||||||
export PATH="/tmp/extra-container/bin${PATH:+:}$PATH"
|
export PATH="/tmp/extra-container/bin${PATH:+:}$PATH"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
read -rd '' src <<EOF || true
|
exec "$container"/bin/container "$containerCommand" "$@"
|
||||||
((import "$scriptDir/tests.nix" {}).getTest "$scenario").container
|
|
||||||
EOF
|
|
||||||
exec extra-container "$containerCommand" -E "$src" "$@"
|
|
||||||
|
@ -1,25 +1,35 @@
|
|||||||
pkgs:
|
pkgs:
|
||||||
let
|
let
|
||||||
pythonTesting = import "${toString pkgs.path}/nixos/lib/testing-python.nix" {
|
pythonTesting = import (pkgs.path + "/nixos/lib/testing-python.nix") {
|
||||||
system = pkgs.stdenv.hostPlatform.system;
|
system = pkgs.stdenv.hostPlatform.system;
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
|
|
||||||
args:
|
module:
|
||||||
let
|
let
|
||||||
test = pythonTesting.makeTest args;
|
test = (pythonTesting.evalTest module).config;
|
||||||
|
|
||||||
# 1. Save test logging output
|
runTest = pkgs.stdenv.mkDerivation {
|
||||||
# 2. Add link to driver so that a gcroot to a test prevents the driver from
|
name = "vm-test-run-${test.name}";
|
||||||
# being garbage-collected
|
|
||||||
fixedTest = test.overrideAttrs (_: {
|
requiredSystemFeatures = [ "kvm" "nixos-test" ];
|
||||||
# See `runTests` in nixpkgs/nixos/lib/testing-python.nix for the original definition of `buildCommand`
|
|
||||||
|
# 1. Save test logging output
|
||||||
|
# 2. Add link to driver so that a gcroot to a test prevents the driver from
|
||||||
|
# being garbage-collected
|
||||||
buildCommand = ''
|
buildCommand = ''
|
||||||
mkdir "$out"
|
mkdir "$out"
|
||||||
LOGFILE=$out/output.xml tests='exec(os.environ["testScript"])' ${test.driver}/bin/nixos-test-driver
|
LOGFILE=$out/output.xml tests='exec(os.environ["testScript"])' ${test.driver}/bin/nixos-test-driver
|
||||||
ln -s ${test.driver} "$out/driver"
|
ln -s ${test.driver} "$out/driver"
|
||||||
'';
|
'';
|
||||||
});
|
|
||||||
|
inherit (test) meta passthru;
|
||||||
|
} // test;
|
||||||
in
|
in
|
||||||
fixedTest
|
runTest // {
|
||||||
|
# A VM runner for interactive use
|
||||||
|
run = pkgs.writers.writeBashBin "run-vm" ''
|
||||||
|
. ${./run-vm.sh} ${runTest.driver} "$@"
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
@ -1,29 +1,25 @@
|
|||||||
pkgs:
|
flake: pkgs: makeTestVM:
|
||||||
let
|
let
|
||||||
makeVM = import ./make-test-vm.nix pkgs;
|
inherit (flake.inputs) extra-container;
|
||||||
inherit (pkgs) lib;
|
inherit (pkgs.stdenv.hostPlatform) system;
|
||||||
in
|
in
|
||||||
|
|
||||||
name: testConfig:
|
{ name ? "nix-bitcoin-test", config }:
|
||||||
{
|
let
|
||||||
vm = makeVM {
|
inherit (pkgs) lib;
|
||||||
name = "nix-bitcoin-${name}";
|
|
||||||
|
testConfig = config;
|
||||||
|
|
||||||
|
test = makeTestVM {
|
||||||
|
inherit name;
|
||||||
|
|
||||||
nodes.machine = { config, ... }: {
|
nodes.machine = { config, ... }: {
|
||||||
imports = [ testConfig ];
|
imports = [
|
||||||
|
testConfig
|
||||||
|
commonVmConfig
|
||||||
|
];
|
||||||
|
|
||||||
virtualisation = {
|
test.shellcheckServices.enable = true;
|
||||||
# Needed because duplicity requires 270 MB of free temp space, regardless of backup size
|
|
||||||
diskSize = 1024;
|
|
||||||
|
|
||||||
# Min. 800 MiB needed to avoid 'out of memory' errors
|
|
||||||
memorySize = lib.mkDefault 2048;
|
|
||||||
|
|
||||||
cores = lib.mkDefault 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Run shellcheck on all nix-bitcoin services during machine build time
|
|
||||||
system.extraDependencies = [ config.test.shellcheckServices ];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = nodes: let
|
testScript = nodes: let
|
||||||
@ -48,62 +44,100 @@ name: testConfig:
|
|||||||
(builtins.readFile ./../tests.py)
|
(builtins.readFile ./../tests.py)
|
||||||
cfg.test.extraTestScript
|
cfg.test.extraTestScript
|
||||||
# Don't run tests in interactive mode.
|
# Don't run tests in interactive mode.
|
||||||
# is_interactive is set in ../run-tests.sh
|
# is_interactive is set in ./run-vm.sh
|
||||||
''
|
''
|
||||||
if not "is_interactive" in vars():
|
if not "is_interactive" in vars():
|
||||||
run_tests()
|
nb_run_tests()
|
||||||
''
|
''
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
container = {
|
mkContainer = legacyInstallDirs:
|
||||||
# The container name has a 11 char length limit
|
extra-container.lib.buildContainers {
|
||||||
containers.nb-test = { config, ... }: {
|
inherit system legacyInstallDirs;
|
||||||
imports = [
|
config = {
|
||||||
{
|
# The container name has a 11 char length limit
|
||||||
config = {
|
containers.nb-test = { config, ... }: {
|
||||||
extra = config.config.test.container;
|
imports = [
|
||||||
config = testConfig;
|
{
|
||||||
};
|
config = {
|
||||||
}
|
extra = config.config.test.container;
|
||||||
|
config = testConfig;
|
||||||
# Enable FUSE inside the container when clightning replication
|
};
|
||||||
# is enabled.
|
|
||||||
# TODO-EXTERNAL: Remove this when
|
|
||||||
# https://github.com/systemd/systemd/issues/17607
|
|
||||||
# has been resolved. This will also improve security.
|
|
||||||
(
|
|
||||||
let
|
|
||||||
clightning = config.config.services.clightning;
|
|
||||||
in
|
|
||||||
lib.mkIf (clightning.enable && clightning.replication.enable) {
|
|
||||||
bindMounts."/dev/fuse" = { hostPath = "/dev/fuse"; };
|
|
||||||
allowedDevices = [ { node = "/dev/fuse"; modifier = "rw"; } ];
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
];
|
# Enable FUSE inside the container when clightning replication
|
||||||
|
# is enabled.
|
||||||
|
# TODO-EXTERNAL: Remove this when
|
||||||
|
# https://github.com/systemd/systemd/issues/17607
|
||||||
|
# has been resolved. This will also improve security.
|
||||||
|
(
|
||||||
|
let
|
||||||
|
s = config.config.services;
|
||||||
|
in
|
||||||
|
lib.mkIf (s ? clightning && s.clightning.enable && s.clightning.replication.enable) {
|
||||||
|
bindMounts."/dev/fuse" = { hostPath = "/dev/fuse"; };
|
||||||
|
allowedDevices = [ { node = "/dev/fuse"; modifier = "rw"; } ];
|
||||||
|
}
|
||||||
|
)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
container = mkContainer false;
|
||||||
|
containerLegacy = mkContainer true;
|
||||||
|
|
||||||
# This allows running a test scenario in a regular NixOS VM.
|
# This allows running a test scenario in a regular NixOS VM.
|
||||||
# No tests are executed.
|
# No tests are executed.
|
||||||
vmWithoutTests = (pkgs.nixos ({ config, ... }: {
|
vm = (pkgs.nixos ({ config, ... }: {
|
||||||
imports = [
|
imports = [
|
||||||
testConfig
|
testConfig
|
||||||
"${toString pkgs.path}/nixos/modules/virtualisation/qemu-vm.nix"
|
commonVmConfig
|
||||||
|
(pkgs.path + "/nixos/modules/virtualisation/qemu-vm.nix")
|
||||||
];
|
];
|
||||||
virtualisation.graphics = false;
|
virtualisation.graphics = false;
|
||||||
services.getty.autologinUser = "root";
|
services.getty.autologinUser = "root";
|
||||||
|
|
||||||
# Provide a shortcut for instant poweroff from within the machine
|
# Avoid lengthy build of the nixos manual
|
||||||
environment.systemPackages = with pkgs; [
|
documentation.nixos.enable = false;
|
||||||
(lowPrio (writeScriptBin "q" ''
|
|
||||||
echo o >/proc/sysrq-trigger
|
# Power off VM when the user exits the shell
|
||||||
''))
|
systemd.services."serial-getty@".preStop = ''
|
||||||
];
|
echo o >/proc/sysrq-trigger
|
||||||
|
'';
|
||||||
|
|
||||||
system.stateVersion = lib.mkDefault config.system.nixos.release;
|
system.stateVersion = lib.mkDefault config.system.nixos.release;
|
||||||
})).config.system.build.vm;
|
})).config.system.build.vm.overrideAttrs (old: {
|
||||||
|
meta = old.meta // { mainProgram = "run-vm-in-tmpdir"; };
|
||||||
|
buildCommand = old.buildCommand + "\n" + ''
|
||||||
|
install -m 700 ${./run-vm-without-tests.sh} $out/bin/run-vm-in-tmpdir
|
||||||
|
patchShebangs $out/bin/run-vm-in-tmpdir
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
|
||||||
|
commonVmConfig = {
|
||||||
|
virtualisation = {
|
||||||
|
# Needed because duplicity requires 270 MB of free temp space, regardless of backup size
|
||||||
|
diskSize = 1024;
|
||||||
|
|
||||||
|
# Min. 800 MiB needed to avoid 'out of memory' errors
|
||||||
|
memorySize = lib.mkDefault 2048;
|
||||||
|
|
||||||
|
# There are no perf gains beyond 3 cores.
|
||||||
|
# Benchmark: Ryzen 7 2700 (8 cores), VM test `default` as of 34f6eb90.
|
||||||
|
# Num. Cores | 1 | 2 | 3 | 4 | 6
|
||||||
|
# Runtime (sec) | 125 | 95 | 89 | 89 | 90
|
||||||
|
cores = lib.mkDefault 3;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
test // {
|
||||||
|
inherit
|
||||||
|
vm
|
||||||
|
container
|
||||||
|
# For NixOS with `system.stateVersion` <22.05
|
||||||
|
containerLegacy;
|
||||||
|
|
||||||
config = testConfig;
|
config = testConfig;
|
||||||
}
|
}
|
||||||
|
30
test/lib/run-vm-without-tests.sh
Normal file
30
test/lib/run-vm-without-tests.sh
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# This script uses the following env vars:
|
||||||
|
# NIX_BITCOIN_VM_ENABLE_NETWORK
|
||||||
|
# NIX_BITCOIN_VM_DATADIR
|
||||||
|
# QEMU_OPTS
|
||||||
|
# QEMU_NET_OPTS
|
||||||
|
|
||||||
|
if [[ ${NIX_BITCOIN_VM_DATADIR:-} ]]; then
|
||||||
|
dataDir=$NIX_BITCOIN_VM_DATADIR
|
||||||
|
else
|
||||||
|
dataDir=$(mktemp -d /tmp/nix-bitcoin-vm.XXX)
|
||||||
|
trap 'rm -rf "$dataDir"' EXIT
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! ${NIX_BITCOIN_VM_ENABLE_NETWORK:-} ]]; then
|
||||||
|
QEMU_NET_OPTS='restrict=on'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO-EXTERNAL:
|
||||||
|
# Pass PATH because run-*-vm is impure (requires coreutils from PATH)
|
||||||
|
env -i \
|
||||||
|
PATH="$PATH" \
|
||||||
|
USE_TMPDIR=1 \
|
||||||
|
TMPDIR="$dataDir" \
|
||||||
|
NIX_DISK_IMAGE="$dataDir/img.qcow2" \
|
||||||
|
QEMU_OPTS="${QEMU_OPTS:-}" \
|
||||||
|
QEMU_NET_OPTS="${QEMU_NET_OPTS:-}" \
|
||||||
|
"${BASH_SOURCE[0]%/*}"/run-*-vm
|
50
test/lib/run-vm.sh
Normal file
50
test/lib/run-vm.sh
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# This script uses the following env vars:
|
||||||
|
# NIX_BITCOIN_VM_ENABLE_NETWORK
|
||||||
|
# NIX_BITCOIN_VM_DATADIR
|
||||||
|
# QEMU_OPTS
|
||||||
|
# QEMU_NET_OPTS
|
||||||
|
|
||||||
|
if [[ ${NIX_BITCOIN_VM_DATADIR:-} ]]; then
|
||||||
|
dataDir=$NIX_BITCOIN_VM_DATADIR
|
||||||
|
else
|
||||||
|
dataDir=$(mktemp -d /tmp/nix-bitcoin-vm.XXX)
|
||||||
|
trap 'rm -rf "$dataDir"' EXIT
|
||||||
|
fi
|
||||||
|
|
||||||
|
testDriver=$1
|
||||||
|
shift
|
||||||
|
|
||||||
|
# Variable 'tests' contains the Python code that is executed by the driver on startup
|
||||||
|
if [[ ${1:-} == --debug ]]; then
|
||||||
|
shift
|
||||||
|
echo "Running interactive testing environment"
|
||||||
|
# Start REPL.
|
||||||
|
# Use `code.interact` for the REPL instead of the builtin test driver REPL
|
||||||
|
# because it supports low featured terminals like Emacs' shell-mode.
|
||||||
|
tests='
|
||||||
|
is_interactive = True
|
||||||
|
exec(open(os.environ["testScript"]).read())
|
||||||
|
if "machine" in vars(): machine.start()
|
||||||
|
import code
|
||||||
|
code.interact(local=globals())
|
||||||
|
'
|
||||||
|
echo
|
||||||
|
echo "Starting VM, data dir: $dataDir"
|
||||||
|
else
|
||||||
|
tests='exec(open(os.environ["testScript"]).read())'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! ${NIX_BITCOIN_VM_ENABLE_NETWORK:-} ]]; then
|
||||||
|
QEMU_NET_OPTS='restrict=on'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# The VM creates a VDE control socket in $PWD
|
||||||
|
env --chdir "$dataDir" -i \
|
||||||
|
USE_TMPDIR=1 \
|
||||||
|
TMPDIR="$dataDir" \
|
||||||
|
QEMU_OPTS="-nographic ${QEMU_OPTS:-}" \
|
||||||
|
QEMU_NET_OPTS="${QEMU_NET_OPTS:-}" \
|
||||||
|
"$testDriver/bin/nixos-test-driver" <(echo "$tests") "$@"
|
@ -1,10 +1,26 @@
|
|||||||
{ config, pkgs, lib, extendModules, ... }:
|
{ config, pkgs, lib, extendModules, ... }@args:
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
options = {
|
options.test.shellcheckServices = {
|
||||||
test.shellcheckServices = mkOption {
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = mdDoc ''
|
||||||
|
Whether to shellcheck services during system build time.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
sourcePrefix = mkOption {
|
||||||
|
type = with types; nullOr str;
|
||||||
|
default = null;
|
||||||
|
description = mdDoc ''
|
||||||
|
The definition source path prefix of services to include in the shellcheck.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
runShellcheck = mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
A derivation that runs shellcheck on all bash scripts included
|
A derivation that runs shellcheck on all bash scripts included
|
||||||
in nix-bitcoin services.
|
in nix-bitcoin services.
|
||||||
'';
|
'';
|
||||||
@ -12,70 +28,42 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# TODO-EXTERNAL:
|
cfg = config.test.shellcheckServices;
|
||||||
# This can be removed when https://github.com/NixOS/nixpkgs/pull/189836 is merged.
|
|
||||||
#
|
|
||||||
# A list of all systemd service definitions and their locations, with format
|
|
||||||
# [
|
|
||||||
# {
|
|
||||||
# file = ...;
|
|
||||||
# value = { postgresql = ...; };
|
|
||||||
# }
|
|
||||||
# ...
|
|
||||||
# ]
|
|
||||||
systemdServiceDefs =
|
|
||||||
(extendModules {
|
|
||||||
modules = [
|
|
||||||
{
|
|
||||||
# Currently, NixOS modules only allow accessing option definition locations
|
|
||||||
# via type.merge.
|
|
||||||
# Override option `systemd.services` and use it to return the list of service defs.
|
|
||||||
options.systemd.services = lib.mkOption {
|
|
||||||
type = lib.types.anything // {
|
|
||||||
merge = loc: defs: defs;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Disable all modules that define options.systemd.services so that these
|
# A list of all service names that are defined in source paths prefixed by
|
||||||
# defs don't collide with our definition
|
# `sourcePrefix`.
|
||||||
disabledModules = [
|
|
||||||
"system/boot/systemd.nix"
|
|
||||||
# These files amend option systemd.services
|
|
||||||
"testing/service-runner.nix"
|
|
||||||
"security/systemd-confinement.nix"
|
|
||||||
];
|
|
||||||
|
|
||||||
config._module.check = false;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}).config.systemd.services;
|
|
||||||
|
|
||||||
# A list of all service names that are defined by nix-bitcoin.
|
|
||||||
# [ "bitcoind", "clightning", ... ]
|
# [ "bitcoind", "clightning", ... ]
|
||||||
#
|
#
|
||||||
# Algorithm: Parse `systemdServiceDefs` and return all services that
|
# Algorithm: Parse defintions of `systemd.services` and return all services
|
||||||
# only have definitions located in the nix-bitcoin source.
|
# that only have definitions located within `sourcePrefix`.
|
||||||
nix-bitcoin-services = let
|
servicesToCheck = let
|
||||||
nix-bitcoin-source = toString ../..;
|
inherit (cfg) sourcePrefix;
|
||||||
nbServices = collectServices true;
|
systemdServices = args.options.systemd.services;
|
||||||
nonNbServices = collectServices false;
|
configSystemdServices = args.config.systemd.services;
|
||||||
|
matchingServices = collectServices true;
|
||||||
|
nonMatchingServices = collectServices false;
|
||||||
# Return set of services ({ service1 = true; service2 = true; ... })
|
# Return set of services ({ service1 = true; service2 = true; ... })
|
||||||
# which are either defined or not defined by nix-bitcoin, depending
|
# which are either defined or not defined within `sourcePrefix`, depending
|
||||||
# on `fromNixBitcoin`.
|
# on `shouldMatch`.
|
||||||
collectServices = fromNixBitcoin: lib.listToAttrs (builtins.concatLists (map (def:
|
collectServices = shouldMatch: lib.listToAttrs (builtins.concatLists (map (def:
|
||||||
let
|
let
|
||||||
isNbSource = lib.hasPrefix nix-bitcoin-source def.file;
|
services = def.value;
|
||||||
|
inherit (def) file;
|
||||||
|
isMatching = lib.hasPrefix sourcePrefix file;
|
||||||
in
|
in
|
||||||
# Nix has nor boolean XOR, so use `if`
|
# Nix has no boolean XOR, so use `if`
|
||||||
lib.optionals (if fromNixBitcoin then isNbSource else !isNbSource) (
|
lib.optionals (if shouldMatch then isMatching else !isMatching) (
|
||||||
(map (service: { name = service; value = true; }) (builtins.attrNames def.value))
|
(map (service: { name = service; value = true; }) (builtins.attrNames services))
|
||||||
)
|
)
|
||||||
) systemdServiceDefs));
|
) systemdServices.definitionsWithLocations));
|
||||||
in
|
in
|
||||||
# Set difference: nbServices - nonNbServices
|
# Calculate set difference: matchingServices - nonMatchingServices
|
||||||
builtins.filter (nbService: ! nonNbServices ? ${nbService}) (builtins.attrNames nbServices);
|
# and exclude unavailable services (defined via `mkIf false ...`) by checking `configSystemdServices`.
|
||||||
|
builtins.filter (prefixedService:
|
||||||
|
configSystemdServices ? ${prefixedService} && (! nonMatchingServices ? ${prefixedService})
|
||||||
|
) (builtins.attrNames matchingServices);
|
||||||
|
|
||||||
# The concatenated list of values of ExecStart, ExecStop, ... (`scriptAttrs`) of all `nix-bitcoin-services`.
|
# The concatenated list of values of ExecStart, ExecStop, ... (`scriptAttrs`) of all `servicesToCheck`.
|
||||||
serviceCmds = let
|
serviceCmds = let
|
||||||
scriptAttrs = [
|
scriptAttrs = [
|
||||||
"ExecStartPre"
|
"ExecStartPre"
|
||||||
@ -99,7 +87,7 @@ let
|
|||||||
if builtins.typeOf cmd == "list" then cmd else [ cmd ]
|
if builtins.typeOf cmd == "list" then cmd else [ cmd ]
|
||||||
)
|
)
|
||||||
) scriptAttrs
|
) scriptAttrs
|
||||||
) nix-bitcoin-services;
|
) servicesToCheck;
|
||||||
|
|
||||||
# A list of all binaries included in `serviceCmds`
|
# A list of all binaries included in `serviceCmds`
|
||||||
serviceBinaries = map (cmd: builtins.head (
|
serviceBinaries = map (cmd: builtins.head (
|
||||||
@ -125,4 +113,15 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
inherit options;
|
inherit options;
|
||||||
|
|
||||||
|
config = mkIf (cfg.enable && cfg.sourcePrefix != null) {
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = builtins.length servicesToCheck > 0;
|
||||||
|
message = "test.shellcheckServices: No services found with source prefix `${cfg.sourcePrefix}`";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
system.extraDependencies = [ shellcheckServices ];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ with lib;
|
|||||||
noConnections = mkOption {
|
noConnections = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = !config.test.container.enableWAN;
|
default = !config.test.container.enableWAN;
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Whether services should be configured to not connect to external hosts.
|
Whether services should be configured to not connect to external hosts.
|
||||||
This can silence some warnings while running the test in an offline environment.
|
This can silence some warnings while running the test in an offline environment.
|
||||||
'';
|
'';
|
||||||
@ -18,9 +18,9 @@ with lib;
|
|||||||
data = mkOption {
|
data = mkOption {
|
||||||
type = types.attrs;
|
type = types.attrs;
|
||||||
default = {};
|
default = {};
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Attrs that are available in the Python test script under the global
|
Attrs that are available in the Python test script under the global
|
||||||
dictionary variable 'test_data'. The data is exported via JSON.
|
dictionary variable {var}`test_data`. The data is exported via JSON.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
extraTestScript = mkOption {
|
extraTestScript = mkOption {
|
||||||
|
44
test/nixos-search/flake-info-sandboxed.sh
Executable file
44
test/nixos-search/flake-info-sandboxed.sh
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Run flake-info for the nix-bitcoin flake in a sandbox:
|
||||||
|
# - Adds a consistent, reproducible runtime environment
|
||||||
|
# - Removes the need to trust the flake-info binary
|
||||||
|
#
|
||||||
|
# Use bubblewrap instead of a sandboxed Nix build so that we don't have to copy
|
||||||
|
# the whole repo to the sandbox when running this test.
|
||||||
|
|
||||||
|
cd "${BASH_SOURCE[0]%/*}"
|
||||||
|
|
||||||
|
nbFlake=$(realpath ../..)
|
||||||
|
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
PATH=$(nix shell -L .#{flake-info,bubblewrap} -c sh -c 'echo $PATH')
|
||||||
|
|
||||||
|
tmpDir=$(mktemp -d /tmp/nix-bitcoin-flake-info.XXX)
|
||||||
|
trap 'rm -rf $tmpDir' EXIT
|
||||||
|
|
||||||
|
echo '
|
||||||
|
experimental-features = nix-command flakes
|
||||||
|
flake-registry = /dev/null
|
||||||
|
' > "$tmpDir/nix.conf"
|
||||||
|
|
||||||
|
echo "Running flake-info (nixos-search)"
|
||||||
|
|
||||||
|
bwrap \
|
||||||
|
--unshare-all \
|
||||||
|
--clearenv \
|
||||||
|
--setenv PATH "$PATH" \
|
||||||
|
--setenv NIX_PATH "$NIX_PATH" \
|
||||||
|
--bind "$tmpDir" / \
|
||||||
|
--proc /proc \
|
||||||
|
--dev /dev \
|
||||||
|
--tmpfs /tmp \
|
||||||
|
--ro-bind "$nbFlake" "$nbFlake" \
|
||||||
|
--ro-bind /nix /nix \
|
||||||
|
--ro-bind /etc /etc \
|
||||||
|
--tmpfs /etc/nix \
|
||||||
|
--ro-bind "$tmpDir/nix.conf" /etc/nix/nix.conf \
|
||||||
|
--ro-bind /usr /usr \
|
||||||
|
--ro-bind-try /run /run \
|
||||||
|
-- flake-info flake "$nbFlake"
|
@ -2,11 +2,11 @@
|
|||||||
"nodes": {
|
"nodes": {
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1659877975,
|
"lastModified": 1667395993,
|
||||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -18,11 +18,11 @@
|
|||||||
"nixos-org-configurations": {
|
"nixos-org-configurations": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1660725019,
|
"lastModified": 1674564797,
|
||||||
"narHash": "sha256-729dr5TzCG3JIYgrcyyZQoG/e+Ugr6r2NB08Izer0q8=",
|
"narHash": "sha256-MgGsFleE8Wzhu8XX3ulcBojkHzFLkII+D9sxkTHg7OU=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixos-org-configurations",
|
"repo": "nixos-org-configurations",
|
||||||
"rev": "569797100aac69780a12542c2143bb741380d4ec",
|
"rev": "3ce43a1fb5181a0e33b1f67d36fa0f3affa6bc6c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -35,14 +35,15 @@
|
|||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"nixos-org-configurations": "nixos-org-configurations",
|
"nixos-org-configurations": "nixos-org-configurations",
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs",
|
||||||
|
"npmlock2nix": "npmlock2nix"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1661847188,
|
"lastModified": 1674593115,
|
||||||
"narHash": "sha256-GSA60qVevqN2Q+bbD4O6nbWUCzNtjbEQhYBvcSSRIkI=",
|
"narHash": "sha256-P4bjLR/8tJ/jVBBeHDzNS2BgVUdB6vS7Udfh30kULJs=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixos-search",
|
"repo": "nixos-search",
|
||||||
"rev": "7d1c1046ba918625fef44a204c219188824f46fb",
|
"rev": "be9a717b8032c7410337139f9dcfd6227b7407a4",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -53,11 +54,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1661450036,
|
"lastModified": 1667629849,
|
||||||
"narHash": "sha256-0/9UyJLtfWqF4uvOrjFIzk8ue1YYUHa6JIhV0mALkH0=",
|
"narHash": "sha256-P+v+nDOFWicM4wziFK9S/ajF2lc0N2Rg9p6Y35uMoZI=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "f3d0897be466aa09a37f6bf59e62c360c3f9a6cc",
|
"rev": "3bacde6273b09a21a8ccfba15586fb165078fb62",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -66,6 +67,22 @@
|
|||||||
"type": "indirect"
|
"type": "indirect"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"npmlock2nix": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1666460237,
|
||||||
|
"narHash": "sha256-HME6rnysvCwUVtH+BDWDGahmweMaLgD2wqHeRuGp6QI=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "npmlock2nix",
|
||||||
|
"rev": "eeed152290ec2425f96c5e74e469c40b621e1468",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "npmlock2nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixos-search": "nixos-search"
|
"nixos-search": "nixos-search"
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
# it to the main flake.
|
# it to the main flake.
|
||||||
{
|
{
|
||||||
inputs.nixos-search.url = "github:nixos/nixos-search";
|
inputs.nixos-search.url = "github:nixos/nixos-search";
|
||||||
|
|
||||||
outputs = { self, nixos-search }: {
|
outputs = { self, nixos-search }: {
|
||||||
inherit (nixos-search) packages;
|
inherit (nixos-search) packages;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# The tests (defined in ./tests.nix) use the NixOS testing framework and are executed in a VM.
|
# The tests (defined in ./tests.nix) use the NixOS testing framework and are executed in a VM.
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# Run all tests
|
# Run the basic set of tests. These are also run on the CI server.
|
||||||
# ./run-tests.sh
|
# ./run-tests.sh
|
||||||
#
|
#
|
||||||
# Test specific scenario
|
# Test specific scenario
|
||||||
@ -57,7 +57,8 @@
|
|||||||
# and reading source files.
|
# and reading source files.
|
||||||
# Files are copied to /tmp, a caching scheme helps minimizing copies.
|
# Files are copied to /tmp, a caching scheme helps minimizing copies.
|
||||||
#
|
#
|
||||||
# To add custom scenarios, set the environment variable `scenarioOverridesFile`.
|
# Add custom scenarios from a file
|
||||||
|
# ./run-tests.sh --extra-scenarios ~/my/scenarios.nix ...
|
||||||
|
|
||||||
set -eo pipefail
|
set -eo pipefail
|
||||||
|
|
||||||
@ -66,7 +67,7 @@ scriptDir=$(cd "${BASH_SOURCE[0]%/*}" && pwd)
|
|||||||
args=("$@")
|
args=("$@")
|
||||||
scenario=
|
scenario=
|
||||||
outLinkPrefix=
|
outLinkPrefix=
|
||||||
ciBuild=
|
scenarioOverridesFile=
|
||||||
while :; do
|
while :; do
|
||||||
case $1 in
|
case $1 in
|
||||||
--scenario|-s)
|
--scenario|-s)
|
||||||
@ -89,9 +90,15 @@ while :; do
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
--ci)
|
--extra-scenarios)
|
||||||
shift
|
if [[ $2 ]]; then
|
||||||
ciBuild=1
|
scenarioOverridesFile=$2
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
>&2 echo "Error: $1 requires an argument."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
--copy-src|-c)
|
--copy-src|-c)
|
||||||
shift
|
shift
|
||||||
@ -105,228 +112,185 @@ while :; do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
numCPUs=${numCPUs:-$(nproc)}
|
tmpDir=
|
||||||
# Min. 800 MiB needed to avoid 'out of memory' errors
|
# Sets global var `tmpDir`
|
||||||
memoryMiB=${memoryMiB:-2048}
|
makeTmpDir() {
|
||||||
|
if [[ ! $tmpDir ]]; then
|
||||||
NIX_PATH=nixpkgs=$(nix eval --raw -f "$scriptDir/../pkgs/nixpkgs-pinned.nix" nixpkgs):nix-bitcoin=$(realpath "$scriptDir/..")
|
tmpDir=$(mktemp -d /tmp/nix-bitcoin-tests.XXX)
|
||||||
export NIX_PATH
|
# shellcheck disable=SC2064
|
||||||
|
trap "rm -rf '$tmpDir'" EXIT
|
||||||
runAtExit=
|
fi
|
||||||
trap 'eval "$runAtExit"' EXIT
|
}
|
||||||
|
|
||||||
# Support explicit scenario definitions
|
# Support explicit scenario definitions
|
||||||
if [[ $scenario = *' '* ]]; then
|
if [[ $scenario = *' '* ]]; then
|
||||||
scenarioOverridesFile=$(mktemp "${XDG_RUNTIME_DIR:-/tmp}/nb-scenario.XXX")
|
makeTmpDir
|
||||||
export scenarioOverridesFile
|
scenarioOverridesFile=$tmpDir/scenario-overrides.nix
|
||||||
|
echo "{ scenarios, pkgs, lib, nix-bitcoin }: with lib; { tmp = $scenario; }" > "$scenarioOverridesFile"
|
||||||
# shellcheck disable=SC2016
|
|
||||||
runAtExit+='rm -f "$scenarioOverridesFile";'
|
|
||||||
echo "{ scenarios, pkgs, lib }: with lib; { tmp = $scenario; }" > "$scenarioOverridesFile"
|
|
||||||
scenario=tmp
|
scenario=tmp
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Run the test. No temporary files are left on the host system.
|
# Run the test. No temporary files are left on the host system.
|
||||||
run() {
|
run() {
|
||||||
# TMPDIR is also used by the test driver for VM tmp files
|
makeTmpDir
|
||||||
TMPDIR=$(mktemp -d /tmp/nix-bitcoin-test.XXX)
|
buildTestAttr .run --out-link "$tmpDir/run-vm"
|
||||||
export TMPDIR
|
NIX_BITCOIN_VM_DATADIR=$tmpDir "$tmpDir/run-vm/bin/run-vm" "$@"
|
||||||
runAtExit+="rm -rf ${TMPDIR};"
|
|
||||||
|
|
||||||
nix-build --out-link "$TMPDIR/driver" -E "((import \"$scriptDir/tests.nix\" {}).getTest \"$scenario\").vm" -A driver
|
|
||||||
|
|
||||||
# Variable 'tests' contains the Python code that is executed by the driver on startup
|
|
||||||
if [[ $1 == --interactive ]]; then
|
|
||||||
echo "Running interactive testing environment"
|
|
||||||
tests=$(
|
|
||||||
echo 'is_interactive = True'
|
|
||||||
echo 'exec(open(os.environ["testScript"]).read())'
|
|
||||||
# Start VM
|
|
||||||
echo 'if "machine" in vars(): machine.start()'
|
|
||||||
# Start REPL.
|
|
||||||
# Use `code.interact` for the REPL instead of the builtin test driver REPL
|
|
||||||
# because it supports low featured terminals like Emacs' shell-mode.
|
|
||||||
echo 'import code'
|
|
||||||
echo 'code.interact(local=globals())'
|
|
||||||
)
|
|
||||||
else
|
|
||||||
tests='exec(open(os.environ["testScript"]).read())'
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "VM stats: CPUs: $numCPUs, memory: $memoryMiB MiB"
|
|
||||||
[[ $NB_TEST_ENABLE_NETWORK ]] || QEMU_NET_OPTS='restrict=on'
|
|
||||||
cd "$TMPDIR" # The VM creates a VDE control socket in $PWD
|
|
||||||
env -i \
|
|
||||||
NIX_PATH="$NIX_PATH" \
|
|
||||||
TMPDIR="$TMPDIR" \
|
|
||||||
USE_TMPDIR=1 \
|
|
||||||
QEMU_OPTS="-smp $numCPUs -m $memoryMiB -nographic $QEMU_OPTS" \
|
|
||||||
QEMU_NET_OPTS="$QEMU_NET_OPTS" \
|
|
||||||
"$TMPDIR/driver/bin/nixos-test-driver" <(echo "$tests")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug() {
|
debug() {
|
||||||
run --interactive
|
run --debug
|
||||||
}
|
|
||||||
|
|
||||||
evalTest() {
|
|
||||||
nix-instantiate --eval -E "($(vmTestNixExpr)).outPath"
|
|
||||||
}
|
|
||||||
|
|
||||||
instantiate() {
|
|
||||||
nix-instantiate -E "$(vmTestNixExpr)" "$@"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
container() {
|
container() {
|
||||||
export scriptDir scenario
|
local nixosContainer
|
||||||
|
if ! nixosContainer=$(type -p nixos-container) \
|
||||||
|
|| grep -q '"/etc/nixos-containers"' "$nixosContainer"; then
|
||||||
|
local attr=container
|
||||||
|
else
|
||||||
|
# NixOS with `system.stateVersion` <22.05
|
||||||
|
local attr=containerLegacy
|
||||||
|
fi
|
||||||
|
echo "Building container"
|
||||||
|
makeTmpDir
|
||||||
|
export container=$tmpDir/container
|
||||||
|
buildTestAttr ".$attr" --out-link "$container"
|
||||||
|
export scriptDir
|
||||||
"$scriptDir/lib/make-container.sh" "$@"
|
"$scriptDir/lib/make-container.sh" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Run a regular NixOS VM
|
# Run a regular NixOS VM
|
||||||
vm() {
|
vm() {
|
||||||
TMPDIR=$(mktemp -d /tmp/nix-bitcoin-vm.XXX)
|
makeTmpDir
|
||||||
export TMPDIR
|
buildTestAttr .vm --out-link "$tmpDir/vm"
|
||||||
runAtExit+="rm -rf $TMPDIR;"
|
NIX_BITCOIN_VM_DATADIR=$tmpDir "$tmpDir/vm/bin/run-vm-in-tmpdir"
|
||||||
|
|
||||||
nix-build --out-link "$TMPDIR/vm" -E "((import \"$scriptDir/tests.nix\" {}).getTest \"$scenario\").vmWithoutTests"
|
|
||||||
|
|
||||||
echo "VM stats: CPUs: $numCPUs, memory: $memoryMiB MiB"
|
|
||||||
[[ $NB_TEST_ENABLE_NETWORK ]] || export QEMU_NET_OPTS="restrict=on,$QEMU_NET_OPTS"
|
|
||||||
|
|
||||||
# shellcheck disable=SC2211
|
|
||||||
USE_TMPDIR=1 \
|
|
||||||
NIX_DISK_IMAGE=$TMPDIR/img.qcow2 \
|
|
||||||
QEMU_OPTS="-smp $numCPUs -m $memoryMiB -nographic $QEMU_OPTS" \
|
|
||||||
"$TMPDIR"/vm/bin/run-*-vm
|
|
||||||
}
|
|
||||||
|
|
||||||
doBuild() {
|
|
||||||
name=$1
|
|
||||||
shift
|
|
||||||
if [[ $ciBuild ]]; then
|
|
||||||
"$scriptDir/ci/build-to-cachix.sh" "$@"
|
|
||||||
else
|
|
||||||
if [[ $outLinkPrefix ]]; then
|
|
||||||
outLink="--out-link $outLinkPrefix-$name"
|
|
||||||
else
|
|
||||||
outLink=--no-out-link
|
|
||||||
fi
|
|
||||||
nix-build $outLink "$@"
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Run the test by building the test derivation
|
# Run the test by building the test derivation
|
||||||
buildTest() {
|
buildTest() {
|
||||||
vmTestNixExpr | doBuild $scenario "$@" -
|
buildTestAttr "" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
vmTestNixExpr() {
|
evalTest() {
|
||||||
extraQEMUOpts=
|
nixInstantiateTest "" "$@"
|
||||||
|
# Print out path
|
||||||
if [[ $ciBuild ]]; then
|
nix-store -q "$drv"
|
||||||
# On continuous integration nodes there are few other processes running alongside the
|
# Print drv path
|
||||||
# test, so use more memory here for maximum performance.
|
realpath "$drv"
|
||||||
memoryMiB=4096
|
|
||||||
memTotalKiB=$(awk '/MemTotal/ { print $2 }' /proc/meminfo)
|
|
||||||
memAvailableKiB=$(awk '/MemAvailable/ { print $2 }' /proc/meminfo)
|
|
||||||
# Round down to nearest multiple of 50 MiB for improved test build caching
|
|
||||||
# shellcheck disable=SC2017
|
|
||||||
((memAvailableMiB = memAvailableKiB / (1024 * 50) * 50))
|
|
||||||
((memAvailableMiB < memoryMiB)) && memoryMiB=$memAvailableMiB
|
|
||||||
>&2 echo "VM stats: CPUs: $numCPUs, memory: $memoryMiB MiB"
|
|
||||||
>&2 echo "Host memory total: $((memTotalKiB / 1024)) MiB, available: $memAvailableMiB MiB"
|
|
||||||
|
|
||||||
# VMX is usually not available on CI nodes due to recursive virtualisation.
|
|
||||||
# Explicitly disable VMX, otherwise QEMU 4.20 fails with message
|
|
||||||
# "error: failed to set MSR 0x48b to 0x159ff00000000"
|
|
||||||
extraQEMUOpts="-cpu host,-vmx"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat <<EOF
|
|
||||||
((import "$scriptDir/tests.nix" {}).getTest "$scenario").vm.overrideAttrs (old: rec {
|
|
||||||
buildCommand = ''
|
|
||||||
export QEMU_OPTS="-smp $numCPUs -m $memoryMiB $extraQEMUOpts"
|
|
||||||
echo "VM stats: CPUs: $numCPUs, memory: $memoryMiB MiB"
|
|
||||||
'' + old.buildCommand;
|
|
||||||
})
|
|
||||||
EOF
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFlakeSupport() {
|
buildTestAttr() {
|
||||||
testName=$1
|
local attr=$1
|
||||||
if [[ ! -v hasFlakes ]]; then
|
shift
|
||||||
if [[ $(nix flake 2>&1) == *"requires a sub-command"* ]]; then
|
# TODO-EXTERNAL:
|
||||||
hasFlakes=1
|
# Simplify and switch to pure build when `nix build` can build flake function outputs
|
||||||
else
|
nixInstantiateTest "$attr"
|
||||||
hasFlakes=
|
nixBuild "$scenario" "$drv" "$@"
|
||||||
fi
|
}
|
||||||
|
|
||||||
|
buildTests() {
|
||||||
|
local -n tests=$1
|
||||||
|
shift
|
||||||
|
# TODO-EXTERNAL:
|
||||||
|
# Simplify and switch to pure build when `nix build` can instantiate flake function outputs
|
||||||
|
# shellcheck disable=SC2207
|
||||||
|
drvs=($(nixInstantiate "pkgs.instantiateTests \"${tests[*]}\""))
|
||||||
|
for i in "${!tests[@]}"; do
|
||||||
|
testName=${tests[$i]}
|
||||||
|
drv=${drvs[$i]}
|
||||||
|
echo
|
||||||
|
echo "Building test '$testName'"
|
||||||
|
nixBuild "$testName" "$drv" "$@"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Instantiate an attr of the test defined in global var `scenario`
|
||||||
|
nixInstantiateTest() {
|
||||||
|
local attr=$1
|
||||||
|
shift
|
||||||
|
if [[ $scenarioOverridesFile ]]; then
|
||||||
|
local file="extraScenariosFile = \"$scenarioOverridesFile\";"
|
||||||
|
else
|
||||||
|
local file=
|
||||||
fi
|
fi
|
||||||
if [[ ! $hasFlakes ]]; then
|
nixInstantiate "(pkgs.getTest { name = \"$scenario\"; $file })$attr" "$@" >/dev/null
|
||||||
echo "Skipping test '$testName'. Nix flake support is not enabled."
|
}
|
||||||
return 1
|
|
||||||
|
drv=
|
||||||
|
# Sets global var `drv` to the gcroot link of the instantiated derivation
|
||||||
|
nixInstantiate() {
|
||||||
|
local expr=$1
|
||||||
|
shift
|
||||||
|
makeTmpDir
|
||||||
|
drv="$tmpDir/drv"
|
||||||
|
nix-instantiate --add-root "$drv" -E "
|
||||||
|
let
|
||||||
|
pkgs = (builtins.getFlake \"git+file://$scriptDir/..\").legacyPackages.\${builtins.currentSystem};
|
||||||
|
in
|
||||||
|
$expr
|
||||||
|
" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
nixBuild() {
|
||||||
|
local outLinkName=$1
|
||||||
|
shift
|
||||||
|
args=(--print-out-paths -L)
|
||||||
|
if [[ $outLinkPrefix ]]; then
|
||||||
|
args+=(--out-link "$outLinkPrefix-$outLinkName")
|
||||||
|
else
|
||||||
|
args+=(--no-link)
|
||||||
fi
|
fi
|
||||||
|
nix build "${args[@]}" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
flake() {
|
flake() {
|
||||||
if ! checkFlakeSupport "flake"; then return; fi
|
|
||||||
|
|
||||||
nix flake check "$scriptDir/.."
|
nix flake check "$scriptDir/.."
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test generating module documentation for search.nixos.org
|
# Test generating module documentation for search.nixos.org
|
||||||
nixosSearch() {
|
nixosSearch() {
|
||||||
# TODO-EXTERNAL:
|
|
||||||
# Remove this when nixos-search has been fixed
|
|
||||||
echo "Skipping test nixosSearch"
|
|
||||||
return
|
|
||||||
|
|
||||||
if ! checkFlakeSupport "nixosSearch"; then return; fi
|
|
||||||
|
|
||||||
if [[ $_nixBitcoinInCopiedSrc ]]; then
|
|
||||||
# flake-info requires that its target flake is under version control
|
|
||||||
. "$scriptDir/lib/create-git-repo.sh"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $outLinkPrefix ]]; then
|
if [[ $outLinkPrefix ]]; then
|
||||||
# Add gcroots for flake-info
|
# Add gcroots for flake-info
|
||||||
nix build "$scriptDir/nixos-search#flake-info" -o "$outLinkPrefix-flake-info"
|
nix build "$scriptDir/nixos-search#flake-info" -o "$outLinkPrefix-flake-info"
|
||||||
fi
|
fi
|
||||||
echo "Running flake-info (nixos-search)"
|
"$scriptDir/nixos-search/flake-info-sandboxed.sh"
|
||||||
nix run "$scriptDir/nixos-search#flake-info" -- flake "$scriptDir/.."
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# A basic subset of tests to keep the total runtime within
|
# A basic subset of tests to keep the total runtime within
|
||||||
# manageable bounds (<4 min on desktop systems).
|
# manageable bounds.
|
||||||
# These are also run on the CI server.
|
# These are also run on the CI server.
|
||||||
basic() {
|
basic=(
|
||||||
scenario=default buildTest "$@"
|
default
|
||||||
scenario=netns buildTest "$@"
|
netns
|
||||||
scenario=netnsRegtest buildTest "$@"
|
netnsRegtest
|
||||||
}
|
)
|
||||||
|
basic() { buildTests basic "$@"; }
|
||||||
|
|
||||||
# All tests that only consist of building a nix derivation.
|
# All tests that only consist of building a nix derivation.
|
||||||
# Their output is cached in /nix/store.
|
# shellcheck disable=2034
|
||||||
buildable() {
|
buildable=(
|
||||||
basic "$@"
|
"${basic[@]}"
|
||||||
scenario=full buildTest "$@"
|
full
|
||||||
scenario=regtest buildTest "$@"
|
regtest
|
||||||
scenario=hardened buildTest "$@"
|
hardened
|
||||||
scenario=clightningReplication buildTest "$@"
|
clightning-replication
|
||||||
}
|
lndPruned
|
||||||
|
)
|
||||||
|
buildable() { buildTests buildable "$@"; }
|
||||||
|
|
||||||
examples() {
|
examples() {
|
||||||
script="
|
# shellcheck disable=SC2016
|
||||||
|
script='
|
||||||
set -e
|
set -e
|
||||||
./deploy-container.sh
|
runExample() { echo; echo Running example $1; ./$1; }
|
||||||
./deploy-container-minimal.sh
|
runExample deploy-container.sh
|
||||||
./deploy-qemu-vm.sh
|
runExample deploy-container-minimal.sh
|
||||||
./deploy-krops.sh
|
runExample deploy-qemu-vm.sh
|
||||||
"
|
runExample deploy-krops.sh
|
||||||
|
'
|
||||||
(cd "$scriptDir/../examples" && nix-shell --run "$script")
|
(cd "$scriptDir/../examples" && nix-shell --run "$script")
|
||||||
}
|
}
|
||||||
|
|
||||||
shellcheck() {
|
shellcheck() {
|
||||||
if ! checkFlakeSupport "shellcheck"; then return; fi
|
|
||||||
"$scriptDir/shellcheck.sh"
|
"$scriptDir/shellcheck.sh"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
184
test/tests.nix
184
test/tests.nix
@ -1,19 +1,11 @@
|
|||||||
# Integration tests, can be run without internet access.
|
# Integration tests, can be run without internet access.
|
||||||
|
|
||||||
|
lib:
|
||||||
let
|
let
|
||||||
nixpkgs = (import ../pkgs/nixpkgs-pinned.nix).nixpkgs;
|
# Included in all scenarios
|
||||||
in
|
baseConfig = { config, pkgs, ... }: with lib; let
|
||||||
|
|
||||||
{ extraScenarios ? { ... }: {}
|
|
||||||
, pkgs ? import nixpkgs { config = {}; overlays = []; }
|
|
||||||
}:
|
|
||||||
with pkgs.lib;
|
|
||||||
let
|
|
||||||
globalPkgs = pkgs;
|
|
||||||
|
|
||||||
baseConfig = { pkgs, config, ... }: let
|
|
||||||
cfg = config.services;
|
cfg = config.services;
|
||||||
mkIfTest = test: mkIf (config.tests.${test} or false);
|
inherit (config.nix-bitcoin.lib.test) mkIfTest;
|
||||||
in {
|
in {
|
||||||
imports = [
|
imports = [
|
||||||
./lib/test-lib.nix
|
./lib/test-lib.nix
|
||||||
@ -32,9 +24,6 @@ let
|
|||||||
};
|
};
|
||||||
|
|
||||||
config = mkMerge [{
|
config = mkMerge [{
|
||||||
# Share the same pkgs instance among tests
|
|
||||||
nixpkgs.pkgs = mkDefault globalPkgs;
|
|
||||||
|
|
||||||
environment.systemPackages = mkMerge (with pkgs; [
|
environment.systemPackages = mkMerge (with pkgs; [
|
||||||
# Needed to test macaroon creation
|
# Needed to test macaroon creation
|
||||||
(mkIfTest "btcpayserver" [ openssl xxd ])
|
(mkIfTest "btcpayserver" [ openssl xxd ])
|
||||||
@ -64,12 +53,6 @@ let
|
|||||||
clboss.path = "${nbPkgs.clboss}/bin/clboss";
|
clboss.path = "${nbPkgs.clboss}/bin/clboss";
|
||||||
};
|
};
|
||||||
in map (plugin: pluginPkgs.${plugin}.path) enabled;
|
in map (plugin: pluginPkgs.${plugin}.path) enabled;
|
||||||
# Torified 'dig' subprocesses of clboss don't respond to SIGTERM and keep
|
|
||||||
# running for a long time when WAN is disabled, which prevents clightning units
|
|
||||||
# from stopping quickly.
|
|
||||||
# Set TimeoutStopSec for faster stopping.
|
|
||||||
systemd.services.clightning.serviceConfig.TimeoutStopSec =
|
|
||||||
mkIf config.services.clightning.plugins.clboss.enable "500ms";
|
|
||||||
|
|
||||||
tests.clightning-rest = cfg.clightning-rest.enable;
|
tests.clightning-rest = cfg.clightning-rest.enable;
|
||||||
|
|
||||||
@ -101,6 +84,8 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
nix-bitcoin.onionServices.lnd.public = true;
|
||||||
|
|
||||||
tests.lndconnect-onion-lnd = cfg.lnd.lndconnectOnion.enable;
|
tests.lndconnect-onion-lnd = cfg.lnd.lndconnectOnion.enable;
|
||||||
tests.lndconnect-onion-clightning = cfg.clightning-rest.lndconnectOnion.enable;
|
tests.lndconnect-onion-clightning = cfg.clightning-rest.lndconnectOnion.enable;
|
||||||
|
|
||||||
@ -108,7 +93,6 @@ let
|
|||||||
services.lightning-loop.certificate.extraIPs = [ "20.0.0.1" ];
|
services.lightning-loop.certificate.extraIPs = [ "20.0.0.1" ];
|
||||||
|
|
||||||
tests.lightning-pool = cfg.lightning-pool.enable;
|
tests.lightning-pool = cfg.lightning-pool.enable;
|
||||||
nix-bitcoin.onionServices.lnd.public = true;
|
|
||||||
|
|
||||||
tests.charge-lnd = cfg.charge-lnd.enable;
|
tests.charge-lnd = cfg.charge-lnd.enable;
|
||||||
|
|
||||||
@ -151,6 +135,13 @@ let
|
|||||||
# Avoid timeout failures on slow CI nodes
|
# Avoid timeout failures on slow CI nodes
|
||||||
systemd.services.postgresql.serviceConfig.TimeoutStartSec = "5min";
|
systemd.services.postgresql.serviceConfig.TimeoutStartSec = "5min";
|
||||||
}
|
}
|
||||||
|
(mkIf config.services.clightning.plugins.clboss.enable {
|
||||||
|
# Torified 'dig' subprocesses of clboss don't respond to SIGTERM and keep
|
||||||
|
# running for a long time when WAN is disabled, which prevents clightning units
|
||||||
|
# from stopping quickly.
|
||||||
|
# Set TimeoutStopSec for faster stopping.
|
||||||
|
systemd.services.clightning.serviceConfig.TimeoutStopSec = "500ms";
|
||||||
|
})
|
||||||
(mkIf config.test.features.clightningPlugins {
|
(mkIf config.test.features.clightningPlugins {
|
||||||
services.clightning.plugins = {
|
services.clightning.plugins = {
|
||||||
clboss.enable = true;
|
clboss.enable = true;
|
||||||
@ -176,8 +167,9 @@ let
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
scenarios = {
|
scenarios = with lib; {
|
||||||
base = baseConfig; # Included in all scenarios
|
# Included in all scenarios by ./lib/make-test.nix
|
||||||
|
base = baseConfig;
|
||||||
|
|
||||||
default = scenarios.secureNode;
|
default = scenarios.secureNode;
|
||||||
|
|
||||||
@ -273,7 +265,7 @@ let
|
|||||||
environment.systemPackages = [ pkgs.fping ];
|
environment.systemPackages = [ pkgs.fping ];
|
||||||
};
|
};
|
||||||
|
|
||||||
regtestBase = { config, ... }: {
|
regtestBase = { config, pkgs, ... }: {
|
||||||
tests.regtest = true;
|
tests.regtest = true;
|
||||||
test.data.num_blocks = 100;
|
test.data.num_blocks = 100;
|
||||||
|
|
||||||
@ -318,8 +310,17 @@ let
|
|||||||
services.btcpayserver.lbtc = mkForce false;
|
services.btcpayserver.lbtc = mkForce false;
|
||||||
};
|
};
|
||||||
|
|
||||||
## Examples / debug helper
|
# Test the special bitcoin RPC setup that lnd uses when bitcoin is pruned
|
||||||
|
lndPruned = {
|
||||||
|
services.lnd.enable = true;
|
||||||
|
services.bitcoind.prune = 1000;
|
||||||
|
};
|
||||||
|
} // (import ../dev/dev-scenarios.nix {
|
||||||
|
inherit lib scenarios;
|
||||||
|
});
|
||||||
|
|
||||||
|
## Example scenarios that showcase extra features
|
||||||
|
exampleScenarios = with lib; {
|
||||||
# Run a selection of tests in scenario 'netns'
|
# Run a selection of tests in scenario 'netns'
|
||||||
selectedTests = {
|
selectedTests = {
|
||||||
imports = [ scenarios.netns ];
|
imports = [ scenarios.netns ];
|
||||||
@ -337,39 +338,106 @@ let
|
|||||||
test.container.exposeLocalhost = true;
|
test.container.exposeLocalhost = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
adhoc = {
|
## Scenarios with a custom Python test
|
||||||
# <Add your config here>
|
|
||||||
# You can also set the env var `scenarioOverridesFile` (used below) to define custom scenarios.
|
# Variant 1: Define testing code that always runs
|
||||||
|
customTestSimple = {
|
||||||
|
networking.hostName = "myhost";
|
||||||
|
|
||||||
|
# Variant 1: Define testing code that always runs
|
||||||
|
test.extraTestScript = ''
|
||||||
|
succeed("[[ $(hostname) == myhost ]]")
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# Variant 2: Define a test that can be enabled/disabled
|
||||||
|
# via the Nix module system.
|
||||||
|
customTestExtended = {
|
||||||
|
networking.hostName = "myhost";
|
||||||
|
|
||||||
|
tests.hostName = true;
|
||||||
|
test.extraTestScript = ''
|
||||||
|
@test("hostName")
|
||||||
|
def _():
|
||||||
|
succeed("[[ $(hostname) == myhost ]]")
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
in {
|
||||||
|
inherit scenarios;
|
||||||
|
|
||||||
overrides = builtins.getEnv "scenarioOverridesFile";
|
pkgs = flake: pkgs: rec {
|
||||||
extraScenarios' = (if (overrides != "") then import overrides else extraScenarios) {
|
# A basic test using the nix-bitcoin test framework
|
||||||
inherit scenarios pkgs;
|
makeTestBasic = import ./lib/make-test.nix flake pkgs makeTestVM;
|
||||||
inherit (pkgs) lib;
|
|
||||||
|
# Wraps `makeTest` in NixOS' testing-python.nix so that the drv includes the
|
||||||
|
# log output and the test driver
|
||||||
|
makeTestVM = import ./lib/make-test-vm.nix pkgs;
|
||||||
|
|
||||||
|
# A test using the nix-bitcoin test framework, with some helpful defaults
|
||||||
|
makeTest = { name ? "nix-bitcoin-test", config }:
|
||||||
|
makeTestBasic {
|
||||||
|
inherit name;
|
||||||
|
config = {
|
||||||
|
imports = [
|
||||||
|
scenarios.base
|
||||||
|
config
|
||||||
|
];
|
||||||
|
# Share the same pkgs instance among tests
|
||||||
|
nixpkgs.pkgs = pkgs.lib.mkDefault pkgs;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# A test using the nix-bitcoin test framework, with defaults specific to nix-bitcoin
|
||||||
|
makeTestNixBitcoin = { name, config }:
|
||||||
|
makeTest {
|
||||||
|
name = "nix-bitcoin-${name}";
|
||||||
|
config = {
|
||||||
|
imports = [ config ];
|
||||||
|
test.shellcheckServices.sourcePrefix = toString ./..;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
makeTests = scenarios: let
|
||||||
|
mainTests = builtins.mapAttrs (name: config:
|
||||||
|
makeTestNixBitcoin { inherit name config; }
|
||||||
|
) scenarios;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
clightning-replication = import ./clightning-replication.nix makeTestVM pkgs;
|
||||||
|
} // mainTests;
|
||||||
|
|
||||||
|
tests = makeTests scenarios;
|
||||||
|
|
||||||
|
## Helper for ./run-tests.sh
|
||||||
|
|
||||||
|
getTest = { name, extraScenariosFile ? null }:
|
||||||
|
let
|
||||||
|
tests = makeTests (scenarios // (
|
||||||
|
lib.optionalAttrs (extraScenariosFile != null)
|
||||||
|
(import extraScenariosFile {
|
||||||
|
inherit scenarios lib pkgs;
|
||||||
|
nix-bitcoin = flake;
|
||||||
|
})
|
||||||
|
));
|
||||||
|
in
|
||||||
|
tests.${name} or (makeTestNixBitcoin {
|
||||||
|
inherit name;
|
||||||
|
config = {
|
||||||
|
services.${name}.enable = true;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
instantiateTests = testNames:
|
||||||
|
let
|
||||||
|
testNames' = lib.splitString " " testNames;
|
||||||
|
in
|
||||||
|
map (name:
|
||||||
|
let
|
||||||
|
test = tests.${name};
|
||||||
|
in
|
||||||
|
builtins.seq (builtins.trace "Evaluating test '${name}'" test.outPath)
|
||||||
|
test
|
||||||
|
) testNames';
|
||||||
};
|
};
|
||||||
allScenarios = scenarios // extraScenarios';
|
}
|
||||||
|
|
||||||
makeTest = name: config:
|
|
||||||
makeTest' name {
|
|
||||||
imports = [
|
|
||||||
allScenarios.base
|
|
||||||
config
|
|
||||||
];
|
|
||||||
};
|
|
||||||
makeTest' = import ./lib/make-test.nix pkgs;
|
|
||||||
|
|
||||||
tests = builtins.mapAttrs makeTest allScenarios // {
|
|
||||||
clightningReplication.vm = import ./clightning-replication.nix {
|
|
||||||
inherit pkgs;
|
|
||||||
inherit (pkgs.stdenv) system;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
getTest = name: tests.${name} or (makeTest name {
|
|
||||||
services.${name}.enable = true;
|
|
||||||
});
|
|
||||||
in
|
|
||||||
tests // {
|
|
||||||
inherit getTest;
|
|
||||||
}
|
|
||||||
|
@ -48,7 +48,8 @@ def test(name):
|
|||||||
tests[name] = fn
|
tests[name] = fn
|
||||||
return x
|
return x
|
||||||
|
|
||||||
def run_tests():
|
# `run_tests` is already defined by the NixOS test driver
|
||||||
|
def nb_run_tests():
|
||||||
enabled = enabled_tests.copy()
|
enabled = enabled_tests.copy()
|
||||||
to_run = []
|
to_run = []
|
||||||
for test in tests:
|
for test in tests:
|
||||||
|
Loading…
Reference in New Issue
Block a user