nix-bitcoin/modules/onion-services.nix

120 lines
3.8 KiB
Nix
Raw Normal View History

2021-01-14 15:24:17 +03:00
# This module creates onion-services for NixOS services.
# An onion service can be enabled for every service that defines
# options 'address', 'port' and optionally 'getPublicAddressCmd'.
#
# See it in use at ./presets/enable-tor.nix
{ config, lib, pkgs, ... }:
with lib;
let
options.nix-bitcoin.onionServices = mkOption {
default = {};
type = with types; attrsOf (submodule (
{ config, ... }: {
options = {
enable = mkOption {
type = types.bool;
default = config.public;
description = mdDoc ''
2021-01-14 15:24:17 +03:00
Create an onion service for the given service.
The service must define options {option}'address' and {option}'onionPort' (or `port`).
2021-01-14 15:24:17 +03:00
'';
};
public = mkOption {
type = types.bool;
default = false;
description = mdDoc ''
2021-01-14 15:24:17 +03:00
Make the onion address accessible to the service.
If enabled, the onion service is automatically enabled.
Only available for services that define option {option}`getPublicAddressCmd`.
2021-01-14 15:24:17 +03:00
'';
};
externalPort = mkOption {
type = types.nullOr types.port;
default = null;
description = mdDoc "Override the external port of the onion service.";
2021-01-14 15:24:17 +03:00
};
};
}
));
};
cfg = config.nix-bitcoin.onionServices;
nbLib = config.nix-bitcoin.lib;
onionServices = builtins.attrNames cfg;
activeServices = builtins.filter (service:
config.services.${service}.enable && cfg.${service}.enable
) onionServices;
publicServices = builtins.filter (service: cfg.${service}.public) activeServices;
in {
inherit options;
2021-01-14 15:24:17 +03:00
config = mkMerge [
(mkIf (activeServices != []) {
2021-01-14 15:24:17 +03:00
# Define hidden services
services.tor = {
enable = true;
2021-08-05 01:49:00 +03:00
relay.onionServices = genAttrs activeServices (name:
2021-01-14 15:24:17 +03:00
let
service = config.services.${name};
inherit (cfg.${name}) externalPort;
2021-08-05 01:49:00 +03:00
in nbLib.mkOnionService {
2021-02-04 00:44:42 +03:00
port = if externalPort != null then externalPort else service.port;
target.port = service.onionPort or service.port;
target.addr = nbLib.address service.address;
2021-01-14 15:24:17 +03:00
}
);
};
nix-bitcoin.onionAddresses = {
# Enable public services to access their own onion addresses
services = publicServices;
2021-01-14 15:24:17 +03:00
# Allow the operator user to access onion addresses for all active services
access.${config.nix-bitcoin.operator.name} = mkIf config.nix-bitcoin.operator.enable activeServices;
2021-01-14 15:24:17 +03:00
};
systemd.services = let
onionAddresses = [ "onion-addresses.service" ];
in genAttrs publicServices (service: {
# TODO-EXTERNAL: Instead of `wants`, use a future systemd dependency type
# that propagates initial start failures but no restarts
wants = onionAddresses;
2021-01-14 15:24:17 +03:00
after = onionAddresses;
});
})
# Set getPublicAddressCmd for public services
{
services = let
# publicServices' doesn't depend on config.services.*.enable,
# so we can use it to define config.services without causing infinite recursion
publicServices' = builtins.filter (service:
let srv = cfg.${service};
in srv.public && srv.enable
) onionServices;
2021-01-14 15:24:17 +03:00
in genAttrs publicServices' (service: {
getPublicAddressCmd = "cat ${config.nix-bitcoin.onionAddresses.dataDir}/services/${service}";
2021-01-14 15:24:17 +03:00
});
}
# Set sensible defaults for some services
{
nix-bitcoin.onionServices = {
btcpayserver = {
externalPort = 80;
};
2021-01-17 15:24:57 +03:00
joinmarket-ob-watcher = {
externalPort = 80;
};
2021-11-08 14:43:14 +03:00
rtl = {
externalPort = 80;
};
};
}
2021-01-14 15:24:17 +03:00
];
}