Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

nixos/wasabibackend: init 1.1.11.1 #90884

Merged
merged 4 commits into from Jun 20, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions nixos/modules/module-list.nix
Expand Up @@ -756,6 +756,7 @@
./services/networking/v2ray.nix
./services/networking/vsftpd.nix
./services/networking/wakeonlan.nix
./services/networking/wasabibackend.nix
./services/networking/websockify.nix
./services/networking/wg-quick.nix
./services/networking/wicd.nix
Expand Down
158 changes: 158 additions & 0 deletions nixos/modules/services/networking/wasabibackend.nix
@@ -0,0 +1,158 @@
{ config, lib, pkgs, ... }:

let
cfg = config.services.wasabibackend;

inherit (lib) mkEnableOption mkIf mkOption optionalAttrs optionalString types;

confOptions = {
BitcoinRpcConnectionString = "${cfg.rpc.user}:${cfg.rpc.password}";
} // optionalAttrs (cfg.network == "mainnet") {
Network = "Main";
MainNetBitcoinP2pEndPoint = "${cfg.endpoint.ip}:${toString cfg.endpoint.port}";
MainNetBitcoinCoreRpcEndPoint = "${cfg.rpc.ip}:${toString cfg.rpc.port}";
} // optionalAttrs (cfg.network == "testnet") {
Network = "TestNet";
TestNetBitcoinP2pEndPoint = "${cfg.endpoint.ip}:${toString cfg.endpoint.port}";
TestNetBitcoinCoreRpcEndPoint = "${cfg.rpc.ip}:${toString cfg.rpc.port}";
} // optionalAttrs (cfg.network == "regtest") {
Network = "RegTest";
RegTestBitcoinP2pEndPoint = "${cfg.endpoint.ip}:${toString cfg.endpoint.port}";
RegTestBitcoinCoreRpcEndPoint = "${cfg.rpc.ip}:${toString cfg.rpc.port}";
};

configFile = pkgs.writeText "wasabibackend.conf" (builtins.toJSON confOptions);

in {

options = {

services.wasabibackend = {
enable = mkEnableOption "Wasabi backend service";

dataDir = mkOption {
type = types.path;
default = "/var/lib/wasabibackend";
description = "The data directory for the Wasabi backend node.";
};

customConfigFile = mkOption {
type = types.nullOr types.path;
default = null;
description = "Defines the path to a custom configuration file that is copied to the user's directory. Overrides any config options.";
};

network = mkOption {
type = types.enum [ "mainnet" "testnet" "regtest" ];
default = "mainnet";
description = "The network to use for the Wasabi backend service.";
};

endpoint = {
ip = mkOption {
type = types.str;
default = "127.0.0.1";
description = "IP address for P2P connection to bitcoind.";
};

port = mkOption {
type = types.port;
default = 8333;
description = "Port for P2P connection to bitcoind.";
};
};

rpc = {
ip = mkOption {
type = types.str;
default = "127.0.0.1";
description = "IP address for RPC connection to bitcoind.";
};

port = mkOption {
type = types.port;
default = 8332;
description = "Port for RPC connection to bitcoind.";
};

user = mkOption {
type = types.str;
default = "bitcoin";
description = "RPC user for the bitcoin endpoint.";
};

password = mkOption {
type = types.str;
default = "password";
description = "RPC password for the bitcoin endpoint. Warning: this is stored in cleartext in the Nix store! Use <literal>configFile</literal> or <literal>passwordFile</literal> if needed.";
};

passwordFile = mkOption {
type = types.nullOr types.path;
default = null;
description = "File that contains the password the the RPC user.";
mmahut marked this conversation as resolved.
Show resolved Hide resolved
};
};

user = mkOption {
type = types.str;
default = "wasabibackend";
description = "The user as which to run the wasabibackend node.";
};

group = mkOption {
type = types.str;
default = cfg.user;
description = "The group as which to run the wasabibackend node.";
};
};
};

config = mkIf cfg.enable {

systemd.tmpfiles.rules = [
"d '${cfg.dataDir}' 0770 '${cfg.user}' '${cfg.group}' - -"
];

systemd.services.wasabibackend = {
description = "wasabibackend server";
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target" ];
environment = {
DOTNET_PRINT_TELEMETRY_MESSAGE = "false";
DOTNET_CLI_TELEMETRY_OPTOUT = "true";
};
preStart = ''
mkdir -p ${cfg.dataDir}/.walletwasabi/backend
${if cfg.customConfigFile != null then ''
cp -v ${cfg.customConfigFile} ${cfg.dataDir}/.walletwasabi/backend/Config.json
'' else ''
cp -v ${configFile} ${cfg.dataDir}/.walletwasabi/backend/Config.json
${optionalString (cfg.rpc.passwordFile != null) ''
CONFIGTMP=$(mktemp)
cat ${cfg.dataDir}/.walletwasabi/backend/Config.json | ${pkgs.jq}/bin/jq --arg rpconnection "${cfg.rpc.user}:$(cat "${cfg.rpc.passwordFile}")" '. + { BitcoinRpcConnectionString: $rpconnection }' > $CONFIGTMP
mv $CONFIGTMP ${cfg.dataDir}/.walletwasabi/backend/Config.json
''}
''}
chmod ug+w ${cfg.dataDir}/.walletwasabi/backend/Config.json
'';
serviceConfig = {
User = cfg.user;
Group = cfg.group;
ExecStart = "${pkgs.wasabibackend}/bin/WasabiBackend";
ProtectSystem = "full";
};
mmahut marked this conversation as resolved.
Show resolved Hide resolved
};

users.users.${cfg.user} = {
name = cfg.user;
group = cfg.group;
description = "wasabibackend daemon user";
home = cfg.dataDir;
isSystemUser = true;
};

users.groups.${cfg.group} = {};

};
}
1 change: 1 addition & 0 deletions nixos/tests/all-tests.nix
Expand Up @@ -341,6 +341,7 @@ in
vault = handleTest ./vault.nix {};
victoriametrics = handleTest ./victoriametrics.nix {};
virtualbox = handleTestOn ["x86_64-linux"] ./virtualbox.nix {};
wasabibackend = handleTest ./wasabibackend.nix {};
wireguard = handleTest ./wireguard {};
wordpress = handleTest ./wordpress.nix {};
xandikos = handleTest ./xandikos.nix {};
Expand Down
38 changes: 38 additions & 0 deletions nixos/tests/wasabibackend.nix
@@ -0,0 +1,38 @@
import ./make-test-python.nix ({ pkgs, ... }: {
name = "wasabibackend";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ mmahut ];
};

