Compare commits
5 Commits
46d1a49f0f
...
7f2abf7e6e
Author | SHA1 | Date |
---|---|---|
Colin | 7f2abf7e6e | |
Colin | 825812e511 | |
Colin | 69e5495cc9 | |
Colin | b422f15b59 | |
Colin | 889b332ade |
|
@ -2,19 +2,11 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
dyn-dns = config.sane.services.dyn-dns;
|
||||
nativeAddrs = lib.mapAttrs (_name: builtins.head) config.sane.dns.zones."uninsane.org".inet.A;
|
||||
bindOvpn = "10.0.1.5";
|
||||
in lib.mkMerge [
|
||||
in
|
||||
{
|
||||
services.trust-dns.enable = true;
|
||||
|
||||
# don't bind to IPv6 until i explicitly test that stack
|
||||
services.trust-dns.settings.listen_addrs_ipv6 = [];
|
||||
services.trust-dns.quiet = true;
|
||||
# FIXME(2023/11/26): services.trust-dns.debug doesn't log requests: use RUST_LOG=debug env for that.
|
||||
# - see: <https://github.com/hickory-dns/hickory-dns/issues/2082>
|
||||
# services.trust-dns.debug = true;
|
||||
|
||||
sane.ports.ports."53" = {
|
||||
protocol = [ "udp" "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
|
@ -66,23 +58,6 @@ in lib.mkMerge [
|
|||
|
||||
services.trust-dns.settings.zones = [ "uninsane.org" ];
|
||||
|
||||
# TODO: can i transform this into some sort of service group?
|
||||
# have `systemctl restart trust-dns.service` restart all the individual services?
|
||||
systemd.services.trust-dns.serviceConfig = {
|
||||
DynamicUser = lib.mkForce false;
|
||||
User = "trust-dns";
|
||||
Group = "trust-dns";
|
||||
wantedBy = lib.mkForce [];
|
||||
};
|
||||
systemd.services.trust-dns.enable = false;
|
||||
|
||||
users.groups.trust-dns = {};
|
||||
users.users.trust-dns = {
|
||||
group = "trust-dns";
|
||||
isSystemUser = true;
|
||||
};
|
||||
|
||||
# sane.services.dyn-dns.restartOnChange = [ "trust-dns.service" ];
|
||||
|
||||
networking.nat.enable = true;
|
||||
networking.nat.extraCommands = ''
|
||||
|
@ -107,98 +82,73 @@ in lib.mkMerge [
|
|||
visibleTo.lan = true;
|
||||
description = "colin-redirected-dns-for-lan-namespace";
|
||||
};
|
||||
}
|
||||
{
|
||||
systemd.services =
|
||||
let
|
||||
sed = "${pkgs.gnused}/bin/sed";
|
||||
stateDir = "/var/lib/trust-dns";
|
||||
zoneTemplate = pkgs.writeText "uninsane.org.zone.in" config.sane.dns.zones."uninsane.org".rendered;
|
||||
|
||||
zoneDirFor = flavor: "${stateDir}/${flavor}";
|
||||
zoneFor = flavor: "${zoneDirFor flavor}/uninsane.org.zone";
|
||||
mkTrustDnsService = opts: flavor: let
|
||||
flags = let baseCfg = config.services.trust-dns; in
|
||||
(lib.optional baseCfg.debug "--debug") ++ (lib.optional baseCfg.quiet "--quiet");
|
||||
flagsStr = builtins.concatStringsSep " " flags;
|
||||
|
||||
anative = nativeAddrs."servo.${flavor}";
|
||||
|
||||
toml = pkgs.formats.toml { };
|
||||
configTemplate = opts.config or (toml.generate "trust-dns-${flavor}.toml" (
|
||||
(
|
||||
lib.filterAttrsRecursive (_: v: v != null) config.services.trust-dns.settings
|
||||
) // {
|
||||
listen_addrs_ipv4 = opts.listen or [ anative ];
|
||||
}
|
||||
));
|
||||
configFile = "${stateDir}/${flavor}-config.toml";
|
||||
|
||||
port = opts.port or 53;
|
||||
in {
|
||||
description = "trust-dns Domain Name Server (serving ${flavor})";
|
||||
unitConfig.Documentation = "https://trust-dns.org/";
|
||||
|
||||
preStart = ''
|
||||
wan=$(cat '${config.sane.services.dyn-dns.ipPath}')
|
||||
${sed} s/%AWAN%/$wan/ ${configTemplate} > ${configFile}
|
||||
'' + lib.optionalString (!opts ? config) ''
|
||||
mkdir -p ${zoneDirFor flavor}
|
||||
${sed} \
|
||||
-e s/%CNAMENATIVE%/servo.${flavor}/ \
|
||||
-e s/%ANATIVE%/${anative}/ \
|
||||
-e s/%AWAN%/$wan/ \
|
||||
-e s/%AOVPNS%/185.157.162.178/ \
|
||||
${zoneTemplate} > ${zoneFor flavor}
|
||||
'';
|
||||
serviceConfig = config.systemd.services.trust-dns.serviceConfig // {
|
||||
ExecStart = ''
|
||||
${pkgs.trust-dns}/bin/${pkgs.trust-dns.meta.mainProgram} \
|
||||
--port ${builtins.toString port} \
|
||||
--zonedir ${zoneDirFor flavor}/ \
|
||||
--config ${configFile} ${flagsStr}
|
||||
'';
|
||||
};
|
||||
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
in {
|
||||
trust-dns-wan = mkTrustDnsService { listen = [ nativeAddrs."servo.lan" bindOvpn ]; } "wan";
|
||||
trust-dns-lan = mkTrustDnsService { port = 1053; } "lan";
|
||||
trust-dns-hn = mkTrustDnsService { port = 1053; } "hn";
|
||||
trust-dns-hn-resolver = mkTrustDnsService {
|
||||
config = pkgs.writeText "hn-resolver-config.toml" ''
|
||||
# i host a resolver in the wireguard VPN so that clients can resolve DNS through the VPN.
|
||||
# (that's what this file achieves).
|
||||
#
|
||||
# one would expect this resolver could host the authoritative zone for `uninsane.org`, and then forward everything else to the system resolver...
|
||||
# and while that works for `dig`, it breaks for `nslookup` (and so `ssh`, etc).
|
||||
#
|
||||
# DNS responses include a flag for if the responding server is the authority of the zone queried.
|
||||
# it seems that default Linux stub resolvers either:
|
||||
# - expect DNSSEC when the response includes that bit, or
|
||||
# - expect A records to be in the `answer` section instead of `additional` section.
|
||||
# or perhaps something more nuanced. but for `nslookup` to be reliable, it has to talk to an
|
||||
# instance of trust-dns which is strictly a resolver, with no authority.
|
||||
# hence, this config: a resolver which forwards to the actual authority.
|
||||
|
||||
listen_addrs_ipv4 = ["${nativeAddrs."servo.hn"}"]
|
||||
listen_addrs_ipv6 = []
|
||||
|
||||
[[zones]]
|
||||
zone = "uninsane.org"
|
||||
zone_type = "Forward"
|
||||
stores = { type = "forward", name_servers = [{ socket_addr = "${nativeAddrs."servo.hn"}:1053", protocol = "udp", trust_nx_responses = true }] }
|
||||
|
||||
[[zones]]
|
||||
# forward the root zone to the local DNS resolver
|
||||
zone = "."
|
||||
zone_type = "Forward"
|
||||
stores = { type = "forward", name_servers = [{ socket_addr = "127.0.0.53:53", protocol = "udp", trust_nx_responses = true }] }
|
||||
'';
|
||||
} "hn-resolver";
|
||||
sane.services.trust-dns.enable = true;
|
||||
sane.services.trust-dns.instances = let
|
||||
mkSubstitutions = flavor: {
|
||||
"%AWAN%" = "$(cat '${dyn-dns.ipPath}')";
|
||||
"%CNAMENATIVE%" = "servo.${flavor}";
|
||||
"%ANATIVE%" = nativeAddrs."servo.${flavor}";
|
||||
"%AOVPNS%" = "185.157.162.178";
|
||||
};
|
||||
in
|
||||
{
|
||||
wan = {
|
||||
substitutions = mkSubstitutions "wan";
|
||||
listenAddrs = [
|
||||
nativeAddrs."servo.lan"
|
||||
bindOvpn
|
||||
];
|
||||
};
|
||||
lan = {
|
||||
substitutions = mkSubstitutions "lan";
|
||||
listenAddrs = [ nativeAddrs."servo.lan" ];
|
||||
port = 1053;
|
||||
};
|
||||
hn = {
|
||||
substitutions = mkSubstitutions "hn";
|
||||
listenAddrs = [ nativeAddrs."servo.hn" ];
|
||||
port = 1053;
|
||||
};
|
||||
hn-resolver = {
|
||||
# don't need %AWAN% here because we forward to the hn instance.
|
||||
listenAddrs = [ nativeAddrs."servo.hn" ];
|
||||
extraConfig = {
|
||||
zones = [
|
||||
{
|
||||
zone = "uninsane.org";
|
||||
zone_type = "Forward";
|
||||
stores = {
|
||||
type = "forward";
|
||||
name_servers = [
|
||||
{
|
||||
socket_addr = "${nativeAddrs."servo.hn"}:1053";
|
||||
protocol = "udp";
|
||||
trust_nx_responses = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
{
|
||||
# forward the root zone to the local DNS resolver
|
||||
zone = ".";
|
||||
zone_type = "Forward";
|
||||
stores = {
|
||||
type = "forward";
|
||||
name_servers = [
|
||||
{
|
||||
socket_addr = "127.0.0.53:53";
|
||||
protocol = "udp";
|
||||
trust_nx_responses = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.dyn-dns.restartOnChange = [
|
||||
"trust-dns-wan.service"
|
||||
|
@ -207,4 +157,3 @@ in lib.mkMerge [
|
|||
# "trust-dns-hn-resolver.service" # doesn't need restart because it doesn't know about WAN IP
|
||||
];
|
||||
}
|
||||
]
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
#
|
||||
# example of a design which considers these things:
|
||||
# - when unlocked:
|
||||
# - volup tap -> app menu
|
||||
# - volup hold -> file browser
|
||||
# - volup tap -> file browser
|
||||
# - volup hold -> app menu
|
||||
# - voldown press -> keyboard
|
||||
# - voldown hold -> terminal
|
||||
# - power x2 -> screenoff
|
||||
|
@ -60,6 +60,12 @@ KEYBOARD="${KEYBOARD:-wvkbd-mobintl}"
|
|||
|
||||
action="$1"
|
||||
|
||||
log() {
|
||||
printf "sane-input-handler: %s\n" "$1"
|
||||
}
|
||||
|
||||
## HELPERS
|
||||
|
||||
isTouchOn() {
|
||||
# success if all touch inputs have their events enabled
|
||||
swaymsg -t get_inputs --raw \
|
||||
|
@ -73,6 +79,13 @@ isScreenOn() {
|
|||
> /dev/null
|
||||
}
|
||||
|
||||
isLandscape() {
|
||||
# success if all outputs are landscape
|
||||
swaymsg -t get_outputs --raw \
|
||||
| jq --exit-status '. | all(.transform == "90" or .transform == "270")' \
|
||||
> /dev/null
|
||||
}
|
||||
|
||||
isAllOn() {
|
||||
isTouchOn && isScreenOn
|
||||
}
|
||||
|
@ -81,7 +94,23 @@ isInhibited() {
|
|||
pidof rofi
|
||||
}
|
||||
|
||||
handleWith() {
|
||||
local state=
|
||||
if [ -n "$_isInhibited" ]; then
|
||||
state="inhibited+"
|
||||
fi
|
||||
if [ -n "$_isAllOn" ]; then
|
||||
state="${state}on"
|
||||
else
|
||||
state="${state}off"
|
||||
fi
|
||||
log "state=$state action=$action: handleWith: $@"
|
||||
"$@"
|
||||
exit $?
|
||||
}
|
||||
|
||||
|
||||
## HANDLERS
|
||||
ignore() {
|
||||
true
|
||||
}
|
||||
|
@ -101,27 +130,55 @@ allOff() {
|
|||
swaymsg -- input type:touch events disabled
|
||||
}
|
||||
|
||||
toggleKeyboard() {
|
||||
local kbpid=$(pidof "$KEYBOARD")
|
||||
if [ -z "$kbpid" ] || ! ( env kill -s RTMIN+0 "$kbpid" ); then
|
||||
echo "sane-input-handler: failed to toggle keyboard: $KEYBOARD"
|
||||
_keyboardPid=
|
||||
setKeyboard() {
|
||||
if [ -z "$_keyboardPid" ]; then
|
||||
# lazy init
|
||||
_keyboardPid=$(pidof "$KEYBOARD")
|
||||
fi
|
||||
if [ -z "$_keyboardPid" ]; then
|
||||
log "cannot find $KEYBOARD"
|
||||
return
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
"toggle")
|
||||
# `env` so that we get the right `kill` binary instead of bash's builtin
|
||||
env kill -s RTMIN+0 "$_keyboardPid"
|
||||
;;
|
||||
"show")
|
||||
env kill -s USR2 "$_keyboardPid"
|
||||
;;
|
||||
"hide")
|
||||
env kill -s USR1 "$_keyboardPid"
|
||||
;;
|
||||
"set")
|
||||
case "$2" in
|
||||
"0")
|
||||
setKeyboard hide
|
||||
;;
|
||||
"1")
|
||||
setKeyboard show
|
||||
;;
|
||||
*)
|
||||
log "setKeyboard: unknown option 'set $2'"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
"ifRoom")
|
||||
if isLandscape; then
|
||||
setKeyboard hide
|
||||
else
|
||||
setKeyboard show
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
log "setKeyboard: unknown option '$1'"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
handleWith() {
|
||||
state=
|
||||
if [ -n "$_isInhibited" ]; then
|
||||
state="inhibited+"
|
||||
fi
|
||||
if [ -n "$_isAllOn" ]; then
|
||||
state="${state}on"
|
||||
else
|
||||
state="${state}off"
|
||||
fi
|
||||
echo "sane-input-handler: state=$state action=$action: handleWith: $@"
|
||||
"$@"
|
||||
exit 0
|
||||
}
|
||||
## DISPATCHERS
|
||||
|
||||
dispatchDefault() {
|
||||
case "$action" in
|
||||
|
@ -185,17 +242,21 @@ dispatchOn() {
|
|||
;;
|
||||
|
||||
"volup_tap_1")
|
||||
# volume up once: system menu
|
||||
handleWith sane-open-desktop rofi.desktop
|
||||
# volume up once: filesystem browser
|
||||
setKeyboard ifRoom &
|
||||
handleWith sane-open-desktop rofi-filebrowser.desktop
|
||||
;;
|
||||
"volup_hold_1")
|
||||
# volume up hold: just browse files
|
||||
handleWith sane-open-desktop rofi-filebrowser.desktop
|
||||
# volume up hold: browse files and apps
|
||||
setKeyboard ifRoom &
|
||||
# reset fs directory: useful in case you get stuck in broken directory (e.g. one which lacks a `..` entry)
|
||||
rm -f ~/.cache/rofi/rofi3.filebrowsercache
|
||||
handleWith sane-open-desktop rofi.desktop
|
||||
;;
|
||||
|
||||
"voldown_start")
|
||||
# volume down once: toggle keyboard
|
||||
handleWith toggleKeyboard
|
||||
handleWith setKeyboard "toggle"
|
||||
;;
|
||||
"voldown_hold_1")
|
||||
# hold voldown to launch terminal
|
||||
|
|
|
@ -7,5 +7,6 @@
|
|||
./kiwix-serve.nix
|
||||
./mautrix-signal.nix
|
||||
./nixserve.nix
|
||||
./trust-dns.nix
|
||||
];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.sane.services.trust-dns;
|
||||
dns = config.sane.dns;
|
||||
toml = pkgs.formats.toml { };
|
||||
instanceModule = with lib; types.submodule {
|
||||
options = {
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 53;
|
||||
};
|
||||
listenAddrs = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
IP addresses to serve requests from.
|
||||
'';
|
||||
};
|
||||
substitutions = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {};
|
||||
description = ''
|
||||
text substitutions to make on the config and zone file before starting trust-dns.
|
||||
'';
|
||||
example = {
|
||||
"%CNAMESELF%" = "lappy";
|
||||
"%AWAN%" = ''"$(cat /var/www/wan.txt)"'';
|
||||
};
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
mkSystemdService = flavor: { port, listenAddrs, substitutions, extraConfig }: let
|
||||
sed = "${pkgs.gnused}/bin/sed";
|
||||
zoneTemplate = pkgs.writeText
|
||||
"uninsane.org.zone.in"
|
||||
config.sane.dns.zones."uninsane.org".rendered;
|
||||
configTemplate = toml.generate "trust-dns-${flavor}.toml" (
|
||||
(
|
||||
lib.filterAttrsRecursive (_: v: v != null) config.services.trust-dns.settings
|
||||
) // {
|
||||
listen_addrs_ipv4 = listenAddrs;
|
||||
} // extraConfig
|
||||
);
|
||||
configPath = "/var/lib/trust-dns/${flavor}-config.toml";
|
||||
sedArgs = lib.mapAttrsToList (key: value: ''-e "s/${key}/${value}/g"'') substitutions;
|
||||
subs = lib.concatStringsSep " " sedArgs;
|
||||
in {
|
||||
description = "trust-dns Domain Name Server (serving ${flavor})";
|
||||
unitConfig.Documentation = "https://trust-dns.org/";
|
||||
|
||||
preStart = lib.concatStringsSep "\n" (
|
||||
[''
|
||||
mkdir -p "/var/lib/trust-dns/${flavor}"
|
||||
${sed} ${subs} -e "" "${configTemplate}" > "${configPath}"
|
||||
''] ++ lib.mapAttrsToList (zone: { rendered, ... }: ''
|
||||
${sed} ${subs} -e "" ${pkgs.writeText "${zone}.zone.in" rendered} \
|
||||
> "/var/lib/trust-dns/${flavor}/${zone}.zone"
|
||||
'') dns.zones
|
||||
);
|
||||
|
||||
serviceConfig = config.systemd.services.trust-dns.serviceConfig // {
|
||||
ExecStart = lib.escapeShellArgs ([
|
||||
"${pkgs.trust-dns}/bin/${pkgs.trust-dns.meta.mainProgram}"
|
||||
"--port" (builtins.toString port)
|
||||
"--zonedir" "/var/lib/trust-dns/${flavor}"
|
||||
"--config" "${configPath}"
|
||||
] ++ lib.optionals config.services.trust-dns.debug [
|
||||
"--debug"
|
||||
] ++ lib.optionals config.services.trust-dns.quiet [
|
||||
"--quiet"
|
||||
]);
|
||||
ReadOnlyPaths = [ "/var/lib/uninsane" ]; # for dyn-dns (wan.txt)
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options = with lib; {
|
||||
sane.services.trust-dns = {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
};
|
||||
instances = mkOption {
|
||||
default = {};
|
||||
type = types.attrsOf instanceModule;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# enable nixpkgs' trust-dns so that i get its config generation
|
||||
# but don't actually enable the systemd service... i'll instantiate *multiple* instances per interface further below
|
||||
services.trust-dns.enable = true;
|
||||
|
||||
# don't bind to IPv6 until i explicitly test that stack
|
||||
services.trust-dns.settings.listen_addrs_ipv6 = [];
|
||||
services.trust-dns.quiet = true;
|
||||
# FIXME(2023/11/26): services.trust-dns.debug doesn't log requests: use RUST_LOG=debug env for that.
|
||||
# - see: <https://github.com/hickory-dns/hickory-dns/issues/2082>
|
||||
# services.trust-dns.debug = true;
|
||||
|
||||
users.groups.trust-dns = {};
|
||||
users.users.trust-dns = {
|
||||
group = "trust-dns";
|
||||
isSystemUser = true;
|
||||
};
|
||||
|
||||
systemd.services = lib.mkMerge [
|
||||
{
|
||||
trust-dns.enable = false;
|
||||
trust-dns.serviceConfig = {
|
||||
DynamicUser = lib.mkForce false;
|
||||
User = "trust-dns";
|
||||
Group = "trust-dns";
|
||||
wantedBy = lib.mkForce [];
|
||||
};
|
||||
}
|
||||
(lib.mapAttrs'
|
||||
(flavor: instanceConfig: {
|
||||
name = "trust-dns-${flavor}";
|
||||
value = mkSystemdService flavor instanceConfig;
|
||||
})
|
||||
cfg.instances
|
||||
)
|
||||
];
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue