Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

Note

This project and its documentation are a work in progress. Parts of the project and the documentation may change and may be outdated.

Warning

This documentation may be outdated or contain installation steps that do not work with bitcoinix yet (for example, release fetching still points at the upstream nix-bitcoin project). Please report problems at https://github.com/bitcoinix/bitcoinix/issues.

bitcoinix is a collection of Nix packages and NixOS modules for easily installing full-featured Bitcoin nodes with an emphasis on security.

It is a community fork of nix-bitcoin, which was archived in August 2026. bitcoinix is a community initiative to keep the project maintained and to continue its development.

The documentation is largely inherited from nix-bitcoin and is being updated step by step.

Hardware requirements

Hardware requirements

Note

This document is inherited from nix-bitcoin, the predecessor project. It is a work in progress and may be outdated.

  • RAM: 2GB. ECC memory is better. Additionally, it’s recommended to use DDR4 memory with targeted row refresh (TRR) enabled (https://rambleed.com/).
  • Disk space: 1 TB for an unpruned instance of Bitcoin Core.
    • This can be significantly lowered by enabling pruning. Note: Pruning is not supported by electrs and fulcrum.

Tested low-end hardware includes:

Some hardware (including Intel NUCs) may not be compatible with the hardened kernel preset (See https://github.com/fort-nix/nix-bitcoin/issues/39#issuecomment-517366093 for a workaround).

Tutorial: Install and configure NixOS for bitcoinix on a dedicated machine

Note

This document is inherited from nix-bitcoin, the predecessor project. It is a work in progress and may be outdated.

Warning

This documentation may be outdated or contain installation steps that do not work with bitcoinix yet (for example, release fetching still points at the upstream nix-bitcoin project). Please report problems at https://github.com/bitcoinix/bitcoinix/issues.

This tutorial describes how to manage your Bitcoin node comfortably from your personal computer with the deployment tool krops. However, bitcoinix is agnostic to the deployment method and can be used with different or without such tools (see examples).

0. Preparation

  1. Find a machine to deploy bitcoinix on (see hardware.md).

  2. Optional: Make sure you have the latest firmware for your system (BIOS, microcode updates).

  3. Optional: Disable Simultaneous Multi-Threading (SMT) in the BIOS

    Researchers recommend disabling (SMT), also known as Hyper-Threading Technology in the Intel® world to significantly reduce the impact of speculative execution-based attacks (https://mdsattacks.com/).

1. NixOS installation

This is borrowed from the NixOS manual. Look there for more information.

  1. Obtain latest NixOS. For example:

    wget https://releases.nixos.org/nixos/24.05/nixos-24.05.3164.63d37ccd2d17/nixos-minimal-24.05.3164.63d37ccd2d17-x86_64-linux.iso
    # output: 35dd79596f12b159efc533400ba8f730d819eee2d1014683a658020c2b54ae0c
    sha256sum nixos-minimal-24.05.3164.63d37ccd2d17-x86_64-linux.iso
    

    Alternatively you can build NixOS from source by following the instructions at https://nixos.org/nixos/manual/index.html#sec-building-cd.

  2. Write NixOS iso to install media (USB/CD). For example:

    cp nixos-minimal-23.05.3701.e9b4b56e5a20-x86_64-linux.iso /dev/sdX
    

    Replace /dev/sdX with the correct device name. You can find this using sudo fdisk -l

  3. Boot the system and become root

    sudo -i
    

    You will have to find out if your hardware uses UEFI or Legacy Boot for the next step. You can do that, for example, by executing

    ls /sys/firmware/efi
    

    If the file exists you should continue the installation for UEFI otherwise for Legacy Boot.

  4. Option 1: Partition and format for UEFI

    parted /dev/sda -- mklabel gpt
    parted /dev/sda -- mkpart primary 512MiB -8GiB
    parted /dev/sda -- mkpart primary linux-swap -8GiB 100%
    parted /dev/sda -- mkpart ESP fat32 1MiB 512MiB
    parted /dev/sda -- set 3 boot on
    mkfs.ext4 -L nixos /dev/sda1
    mkswap -L swap /dev/sda2
    mkfs.fat -F 32 -n boot /dev/sda3
    mount /dev/disk/by-label/nixos /mnt
    mkdir -p /mnt/boot
    mount /dev/disk/by-label/boot /mnt/boot
    swapon /dev/sda2
    
  5. Option 2: Partition and format for Legacy Boot (MBR)

    parted /dev/sda -- mklabel msdos
    parted /dev/sda -- mkpart primary 1MiB -8GiB
    parted /dev/sda -- mkpart primary linux-swap -8GiB 100%
    mkfs.ext4 -L nixos /dev/sda1
    mkswap -L swap /dev/sda2
    mount /dev/disk/by-label/nixos /mnt
    swapon /dev/sda2
    
  6. Option 3: Set up encrypted partitions:

    Follow the guide at https://gist.github.com/martijnvermaat/76f2e24d0239470dd71050358b4d5134.

  7. Generate NixOS config

    nixos-generate-config --root /mnt
    nano /mnt/etc/nixos/configuration.nix
    

    We now need to adjust the configuration to make sure that we can ssh into the system and that it boots correctly. We add some lines to set services.openssh such that the configuration looks as follows:

    { config, pkgs, ... }:
    
    {
      imports = [
        ...
      ];
    
      # Enable the OpenSSH server.
      services.openssh = {
        enable = true;
        permitRootLogin = "yes";
      };
    
      # The rest of the file are default options and hints.
    }
    

    Now we open hardware-configuration.nix

    nano /mnt/etc/nixos/hardware-configuration.nix
    

    which will look similar to

    { config, pkgs, ... }:
    
    {
      imports = [ ];
    
      # Add line here as explained below
    
      # The rest of the file are generated options.
    }
    

    Now add one of the following lines to the location mentioned in above example hardware config.

    Option 1: UEFI

      boot.loader.systemd-boot.enable = true;
    

    Option 2: Legacy Boot (MBR)

      boot.loader.grub.device = "/dev/sda";
    

    Lastly, in rare circumstances the hardware configuration does not have a fileSystems option. In that case you need to add it with the folllowing line:

      fileSystems."/".device = "/dev/disk/by-label/nixos";
    
  8. Do the installation

    nixos-install
    

    Set root password

    setting root password...
    Enter new UNIX password:
    Retype new UNIX password:
    
  9. If everything went well

    reboot
    

2. Nix installation

The following steps are meant to be run on the machine you deploy from, not the machine you deploy to. You can also build Nix from source by following the instructions at https://nixos.org/nix/manual/#ch-installing-source.

  1. Install Dependencies (Debian 10 Buster)

    sudo apt-get install curl git gnupg2 dirmngr
    
  2. Install latest Nix in “multi-user mode” with GPG Verification according to https://nixos.org/nix/download.html

    curl -o install-nix-2.3.10 https://releases.nixos.org/nix/nix-2.3.10/install
    curl -o install-nix-2.3.10.asc https://releases.nixos.org/nix/nix-2.3.10/install.asc
    gpg2 --recv-keys B541D55301270E0BCF15CA5D8170B4726D7198DE
    gpg2 --verify ./install-nix-2.3.10.asc
    sh ./install-nix-2.3.10 --daemon
    

    Then follow the instructions. Open a new terminal window when you’re done.

    If you get an error similar to

    error: cloning builder process: Operation not permitted
    error: unable to start build process
    /tmp/nix-binary-tarball-unpack.hqawN4uSPr/unpack/nix-2.2.1-x86_64-linux/install: unable to install Nix into your default profile
    

    you’re likely not installing as multi-user because you forgot to pass the --daemon flag to the install script.

  3. Optional: Disallow substitutes

    You can put substitute = false to your nix.conf usually found in /etc/nix/ to build the packages from source. This eliminates an attack vector where nix’s build server or binary cache is compromised.

3. Setup deployment directory

  1. Clone this project

    git clone https://github.com/bitcoinix/bitcoinix
    
  2. Create a new directory for your bitcoinix node config and copy initial files from bitcoinix

    mkdir nix-bitcoin-node
    cd nix-bitcoin-node
    cp -r ../bitcoinix/examples/{configuration.nix,shell.nix,krops,.gitignore} .
    
  3. Obtain the hash of the latest bitcoinix release

    ../bitcoinix/helper/fetch-release > nix-bitcoin-release.nix
    

    Warning

    fetch-release is not adapted to bitcoinix yet: it still downloads and verifies the latest release of the archived upstream project (fort-nix/nix-bitcoin), not of bitcoinix. bitcoinix does not publish signed releases yet.

Optional: Specify the system of your node

This enables evaluating your node config on a machine that has a different system platform than your node.
Examples: Deploying from macOS or deploying from a x86 desktop PC to a Raspberry Pi.

# Run this when your node has a 64-Bit x86 CPU (e.g., an Intel or AMD CPU)
echo "x86_64-linux" > krops/system

# Run this when your node has a 64-Bit ARM CPU (e.g., Raspberry Pi 4 B, Pine64)
echo "aarch64-linux" > krops/system

Other available systems:

  • i686-linux (x86)
  • armv7l-linux (ARMv7)
    This platform is untested and has no binary caches. See here for details.

4. Deploy with krops

  1. Edit your ssh config

    nano ~/.ssh/config
    

    and add the node with an entry similar to the following (make sure to fix Hostname and IdentityFile):

    Host bitcoin-node
        # FIXME
        Hostname NODE_IP_ADDRESS_OR_HOST_NAME_HERE
        User root
        PubkeyAuthentication yes
        # FIXME
        IdentityFile ~/.ssh/id_...
        AddKeysToAgent yes
    
  2. Make sure you are in the deployment directory and edit krops/deploy.nix

    nano krops/deploy.nix
    

    Locate the FIXME and set the target to the name of the ssh config entry created earlier, i.e. bitcoin-node.

    Note that any file imported by your configuration.nix must be copied to the target machine by krops. For example, if there is an import of networking.nix you must add it to extraSources in krops/deploy.nix like this:

    extraSources = {
        "hardware-configuration.nix".file = toString ../hardware-configuration.nix;
        "networking.nix".file = toString ../networking.nix;
    };
    
  3. Optional: Disallow substitutes

    If you prefer to build the system from source instead of copying binaries from the Nix cache, add the following line to configuration.nix:

    nix.extraOptions = "substitute = false";
    

    If the build process fails for some reason when deploying with krops-deploy (see later step), it may be difficult to find the cause due to the missing output. To see the build output, SSH into the target machine and run

    nixos-rebuild -I /var/src switch
    
  4. Copy hardware-configuration.nix from your node to the deployment directory.

    scp root@bitcoin-node:/etc/nixos/hardware-configuration.nix .
    
  5. Adjust configuration by opening the configuration.nix file and enable/disable the modules you want by editing this file.

    nano configuration.nix
    

    Pay attention to lines that are preceded by FIXME comments. In particular:

    1. Make sure to set your SSH pubkey. Otherwise, you loose remote access because the config does not enable permitRootLogin (unless you add that manually).
    2. Uncomment the line ./hardware-configuration.nix by removing #.
  6. Enter the deployment environment

    nix-shell
    
  7. Deploy with krops in nix-shell

    deploy
    

    This will now create a bitcoinix node on the target machine.

  8. You can now access bitcoin-node via ssh

    ssh operator@bitcoin-node
    

    Note that you’re able to log in as the unprivileged operator user because bitcoinix automatically authorizes the ssh key added to root.

For security reasons, all normal system management tasks can and should be performed with the operator user. Logging in as root should be done as rarely as possible.

See also:

Managing your deployment

Note

This document is inherited from nix-bitcoin, the predecessor project. It is a work in progress and may be outdated.

Warning

This documentation may be outdated or contain installation steps that do not work with bitcoinix yet (for example, release fetching still points at the upstream nix-bitcoin project). Please report problems at https://github.com/bitcoinix/bitcoinix/issues.

This section applies to users of the deployment method described in the installation guide.

Deployment shell

Run command nix-shell in your deployment directory.
You now have access to deployment commands:

  • deploy
    Deploy the current configuration to your node.
  • eval-config
    Locally evaluate the configuration. This is useful to check for configuration errors.
  • h, help
    Show help

Updating bitcoinix

Run update-nix-bitcoin from the deployment shell.
This fetches the latest release, verifies its signatures and updates nix-bitcoin-release.nix.

Customizing your configuration

Get started with Nix

See Nix - A One Pager for a short guide to Nix, the language used in configuration.nix.
You can follow along this guide by running command nix repl which allows you to interactively evaluate Nix expressions.

For a general introduction to the Nix and NixOS ecosystem, see nix.dev.

Set options

All features and services are configurable through options. You can find a list of supported options at the top of each bitcoinix module (Examples: bitcoind.nix, btcpayserver.nix).

Example: Set some bitcoind options by adding these lines to your configuration.nix:

# Use a custom data dir
services.bitcoind.dataDir = "/my/datadir";

# Enable txindex
services.bitcoind.txindex = true;

You can also use regular NixOS options for configuring your system:

networking.hostName = "myhost";
time.timeZone = "UTC";

Debug your configuration

To print the values of specific options of your config, add the following to your configuration.nix:

system.extraDependencies = let
  debugVal = config.networking.firewall.allowedTCPPorts;
  # More example options:
  # debugVal = config.environment.systemPackages;
  # debugVal = config.services.bitcoind.dataDir;
in lib.traceSeqN 3 debugVal [];

and run command eval-config from the deployment shell.

Allowing external connections to services

Allow peer connections to bitcoind

services.bitcoind = {
  # Accept incoming peer connections
  listen = true;

  # Listen to connections on all interfaces
  address = "0.0.0.0";

  # Set this to also add IPv6 connectivity.
  extraConfig = ''
    bind=::
  '';

  # If you're using the `secure-node.nix` template, set this to allow non-Tor connections
  # to bitcoind
  tor.enforce = false;
  # Also set this if bitcoind should not use Tor for outgoing peer connections
  tor.proxy = false;
};

# Open the p2p port in the firewall
networking.firewall.allowedTCPPorts = [ config.services.bitcoind.port ];

Allow bitcoind RPC connections from LAN

services.bitcoind = {
  # Listen to RPC connections on all interfaces
  rpc.address = "0.0.0.0";

  # Allow RPC connections from external addresses
  rpc.allowip = [
    "10.10.0.0/24" # Allow a subnet
    "10.50.0.3" # Allow a specific address
    "0.0.0.0/0" # Allow all addresses
  ];

  # Set this if you're using the `secure-node.nix` template
  tor.enforce = false;
};

# Open the RPC port in the firewall
networking.firewall.allowedTCPPorts = [ config.services.bitcoind.rpc.port ];

Allow connections to electrs

services.electrs = {
  # Listen to connections on all interfaces
  address = "0.0.0.0";

  # Set this if you're using the `secure-node.nix` template
  tor.enforce = false;
};

# Open the electrs port in the firewall
networking.firewall.allowedTCPPorts = [ config.services.electrs.port ];

You can use the same approach to allow connections to other services.

Migrate existing services to bitcoinix

Example: bitcoind

# 1. Stop bitcoind on your node
ssh root@nix-bitcoin-node 'systemctl stop bitcoind'
# Also stop bitcoind on the node that you'll be copying data from

# 2. Copy the data to the bitcoinix node
# Important: Add a trailing slash to the source path
rsync /path/to/existing/bitcoind-datadir/ root@nix-bitcoin-node:/var/lib/bitcoind

# 3. Fix data dir permissions on the bitcoinix node
ssh root@nix-bitcoin-node 'chown -R bitcoin: /var/lib/bitcoind'

# 4. Start bitcoind
ssh root@nix-bitcoin-node 'systemctl start bitcoind'

You can use the same workflow for other services.
The default data dir path is /var/lib/<service> for all services.

Some services require extra steps:

  • lnd

    Copy your wallet password to $secretsDir/lnd-wallet-password (See: Secrets dir).

  • btcpayserver

    Copy the postgresql database:

    # Export (on the other node)
    sudo -u postgres pg_dump YOUR_BTCPAYSERVER_DB > export.sql
    # Restore (on the bitcoinix node)
    sudo -u postgres psql btcpaydb < export.sql
    

Use bitcoind from another node

Here’s how to use a bitcoind instance running on another node within a bitcoinix config:

imports = [ <nix-bitcoin/modules/presets/bitcoind-remote.nix> ];

services.bitcoind = {
  enable = true;

  # Address of the other node
  address = "10.10.0.2";
  rpc.address = "10.10.0.2";

  # Some bitcoinix services require whitelisted bitcoind p2p connections
  # to work reliably.
  # Search for `whitelistedPort` in this repo to see the affected services.
  # If you're using one of these services, either add a whitelisted p2p port
  # on your remote node via `whitebind` and set it here:
  whitelistedPort = <remote whitebind RPC port>;
  #
  # Or use the default p2p port and add `whitelist=<address of this node>` to
  # your remote bitcoind config:
  whitelistedPort = config.services.bitcoind.port;

  rpc.users = let
    # The fully privileged bitcoind RPC username of the other node
    name = "myrpcuser";
  in {
    privileged.name = name;
    public.name = name;
    ## Set this if you use btcpayserver
    # btcpayserver.name = name;
  };
};

For each service that connects to bitcoind and has option services.<service>.tor.enforce enabled (either explicitly or by importing secure-node.nix or enable-tor.nix), you need to allow the remote bitcoind connection:

systemd.services.<service>.serviceConfig.IPAddressAllow = [ ${services.bitcoind.rpc.address} ];

The above configuration is only required if the remote bitcoind is not accessed via Tor.

Now save the password of the RPC user to the following files on your bitcoinix node:

$secretsDir/bitcoin-rpcpassword-privileged
$secretsDir/bitcoin-rpcpassword-public

## Only needed when set in the above config snippet
# $secretsDir/bitcoin-rpcpassword-btcpayserver

See: Secrets dir

Afterwards, restart bitcoind: systemctl restart bitcoind.

Temporarily disable a service

Sometimes you might want to disable a service without removing the service user and integration with other services, as it would happen when setting services.<service>.enable = false.

Use the following approach:

systemd.services.<service>.wantedBy = mkForce [];

This way, the systemd service still exists, but is not automatically started.
Note: This only works for services that are not required by other active services.

Appendix

Secrets dir

The secrets dir is set by option nix-bitcoin.secretsDir and has the following default values:

  • If you’re using the krops deployment method: /var/src/secrets

  • Otherwise: /etc/nix-bitcoin-secrets

Note

This document is inherited from nix-bitcoin, the predecessor project. It is a work in progress and may be outdated.

Nodeinfo

Run nodeinfo to see onion addresses and local addresses for enabled services.

Managing services

NixOS uses the systemd service manager.

Usage:

# Show service status
systemctl status bitcoind

# Show the last 100 log messages
journalctl -u bitcoind -n 100
# Show all log messages since the last system boot
journalctl -b -u bitcoind

# These commands require root permissions
systemctl stop bitcoind
systemctl start bitcoind
systemctl restart bitcoind

# Show the service definition
systemctl cat bitcoind
# Show all service parameters
systemctl show bitcoind

clightning database replication

The clightning database can be replicated to a local path or to a remote SSH target.
When remote replication is enabled, bitcoinix mounts a SSHFS to a local path.
Optionally, backups can be encrypted via gocryptfs.

Note: You should also backup the static file hsm_secret (located at /var/lib/clightning/bitcoin/hsm_secret by default), either manually or via the services.backups module.

Remote target via SSHFS

  1. Add this to your configuration.nix:

    services.clightning.replication = {
      enable = true;
      sshfs.destination = "user@hostname:directory";
      # This is optional
      encrypt = true;
    };
    programs.ssh.knownHosts."hostname".publicKey = "<ssh public key from running `ssh-keyscan` on the host>";
    

    Leave out the encrypt line if you want to store data on your destination in plaintext.
    Adjust user, hostname and directory as necessary.

  2. Deploy

  3. To allow SSH access from the bitcoinix node to the target node, either use the remote node config below, or copy the contents of $secretsDir/clightning-replication-ssh.pub to the authorized_keys file of user (or use ssh-copy-id).

  4. You can restrict the bitcoinix node’s capabilities on the SSHFS target using OpenSSH’s builtin features, as detailed here.

    To implement this on NixOS, add the following to the NixOS configuration of the SSHFS target node:

    systemd.tmpfiles.rules = [
      # Because this directory is chrooted by sshd, it must only be writable by user/group root
      "d /var/backup/nb-replication 0755 root root - -"
      "d /var/backup/nb-replication/writable 0700 nb-replication - - -"
    ];
    
    services.openssh = {
      extraConfig = ''
        Match user nb-replication
          ChrootDirectory /var/backup/nb-replication
          AllowTcpForwarding no
          AllowAgentForwarding no
          ForceCommand internal-sftp
          PasswordAuthentication no
          X11Forwarding no
      '';
    };
    
    users.users.nb-replication = {
      isSystemUser = true;
      group = "nb-replication";
      shell = "${pkgs.coreutils}/bin/false";
      openssh.authorizedKeys.keys = [ "<contents of $secretsDir/clightning-replication-ssh.pub>" ];
    };
    users.groups.nb-replication = {};
    

    With this setup, the corresponding sshfs.destination on the bitcoinix node is "nb-replication@hostname:writable".

Local directory target

  1. Add this to your configuration.nix

    services.clightning.replication = {
      enable = true;
      local.directory = "/var/backup/clightning";
      encrypt = true;
    };
    

    Leave out the encrypt line if you want to store data in local.directory in plaintext.

  2. Deploy

clightning will now replicate database files to local.directory. This can be used to replicate to an external HDD by mounting it at path local.directory.

Custom remote destination

Follow the steps in section “Local directory target” above and mount a custom remote destination (e.g., a NFS or SMB share) to local.directory.
You might want to disable local.setupDirectory in order to create the mount directory yourself with custom permissions.

Connect to RTL

Normally you would connect to RTL via SSH tunneling with a command like this

ssh -L 3000:127.0.0.1:3000 root@bitcoin-node

Or like this, if you are using netns-isolation

ssh -L 3000:169.254.1.29:3000 root@bitcoin-node

Otherwise, you can access it via Tor Browser at http://<onion-address>. You can find the <onion-address> with command nodeinfo. The default password location is $secretsDir/rtl-password. See: Secrets dir

Use Zeus (mobile lightning wallet) via Tor

  1. Install Zeus (version ≥ 0.9.0)

  2. Edit your configuration.nix

    For lnd

    Add the following config:

    services.lnd.lndconnect = {
      enable = true;
      onion = true;
    };
    
    For clightning

    Add the following config:

    services.clightning.plugins.clnrest = {
      enable = true;
      lnconnect = {
        enable = true;
        onion = true;
      };
    };
    
  3. Deploy your configuration

  4. Run the following command on your node (as user operator) to create a QR code with address and authentication information:

    For lnd
    lndconnect
    
    For clightning
    lnconnect-clnrest
    
  5. Configure Zeus

    • Add a new node and scan the QR code
    • Click Save node config
    • Start sending and stacking sats privately

Additional lndconnect features

  • Create a plain text URL:
    lndconnect --url
    
  • Set a custom host. By default, lndconnect detects the system’s external IP and uses it as the host.
    lndconnect --host myhost
    

Connecting without Tor or WireGuard

Enabling lndconnect or lnconnect does not change the address that the REST server listens on. By default, the lnd and clnrest REST servers only listen on localhost.

The REST API grants full control over your lightning node, so only expose it to networks you trust. To reach it directly (e.g. via your local network or your own VPN), opt in explicitly. In the examples below, 192.168.1.10 is the address of your node and eth0 is the interface of the trusted network.
These examples don’t apply when using netns-isolation.

For lnd
services.lnd = {
  restAddress = "0.0.0.0";
  # Add the node address to the TLS certificate
  certificate.extraIPs = [ "192.168.1.10" ];
  # Only needed when using `secure-node.nix` or `enable-tor.nix`
  tor.enforce = false;
};
networking.firewall.interfaces.eth0.allowedTCPPorts = [ config.services.lnd.restPort ];
For clightning
services.clightning = {
  plugins.clnrest.address = "0.0.0.0";
  # Only needed when using `secure-node.nix` or `enable-tor.nix`
  tor.enforce = false;
};
networking.firewall.interfaces.eth0.allowedTCPPorts = [ config.services.clightning.plugins.clnrest.port ];

Then create the QR code with your node address as the host:

lndconnect --host 192.168.1.10
lnconnect-clnrest --host 192.168.1.10

Use Zeus (mobile lightning wallet) via WireGuard

Connecting Zeus directly to your node is much faster than using Tor, but a bit more complex to setup.

There are two ways to establish a secure, direct connection:

  • Connecting via TLS. This requires installing your lightning app’s TLS Certificate on your mobile device.

  • Connecting via WireGuard. This approach is simpler and more versatile, and is described in this guide.

  1. Install Zeus (version ≥ 0.9.0) and WireGuard on your mobile device.

  2. Add the following to your configuration.nix:

    imports = [
      # Use this line when using the default deployment method
      <nix-bitcoin/modules/presets/wireguard.nix>
    
      # Use this line when using Flakes
      (nix-bitcoin + /modules/presets/wireguard.nix)
    ]
    
    # For lnd
    services.lnd.lndconnect.enable = true;
    
    # For clightning
    services.clightning = {
      plugins.clnrest = {
        enable = true;
        lnconnect.enable = true;
      };
    };
    
  3. Deploy your configuration.

  4. If your node is behind an external firewall or NAT (e.g. a router), add the following port forwarding rule to the external device:

    • Port: 51820 (the default value of option networking.wireguard.interfaces.wg-nb.listenPort)
    • Protocol: UDP
    • Destination: IP of your node
  5. Setup WireGuard on your mobile device.

    Run the following command on your node (as user operator) to create a QR code for WireGuard:

    nix-bitcoin-wg-connect
    
    # For debugging: Show the WireGuard config as text
    nix-bitcoin-wg-connect --text
    

    The above commands automatically detect your node’s external IP.
    To set a custom IP or hostname, run the following:

    nix-bitcoin-wg-connect 93.184.216.34
    nix-bitcoin-wg-connect mynode.org
    

    Configure WireGuard:

    • Press the + button in the bottom right corner
    • Scan the QR code
    • Add the tunnel
  6. Setup Zeus

    Run the following command on your node (as user operator) to create a QR code for Zeus:

    For lnd
    lndconnect-wg
    
    For clightning
    lnconnect-clnrest-wg
    

    Configure Zeus:

    • Add a new node and scan the QR code
    • Click Save node config
    • On the certificate warning screen, click I understand, save node config.
      Certificates are not needed when connecting via WireGuard.
    • Start sending and stacking sats privately

Additional lndconnect features

Create a plain text URL:

lndconnect-wg --url

Connect to electrs

Requirements Android

Requirements Desktop

  1. Enable electrs in configuration.nix

    Change

    # services.electrs.enable = true;
    

    to

    services.electrs.enable = true;
    
  2. Deploy new configuration.nix

  3. Get electrs onion address with format <onion-address>:<port>

    nodeinfo | jq -r .electrs.onion_address
    
  4. Connect to electrs

    Make sure Tor is running on Desktop or as Orbot on Android.

    On Desktop

    electrum --oneserver -1 -s "<electrs onion address>:t" -p socks5:127.0.0.1:9050
    

    On Android

    Three dots in the upper-right-hand corner
    Network > Proxy mode: socks5, Host: 127.0.0.1, Port: 9050
    Network > Auto-connect: OFF
    Network > One-server mode: ON
    Network > Server: <electrs onion address>:t
    

Connect to bitcoinix node through the SSH onion service

  1. Get the SSH onion address (excluding the port suffix)

    ssh operator@bitcoin-node
    nodeinfo | jq -r .sshd.onion_address | sed 's/:.*//'
    
  2. Create a SSH key

    ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519
    
  3. Place the ed25519 key’s fingerprint in the configuration.nix openssh.authorizedKeys.keys field like so

    # FIXME: Add your SSH pubkey
    services.openssh.enable = true;
    users.users.root = {
      openssh.authorizedKeys.keys = [ "<contents of ~/.ssh/id_ed25519.pub>" ];
    };
    
  4. Connect to your bitcoinix node’s SSH onion service, forwarding a local port to the bitcoinix node’s SSH server

    ssh -i ~/.ssh/id_ed25519 -L <random port of your choosing>:127.0.0.1:22 root@<SSH onion address>
    
  5. Edit your deployment tool’s configuration and change the node’s address to 127.0.0.1 and the ssh port to <random port of your choosing>. If you use krops as described in the installation tutorial, set target = "127.0.0.1:<random port of your choosing>"; in krops/deploy.nix.

  6. After deploying the new configuration, it will connect through the SSH tunnel you established in step iv. This also allows you to do more complex SSH setups that some deployment tools don’t support. An example would be authenticating with Trezor’s SSH agent, which provides extra security.

Initialize a Trezor for Bitcoin Core’s Hardware Wallet Interface

  1. Enable Trezor in configuration.nix

    Change

    # services.hardware-wallets.trezor = true;
    

    to

    services.hardware-wallets.trezor = true;
    
  2. Deploy new configuration.nix

  3. Check that your bitcoinix node recognizes your Trezor

    ssh operator@bitcoin-node
    lsusb
    

    Should show something relating to your Trezor

  4. If your Trezor has outdated firmware or is not yet initialized: Start your Trezor in bootloader mode

    Trezor v1

    Plug in your Trezor with both buttons depressed
    

    Trezor v2

    Start swiping your finger across your Trezor's touchscreen and plug in the USB cable when your finger is halfway through
    
  5. If your Trezor’s firmware is outdated: Update your Trezor’s firmware

    trezorctl firmware-update
    

    Follow the on-screen instructions

    Caution: This command will wipe your Trezor. If you already store Bitcoin on it, only do this with the recovery seed nearby.

  6. If your Trezor is not yet initialized: Set up your Trezor

    trezorctl reset-device -p
    

    Follow the on-screen instructions

  7. Find your Trezor

    hwi enumerate
    hwi -t trezor -d <path from previous command> promptpin
    hwi -t trezor -d <path> sendpin <number positions for the PIN as displayed on your device's screen>
    hwi enumerate
    
  8. Follow Bitcoin Core’s instructions on Using Bitcoin Core with Hardware Wallets to use your Trezor with bitcoin-cli on your bitcoinix node

clightning

Plugins

There is a number of plugins available for clightning. See Readme: Features → clightning or search.nixos.org for a complete list.

You can activate and configure these plugins like so:

services.clightning = {
    enable = true;
    plugins = {
        clboss.enable = true;
        clboss.min-onchain = 40000;
    };
};

Please have a look at the module for a plugin (e.g. clboss.nix) to learn its configuration options.

Trustedcoin

When services.clightning.tor.proxy is enabled, trustedcoin also uses Tor for all external connections by default. In this case, connections to block explorers can sometimes get blocked.

An example of clightning log error output when connections are getting blocked:

lightningd[5138]: plugin-trustedcoin estimatefees error: https://blockstream.info/api error: 403 Forbidden
lightningd[4933]: plugin-trustedcoin getblock error: got something that isn't a block hash: <html><head>...

To work around this and connect via clearnet instead, set this option:

services.clightning.plugins.trustedcoin.tor.proxy = false;

FAQ

Note

This document is inherited from nix-bitcoin, the predecessor project. It is a work in progress and may be outdated.

  • Q: The clightning service is running but when I try to use it (f.e. by running lightning-cli getinfo as user operator) all I get is lightning-cli: Connecting to 'lightning-rpc': Connection refused.
    A: Check your clightning logs with journalctl -eu clightning. Do you see something like bitcoin-cli getblock ... false failed? Are you using pruned mode? That means that clightning hasn’t seen all the blocks it needs to and it can’t get that block because your node is pruned.
    If you’re just setting up a new node you can systemctl stop clightning and wipe your /var/lib/clightning directory. Otherwise you need to reindex the Bitcoin node.

  • Q: My disk space is getting low due to nix.
    A: run nix-collect-garbage -d

  • Q: Where is sudo?
    A: After CVE-2021-3156, we’ve replaced sudo with OpenBSD’s doas for users of the secure-node.nix template. It has greatly reduced complexity and is therefore less likely to be a source of severe vulnerabilities in the future.

Tutorial: Moving from a NixOps to a Krops deployment

Note

This document is inherited from nix-bitcoin, the predecessor project. It is a work in progress and may be outdated.

Warning

This documentation may be outdated or contain installation steps that do not work with bitcoinix yet (for example, release fetching still points at the upstream nix-bitcoin project). Please report problems at https://github.com/bitcoinix/bitcoinix/issues.

  1. Add a new ssh key to your nix-bitcoin node

    Krops doesn’t automatically generate ssh keys like NixOps, instead you add your own.

    If you don’t have a ssh key yet

    ssh-keygen -t ed25519 -f ~/.ssh/bitcoin-node
    

    Edit configuration.nix

    users.users.root = {
      openssh.authorizedKeys.keys = [
        "<contents of ~/.ssh/bitcoin-node.pub or existing .pub key file>"
      ];
    };
    

    Deploy new key

    nixops deploy -d bitcoin-node
    
  2. Update your nix-bitcoin, depending on your setup either with fetch-release or git. Make sure you are at least on v0.0.41.

  3. Pull the latest nix-bitcoin source

    cd ~/nix-bitcoin
    git pull
    
  4. Copy new and updated files into your deployment folder

    cd <deployment directory, for example `~/nix-bitcoin-node`>
    cp -r ~/nix-bitcoin/examples/{krops,shell.nix} .
    
  5. Edit your ssh config

    nano ~/.ssh/config
    

    and add the node with an entry similar to the following (make sure to fix Hostname and IdentityFile):

    Host bitcoin-node
        # FIXME
        Hostname NODE_IP_ADDRESS_OR_HOST_NAME_HERE
        User root
        PubkeyAuthentication yes
        # FIXME
        IdentityFile <ssh key from step 1 or path to existing key>
        AddKeysToAgent yes
    
  6. Make sure you are in the deployment directory and edit krops/deploy.nix

    nano krops/deploy.nix
    

    Locate the FIXME and set the target to the name of the ssh config entry created earlier, i.e. bitcoin-node.

    Note that any file imported by your configuration.nix must be copied to the target machine by krops. For example, if there is an import of networking.nix you must add it to extraSources in krops/deploy.nix like this:

    extraSources = {
        "hardware-configuration.nix".file = toString ../hardware-configuration.nix;
        "networking.nix".file = toString ../networking.nix;
    };
    
  7. If lnd is enabled on your node, run the commmand

    nix-shell --run 'nix-instantiate --eval -E "
      (import <nixpkgs/nixos> {
        configuration = { lib, ... }: {
          imports = [ ./configuration.nix ];
          nix-bitcoin.configVersion = lib.mkDefault \"0.0.31\";
          nix-bitcoin.secretsSetupMethod = lib.mkForce \"manual\";
        };
      }).vm.outPath
    "'
    

    and follow the migration instructions from the error message.

  8. Optional: Disallow substitutes

    You may have been building nix-bitcoin “without substitutes” to avoid pulling in binaries from the Nix cache. If you want to continue doing so, you have to add the following line to the configuration.nix:

    nix.extraOptions = "substitute = false";
    

    If the build process fails for some reason when deploying with krops-deploy (see later step), it may be difficult to find the cause due to the missing output. In that case, it is possible to SSH into the target machine and run

    nixos-rebuild -I /var/src switch
    
  9. Deploy with krops

    nix-shell --run krops-deploy
    

    Remove the old secrets directory. For krops deployments, secrets are always located at /var/src/secrets.

    ssh bitcoin-node 'rm -rf /secrets'
    
  10. You can now access bitcoin-node via ssh

    ssh operator@bitcoin-node
    
  11. You can remove the remaining traces of nixops as follows:

    nix-shell
    nix run -f '<nix-bitcoin>' nixops19_09 -c nixops delete -d bitcoin-node --force
    git rm -r nixops