nodes = {
machine = { ... }: {
services.wasabibackend = {
enable = true;
network = "testnet";
rpc = {
user = "alice";
port = 18332;
};
};
services.bitcoind = {
enable = true;
testnet = true;
rpc.users = {
alice.passwordHMAC = "e7096bc21da60b29ecdbfcdb2c3acc62$f948e61cb587c399358ed99c6ed245a41460b4bf75125d8330c9f6fcc13d7ae7";
};
};
};
};

testScript = ''
start_all()
machine.wait_for_unit("wasabibackend.service")
machine.wait_until_succeeds(
"grep 'Wasabi Backend started' /var/lib/wasabibackend/.walletwasabi/backend/Logs.txt"
)
machine.sleep(5)
mmahut marked this conversation as resolved.
Show resolved Hide resolved
machine.succeed(
"grep 'Config is successfully initialized' /var/lib/wasabibackend/.walletwasabi/backend/Logs.txt"
)
'';
})
98 changes: 98 additions & 0 deletions pkgs/applications/blockchains/wasabibackend/create_deps.sh
@@ -0,0 +1,98 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p dotnet-sdk_3 nixfmt

# Run this script to generate deps.nix
# ./create_deps.sh /path/to/package/source/checkout > deps.nix

# TODO: consolidate with other dotnet deps generation scripts by which
# this script is inspired:
# - pkgs/servers/nosql/eventstore/create-deps.sh
# - pkgs/development/dotnet-modules/python-language-server/create_deps.sh

URLBASE="https://www.nuget.org/api/v2/package"

DEPS_HEADER="
{ fetchurl }:
let
nugetUrlBase = \"$URLBASE\";
fetchNuGet = { name, version, sha256 }: fetchurl {
inherit sha256;
url = \"\${nugetUrlBase}/\${name}/\${version}\";
};
in ["

DEPS_FOOTER="]"

DEPS_TEMPLATE="
(fetchNuGet {
name = \"%s\";
version = \"%s\";
sha256 = \"%s\";
})"


function generate_restore_log() {
checkout_path=$1
>&2 echo "generating restore log for $checkout_path..."
cd $checkout_path
dotnet nuget locals all --clear
dotnet restore -v normal --no-cache WalletWasabi.Backend -r linux-x64
cd -
}

function process_restore_log() {
restore_log=$1
>&2 echo "processing restore log..."
while read line; do
if echo $line | grep -q "^[[:space:]]*Installing"; then
l=$(echo $line | xargs)
l=${l#Installing }
l=${l%.}
echo $l
fi
done < $restore_log
}

function prefetch_deps() {
processed_log=$1
>&2 echo "prefetching deps..."
while read line; do
name=$(echo $line | cut -d' ' -f1)
>&2 echo "prefetching '$name' version: $version"
version=$(echo $line | cut -d' ' -f2)
hash=$(nix-prefetch-url "$URLBASE/$name/$version" 2>/dev/null)
echo "$name $version $hash"
done < $processed_log
}

function generate_deps_expression() {
packages=$1
>&2 echo "generating deps nix-expression..."
echo $DEPS_HEADER
while read line; do
name=$(echo $line | cut -d' ' -f1)
version=$(echo $line | cut -d' ' -f2)
hash=$(echo $line | cut -d' ' -f3)
printf "$DEPS_TEMPLATE" $name $version $hash
done < $packages
echo $DEPS_FOOTER
}

function main() {
checkout_path=$1
tmpdir=$(mktemp -d)
generate_restore_log $checkout_path > $tmpdir/restore.log
process_restore_log $tmpdir/restore.log > $tmpdir/processed.log
prefetch_deps $tmpdir/processed.log > $tmpdir/prefetched.log
generate_deps_expression $tmpdir/prefetched.log > $tmpdir/deps.nix
nixfmt $tmpdir/deps.nix
cat $tmpdir/deps.nix
rm -rf $tmpdir
}

if [ ! -d "$1" ]; then
>&2 echo "First argument must be a directory, the path to the package source checkout"
exit 1
fi

main $@