Compare commits
No commits in common. "f1dae0d3bf59094a2f574ac0acf124e76a74794d" and "550445e0f9a989c03000faf99a4b948b217792a2" have entirely different histories.
f1dae0d3bf
...
550445e0f9
2
firmware/.gitignore
vendored
2
firmware/.gitignore
vendored
@ -1,2 +1,2 @@
|
|||||||
/result
|
/result
|
||||||
/*.img*
|
/*.img
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
{ lib, pkgs, config, ... }:
|
|
||||||
let
|
|
||||||
configurer = pkgs.substituteAll {
|
|
||||||
src = ./configurer.py;
|
|
||||||
isExecutable = true;
|
|
||||||
|
|
||||||
python = pkgs.python3.withPackages (ps: with ps; [ pyyaml ]);
|
|
||||||
utilLinux = pkgs.util-linux;
|
|
||||||
wireguardTools = pkgs.wireguard-tools;
|
|
||||||
systemd = config.systemd.package;
|
|
||||||
inherit (pkgs) iwd;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
config = {
|
|
||||||
systemd = {
|
|
||||||
services = {
|
|
||||||
qclk-configurer = {
|
|
||||||
description = "qclk dynamic configurer";
|
|
||||||
after = [ "network.target" ];
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "notify-reload";
|
|
||||||
ExecStart = "${configurer} serve";
|
|
||||||
};
|
|
||||||
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
|
||||||
udev.extraRules = ''
|
|
||||||
SUBSYSTEM=="block", ACTION=="add", ENV{ID_BUS}=="usb", ENV{ID_FS_TYPE}=="vfat", RUN+="${configurer} ext-load %E{ID_PATH_TAG} %N"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@ -11,7 +11,7 @@ in
|
|||||||
};
|
};
|
||||||
name = "qclk";
|
name = "qclk";
|
||||||
};
|
};
|
||||||
documentation.enable = false;
|
documentation.nixos.enable = false;
|
||||||
|
|
||||||
time.timeZone = "Europe/Dublin";
|
time.timeZone = "Europe/Dublin";
|
||||||
i18n.defaultLocale = "en_IE.UTF-8";
|
i18n.defaultLocale = "en_IE.UTF-8";
|
||||||
|
@ -1,229 +0,0 @@
|
|||||||
#! @python@/bin/python -B
|
|
||||||
import argparse
|
|
||||||
import base64
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import signal
|
|
||||||
import socket
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import tomllib
|
|
||||||
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
CONF_FILE = '/etc/qclk/config.yaml'
|
|
||||||
WG_KEY_FILE = '/etc/qclk/wg.key'
|
|
||||||
|
|
||||||
IWD_PATH = '/var/lib/iwd'
|
|
||||||
IWD_CONF = '''[Settings]
|
|
||||||
Hidden={hidden}
|
|
||||||
|
|
||||||
[Security]
|
|
||||||
Passphrase={psk}
|
|
||||||
'''
|
|
||||||
|
|
||||||
MANAGEMENT_NET = '''[Match]
|
|
||||||
Name=management
|
|
||||||
|
|
||||||
[Network]
|
|
||||||
Address={ip}/32
|
|
||||||
'''
|
|
||||||
|
|
||||||
def log(m):
|
|
||||||
print(m, file=sys.stderr)
|
|
||||||
|
|
||||||
def iwd_ssid_basename(ssid: str) -> str:
|
|
||||||
if ssid.isalnum() and not any(c in ssid for c in '-_ '):
|
|
||||||
return ssid
|
|
||||||
|
|
||||||
return f"={ssid.encode('utf-8').hex()}"
|
|
||||||
|
|
||||||
class Configurer:
|
|
||||||
tmpdir = '/run/qclk'
|
|
||||||
|
|
||||||
def __init__(self, conf_file: str, wg_key_file: str):
|
|
||||||
self.conf_file = conf_file
|
|
||||||
self.load_config()
|
|
||||||
|
|
||||||
with open(wg_key_file, 'rb') as f:
|
|
||||||
output = subprocess.check_output(['@wireguardTools@/bin/wg', 'pubkey'], input=f.read())
|
|
||||||
pubkey = base64.b64decode(output)
|
|
||||||
self.id = pubkey[:4].hex()
|
|
||||||
|
|
||||||
self.load_dir = os.path.join(self.tmpdir, 'load')
|
|
||||||
self.sd_sock = None
|
|
||||||
|
|
||||||
os.makedirs(self.tmpdir, exist_ok=True)
|
|
||||||
os.makedirs(self.load_dir, exist_ok=True)
|
|
||||||
|
|
||||||
def load_config(self):
|
|
||||||
with open(self.conf_file) as f:
|
|
||||||
self.config = yaml.safe_load(f)
|
|
||||||
|
|
||||||
def write_config(self):
|
|
||||||
log(f'Updaing config')
|
|
||||||
tmp = os.path.join(self.tmpdir, 'new-config.yaml')
|
|
||||||
with open(tmp, 'w') as f:
|
|
||||||
yaml.dump(self.config, f)
|
|
||||||
|
|
||||||
shutil.move(tmp, self.conf_file)
|
|
||||||
|
|
||||||
def _setup_hostname(self):
|
|
||||||
hostname = f'qclk-{self.id}'
|
|
||||||
log(f"Setting hostname to '{hostname}'")
|
|
||||||
socket.sethostname(hostname)
|
|
||||||
|
|
||||||
def _setup_wifi(self):
|
|
||||||
os.makedirs(IWD_CONF, exist_ok=True)
|
|
||||||
if 'wifi' in self.config:
|
|
||||||
conf = self.config['wifi']
|
|
||||||
tmp = os.path.join(self.tmpdir, 'wifi.psk')
|
|
||||||
with open(tmp, 'w') as f:
|
|
||||||
print(
|
|
||||||
IWD_CONF.format(
|
|
||||||
hidden=str(conf['hidden']).lower(),
|
|
||||||
psk=conf['password']),
|
|
||||||
file=f)
|
|
||||||
|
|
||||||
fname = f"{iwd_ssid_basename(conf['ssid'])}.psk"
|
|
||||||
log(f"Writing IWD config file '{fname}' for network '{conf['ssid']}'")
|
|
||||||
shutil.move(tmp, os.path.join(IWD_PATH, fname))
|
|
||||||
else:
|
|
||||||
fname = None
|
|
||||||
|
|
||||||
for f in os.listdir(IWD_PATH):
|
|
||||||
if (fname is not None and f != fname) and f.endswith('.psk'):
|
|
||||||
log(f"Cleaning up old IWD config '{f}'")
|
|
||||||
os.remove(os.path.join(IWD_PATH, f))
|
|
||||||
|
|
||||||
subprocess.call(['@iwd@/bin/iwctl', 'station', 'wifi', 'scan'])
|
|
||||||
|
|
||||||
def _setup_mgmt(self):
|
|
||||||
conf = self.config['management']
|
|
||||||
tmp = os.path.join(self.tmpdir, 'management.network')
|
|
||||||
with open(tmp, 'w') as f:
|
|
||||||
print(MANAGEMENT_NET.format(ip=conf['ip']), file=f)
|
|
||||||
|
|
||||||
log(f"Configuring management IP {conf['ip']}")
|
|
||||||
os.makedirs('/run/systemd/network', exist_ok=True)
|
|
||||||
shutil.move(tmp, '/run/systemd/network/20-management.network')
|
|
||||||
subprocess.check_call(['@systemd@/bin/networkctl', 'reload'])
|
|
||||||
|
|
||||||
def reconcile(self):
|
|
||||||
if self.sd_sock is not None:
|
|
||||||
self.sd_sock.sendall(b'STATUS=Reconciling configuration...')
|
|
||||||
|
|
||||||
self._setup_hostname()
|
|
||||||
self._setup_wifi()
|
|
||||||
self._setup_mgmt()
|
|
||||||
|
|
||||||
if self.sd_sock is not None:
|
|
||||||
self.sd_sock.sendall(b'STATUS=OK\nREADY=1')
|
|
||||||
|
|
||||||
def _ext_load(self, identifier: str, device: str):
|
|
||||||
mountpoint = os.path.join(self.tmpdir, 'mnt', identifier)
|
|
||||||
os.makedirs(mountpoint, exist_ok=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
log(f'Mounting {device} -> {mountpoint}')
|
|
||||||
subprocess.check_call(['@utilLinux@/bin/mount', '-t', 'vfat', '-o', 'ro', device, mountpoint])
|
|
||||||
try:
|
|
||||||
path = os.path.join(mountpoint, 'qclk.toml')
|
|
||||||
if not os.path.exists(path):
|
|
||||||
log(f'No config file found on {device}')
|
|
||||||
return
|
|
||||||
|
|
||||||
with open(path, 'rb') as f:
|
|
||||||
ext_conf = tomllib.load(f)
|
|
||||||
finally:
|
|
||||||
subprocess.check_call(['@utilLinux@/bin/umount', mountpoint])
|
|
||||||
finally:
|
|
||||||
os.rmdir(mountpoint)
|
|
||||||
|
|
||||||
if 'wifi' in ext_conf:
|
|
||||||
log(f'Loading WiFi settings from {device}')
|
|
||||||
self.config['wifi'] = {
|
|
||||||
'ssid': ext_conf['wifi']['ssid'],
|
|
||||||
'password': ext_conf['wifi'].get('password', ''),
|
|
||||||
'hidden': ext_conf['wifi'].get('hidden', False),
|
|
||||||
}
|
|
||||||
self._setup_wifi()
|
|
||||||
self.write_config()
|
|
||||||
|
|
||||||
def serve(self, args: argparse.Namespace):
|
|
||||||
os.makedirs(os.path.join(self.tmpdir, 'load'), exist_ok=True)
|
|
||||||
|
|
||||||
addr = os.getenv('NOTIFY_SOCKET')
|
|
||||||
if addr is not None:
|
|
||||||
self.sd_sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
|
|
||||||
if addr[0] == '@':
|
|
||||||
addr = '\0' + addr[1:]
|
|
||||||
self.sd_sock.connect(addr)
|
|
||||||
|
|
||||||
running = True
|
|
||||||
def sighandler(sig, frame):
|
|
||||||
nonlocal running
|
|
||||||
if sig in (signal.SIGINT, signal.SIGTERM):
|
|
||||||
running = False
|
|
||||||
return
|
|
||||||
|
|
||||||
if sig == signal.SIGHUP:
|
|
||||||
if self.sd_sock is not None:
|
|
||||||
t = time.clock_gettime_ns(time.CLOCK_MONOTONIC) // 1000
|
|
||||||
self.sd_sock.sendall(f'RELOADING=1\nMONOTONIC_USEC={t}'.encode('ascii'))
|
|
||||||
self.load_config()
|
|
||||||
self.reconcile()
|
|
||||||
elif sig == signal.SIGUSR1:
|
|
||||||
for identifier in os.listdir(self.load_dir):
|
|
||||||
fname = os.path.join(self.load_dir, identifier)
|
|
||||||
with open(fname) as f:
|
|
||||||
device = f.read().strip()
|
|
||||||
os.remove(fname)
|
|
||||||
|
|
||||||
try:
|
|
||||||
self._ext_load(identifier, device)
|
|
||||||
except Exception as ex:
|
|
||||||
log(f'Failed to load config from {device}: {ex}')
|
|
||||||
|
|
||||||
for s in [signal.SIGINT, signal.SIGTERM, signal.SIGHUP, signal.SIGUSR1]:
|
|
||||||
signal.signal(s, sighandler)
|
|
||||||
|
|
||||||
self.reconcile()
|
|
||||||
while running:
|
|
||||||
signal.pause()
|
|
||||||
|
|
||||||
if self.sd_sock is not None:
|
|
||||||
self.sd_sock.close()
|
|
||||||
|
|
||||||
def ext_load(self, args: argparse.Namespace):
|
|
||||||
with open(os.path.join(self.load_dir, args.identifier), 'w') as f:
|
|
||||||
print(args.device, file=f)
|
|
||||||
output = subprocess.check_output(
|
|
||||||
['@systemd@/bin/systemctl', 'show', '--property', 'MainPID', '--value', 'qclk-configurer.service'], encoding='ascii')
|
|
||||||
pid = int(output.strip())
|
|
||||||
|
|
||||||
os.kill(pid, signal.SIGUSR1)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser(description='qclkOS configurer')
|
|
||||||
cmds = parser.add_subparsers(title='commands', help='reconcile')
|
|
||||||
|
|
||||||
rec_parser = cmds.add_parser('serve')
|
|
||||||
rec_parser.set_defaults(func=Configurer.serve)
|
|
||||||
|
|
||||||
eload_parser = cmds.add_parser('ext-load')
|
|
||||||
eload_parser.set_defaults(func=Configurer.ext_load)
|
|
||||||
eload_parser.add_argument('identifier', help='Unique device name')
|
|
||||||
eload_parser.add_argument('device', help='Block device path')
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
c = Configurer(CONF_FILE, WG_KEY_FILE)
|
|
||||||
if not hasattr(args, 'func'):
|
|
||||||
c.serve(args)
|
|
||||||
else:
|
|
||||||
args.func(c, args)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
@ -26,7 +26,6 @@ let
|
|||||||
./base.nix
|
./base.nix
|
||||||
./disk.nix
|
./disk.nix
|
||||||
./network.nix
|
./network.nix
|
||||||
./app.nix
|
|
||||||
|
|
||||||
target
|
target
|
||||||
];
|
];
|
||||||
@ -37,107 +36,49 @@ in
|
|||||||
qclk-rpi3 = mkSystem target/rpi3.nix;
|
qclk-rpi3 = mkSystem target/rpi3.nix;
|
||||||
};
|
};
|
||||||
|
|
||||||
perSystem = { lib, libMy, pkgs, ... }:
|
perSystem = { libMy, pkgs, ... }: {
|
||||||
let
|
|
||||||
inherit (lib) concatMapStringsSep;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
devenv.shells.firmware = libMy.withRootdir {
|
devenv.shells.firmware = libMy.withRootdir {
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
nixos-rebuild
|
nixos-rebuild
|
||||||
nixVersions.latest
|
nixVersions.latest
|
||||||
wireguard-tools
|
|
||||||
];
|
];
|
||||||
|
|
||||||
scripts =
|
scripts = {
|
||||||
let
|
|
||||||
shellUtils = ''
|
|
||||||
die() {
|
|
||||||
echo "$1" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
exportPath = ps:
|
|
||||||
let pkgsPath = concatMapStringsSep ":" (p: "${p}/bin") ps; in ''export PATH="$PATH:${pkgsPath}"'';
|
|
||||||
|
|
||||||
buildImgRootHelper = pkgs.writeShellScript "fixup-perms" ''
|
|
||||||
pushd "$1"
|
|
||||||
# systemd-network GID
|
|
||||||
chgrp 152 etc/qclk/wg.key
|
|
||||||
chmod 640 etc/qclk/wg.key
|
|
||||||
popd
|
|
||||||
|
|
||||||
mkfs.ext4 -L qclkos-persist -d "$1" "$2"
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
{
|
|
||||||
build.exec = ''
|
build.exec = ''
|
||||||
nix build "..#nixosConfigurations.qclk-$1.config.system.build.toplevel"
|
nix build "..#nixosConfigurations.qclk-$1.config.system.build.toplevel"
|
||||||
'';
|
'';
|
||||||
build-image.exec = ''
|
build-image.exec = ''
|
||||||
set -e
|
set -e
|
||||||
${exportPath (with pkgs; [ util-linux fakeroot e2fsprogs zstd python3 ])}
|
export PATH="$PATH:${pkgs.util-linux}/bin:${pkgs.fakeroot}/bin:${pkgs.e2fsprogs}/bin"
|
||||||
${shellUtils}
|
die() {
|
||||||
usage() {
|
echo "$1" >&2
|
||||||
die "usage: $0 <target> <IP>"
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
populate_persist() {
|
[ -z "$1" ] && die "Need to set target"
|
||||||
mkdir -p etc/qclk
|
|
||||||
|
|
||||||
old_umask="$(umask)"
|
|
||||||
umask 077
|
|
||||||
|
|
||||||
wg genkey > etc/qclk/wg.key
|
|
||||||
wg_pubkey="$(wg pubkey < etc/qclk/wg.key)"
|
|
||||||
id="$(python3 -c "import base64; print(base64.b64decode('$wg_pubkey')[:4].hex())")"
|
|
||||||
|
|
||||||
pin="$(python3 -c "import random; print('''.join(str(random.randint(0, 9)) for _ in range(6)))")"
|
|
||||||
cat << EOF > etc/qclk/config.yaml
|
|
||||||
management:
|
|
||||||
ip: $ip
|
|
||||||
pin: '$pin'
|
|
||||||
EOF
|
|
||||||
umask "$old_umask"
|
|
||||||
}
|
|
||||||
|
|
||||||
[ $# -eq 2 ] || usage
|
|
||||||
|
|
||||||
target=$1
|
target=$1
|
||||||
ip=$2
|
out=qclkos-$target.img
|
||||||
|
|
||||||
nix build "..#nixosConfigurations.qclk-$target.config.my.disk.image"
|
nix build "..#nixosConfigurations.qclk-$target.config.my.disk.image"
|
||||||
|
|
||||||
persistRoot=$(mktemp --tmpdir -d qclkos-persist-XXXXX)
|
persistRoot=$(mktemp --tmpdir -d qclkos-persist-XXXXX)
|
||||||
pushd "$persistRoot"
|
# TODO: bless with unique stuff (e.g. keys)
|
||||||
populate_persist
|
touch "$persistRoot"/test.txt
|
||||||
popd
|
|
||||||
|
|
||||||
out=qclkos-$target-$id.img
|
cp --sparse=always result/$out $out
|
||||||
cp --sparse=always result/qclkos-$target.img $out
|
|
||||||
chmod u+w $out
|
chmod u+w $out
|
||||||
|
|
||||||
eval $(partx $out -o START,SECTORS --nr 2 --pairs)
|
eval $(partx $out -o START,SECTORS --nr 2 --pairs)
|
||||||
persistImg=$(mktemp --tmpdir qclkos-persist-XXXXX.img)
|
persistImg=$(mktemp --tmpdir qclkos-persist-XXXXX.img)
|
||||||
truncate -s $((SECTORS * 512)) $persistImg
|
truncate -s $((SECTORS * 512)) $persistImg
|
||||||
fakeroot ${buildImgRootHelper} $persistRoot $persistImg
|
fakeroot mkfs.ext4 -L qclkos-persist -d $persistRoot $persistImg
|
||||||
|
|
||||||
dd conv=notrunc if=$persistImg of=$out seek=$START count=$SECTORS
|
dd conv=notrunc if=$persistImg of=$out seek=$START count=$SECTORS
|
||||||
rm -r "$persistRoot" "$persistImg"
|
rm -r "$persistRoot" "$persistImg"
|
||||||
[ -z "$NO_COMPRESS" ] && zstd -7 -T0 --rm -f $out
|
|
||||||
|
|
||||||
echo "====== DONE! ======"
|
|
||||||
echo "WireGuard pubkey: $wg_pubkey"
|
|
||||||
echo "Control PIN: $pin"
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
push-config.exec = ''
|
push-config.exec = ''
|
||||||
${shellUtils}
|
|
||||||
usage() {
|
|
||||||
die "usage: $0 <host> <target> <verb>"
|
|
||||||
}
|
|
||||||
[ $# -eq 3 ] || usage
|
|
||||||
|
|
||||||
host=$1; shift
|
host=$1; shift
|
||||||
target=$1; shift
|
target=$1; shift
|
||||||
verb=$1; shift
|
verb=$1; shift
|
||||||
@ -145,9 +86,6 @@ in
|
|||||||
export NIX_SSHOPTS="-i .keys/management.key"
|
export NIX_SSHOPTS="-i .keys/management.key"
|
||||||
nixos-rebuild $verb --flake ..#qclk-$target --target-host root@"$host" --use-substitutes "$@"
|
nixos-rebuild $verb --flake ..#qclk-$target --target-host root@"$host" --use-substitutes "$@"
|
||||||
'';
|
'';
|
||||||
clean.exec = ''
|
|
||||||
rm -f qclkos-*.img*
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -12,16 +12,15 @@ let
|
|||||||
compressImage = false;
|
compressImage = false;
|
||||||
}).overrideAttrs (o: {
|
}).overrideAttrs (o: {
|
||||||
buildCommand = ''
|
buildCommand = ''
|
||||||
# We need to move the store up a level since we're not using this as a rootfs but as /nix
|
# HACK: `populateImageCommands` is executed in a subshell _before_ the paths are copied in...
|
||||||
# HACK: `populateImageCommands` is executed in a subshell _before_ the store paths are copied in...
|
|
||||||
shopt -s expand_aliases
|
shopt -s expand_aliases
|
||||||
nixUpThenFaketime() {
|
nixUpThenMkfs() {
|
||||||
mv rootImage/{nix/store,}
|
mv rootImage/{nix/store,}
|
||||||
rmdir rootImage/nix
|
rmdir rootImage/nix
|
||||||
|
|
||||||
faketime "$@"
|
faketime "$@"
|
||||||
}
|
}
|
||||||
alias faketime=nixUpThenFaketime
|
alias faketime=nixUpThenMkfs
|
||||||
|
|
||||||
${o.buildCommand}
|
${o.buildCommand}
|
||||||
'';
|
'';
|
||||||
@ -124,8 +123,6 @@ in
|
|||||||
directories = [
|
directories = [
|
||||||
"/var/lib/nixos"
|
"/var/lib/nixos"
|
||||||
"/var/lib/systemd"
|
"/var/lib/systemd"
|
||||||
|
|
||||||
"/etc/qclk"
|
|
||||||
];
|
];
|
||||||
files = [
|
files = [
|
||||||
"/etc/machine-id"
|
"/etc/machine-id"
|
||||||
|
@ -1,52 +1,27 @@
|
|||||||
{ lib, config, pkgs, ... }: {
|
{ lib, config, ... }: {
|
||||||
environment = {
|
|
||||||
systemPackages = with pkgs; [
|
|
||||||
wireguard-tools
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
hostName = config.system.name;
|
hostName = config.system.name;
|
||||||
useDHCP = false;
|
useDHCP = false;
|
||||||
useNetworkd = true;
|
useNetworkd = true;
|
||||||
wireless.iwd = {
|
wireless.iwd = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings.DriverQuirks.DefaultInterface = "*";
|
||||||
# systemd-networkd gets confused if we hop between networks and doesn't redo DHCP
|
|
||||||
General.EnableNetworkConfiguration = true;
|
|
||||||
DriverQuirks.DefaultInterface = "*";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd = {
|
systemd = {
|
||||||
network = {
|
network = {
|
||||||
wait-online.enable = false;
|
wait-online.enable = false;
|
||||||
netdevs = {
|
|
||||||
"10-management" = {
|
|
||||||
netdevConfig = {
|
|
||||||
Name = "management";
|
|
||||||
Kind = "wireguard";
|
|
||||||
};
|
|
||||||
wireguardConfig = {
|
|
||||||
PrivateKeyFile = "/etc/qclk/wg.key";
|
|
||||||
RouteTable = "main";
|
|
||||||
};
|
|
||||||
wireguardPeers = [
|
|
||||||
{
|
|
||||||
Endpoint = "94.142.240.44:51821";
|
|
||||||
PublicKey = "itMQ2DlPEMdJFlIZRQkwa+Mv7cLc9d4zgfzlljEtLn4=";
|
|
||||||
AllowedIPs = [ "10.100.4.1/32" ];
|
|
||||||
PersistentKeepalive = 15;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
networks = {
|
networks = {
|
||||||
"10-ethernet" = {
|
"10-ethernet" = {
|
||||||
matchConfig.Name = "ethernet";
|
matchConfig.Name = "ethernet";
|
||||||
DHCP = "yes";
|
DHCP = "yes";
|
||||||
};
|
};
|
||||||
|
"10-wifi" = {
|
||||||
|
matchConfig.Name = "wifi";
|
||||||
|
DHCP = "yes";
|
||||||
|
networkConfig.IgnoreCarrierLoss = "3s";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user