init: dcrd, dcrwallet, and dcrctl at 2.0.6. init modules for dcrd and dcrwallet
This commit is contained in:
commit
ef50d6a637
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.stfolder/
|
||||
24
README.md
Normal file
24
README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# nix-decred
|
||||
|
||||
nix-decred is a collection of Nix packages and NixOS modules, inspired by [nix-bitcoin](https://github.com/fort-nix/nix-bitcoin).
|
||||
|
||||
Overview
|
||||
---
|
||||
While nix-decred is used in production today, it is considered experimental.
|
||||
|
||||
nix-decred nodes can be deployed on dedicated hardware, virtual machines or containers.
|
||||
The Nix packages and NixOS modules can be used independently and combined freely.
|
||||
|
||||
nix-decred is built on top of Nix and [NixOS](https://nixos.org/) which provide powerful abstractions to keep it highly customizable and maintainable. Running nix-decred currently requires previous experience with the Nix ecosystem, as no support is provided.
|
||||
|
||||
Security Considerations
|
||||
---
|
||||
Using this flake could be dangerous, as it provides the hashes for the software you'll be running.
|
||||
|
||||
If you want to use this today, the sane way would be to fork the project, review the codebase, and then review and merge all future changes as necessary. If you're familiar with nix, forking should still be faster than writing the packages and modules from scratch yourself.
|
||||
|
||||
The git server for this project runs on a shared virtual server, so don't trust unsigned or unverified messages.
|
||||
|
||||
Support
|
||||
---
|
||||
No support is provided. If you have ideas for improvement, general feedback, or a PR, you can tag @stakeynet on the Decred matrix channels.
|
||||
49
docs/dcrd.md
Normal file
49
docs/dcrd.md
Normal file
@ -0,0 +1,49 @@
|
||||
# dcrd options
|
||||
|
||||
`dcrd` uses rpc credentials, so it's recommended to secure your secrets using a tool like [sops-nix](https://github.com/Mic92/sops-nix).
|
||||
|
||||
## sops-nix
|
||||
|
||||
Render `dcrd.conf` with `sops-nix` and point the service at it. Example:
|
||||
|
||||
```nix
|
||||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
# Define credentials as secrets
|
||||
sops.secrets."dcrd/rpcuser" = {};
|
||||
sops.secrets."dcrd/rpcpass" = {};
|
||||
|
||||
# Render dcrd.conf owned by the dcrd service user/group
|
||||
sops.templates."dcrd.conf" = {
|
||||
owner = config.services.dcrd.user;
|
||||
group = config.services.dcrd.group;
|
||||
mode = "0440";
|
||||
restartUnits = [ "dcrd.service" ];
|
||||
content = ''
|
||||
[Application Options]
|
||||
# example settings
|
||||
rpcuser=${config.sops.placeholder."dcrd/rpcuser"}
|
||||
rpcpass=${config.sops.placeholder."dcrd/rpcpass"}
|
||||
'';
|
||||
};
|
||||
|
||||
# Ensure dcrd only starts when the config exists
|
||||
systemd.services.dcrd.unitConfig.ConditionPathExists =
|
||||
config.sops.templates."dcrd.conf".path;
|
||||
|
||||
# Point the module to the rendered config
|
||||
services.dcrd = {
|
||||
enable = true;
|
||||
configFile = config.sops.templates."dcrd.conf".path;
|
||||
};
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
Instead of using DynamicUser, the module necessarily runs `dcrd` as a fixed `User`/`Group` and uses a non-private state directory so `rpc.cert` can be read by intended consumers.
|
||||
|
||||
- `dcrd` writes `rpc.cert` into its data dir (`--appdata`, defaulting to `/var/lib/dcrd`).
|
||||
- Consumers (e.g., wallets, tooling) often need to read `rpc.cert` without elevated privileges.
|
||||
- With `DynamicUser=true`, systemd places state under `/var/lib/private/dcrd` and uses an ephemeral UID, which prevents other users/services from traversing the directory and reading `rpc.cert`.
|
||||
95
docs/dcrwallet.md
Normal file
95
docs/dcrwallet.md
Normal file
@ -0,0 +1,95 @@
|
||||
# dcrwallet options
|
||||
|
||||
`dcrwallet` uses rpc credentials, so it's recommended to secure your secrets using a tool like [sops-nix](https://github.com/Mic92/sops-nix).
|
||||
|
||||
## sops-nix
|
||||
|
||||
Render `dcrwallet.conf` with `sops-nix` and point the service at it. For example, here's a sample configuration for a voting wallet:
|
||||
|
||||
```nix
|
||||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
# Define credentials as secrets
|
||||
sops.secrets."dcrwallet/rpcuser" = {};
|
||||
sops.secrets."dcrwallet/rpcpass" = {};
|
||||
|
||||
sops.templates."dcrctl.conf" = {
|
||||
path = "/home/operator/.dcrctl/dcrctl.conf";
|
||||
owner = "operator";
|
||||
group = "users";
|
||||
mode = "0400";
|
||||
content = ''
|
||||
[Application Options]
|
||||
rpcuser=${config.sops.placeholder."dcrwallet/rpcuser"}
|
||||
rpcpass=${config.sops.placeholder."dcrwallet/rpcpass"}
|
||||
rpccert=/var/lib/dcrwallet/rpc.cert
|
||||
wallet=1
|
||||
'';
|
||||
};
|
||||
sops.templates."dcrwallet.conf" = {
|
||||
owner = config.services.dcrwallet.user;
|
||||
group = config.services.dcrwallet.group;
|
||||
mode = "0440";
|
||||
restartUnits = [ "dcrwallet.service" ];
|
||||
content = ''
|
||||
[Application Options]
|
||||
CAFile=/var/lib/dcrd/rpc.cert
|
||||
rpclisten=0.0.0.0:9110
|
||||
username=${config.sops.placeholder."dcrwallet/rpcpass"}
|
||||
password=${config.sops.placeholder."dcrwallet/rpcpass"}
|
||||
enablevoting=1
|
||||
manualtickets=1
|
||||
'';
|
||||
};
|
||||
|
||||
# Ensure dcrwallet only starts when the config exists
|
||||
systemd.services.dcrwallet.unitConfig.ConditionPathExists = config.sops.templates."dcrwallet.conf".path;
|
||||
|
||||
services.dcrwallet = {
|
||||
enable = true;
|
||||
configFile = config.sops.templates."dcrwallet.conf".path;
|
||||
extraPackages = [
|
||||
pkgs.dcrctl
|
||||
pkgs.dcrd # promptsecret
|
||||
];
|
||||
operator = {
|
||||
enable = true;
|
||||
name = "stakey";
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Initialization
|
||||
|
||||
If you run dcrwallet as a service, here's how to intialize a wallet as `root`.
|
||||
|
||||
```bash
|
||||
cd /var/lib/dcrwallet
|
||||
export DCRWALLET_BIN=$(systemctl cat --runtime dcrwallet.service | grep ExecStart | awk '{print $1}' | cut -d= -f2)
|
||||
doas -u dcrwallet $DCRWALLET_BIN \
|
||||
--configfile=/run/secrets/rendered/dcrwallet.conf \
|
||||
--appdata=/var/lib/dcrwallet \
|
||||
--create
|
||||
```
|
||||
|
||||
Then you need to start dcrwallet manually the first time to sync.
|
||||
|
||||
```sh
|
||||
tmux new "doas -u dcrwallet $DCRWALLET_BIN --configfile=/run/secrets/rendered/dcrwallet.conf --appdata=/var/lib/dcrwallet"
|
||||
```
|
||||
|
||||
## Using the operator
|
||||
|
||||
```sh
|
||||
su - operator
|
||||
dcrctl help
|
||||
```
|
||||
|
||||
## Enable Voting
|
||||
|
||||
Use the operator account.
|
||||
|
||||
```sh
|
||||
promptsecret | dcrwallet walletpassphrase - 0
|
||||
```
|
||||
43
flake.nix
Normal file
43
flake.nix
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
description = ''
|
||||
A collection of Nix packages and NixOS modules for easily
|
||||
installing full-featured Decred nodes.
|
||||
'';
|
||||
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs }: let
|
||||
supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
|
||||
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||
in {
|
||||
packages = forAllSystems (system: let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
in {
|
||||
dcrd = pkgs.callPackage ./pkgs/dcrd.nix {};
|
||||
dcrctl = pkgs.callPackage ./pkgs/dcrctl.nix {};
|
||||
dcrwallet = pkgs.callPackage ./pkgs/dcrwallet.nix {};
|
||||
});
|
||||
|
||||
overlays.default = final: prev: {
|
||||
dcrd = final.callPackage ./pkgs/dcrd.nix {};
|
||||
dcrctl = final.callPackage ./pkgs/dcrctl.nix {};
|
||||
dcrwallet = final.callPackage ./pkgs/dcrwallet.nix {};
|
||||
};
|
||||
|
||||
nixosModules = {
|
||||
dcrd = ./modules/dcrd.nix;
|
||||
dcrwallet = ./modules/dcrwallet.nix;
|
||||
default = { config, lib, pkgs, ... }: {
|
||||
imports = [
|
||||
self.nixosModules.dcrd
|
||||
self.nixosModules.dcrwallet
|
||||
];
|
||||
nixpkgs.overlays = [ self.overlays.default ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
123
modules/dcrd.nix
Normal file
123
modules/dcrd.nix
Normal file
@ -0,0 +1,123 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.dcrd;
|
||||
settingsFormat = pkgs.formats.ini {
|
||||
listsAsDuplicateKeys = true;
|
||||
};
|
||||
networkPorts = {
|
||||
mainnet = 9108;
|
||||
testnet = 19108;
|
||||
simnet = 18555;
|
||||
regnet = 18655;
|
||||
};
|
||||
effectivePort = if cfg.port == null then networkPorts.${cfg.network} else cfg.port;
|
||||
# dcrd requires settings to be lowercase
|
||||
lowercaseKeys = attrs: lib.mapAttrs' (k: v: { name = lib.strings.toLower k; value = v; }) attrs;
|
||||
baseAppOptions =
|
||||
{}
|
||||
// (if cfg.network == "testnet" then { testnet = true; }
|
||||
else if cfg.network == "simnet" then { simnet = true; }
|
||||
else if cfg.network == "regnet" then { regnet = true; }
|
||||
else {})
|
||||
// lib.optionalAttrs (cfg.port != null || cfg.listenAddress != "0.0.0.0") {
|
||||
listen = "${cfg.listenAddress}:${toString effectivePort}";
|
||||
};
|
||||
combinedAppOptions = lib.recursiveUpdate baseAppOptions (lowercaseKeys cfg.settings);
|
||||
finalSettings = { "Application Options" = combinedAppOptions; };
|
||||
generatedConfig = settingsFormat.generate "dcrd.conf" finalSettings;
|
||||
in
|
||||
{
|
||||
options.services.dcrd = with lib; {
|
||||
enable = mkEnableOption "Decred daemon";
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.dcrd;
|
||||
description = "Package providing the dcrd binary";
|
||||
};
|
||||
network = mkOption {
|
||||
type = types.enum [ "mainnet" "testnet" "simnet" "regnet" ];
|
||||
default = "mainnet";
|
||||
description = "Select which network to run: mainnet, testnet, simnet, or regnet";
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.nullOr types.port;
|
||||
default = null;
|
||||
description = "P2P port override. Null uses the default for the selected network";
|
||||
};
|
||||
listenAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "0.0.0.0";
|
||||
description = "IP address to bind to listen for connections";
|
||||
};
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Open P2P port in the firewall";
|
||||
};
|
||||
configFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = "Absolute path to a dcrd.conf to use instead of the generated config. When set, the generated settings are ignored.";
|
||||
};
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "dcrd";
|
||||
description = "User to run dcrd as";
|
||||
};
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = cfg.user;
|
||||
description = "Group to run dcrd as";
|
||||
};
|
||||
settings = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = types.attrsOf settingsFormat.lib.types.atom;
|
||||
};
|
||||
default = {};
|
||||
example = {
|
||||
externalip = [ "203.0.113.42" ];
|
||||
rpclisten = [ "127.0.0.1:9109" "192.168.1.100:9109" ];
|
||||
rpcuser = "dcrd";
|
||||
rpcpass = "hunter2";
|
||||
txindex = true;
|
||||
proxy = "127.0.0.1:9050";
|
||||
};
|
||||
description = ''
|
||||
Options that accept multiple values (like rpclisten, externalip,
|
||||
listen, addpeer, miningaddr, altdnsnames, whitelist) should be
|
||||
specified as lists.
|
||||
|
||||
Single-value options (like rpcuser, rpcpass, proxy, txindex)
|
||||
should be specified as strings or booleans.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
users.groups.${cfg.group} = {};
|
||||
users.users.${cfg.user} = {
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
description = "Decred daemon user";
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ effectivePort ];
|
||||
|
||||
systemd.services.dcrd = {
|
||||
description = "Decred full node";
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
StateDirectory = "dcrd";
|
||||
StateDirectoryMode = "0750";
|
||||
ExecStart = ''${lib.getExe cfg.package} --appdata=/var/lib/dcrd --configfile=${if cfg.configFile != null then cfg.configFile else generatedConfig}'';
|
||||
Restart = "on-failure";
|
||||
RestartSec = 5;
|
||||
};
|
||||
restartTriggers = [ generatedConfig ] ++ lib.optional (cfg.configFile != null) cfg.configFile;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
122
modules/dcrwallet.nix
Normal file
122
modules/dcrwallet.nix
Normal file
@ -0,0 +1,122 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
dcrdEnabled = config.services.dcrd.enable or false;
|
||||
cfg = config.services.dcrwallet;
|
||||
in
|
||||
{
|
||||
options.services.dcrwallet = with lib; {
|
||||
enable = mkEnableOption "Decred wallet daemon";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.dcrwallet;
|
||||
description = "Package providing the dcrwallet binary";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "dcrwallet";
|
||||
description = "User to run dcrwallet as";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = cfg.user;
|
||||
description = "Group to run dcrwallet as";
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/dcrwallet";
|
||||
description = "State directory for dcrwallet (appdata)";
|
||||
};
|
||||
|
||||
configFile = mkOption {
|
||||
type = types.path;
|
||||
description = "Path to dcrwallet configuration file (runtime path)";
|
||||
};
|
||||
|
||||
extraPackages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = [];
|
||||
example = [ pkgs.dcrctl ];
|
||||
description = "Additional packages to add to the dcrwallet user's environment";
|
||||
};
|
||||
|
||||
operator = {
|
||||
enable = mkEnableOption "Install dcrwallet CLI packages for an operator user";
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = "operator";
|
||||
description = "Operator username to receive dcrwallet package(s) in their environment.";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable (lib.mkMerge [
|
||||
{
|
||||
users.users.${cfg.user} = {
|
||||
group = cfg.group;
|
||||
home = cfg.dataDir;
|
||||
isNormalUser = true;
|
||||
packages = [ cfg.package ] ++ cfg.extraPackages;
|
||||
# dcrwallet needs read access to the dcrd RPC certificate
|
||||
extraGroups = lib.optional (dcrdEnabled && config.services.dcrd.group != cfg.group) config.services.dcrd.group;
|
||||
};
|
||||
users.groups.${cfg.group} = {};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${cfg.dataDir} 0750 ${cfg.user} ${cfg.group} -"
|
||||
];
|
||||
|
||||
systemd.services.dcrwallet = {
|
||||
description = "Decred wallet daemon";
|
||||
after = [ "network-online.target" ] ++ lib.optional dcrdEnabled "dcrd.service";
|
||||
wants = [ "network-online.target" ] ++ lib.optional dcrdEnabled "dcrd.service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
RuntimeDirectory = "dcrwallet";
|
||||
StateDirectory = "dcrwallet";
|
||||
StateDirectoryMode = "0750";
|
||||
ExecStart = ''${lib.getExe cfg.package} --appdata=${cfg.dataDir} --configfile=${cfg.configFile}'';
|
||||
};
|
||||
restartTriggers = [ cfg.configFile ];
|
||||
};
|
||||
}
|
||||
(lib.mkIf cfg.operator.enable {
|
||||
users.users.${cfg.operator.name} = {
|
||||
packages = [ cfg.package ] ++ cfg.extraPackages;
|
||||
# Add the operator user to the dcrwallet group and dcrd group
|
||||
extraGroups = [ cfg.group ] ++ lib.optional (dcrdEnabled && config.services.dcrd.group != cfg.group) config.services.dcrd.group;
|
||||
};
|
||||
|
||||
# Ensure operator (a member of cfg.group) can read rpc.cert which dcrwallet
|
||||
# writes with mode 0600 by default. We watch for the file and set g+r.
|
||||
systemd.services.dcrwallet-cert-perms = {
|
||||
description = "Ensure group-read on dcrwallet rpc.cert";
|
||||
after = [ "dcrwallet.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
};
|
||||
script = ''
|
||||
if [ -e ${cfg.dataDir}/rpc.cert ]; then
|
||||
${pkgs.coreutils}/bin/chmod g+r ${cfg.dataDir}/rpc.cert
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.paths.dcrwallet-cert-perms = {
|
||||
description = "Watch dcrwallet rpc.cert to fix permissions";
|
||||
pathConfig = {
|
||||
# PathModified = "${cfg.dataDir}/rpc.cert";
|
||||
PathChanged = "${cfg.dataDir}/rpc.cert";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
32
pkgs/dcrctl.nix
Normal file
32
pkgs/dcrctl.nix
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
lib,
|
||||
buildGoModule,
|
||||
fetchFromGitHub,
|
||||
}:
|
||||
|
||||
buildGoModule (finalAttrs: {
|
||||
pname = "dcrctl";
|
||||
version = "2.0.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "decred";
|
||||
repo = "dcrctl";
|
||||
rev = "release-v${finalAttrs.version}";
|
||||
hash = "sha256-TxXPPe4AUEck3dFS0+TJgEPenAP43UOwqKWK/3unzjA=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-YctyhZV6qf8xPnjrkkOwerazKHVOUAkpKe7kV3t6Tis=";
|
||||
|
||||
ldflags = [
|
||||
"-s"
|
||||
"-w"
|
||||
];
|
||||
|
||||
meta = {
|
||||
homepage = "https://decred.org";
|
||||
description = "Decred CLI tool";
|
||||
license = with lib.licenses; [ isc ];
|
||||
mainProgram = "dcrctl";
|
||||
};
|
||||
})
|
||||
|
||||
37
pkgs/dcrd.nix
Normal file
37
pkgs/dcrd.nix
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
lib,
|
||||
buildGoModule,
|
||||
fetchFromGitHub,
|
||||
}:
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "dcrd";
|
||||
version = "2.0.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "decred";
|
||||
repo = "dcrd";
|
||||
rev = "dabb3760c7ae45e42ee55f0d86dd8def61b41a69";
|
||||
hash = "sha256-mSq4SRSnZOoCuRKVwmb8Y6+KbaTtg+DLf4YX5oApx0k=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-kzb8qh1j2+TlX+et0RSq5qU1LHSEs3Kaf0nHOnGjdd0=";
|
||||
|
||||
subPackages = [
|
||||
"."
|
||||
"cmd/promptsecret"
|
||||
];
|
||||
|
||||
# Keep tests from writing outside the sandbox
|
||||
preCheck = ''
|
||||
export DCRD_APPDATA="$TMPDIR"
|
||||
'';
|
||||
|
||||
meta = {
|
||||
homepage = "https://decred.org";
|
||||
description = "Decred daemon in Go (golang)";
|
||||
license = with lib.licenses; [ isc ];
|
||||
mainProgram = "dcrd";
|
||||
};
|
||||
}
|
||||
|
||||
35
pkgs/dcrwallet.nix
Normal file
35
pkgs/dcrwallet.nix
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
lib,
|
||||
buildGoModule,
|
||||
fetchFromGitHub,
|
||||
}:
|
||||
|
||||
buildGoModule (finalAttrs: {
|
||||
pname = "dcrwallet";
|
||||
version = "2.0.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "decred";
|
||||
repo = "dcrwallet";
|
||||
rev = "release-v${finalAttrs.version}";
|
||||
hash = "sha256-MrQrDip8vE0l5XHkx/zIegSZd/AkWq1aFZLUVPdMy50=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-Ulh6RxK+PvS70mJ7TYiGMzKFsR79+asWuQ5W1FAI23I=";
|
||||
|
||||
subPackages = [ "." ];
|
||||
|
||||
checkFlags = [
|
||||
# Test fails with:
|
||||
# 'x509_test.go:201: server did not report bad certificate error;
|
||||
# instead errored with [...] tls: unknown certificate authority (*url.Error)'
|
||||
"-skip=^TestUntrustedClientCert$"
|
||||
];
|
||||
|
||||
meta = {
|
||||
homepage = "https://decred.org";
|
||||
description = "Decred wallet daemon written in Go (golang)";
|
||||
license = with lib.licenses; [ isc ];
|
||||
mainProgram = "dcrwallet";
|
||||
};
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user