Creating a HTTPS grin wallet using NixOS

NixOS is a Linux distribution which is configured via declarative scripts. The main system configuration is found in /etc/nixos/configuration.nix which allows one to deploy a wallet either at home or on a remote machine with ease. This is useful when one wishes to host a wallet without giving up control or privacy.

To test the setup NixOS 19.03 on EC2 was used and some grin were withdrawn from an exchange. NixOS is cool because it can be customised using nix scripts.

The assumptions are that you have a domain name somewhere that you can point to your public
IP. You can either setup a NixOS box at home and forward the inbound ports 80 and 443 to
the machine or set up an instance in the cloud provisioned with a NixOS image.

Step 1. Installing basic tools

You’ll need git in order to download grin. The following needs to be added to /etc/nixos/configuration.nix in order to add git and tmux to your environment.

{ pkgs, ... }:
{
  ...

  environment.systemPackages = with pkgs; [
    wget git tmux
  ];

}

Step 2. Setting up an environment

We can use the rust overlay from mozilla to setup a shell so that the grin wallet and server become buildable.

This script could be improved but I will leave that up to readers. For the sake of simplicity save this file as default.nix and run nix-shell in the directory where it is saved.

{ pkgs ? import <nixpkgs> {} }:

let
  src = pkgs.fetchFromGitHub {
    owner = "mozilla";
    repo = "nixpkgs-mozilla";
    rev = "9f35c4b09fd44a77227e79ff0c1b4b6a69dff533";
    sha256 = "18h0nvh55b5an4gmlgfbvwbyqj91bklf1zymis6lbdh75571qaz0";
  };
in
with import "${src.out}/rust-overlay.nix" pkgs pkgs;

let
  rustPlatform = pkgs.makeRustPlatform {
    cargo = latest.rustChannels.stable.rust;
    rustc = latest.rustChannels.stable.rust;
  };
in

rustPlatform.buildRustPackage rec {
  name = "grin-miner-${version}";
  version = "0.1";
  src = pkgs.fetchFromGitHub {
    owner = "mimblewimble";
    repo = "grin-miner";
    rev = "143db3b13ce9a2aee5150b41c8691f133f74bc7d";
    sha256 = "0gh4hy1cs9l2yq1nnsqv1zv6qc4808g1dx1am27jb8ycqgpbkyhf";
    fetchSubmodules = true;
  };
  RUST_BACKTRACE = 1;
  hardeningDisable = [ "format" ];
  LIBCLANG_PATH="${pkgs.llvmPackages_5.libclang}/lib";
  buildInputs = with pkgs; [
    ncurses
    zlib
    pkgconfig
    openssl
    cmake
    clang
  ];
  cargoSha256 = "053711lsgi6zhgq7a2h4mkrxymws66c8g5y60hpifz5x1sxcgiiw";
  meta = with pkgs.stdenv.lib; {
    description = "grin-tech";
    homepage = https://github.com/mimblewimble/grin-miner;
    license = licenses.mit;
  };
}

Running nix-shell brings you into a new prompt with the tools required to build.

In the new shell clone the grin repositories, cd into them and run cargo build --release.

[nix-shell]$ cd ~/
[nix-shell]$ git clone https://github.com/mimblewimble/grin
[nix-shell]$ git clone https://github.com/mimblewimble/grin-wallet
[nix-shell]$ cd grin && cargo build --release && cd ../
[nix-shell]$ cd grin-wallet && cargo build --release && cd ../

This will build the grin and grin-wallet under target/release.

Step 3. Setting up tmux

tmux is useful to create a session in the shell that can be re-connected to in case you get disconnected from the remote machine.

To start a tmux session just type tmux in the shell, use ctrl b c to create two new tabs and use ctrl b <n> where n is the tab number to switch between them.

You want to be running grin server in the first tab, grin-wallet in the second and use the third to navigate your machine or perform maintenance.

Switch to the first tab (ctrl b 0), cd into the grin directory (e.g cd ~/grin) and run the grin server.

Switch to the second tab (ctrl b 1), cd into the grin-wallet directory (e.g cd ~/grin-wallet) and run the grin wallet.

Instructions for running these programs can be found on the github but basically you want the grin server to be started and the grin wallet to be listening (target/release/grin-wallet listen).

Once both are running, go to the third tab ctrl b 2 in order to continue.

Step 4. Setting up self signed SSL certificates

You need SSL certificates in order for be able to serve HTTPS. Add the following to /etc/nixos/configuration.nix and do nixos-rebuild switch where wallet.example.com is replaced with your real domain / subdomain.

  security.acme.certs."wallet.example.com" = {
    webroot = "/var/www/challenges";
    email = "contact@example.com";
  };

Step 5. Setting up a reverse proxy

You need a reverse proxy which will proxy requests to your listening wallet. Uncomment the lines you added previously to /etc/nixos/configuration.nix and add the nginx configuration below it as shown below. Modify the domain accordingly to your requirements.

  # Make sure these lines are uncommented
  # security.acme.certs."wallet.example.com" = {
  #  webroot = "/var/www/challenges";
  #  email = "contact@example.com";
  # };

  networking.firewall.allowedTCPPorts = [ 80 443 ];

  services.nginx = {
    enable = true;
    recommendedGzipSettings = true;
    recommendedOptimisation = true;
    recommendedProxySettings = true;
    recommendedTlsSettings = true;

    virtualHosts = {
      "wallet.example.com" = {
        addSSL = true;
        enableACME = true;
        locations."/" = {
          proxyPass = "http://127.0.0.1:3415/";
        };
      };
    };
  };

Once the configuration has been modified, run nixos-rebuild switch which will start the reverse proxy. If the grin wallet is listening on the default port (3415) this will proxy requests to the listening wallet. You also have to make sure that the domain name that you own points to the public IP address of the machine. This involves adding an A record with the domain host.

You should now be able to send grin to https://wallet.example.com.

1 Like