Compare commits
5 commits
e3068a144a
...
b544e127b6
Author | SHA1 | Date | |
---|---|---|---|
b544e127b6 | |||
e90afae7ac | |||
5b79e6826b | |||
5d258de497 | |||
5f70f26e98 |
17 changed files with 259 additions and 62 deletions
|
@ -4,11 +4,17 @@
|
||||||
imports = [
|
imports = [
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
./home.nix
|
./home.nix
|
||||||
./wireguard.nix
|
|
||||||
];
|
];
|
||||||
|
|
||||||
boot.loader.systemd-boot.enable = true;
|
boot.loader.systemd-boot.enable = true;
|
||||||
boot.loader.efi.canTouchEfiVariables = true;
|
boot.loader.efi.canTouchEfiVariables = true;
|
||||||
|
|
||||||
|
age.secrets.wireguard-peer-orm.file = ../../secrets/wireguard-peer-orm.age;
|
||||||
|
|
||||||
|
birdsong.peer = {
|
||||||
|
enable = true;
|
||||||
|
privateKeyFile = config.age.secrets.wireguard-peer-orm.path;
|
||||||
|
};
|
||||||
|
|
||||||
system.stateVersion = "23.11";
|
system.stateVersion = "23.11";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
age.secrets.wireguard-hub.file = ../../secrets/wireguard-hub.age;
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
nat = {
|
|
||||||
enable = true;
|
|
||||||
externalInterface = "ens3";
|
|
||||||
internalInterfaces = [ "wg0" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
firewall.allowedUDPPorts = [ config.networking.wireguard.interfaces.wg0.listenPort ];
|
|
||||||
|
|
||||||
wireguard.interfaces.wg0 = {
|
|
||||||
ips = [ "10.127.1.1/24" "fd70:81ca:0f8f:1::1/64" ];
|
|
||||||
listenPort = 51820;
|
|
||||||
privateKeyFile = config.age.secrets.wireguard-hub.path;
|
|
||||||
peers = [
|
|
||||||
{
|
|
||||||
name = "shaw";
|
|
||||||
publicKey = "eD79pROC2zjhKz4tGRS43O95gcFRqO+SFb2XDnTr0zc=";
|
|
||||||
allowedIPs = [ "10.127.1.2" "fd70:81ca:0f8f:1::2" ];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "tohru";
|
|
||||||
publicKey = "lk3PCQM1jmZoI8sM/rWSyKNuZOUnjox3n9L9geJD+18=";
|
|
||||||
allowedIPs = [ "10.127.1.3" "fd70:81ca:0f8f:1::3" ];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -8,13 +8,20 @@
|
||||||
../../services/fonts.nix
|
../../services/fonts.nix
|
||||||
../../services/steam.nix
|
../../services/steam.nix
|
||||||
./syncthing.nix
|
./syncthing.nix
|
||||||
./wireguard.nix
|
|
||||||
];
|
];
|
||||||
|
|
||||||
boot.loader.systemd-boot.enable = true;
|
boot.loader.systemd-boot.enable = true;
|
||||||
boot.loader.efi.canTouchEfiVariables = true;
|
boot.loader.efi.canTouchEfiVariables = true;
|
||||||
boot.loader.systemd-boot.editor = false;
|
boot.loader.systemd-boot.editor = false;
|
||||||
|
|
||||||
|
age.secrets.wireguard-peer-tohru.file = ../../secrets/wireguard-peer-tohru.age;
|
||||||
|
|
||||||
|
birdsong.peer = {
|
||||||
|
enable = true;
|
||||||
|
privateKeyFile = config.age.secrets.wireguard-peer-tohru.path;
|
||||||
|
persistentKeepalive = 23;
|
||||||
|
};
|
||||||
|
|
||||||
programs.evolution.enable = true;
|
programs.evolution.enable = true;
|
||||||
qenya.services.fonts.enable = true;
|
qenya.services.fonts.enable = true;
|
||||||
qenya.services.steam.enable = true;
|
qenya.services.steam.enable = true;
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
age.secrets.wireguard-peer-tohru.file = ../../secrets/wireguard-peer-tohru.age;
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
firewall.allowedUDPPorts = [ config.networking.wireguard.interfaces.wg0.listenPort ];
|
|
||||||
|
|
||||||
wireguard.interfaces.wg0 = {
|
|
||||||
ips = [ "10.127.1.3/24" "fd70:81ca:0f8f:1::3/64" ];
|
|
||||||
listenPort = 51821;
|
|
||||||
privateKeyFile = config.age.secrets.wireguard-peer-tohru.path;
|
|
||||||
peers = [
|
|
||||||
{
|
|
||||||
publicKey = "birdLVh8roeZpcVo308Ums4l/aibhAxbi7MBsglkJyA=";
|
|
||||||
allowedIPs = [ "10.127.1.0/24" "fd70:81ca:0f8f:1::/64" ];
|
|
||||||
endpoint = "birdsong.network:51820";
|
|
||||||
persistentKeepalive = 23;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -9,6 +9,13 @@
|
||||||
boot.loader.systemd-boot.enable = true;
|
boot.loader.systemd-boot.enable = true;
|
||||||
boot.loader.efi.canTouchEfiVariables = true;
|
boot.loader.efi.canTouchEfiVariables = true;
|
||||||
|
|
||||||
|
age.secrets.wireguard-peer-yevaud.file = ../../secrets/wireguard-peer-yevaud.age;
|
||||||
|
|
||||||
|
birdsong.peer = {
|
||||||
|
enable = true;
|
||||||
|
privateKeyFile = config.age.secrets.wireguard-peer-yevaud.path;
|
||||||
|
};
|
||||||
|
|
||||||
qenya.services.forgejo = {
|
qenya.services.forgejo = {
|
||||||
enable = true;
|
enable = true;
|
||||||
domain = "git.qenya.tel";
|
domain = "git.qenya.tel";
|
||||||
|
|
|
@ -5,8 +5,8 @@ let
|
||||||
|
|
||||||
secrets = with keys; {
|
secrets = with keys; {
|
||||||
wireguard-hub = [ machines.orm ];
|
wireguard-hub = [ machines.orm ];
|
||||||
wireguard-peer-orm = [ machines.orm ];
|
|
||||||
wireguard-peer-tohru = [ machines.tohru ];
|
wireguard-peer-tohru = [ machines.tohru ];
|
||||||
|
wireguard-peer-yevaud = [ machines.yevaud ];
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
builtins.listToAttrs (
|
builtins.listToAttrs (
|
||||||
|
|
BIN
secrets/wireguard-peer-yevaud.age
Normal file
BIN
secrets/wireguard-peer-yevaud.age
Normal file
Binary file not shown.
1
secrets/wireguard-peer-yevaud.pub
Normal file
1
secrets/wireguard-peer-yevaud.pub
Normal file
|
@ -0,0 +1 @@
|
||||||
|
YPJsIs9x4wuWdFi/QRWSJbWvKE0GQAfVL4MNMqHygDw=
|
6
services/birdsong/default.nix
Normal file
6
services/birdsong/default.nix
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./peer.nix
|
||||||
|
./hosts.nix
|
||||||
|
];
|
||||||
|
}
|
134
services/birdsong/hosts.nix
Normal file
134
services/birdsong/hosts.nix
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
{
|
||||||
|
options.birdsong.hosts = mkOption {
|
||||||
|
description = "List of hosts in the birdsong network";
|
||||||
|
type = types.attrsOf
|
||||||
|
(types.submodule {
|
||||||
|
options = {
|
||||||
|
hostKey = mkOption {
|
||||||
|
default = null;
|
||||||
|
description = "SSH public key of the host, for use in known_hosts files";
|
||||||
|
type = with types; nullOr str;
|
||||||
|
};
|
||||||
|
subnet = mkOption {
|
||||||
|
default = "internet";
|
||||||
|
example = "roaming";
|
||||||
|
description = ''
|
||||||
|
Identifier representing a LAN the host belongs to. Hosts in the
|
||||||
|
same LAN will peer with each other.
|
||||||
|
|
||||||
|
The special value `internet` (the default) will accept peering
|
||||||
|
from all other hosts. This is to be used for servers that are
|
||||||
|
accessible from the public internet.
|
||||||
|
|
||||||
|
The special value `roaming` will not peer with other `roaming`
|
||||||
|
hosts, but will still peer with `internet` hosts. This is to be
|
||||||
|
used for portable devices like laptops that regularly move between
|
||||||
|
networks.
|
||||||
|
'';
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
endpoint = mkOption {
|
||||||
|
default = null;
|
||||||
|
example = "example.com";
|
||||||
|
description = ''
|
||||||
|
Address (e.g. IP or domain name) by which the host is reachable
|
||||||
|
within its LAN.
|
||||||
|
|
||||||
|
If {option}`birdsong.hosts.<name>.subnet` is set to `internet`,
|
||||||
|
the host must be reachable at this address from the public
|
||||||
|
internet.
|
||||||
|
|
||||||
|
If {option}`birdsong.hosts.<name>.subnet` is set to `roaming`,
|
||||||
|
this option is not used.
|
||||||
|
'';
|
||||||
|
type = with types; nullOr str;
|
||||||
|
};
|
||||||
|
ipv4 = mkOption {
|
||||||
|
example = "10.127.1.1";
|
||||||
|
description = "IPv4 address of this peer within the network";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
ipv6 = mkOption {
|
||||||
|
example = "fd70:81ca:0f8f:1::1";
|
||||||
|
description = "IPv6 address of this peer within the network";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
port = mkOption {
|
||||||
|
default = 51820;
|
||||||
|
example = 51821;
|
||||||
|
description = ''
|
||||||
|
Which port to expose WireGuard on. Change this for peers behind
|
||||||
|
NAT, to a port not used by another peer in the same LAN.
|
||||||
|
'';
|
||||||
|
type = types.port;
|
||||||
|
};
|
||||||
|
wireguardKey = mkOption {
|
||||||
|
example = "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=";
|
||||||
|
description = "WireGuard public key for this peer, as generated by `wg pubkey`";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
isRouter = mkOption {
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
The host with this flag set is the subnet router. It forwards
|
||||||
|
packets between WireGuard peers that can't connect directly to
|
||||||
|
each other. WireGuard's scope doesn't (yet) include full mesh
|
||||||
|
networking with load-balancing between routers, so only one peer
|
||||||
|
can hold this status. It should be peered with all other hosts
|
||||||
|
(i.e., {option}`birdsong.hosts.<name>.subnet` set to `internet`).
|
||||||
|
'';
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
config.birdsong.hosts = {
|
||||||
|
yevaud = {
|
||||||
|
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICHUAgyQhl390yUObLUI+jEbuNrZ2U6+8px628DolD+T root@yevaud";
|
||||||
|
endpoint = "yevaud.birdsong.network";
|
||||||
|
ipv4 = "10.127.1.1";
|
||||||
|
ipv6 = "fd70:81ca:0f8f:1::1";
|
||||||
|
wireguardKey = "YPJsIs9x4wuWdFi/QRWSJbWvKE0GQAfVL4MNMqHygDw=";
|
||||||
|
isRouter = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
orm = {
|
||||||
|
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGc9rkcdOVWozBFj3kLVnSyUQQbyyH+UG+bLawanQkRQ root@orm";
|
||||||
|
endpoint = "orm.birdsong.network";
|
||||||
|
ipv4 = "10.127.1.2";
|
||||||
|
ipv6 = "fd70:81ca:0f8f:1::2";
|
||||||
|
wireguardKey = "birdLVh8roeZpcVo308Ums4l/aibhAxbi7MBsglkJyA=";
|
||||||
|
};
|
||||||
|
|
||||||
|
tohru = {
|
||||||
|
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOk8wuGzF0Y7SaH9aimo3SmCz99MTQwL+rEVhx0jsueU root@tohru";
|
||||||
|
subnet = "roaming";
|
||||||
|
ipv4 = "10.127.2.1";
|
||||||
|
ipv6 = "fd70:81ca:0f8f:2::1";
|
||||||
|
port = 51821;
|
||||||
|
wireguardKey = "lk3PCQM1jmZoI8sM/rWSyKNuZOUnjox3n9L9geJD+18=";
|
||||||
|
};
|
||||||
|
|
||||||
|
# kilgharrah = {
|
||||||
|
# # hostKey = "";
|
||||||
|
# subnet = "weyrhold";
|
||||||
|
# endpoint = "192.168.2.1";
|
||||||
|
# ipv4 = "10.127.3.1";
|
||||||
|
# ipv6 = "fd70:81ca:0f8f:3::1";
|
||||||
|
# # wireguardKey = "";
|
||||||
|
# };
|
||||||
|
|
||||||
|
shaw = {
|
||||||
|
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMC0AomCZZiUV/BCpImiV4p/vGvFaz5QNc+fJLXmS5p root@shaw";
|
||||||
|
subnet = "library";
|
||||||
|
# endpoint = "";
|
||||||
|
ipv4 = "10.127.4.1";
|
||||||
|
ipv6 = "fd70:81ca:0f8f:4::1";
|
||||||
|
wireguardKey = "eD79pROC2zjhKz4tGRS43O95gcFRqO+SFb2XDnTr0zc=";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
91
services/birdsong/peer.nix
Normal file
91
services/birdsong/peer.nix
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.birdsong.peer;
|
||||||
|
hostName = if null != cfg.hostName then cfg.hostName else config.networking.hostName;
|
||||||
|
hosts = config.birdsong.hosts;
|
||||||
|
host = hosts.${hostName};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.birdsong.peer = {
|
||||||
|
enable = mkEnableOption "WireGuard peering with the birdsong network";
|
||||||
|
hostName = mkOption {
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
The hostname of this peer within the network. Must be listed in
|
||||||
|
{option}`birdsong.hosts`. If not set, defaults to
|
||||||
|
{option}`networking.hostName`.
|
||||||
|
'';
|
||||||
|
type = with types; nullOr str;
|
||||||
|
};
|
||||||
|
interface = mkOption {
|
||||||
|
default = "birdsong";
|
||||||
|
example = "wg0";
|
||||||
|
description = "The name of the network interface to use for WireGuard.";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
openPorts = mkOption {
|
||||||
|
default = true;
|
||||||
|
description = "Whether to automatically open firewall ports.";
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
privateKeyFile = mkOption {
|
||||||
|
description = "Path to the private key for this peer, as generated by `wg genkey`.";
|
||||||
|
type = types.path;
|
||||||
|
};
|
||||||
|
persistentKeepalive = mkOption {
|
||||||
|
default = null;
|
||||||
|
example = 23;
|
||||||
|
description = ''
|
||||||
|
Constantly ping each peer outside the LAN this often, in seconds, in
|
||||||
|
order to keep the WireGuard tunnel open. Set this if you are behind NAT
|
||||||
|
to keep the NAT session active, or if you have a dynamic IP to keep the
|
||||||
|
other peers aware when your IP changes. To avoid syncing, this should
|
||||||
|
ideally be a prime number that is not shared by another peer in the same
|
||||||
|
LAN.
|
||||||
|
'';
|
||||||
|
type = with types; nullOr int;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = cfg ? privateKeyFile;
|
||||||
|
message = "birdsong.peer.privateKeyFile must be set";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = hostName != null;
|
||||||
|
message = "birdsong.peer.hostName or networking.hostName must be set";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
networking = {
|
||||||
|
firewall.allowedUDPPorts = mkIf cfg.openPorts [ host.port ];
|
||||||
|
|
||||||
|
wireguard.interfaces.${cfg.interface} = {
|
||||||
|
ips = [ "${host.ipv4}/16" "${host.ipv6}/48" ]
|
||||||
|
++ optionals host.isRouter [ "10.127.0.0/16" "fd70:81ca:0f8f::/48" ];
|
||||||
|
privateKeyFile = cfg.privateKeyFile;
|
||||||
|
listenPort = host.port;
|
||||||
|
|
||||||
|
peers =
|
||||||
|
let
|
||||||
|
canDirectPeer = host: peer: peer.subnet == "internet" || (host.subnet != "roaming" && peer.subnet == host.subnet);
|
||||||
|
in
|
||||||
|
mapAttrsToList
|
||||||
|
(name: peer: {
|
||||||
|
name = name;
|
||||||
|
publicKey = peer.wireguardKey;
|
||||||
|
allowedIPs = [ peer.ipv4 peer.ipv6 ]
|
||||||
|
++ optionals peer.isRouter [ "10.127.0.0/16" "fd70:81ca:0f8f::/48" ];
|
||||||
|
endpoint = mkIf (canDirectPeer host peer) "${peer.endpoint}:${toString peer.port}";
|
||||||
|
dynamicEndpointRefreshSeconds = mkIf (canDirectPeer host peer) 5;
|
||||||
|
persistentKeepalive = mkIf (peer.subnet != host.subnet) cfg.persistentKeepalive;
|
||||||
|
})
|
||||||
|
(filterAttrs (name: peer: peer != host && (host.subnet == "internet" || canDirectPeer host peer)) hosts);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
./birdsong
|
||||||
./fonts.nix
|
./fonts.nix
|
||||||
./forgejo.nix
|
./forgejo.nix
|
||||||
./steam.nix
|
./steam.nix
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
let
|
let
|
||||||
cfg = config.qenya.services.fonts;
|
cfg = config.qenya.services.fonts;
|
||||||
inherit (lib) mkIf mkEnableOption;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.qenya.services.fonts = {
|
options.qenya.services.fonts = {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
let
|
let
|
||||||
cfg = config.qenya.services.forgejo;
|
cfg = config.qenya.services.forgejo;
|
||||||
inherit (lib) mkIf mkEnableOption mkOption types;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.qenya.services.forgejo = {
|
options.qenya.services.forgejo = {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
let
|
let
|
||||||
cfg = config.qenya.services.steam;
|
cfg = config.qenya.services.steam;
|
||||||
inherit (lib) mkIf mkEnableOption;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.qenya.services.steam = {
|
options.qenya.services.steam = {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue