Skip to content

Commit

Permalink
examples: add flakes-agenix
Browse files Browse the repository at this point in the history
  • Loading branch information
erikarvstedt committed Dec 23, 2022
1 parent 1bce488 commit 3dd9f74
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 0 deletions.
8 changes: 8 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ By default, [`configuration.nix`](configuration.nix) enables `bitcoind` and `cli
nix-bitcoin configuration to it using [krops](https://github.com/krebs/krops).\
Requires: [Nix](https://nixos.org/nix/), Linux

- [`./flakes-agenix/deploy.sh`](./flakes-agenix/deploy.sh) shows how to deploy a
nix-bitcoin node flake using [agenix](https://github.com/ryantm/agenix) secrets encryption.\
agenix allows repo-defined secrets that can be deployed with any deployment scheme.\
The node is deployed in a container.\
Requires: [Nix](https://nixos.org/), a systemd-based Linux distro and root privileges

- [`./deploy-container-minimal.sh`](deploy-container-minimal.sh) creates a
container defined by [importable-configuration.nix](importable-configuration.nix).\
You can copy and import this file to use nix-bitcoin in an existing NixOS configuration.\
Expand Down Expand Up @@ -116,3 +122,5 @@ The commands in `shell.nix` allow you to locally run the node in a VM or contain

Flakes make it easy to include `nix-bitcoin` in an existing NixOS config.
The [flakes example](./flakes/flake.nix) shows how to use `nix-bitcoin` as an input to a system flake.

To use [agenix](https://github.com/ryantm/agenix), which allows committing secrets to the node repo, see [`./flakes-agenix`](./flakes-agenix).
96 changes: 96 additions & 0 deletions examples/flakes-agenix/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env bash
set -euo pipefail

# Strategy:
# 1. Copy the node flake (./flake.nix) to a temporary dir and create a Git repo.
# 2. Generate age-encrypted secrets by running a package defined by the node flake.
# Commit the secrets.
# 3. Start the node in a container and run test commands.
# The container is destroyed afterwards.
#
# Run this script with arg `-i` or `--interactive` to start an
# interactive shell in the container.

# You can use ./flake.nix as a template for a real deployment.

#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
# 0. Prelude
interactive=
case "${1:-}" in
-i|--interactive)
interactive=1
;;
esac

cd "${BASH_SOURCE[0]%/*}"
scriptDir=$PWD
nixBitcoin="$scriptDir/../.."

tmpDir=$(mktemp -d /tmp/nix-bitcoin-agenix.XXX)
trap 'rm -rf $tmpDir' EXIT

#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
# 1. Create a flake repo in a tmp dir
rsync -a ./ --exclude deploy.sh ./ "$tmpDir"

cd "$tmpDir"

git init
git add .
git commit -a -m init

#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
# 2. Generate age-encrypted secrets

# Use this nix-bitcoin repo as the flake input when generating secrets,
# so that this script can be used for automated testing.
nix run --override-input nix-bitcoin "$nixBitcoin" .#generateAgeSecrets
#
# In a real deployment, you can simply run the following from the deployment repo root:
# nix run .#generateAgeSecrets
#
# or, if you don't define the `generateAgeSecrets` helper package:
# nix run .#nixosConfigurations.demo-node.config.nix-bitcoin.age.generateSecretsScript
#
# Show help
# nix run .#generateAgeSecrets --help

echo
echo "Encrypted secrets:"
ls -al secrets
echo

# Commit age-encrypted secrets
git add ./secrets
git commit -a -m 'add secrets'

# Success!
# This node flake can now be deployed with any deployment method.

#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
# 3. Run node in container

if [[ $interactive ]]; then
# Start interactive container shell
runCmd=()
else
runCmd=(
--run c bash -c '
echo
echo "Unencrypted secrets in /run/agenix:"
ls -alH /run/agenix
echo
systemctl status bitcoind
'
)
fi

runContainer=(
nix run --override-input nix-bitcoin "$nixBitcoin" .#container -- "${runCmd[@]}"
)
nix shell --inputs-from "$nixBitcoin" extra-container -c "${runContainer[@]}"

#―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
# Debug helper: Build flake outputs
# nix build --no-link -L --print-out-paths --override-input nix-bitcoin "$nixBitcoin" .#container
# nix build --no-link -L --print-out-paths --override-input nix-bitcoin "$nixBitcoin" .#generateAgeSecrets
32 changes: 32 additions & 0 deletions examples/flakes-agenix/flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

106 changes: 106 additions & 0 deletions examples/flakes-agenix/flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# When using this file as the base for a real deployment,
# make sure to check all lines marked by 'FIXME:'

# This file is used by ./deploy.sh to deploy a container with
# age-encrypted secrets.

{
inputs.nix-bitcoin.url = "github:fort-nix/nix-bitcoin/release";
inputs.agenix.url = "github:ryantm/agenix";
inputs.agenix.inputs.nixpkgs.follows = "nix-bitcoin/nixpkgs";

inputs.flake-utils.follows = "nix-bitcoin/flake-utils";

outputs = { self, nix-bitcoin, agenix, flake-utils }: {
modules = {
demoNode = { config, lib, ... }: {
imports = [
# TODO-EXTERNAL:
# Set this to `agenix.nixosModules.default` when
# https://github.com/ryantm/agenix/pull/126 is merged
agenix.nixosModules.age
nix-bitcoin.nixosModules.default
(nix-bitcoin + "/modules/secrets/age.nix")
];

# Use age-encrypted secrets
nix-bitcoin.age = {
enable = true;

# The local secrets dir and its contents can be created with the
# `generateAgeSecrets` flake package (defined below).
# Use it like so:
# nix run .#generateAgeSecrets
# and commit the newly created ./secrets dir afterwards.
#
# This script must be rerun when adding node services that
# require new secrets.
#
# For a real-life example, see ./deploy.sh
secretsSourceDir = ./secrets;

# FIXME:
# Set this to a public SSH host key of your node (preferably key type `ed25519`).
# You can query host keys with command `ssh-keyscan <node address>`.
# The keys defined here are used to age-encrypt the secrets.
publicKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDoAaEMk8jMbg5MnvKDApWC6EpUHRJTzavy/wU2EtgtU none"
];
};

# Enable services.
# See ../configuration.nix for all available features.
services.bitcoind.enable = true;
#
# See ../flakes/flake.nix for more settings useful for production nodes.


# WARNING:
# FIXME:
# Remove the following `age.identityPaths` setting in a real deployment.
# This copies a private key to the (publicly readable) Nix store,
# which allows ./deploy.sh to start a age-based container in
# a single deployment step.
#
# In a real deployment, just leave `age.identityPaths` undefined.
# In this case, agenix uses the auto-generated SSH host key.
age.identityPaths = [ ./host-key ];
};
};

nixosConfigurations.demoNode = nix-bitcoin.inputs.nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ self.modules.demoNode ];
};
}
// (nix-bitcoin.inputs.nixpkgs.lib.recursiveUpdate

# Allow runnning this node as a container, used by ./deploy.sh
(flake-utils.lib.eachSystem nix-bitcoin.lib.supportedSystems (system: {
packages = {
container = nix-bitcoin.inputs.extra-container.lib.buildContainers {
inherit system;
config.containers.nb-agenix = {
privateNetwork = true;
config.imports = [ self.modules.demoNode ];
};
};
};
}))

# This allows generating age-encrypted secrets on systems
# that differ from the target node.
# E.g. manage a `x86_64-linux` node from macOS (`aarch64-darwin`)
(flake-utils.lib.eachDefaultSystem (system: {
packages = {
generateAgeSecrets = let
nodeSystem = nix-bitcoin.inputs.nixpkgs.lib.nixosSystem {
inherit system;
modules = [ self.modules.demoNode ];
};
in
nodeSystem.config.nix-bitcoin.age.generateSecretsScript;
};
}))
);
}
7 changes: 7 additions & 0 deletions examples/flakes-agenix/host-key
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACA6AGhDJPIzG4OTJ7ygwKVguhKVB0SU82r8v8FNhLYLVAAAAIhEbEOERGxD
hAAAAAtzc2gtZWQyNTUxOQAAACA6AGhDJPIzG4OTJ7ygwKVguhKVB0SU82r8v8FNhLYLVA
AAAECBS5tCD9AcaOcNzPYlreA4BVrsy2f0FaGgEoJfBQzMqzoAaEMk8jMbg5MnvKDApWC6
EpUHRJTzavy/wU2EtgtUAAAABG5vbmUB
-----END OPENSSH PRIVATE KEY-----
1 change: 1 addition & 0 deletions test/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ examples() {
runExample deploy-container-minimal.sh
runExample deploy-qemu-vm.sh
runExample deploy-krops.sh
runExample flakes-agenix/deploy.sh
'
(cd "$scriptDir/../examples" && nix-shell --run "$script")
}
Expand Down

0 comments on commit 3dd9f74

Please sign in to comment.