huge refactor
This commit is contained in:
parent
03e5a47910
commit
1d4c8455ee
30 changed files with 972 additions and 697 deletions
69
moduler/services/network/default.nix
Normal file
69
moduler/services/network/default.nix
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
{
|
||||
options.features.network = {
|
||||
enable = mkEnableOption "enable network tooling and VPN services";
|
||||
netbird = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable NetBird service.";
|
||||
};
|
||||
uiEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable NetBird UI component.";
|
||||
};
|
||||
};
|
||||
tailscale = {
|
||||
waitForNetbird = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Add netbird ordering to tailscaled unit.";
|
||||
};
|
||||
};
|
||||
tooling = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Install network troubleshooting CLI tools.";
|
||||
};
|
||||
packages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = with pkgs; [
|
||||
dnsutils
|
||||
nmap
|
||||
ipcalc
|
||||
];
|
||||
description = "Packages installed when network tooling is enabled.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.features.network.enable {
|
||||
services.netbird = mkIf config.features.network.netbird.enable {
|
||||
enable = true;
|
||||
ui.enable = config.features.network.netbird.uiEnable;
|
||||
};
|
||||
|
||||
systemd.services.tailscaled =
|
||||
mkIf (config.features.network.tailscale.waitForNetbird && config.features.network.netbird.enable)
|
||||
{
|
||||
after = [
|
||||
"netbird.service"
|
||||
"network-online.target"
|
||||
];
|
||||
wants = [
|
||||
"netbird.service"
|
||||
"network-online.target"
|
||||
];
|
||||
};
|
||||
|
||||
environment.systemPackages = mkIf config.features.network.tooling.enable config.features.network.tooling.packages;
|
||||
};
|
||||
}
|
||||
71
moduler/services/sound/default.nix
Normal file
71
moduler/services/sound/default.nix
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.features.sound = {
|
||||
enable = mkEnableOption "enable sound and bluetooth stack";
|
||||
pipewire = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable PipeWire audio stack.";
|
||||
};
|
||||
alsa32Bit = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable 32-bit ALSA support.";
|
||||
};
|
||||
pulseCompat = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable PulseAudio compatibility through PipeWire.";
|
||||
};
|
||||
};
|
||||
bluetooth = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable Bluetooth subsystem.";
|
||||
};
|
||||
powerOnBoot = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Power on Bluetooth at boot.";
|
||||
};
|
||||
disableHeadsetProfile = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Disable headset profile for Bluetooth devices.";
|
||||
};
|
||||
bluemanEnable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Enable Blueman service.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.features.sound.enable {
|
||||
services.pulseaudio.enable = false;
|
||||
security.rtkit.enable = true;
|
||||
services = {
|
||||
pipewire = {
|
||||
enable = config.features.sound.pipewire.enable;
|
||||
alsa.enable = config.features.sound.pipewire.enable;
|
||||
alsa.support32Bit = config.features.sound.pipewire.alsa32Bit;
|
||||
pulse.enable = config.features.sound.pipewire.pulseCompat;
|
||||
};
|
||||
blueman.enable = config.features.sound.bluetooth.bluemanEnable;
|
||||
};
|
||||
hardware = {
|
||||
bluetooth = mkIf config.features.sound.bluetooth.enable {
|
||||
enable = config.features.sound.bluetooth.enable;
|
||||
powerOnBoot = config.features.sound.bluetooth.powerOnBoot;
|
||||
settings = {
|
||||
General = mkIf config.features.sound.bluetooth.disableHeadsetProfile {
|
||||
Disable = "Headset";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
78
moduler/services/system/default.nix
Normal file
78
moduler/services/system/default.nix
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
{
|
||||
options.features.system = {
|
||||
enable = mkEnableOption "enable shared system utilities";
|
||||
preset = mkOption {
|
||||
type = types.enum [
|
||||
"minimal"
|
||||
"desktop"
|
||||
"ops"
|
||||
];
|
||||
default = "desktop";
|
||||
description = "Package profile for shared system tooling.";
|
||||
};
|
||||
corePackages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = with pkgs; [
|
||||
sops
|
||||
unzip
|
||||
zip
|
||||
wget
|
||||
htop
|
||||
procps
|
||||
fastfetch
|
||||
bc
|
||||
fzf
|
||||
eza
|
||||
rsync
|
||||
ripgrep
|
||||
fd
|
||||
];
|
||||
description = "Always-installed core system packages.";
|
||||
};
|
||||
desktopPackages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = with pkgs; [
|
||||
bluez
|
||||
bluez-tools
|
||||
poppler-utils
|
||||
alsa-utils
|
||||
libnotify
|
||||
hyprpicker
|
||||
];
|
||||
description = "Additional packages for desktop-oriented hosts.";
|
||||
};
|
||||
opsPackages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = with pkgs; [
|
||||
grc
|
||||
lazygit
|
||||
];
|
||||
description = "Additional packages for operations-heavy hosts.";
|
||||
};
|
||||
extras = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = with pkgs; [
|
||||
lolcat
|
||||
fortune
|
||||
cowsay
|
||||
typst
|
||||
];
|
||||
description = "Additional optional packages for all presets except minimal.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.features.system.enable {
|
||||
environment.systemPackages =
|
||||
config.features.system.corePackages
|
||||
++ optionals (config.features.system.preset != "minimal") config.features.system.extras
|
||||
++ optionals (config.features.system.preset == "desktop") config.features.system.desktopPackages
|
||||
++ optionals (config.features.system.preset == "ops") config.features.system.opsPackages;
|
||||
};
|
||||
}
|
||||
62
moduler/services/users/default.nix
Normal file
62
moduler/services/users/default.nix
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
{
|
||||
options.features.users = {
|
||||
enable = mkEnableOption "enable default users";
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = "fw";
|
||||
description = "Primary user account name.";
|
||||
};
|
||||
fullName = mkOption {
|
||||
type = types.str;
|
||||
default = "Fredrik Wastring";
|
||||
description = "Primary user full name.";
|
||||
};
|
||||
initialPassword = mkOption {
|
||||
type = types.str;
|
||||
default = "password";
|
||||
description = "Initial password for the primary user.";
|
||||
};
|
||||
extraGroups = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [
|
||||
"networkmanager"
|
||||
"wheel"
|
||||
"audio"
|
||||
"docker"
|
||||
"input"
|
||||
];
|
||||
description = "Additional groups for the primary user.";
|
||||
};
|
||||
sshAuthorizedKeys = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFpJBGPIfPB1BwSG7aoKqwfccyZSaU7J3xpJ8behMp9N fw@core"
|
||||
];
|
||||
description = "SSH authorized keys for the primary user.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.features.users.enable {
|
||||
users = {
|
||||
defaultUserShell = pkgs.bash;
|
||||
users = {
|
||||
${config.features.users.name} = {
|
||||
initialPassword = config.features.users.initialPassword;
|
||||
isNormalUser = true;
|
||||
description = config.features.users.fullName;
|
||||
extraGroups = config.features.users.extraGroups;
|
||||
openssh.authorizedKeys = {
|
||||
keys = config.features.users.sshAuthorizedKeys;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -100,6 +100,21 @@ in
|
|||
default = 24;
|
||||
description = "VAAPI quality parameter (lower means better quality, higher CPU/bitrate).";
|
||||
};
|
||||
waitForRtsp = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Wait for the RTSP destination to accept TCP connections before ffmpeg starts.";
|
||||
};
|
||||
waitForRtspTimeoutSec = mkOption {
|
||||
type = types.int;
|
||||
default = 30;
|
||||
description = "Maximum seconds to wait for RTSP destination availability.";
|
||||
};
|
||||
waitForRtspIntervalSec = mkOption {
|
||||
type = types.int;
|
||||
default = 1;
|
||||
description = "Seconds between RTSP availability checks.";
|
||||
};
|
||||
vaapiDriver = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
|
|
@ -209,6 +224,13 @@ in
|
|||
"-rc_mode VBR -b:v ${toString streamCfg.bitrateKbps}k -maxrate ${toString maxrateKbps}k -bufsize ${toString bufsizeKbps}k"
|
||||
else
|
||||
"-rc_mode CQP -qp ${toString streamCfg.vaapiQp}";
|
||||
rtspUrlMatch = builtins.match "rtsp://([^/:]+)(:([0-9]+))?/.*" streamCfg.rtspUrl;
|
||||
rtspHost = if rtspUrlMatch != null then builtins.elemAt rtspUrlMatch 0 else "127.0.0.1";
|
||||
rtspPort =
|
||||
if rtspUrlMatch != null && builtins.elemAt rtspUrlMatch 2 != null then
|
||||
builtins.elemAt rtspUrlMatch 2
|
||||
else
|
||||
"8554";
|
||||
videoCodecArgs =
|
||||
if streamCfg.useVaapi then
|
||||
"-vaapi_device ${streamCfg.vaapiDevice} -vf format=nv12,hwupload -c:v h264_vaapi -profile:v main -level:v 4.1 ${vaapiRateControlArgs} -g ${
|
||||
|
|
@ -230,6 +252,22 @@ in
|
|||
Restart = "always";
|
||||
RestartSec = "2";
|
||||
Environment = optional (streamCfg.vaapiDriver != null) "LIBVA_DRIVER_NAME=${streamCfg.vaapiDriver}";
|
||||
ExecStartPre = optional cfg.waitForRtsp (
|
||||
pkgs.writeShellScript "wait-for-rtsp-${sanitizeName streamName}" ''
|
||||
set -eu
|
||||
retries=${toString cfg.waitForRtspTimeoutSec}
|
||||
interval=${toString cfg.waitForRtspIntervalSec}
|
||||
i=0
|
||||
until ${pkgs.netcat-openbsd}/bin/nc -z -w1 ${rtspHost} ${rtspPort}; do
|
||||
i=$((i + 1))
|
||||
if [ "$i" -ge "$retries" ]; then
|
||||
echo "Timed out waiting for RTSP server at ${rtspHost}:${rtspPort}" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep "$interval"
|
||||
done
|
||||
''
|
||||
);
|
||||
ExecStart = "${pkgs.ffmpeg}/bin/ffmpeg -hide_banner -loglevel warning -f v4l2 -framerate ${toString streamCfg.framerate} -video_size ${streamCfg.videoSize} -i ${streamCfg.device} ${videoCodecArgs} -f rtsp -rtsp_transport tcp ${streamCfg.rtspUrl}";
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue