1 Commits

Author SHA1 Message Date
89c507bfae flake.lock: Update
All checks were successful
Check Flake / check-flake (push) Successful in 29m23s
Flake lock file updates:

• Updated input 'deploy-rs':
    'github:serokell/deploy-rs/c2ea4e642dc50fd44b537e9860ec95867af30d39' (2023-04-21)
  → 'github:serokell/deploy-rs/64160276cd6569694131ed8864d4d35470a84ec3' (2023-05-08)
• Updated input 'nix-index-database':
    'github:Mic92/nix-index-database/e3e320b19c192f40a5b98e8776e3870df62dee8a' (2023-04-25)
  → 'github:Mic92/nix-index-database/219067a5e3cf4b9581c8b4fcfc59ecd5af953d07' (2023-05-09)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/297187b30a19f147ef260abb5abd93b0706af238' (2023-04-30)
  → 'github:NixOS/nixpkgs/f431ee4a85cb985075b4ed27596913e8087f4264' (2023-05-10)
2023-05-10 12:07:18 -06:00
115 changed files with 1372 additions and 2870 deletions

View File

@@ -4,16 +4,35 @@ on: [push]
env: env:
DEBIAN_FRONTEND: noninteractive DEBIAN_FRONTEND: noninteractive
PATH: /run/current-system/sw/bin/ PATH: /run/current-system/sw/bin/:/nix/var/nix/profiles/per-user/gitea-runner/profile/bin
# defaults:
# run:
# shell: nix shell nixpkgs#nodejs-18_x
jobs: jobs:
check-flake: check-flake:
runs-on: nixos runs-on: nixos
steps: steps:
# - run: node --version
# - name: Install basic dependencies
# run: apt-get update && apt-get install -y --no-install-recommends sudo curl ca-certificates xz-utils
# - name: Install Nix
# uses: https://github.com/cachix/install-nix-action@v20
# with:
# github_access_token: ${{ secrets.__GITHUB_TOKEN }}
- name: Install dependencies
run: nix profile install nixpkgs#nodejs-18_x
- name: Checkout the repository - name: Checkout the repository
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
# - name: Get ENV var names
# run: printenv | cut -d'=' -f1
- name: Check Flake - name: Check Flake
run: nix flake check --all-systems --print-build-logs --log-format raw --show-trace run: nix flake check --show-trace

View File

@@ -1,42 +0,0 @@
# Lockfile utils
.PHONY: update-lockfile
update-lockfile:
nix flake update --commit-lock-file
.PHONY: update-lockfile-without-commit
update-lockfile-without-commit:
nix flake update
# Agenix utils
.PHONY: edit-secret
edit-secret:
cd secrets && agenix -e $(filter-out $@,$(MAKECMDGOALS))
.PHONY: rekey-secrets
rekey-secrets:
cd secrets && agenix -r
# NixOS utils
.PHONY: clean-old-nixos-profiles
clean-old-nixos-profiles:
doas nix-collect-garbage -d
# Garbage Collect
.PHONY: gc
gc:
nix store gc
# Update a flake input by name (ex: 'nixpkgs')
.PHONY: update-input
update-input:
nix flake update $(filter-out $@,$(MAKECMDGOALS))
# Build Custom Install ISO
.PHONY: iso
iso:
nix build .#packages.x86_64-linux.iso
# Deploy a host by name (ex: 's0')
.PHONY: deploy
deploy:
deploy --remote-build --boot --debug-logs --skip-checks .#$(filter-out $@,$(MAKECMDGOALS))

View File

@@ -4,7 +4,7 @@
- `/common` - common configuration imported into all `/machines` - `/common` - common configuration imported into all `/machines`
- `/boot` - config related to bootloaders, cpu microcode, and unlocking LUKS root disks over tor - `/boot` - config related to bootloaders, cpu microcode, and unlocking LUKS root disks over tor
- `/network` - config for tailscale, and NixOS container with automatic vpn tunneling via PIA - `/network` - config for tailscale, and NixOS container with automatic vpn tunneling via PIA
- `/pc` - config that a graphical PC should have. Have the `personal` role set in the machine's `properties.nix` to enable everthing. - `/pc` - config that a graphical desktop computer should have. Use `de.enable = true;` to enable everthing.
- `/server` - config that creates new nixos services or extends existing ones to meet my needs - `/server` - config that creates new nixos services or extends existing ones to meet my needs
- `/machines` - all my NixOS machines along with their machine unique configuration for hardware and services - `/machines` - all my NixOS machines along with their machine unique configuration for hardware and services
- `/kexec` - a special machine for generating minimal kexec images. Does not import `/common` - `/kexec` - a special machine for generating minimal kexec images. Does not import `/common`

View File

@@ -12,13 +12,6 @@
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"s0.koi-bebop.ts.net:OjbzD86YjyJZpCp9RWaQKANaflcpKhtzBMNP8I2aPUU=" "s0.koi-bebop.ts.net:OjbzD86YjyJZpCp9RWaQKANaflcpKhtzBMNP8I2aPUU="
]; ];
# Allow substituters to be offline
# This isn't exactly ideal since it would be best if I could set up a system
# so that it is an error if a derivation isn't available for any substituters
# and use this flag as intended for deciding if it should build missing
# derivations locally. See https://github.com/NixOS/nix/issues/6901
fallback = true;
}; };
}; };
} }

View File

@@ -10,20 +10,18 @@ in
device = mkOption { device = mkOption {
type = types.str; type = types.str;
}; };
configurationLimit = mkOption {
default = 20;
type = types.int;
};
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
# Use GRUB 2 for BIOS
boot.loader = { boot.loader = {
timeout = 2; timeout = 2;
grub = { grub = {
enable = true; enable = true;
device = cfg.device; device = cfg.device;
version = 2;
useOSProber = true; useOSProber = true;
configurationLimit = cfg.configurationLimit; configurationLimit = 20;
theme = pkgs.nixos-grub2-theme; theme = pkgs.nixos-grub2-theme;
}; };
}; };

View File

@@ -7,23 +7,21 @@ in
{ {
options.efi = { options.efi = {
enable = mkEnableOption "enable efi boot"; enable = mkEnableOption "enable efi boot";
configurationLimit = mkOption {
default = 20;
type = types.int;
};
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
# Use GRUB2 for EFI
boot.loader = { boot.loader = {
efi.canTouchEfiVariables = true; efi.canTouchEfiVariables = true;
timeout = 2; timeout = 2;
grub = { grub = {
enable = true; enable = true;
device = "nodev"; device = "nodev";
version = 2;
efiSupport = true; efiSupport = true;
useOSProber = true; useOSProber = true;
# memtest86.enable = true; # memtest86.enable = true;
configurationLimit = cfg.configurationLimit; configurationLimit = 20;
theme = pkgs.nixos-grub2-theme; theme = pkgs.nixos-grub2-theme;
}; };
}; };

View File

@@ -1,7 +1,5 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
# TODO: use tailscale instead of tor https://gist.github.com/antifuchs/e30d58a64988907f282c82231dde2cbc
let let
cfg = config.remoteLuksUnlock; cfg = config.remoteLuksUnlock;
in in
@@ -35,6 +33,11 @@ in
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
# boot.initrd.luks.devices.${cfg.device.name} = {
# device = cfg.device.path;
# allowDiscards = cfg.device.allowDiscards;
# };
# Unlock LUKS disk over ssh # Unlock LUKS disk over ssh
boot.initrd.network.enable = true; boot.initrd.network.enable = true;
boot.initrd.kernelModules = cfg.kernelModules; boot.initrd.kernelModules = cfg.kernelModules;

View File

@@ -1,4 +1,4 @@
{ config, pkgs, lib, ... }: { config, pkgs, ... }:
{ {
imports = [ imports = [
@@ -18,21 +18,15 @@
nix.flakes.enable = true; nix.flakes.enable = true;
system.stateVersion = "23.11"; system.stateVersion = "21.11";
networking.useDHCP = lib.mkDefault true; networking.useDHCP = false;
networking.firewall.enable = true; networking.firewall.enable = true;
networking.firewall.allowPing = true; networking.firewall.allowPing = true;
time.timeZone = "America/Los_Angeles"; time.timeZone = "America/Denver";
i18n = { i18n.defaultLocale = "en_US.UTF-8";
defaultLocale = "en_US.UTF-8";
extraLocaleSettings = {
LANGUAGE = "en_US.UTF-8";
LC_ALL = "en_US.UTF-8";
};
};
services.openssh = { services.openssh = {
enable = true; enable = true;
@@ -61,8 +55,6 @@
lm_sensors lm_sensors
picocom picocom
lf lf
gnumake
tree
]; ];
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;
@@ -98,7 +90,4 @@
security.acme.acceptTerms = true; security.acme.acceptTerms = true;
security.acme.defaults.email = "zuckerberg@neet.dev"; security.acme.defaults.email = "zuckerberg@neet.dev";
# Enable Desktop Environment if this is a PC (machine role is "personal")
de.enable = lib.mkDefault (config.thisMachine.hasRole."personal");
} }

View File

@@ -10,9 +10,16 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
nix = { nix = {
package = pkgs.nixFlakes;
extraOptions = '' extraOptions = ''
experimental-features = nix-command flakes experimental-features = nix-command flakes
''; '';
# pin nixpkgs for system commands such as "nix shell"
registry.nixpkgs.flake = config.inputs.nixpkgs;
# pin system nixpkgs to the same version as the flake input
nixPath = [ "nixpkgs=${config.inputs.nixpkgs}" ];
}; };
}; };
} }

View File

@@ -5,9 +5,20 @@
let let
machines = config.machines.hosts; machines = config.machines.hosts;
in
{
imports = [
./ssh.nix
./roles.nix
];
hostOptionsSubmoduleType = lib.types.submodule { options.machines = {
hosts = lib.mkOption {
type = lib.types.attrsOf
(lib.types.submodule {
options = { options = {
hostNames = lib.mkOption { hostNames = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
description = '' description = ''
@@ -15,18 +26,21 @@ let
Used for automatically trusting hosts for ssh connections. Used for automatically trusting hosts for ssh connections.
''; '';
}; };
arch = lib.mkOption { arch = lib.mkOption {
type = lib.types.enum [ "x86_64-linux" "aarch64-linux" ]; type = lib.types.enum [ "x86_64-linux" "aarch64-linux" ];
description = '' description = ''
The architecture of this machine. The architecture of this machine.
''; '';
}; };
systemRoles = lib.mkOption { systemRoles = lib.mkOption {
type = lib.types.listOf lib.types.str; # TODO: maybe use an enum? type = lib.types.listOf lib.types.str; # TODO: maybe use an enum?
description = '' description = ''
The set of roles this machine holds. Affects secrets available. (TODO add service config as well using this info) The set of roles this machine holds. Affects secrets available. (TODO add service config as well using this info)
''; '';
}; };
hostKey = lib.mkOption { hostKey = lib.mkOption {
type = lib.types.str; type = lib.types.str;
description = '' description = ''
@@ -34,6 +48,7 @@ let
and for decrypting secrets with agenix. and for decrypting secrets with agenix.
''; '';
}; };
remoteUnlock = lib.mkOption { remoteUnlock = lib.mkOption {
default = null; default = null;
type = lib.types.nullOr (lib.types.submodule { type = lib.types.nullOr (lib.types.submodule {
@@ -65,6 +80,7 @@ let
}; };
}); });
}; };
userKeys = lib.mkOption { userKeys = lib.mkOption {
default = [ ]; default = [ ];
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
@@ -74,6 +90,7 @@ let
TODO: consider auto populating other programs that use ssh keys such as gitea TODO: consider auto populating other programs that use ssh keys such as gitea
''; '';
}; };
deployKeys = lib.mkOption { deployKeys = lib.mkOption {
default = [ ]; default = [ ];
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
@@ -81,30 +98,17 @@ let
The list of deployment keys. Each key here can be used to log into all other systems as `root`. The list of deployment keys. Each key here can be used to log into all other systems as `root`.
''; '';
}; };
configurationPath = lib.mkOption { configurationPath = lib.mkOption {
type = lib.types.path; type = lib.types.path;
description = '' description = ''
The path to this machine's configuration directory. The path to this machine's configuration directory.
''; '';
}; };
};
};
in
{
imports = [
./ssh.nix
./roles.nix
];
options.machines = {
hosts = lib.mkOption {
type = lib.types.attrsOf hostOptionsSubmoduleType;
}; };
});
}; };
options.thisMachine.config = lib.mkOption {
# For ease of use, a direct copy of the host config from machines.hosts.${hostName}
type = hostOptionsSubmoduleType;
}; };
config = { config = {
@@ -192,16 +196,5 @@ in
builtins.map (p: { "${dirName p}" = p; }) propFiles; builtins.map (p: { "${dirName p}" = p; }) propFiles;
in in
properties ../../machines; properties ../../machines;
# Don't try to evaluate "thisMachine" when reflecting using moduleless.nix.
# When evaluated by moduleless.nix this will fail due to networking.hostName not
# existing. This is because moduleless.nix is not intended for reflection from the
# perspective of a perticular machine but is instead intended for reflecting on
# the properties of all machines as a whole system.
thisMachine.config = config.machines.hosts.${config.networking.hostName};
# Add ssh keys from KeepassXC
machines.ssh.userKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILACiZO7QnB4bcmziVaUkUE0ZPMR0M/yJbbHYsHIZz9g" ];
machines.ssh.deployKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID58MvKGs3GDMMcN8Iyi9S59SciSrVM97wKtOvUAl3li" ];
}; };
} }

View File

@@ -1,55 +1,19 @@
{ config, lib, ... }: { config, lib, ... }:
# Maps roles to their hosts. # Maps roles to their hosts
# machines.withRole = {
# personal = [
# "machine1" "machine3"
# ];
# cache = [
# "machine2"
# ];
# };
#
# A list of all possible roles
# machines.allRoles = [
# "personal"
# "cache"
# ];
#
# For each role has true or false if the current machine has that role
# thisMachine.hasRole = {
# personal = true;
# cache = false;
# };
{ {
options.machines.withRole = lib.mkOption { options.machines.roles = lib.mkOption {
type = lib.types.attrsOf (lib.types.listOf lib.types.str); type = lib.types.attrsOf (lib.types.listOf lib.types.str);
}; };
options.machines.allRoles = lib.mkOption {
type = lib.types.listOf lib.types.str;
};
options.thisMachine.hasRole = lib.mkOption {
type = lib.types.attrsOf lib.types.bool;
};
config = { config = {
machines.withRole = lib.zipAttrs machines.roles = lib.zipAttrs
(lib.mapAttrsToList (lib.mapAttrsToList
(host: cfg: (host: cfg:
lib.foldl (lib.mergeAttrs) { } lib.foldl (lib.mergeAttrs) { }
(builtins.map (role: { ${role} = host; }) (builtins.map (role: { ${role} = host; })
cfg.systemRoles)) cfg.systemRoles))
config.machines.hosts); config.machines.hosts);
machines.allRoles = lib.attrNames config.machines.withRole;
thisMachine.hasRole = lib.mapAttrs
(role: cfg:
builtins.elem config.networking.hostName config.machines.withRole.${role}
)
config.machines.withRole;
}; };
} }

View File

@@ -39,6 +39,6 @@ in
builtins.map builtins.map
(host: machines.hosts.${host}.hostKey) (host: machines.hosts.${host}.hostKey)
hosts) hosts)
machines.withRole; machines.roles;
}; };
} }

View File

@@ -11,7 +11,6 @@
# TODO implement this module such that the wireguard VPN doesn't have to live in a container # TODO implement this module such that the wireguard VPN doesn't have to live in a container
# TODO don't add forward rules if the PIA port is the same as cfg.forwardedPort # TODO don't add forward rules if the PIA port is the same as cfg.forwardedPort
# TODO verify signatures of PIA responses # TODO verify signatures of PIA responses
# TODO `RuntimeMaxSec = "30d";` for pia-vpn-wireguard-init isn't allowed per the systemd logs. Find alternative.
with builtins; with builtins;
with lib; with lib;
@@ -144,14 +143,14 @@ in
systemd.services.pia-vpn-wireguard-init = { systemd.services.pia-vpn-wireguard-init = {
description = "Creates PIA VPN Wireguard Interface"; description = "Creates PIA VPN Wireguard Interface";
wants = [ "network-online.target" ]; requires = [ "network-online.target" ];
after = [ "network.target" "network-online.target" ]; after = [ "network.target" "network-online.target" ];
before = [ containerServiceName ]; before = [ containerServiceName ];
requiredBy = [ containerServiceName ]; requiredBy = [ containerServiceName ];
partOf = [ containerServiceName ]; partOf = [ containerServiceName ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
path = with pkgs; [ wireguard-tools jq curl iproute2 iputils ]; path = with pkgs; [ wireguard-tools jq curl iproute ];
serviceConfig = { serviceConfig = {
Type = "oneshot"; Type = "oneshot";
@@ -163,11 +162,6 @@ in
}; };
script = '' script = ''
echo Waiting for internet...
while ! ping -c 1 -W 1 1.1.1.1; do
sleep 1
done
# Prepare to connect by generating wg secrets and auth'ing with PIA since the container # Prepare to connect by generating wg secrets and auth'ing with PIA since the container
# cannot do without internet to start with. NAT'ing the host's internet would address this # cannot do without internet to start with. NAT'ing the host's internet would address this
# issue but is not ideal because then leaking network outside of the VPN is more likely. # issue but is not ideal because then leaking network outside of the VPN is more likely.
@@ -220,11 +214,11 @@ in
vpn-container.config.systemd.services.pia-vpn-wireguard = { vpn-container.config.systemd.services.pia-vpn-wireguard = {
description = "Initializes the PIA VPN WireGuard Tunnel"; description = "Initializes the PIA VPN WireGuard Tunnel";
wants = [ "network-online.target" ]; requires = [ "network-online.target" ];
after = [ "network.target" "network-online.target" ]; after = [ "network.target" "network-online.target" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
path = with pkgs; [ wireguard-tools iproute2 curl jq iptables ]; path = with pkgs; [ wireguard-tools iproute curl jq iptables ];
serviceConfig = { serviceConfig = {
Type = "oneshot"; Type = "oneshot";

View File

@@ -72,6 +72,9 @@ in
config = { config = {
imports = allModules ++ [ cfg.config ]; imports = allModules ++ [ cfg.config ];
# speeds up evaluation
nixpkgs.pkgs = pkgs;
# networking.firewall.enable = mkForce false; # networking.firewall.enable = mkForce false;
networking.firewall.trustedInterfaces = [ networking.firewall.trustedInterfaces = [
# completely trust internal interface to host # completely trust internal interface to host

View File

@@ -1,14 +1,18 @@
{ config, lib, ... }: { config, lib, ... }:
let let
builderRole = "nix-builder";
builderUserName = "nix-builder"; builderUserName = "nix-builder";
builderRole = "nix-builder"; machinesByRole = role: lib.filterAttrs (hostname: cfg: builtins.elem role cfg.systemRoles) config.machines.hosts;
builders = config.machines.withRole.${builderRole}; otherMachinesByRole = role: lib.filterAttrs (hostname: cfg: hostname != config.networking.hostName) (machinesByRole role);
thisMachineIsABuilder = config.thisMachine.hasRole.${builderRole}; thisMachineHasRole = role: builtins.hasAttr config.networking.hostName (machinesByRole role);
builders = machinesByRole builderRole;
thisMachineIsABuilder = thisMachineHasRole builderRole;
# builders don't include themselves as a remote builder # builders don't include themselves as a remote builder
otherBuilders = lib.filter (hostname: hostname != config.networking.hostName) builders; otherBuilders = lib.filterAttrs (hostname: cfg: hostname != config.networking.hostName) builders;
in in
lib.mkMerge [ lib.mkMerge [
# configure builder # configure builder
@@ -36,9 +40,9 @@ lib.mkMerge [
nix.distributedBuilds = true; nix.distributedBuilds = true;
nix.buildMachines = builtins.map nix.buildMachines = builtins.map
(builderHostname: { (builderCfg: {
hostName = builderHostname; hostName = builtins.elemAt builderCfg.hostNames 0;
system = config.machines.hosts.${builderHostname}.arch; system = builderCfg.arch;
protocol = "ssh-ng"; protocol = "ssh-ng";
sshUser = builderUserName; sshUser = builderUserName;
sshKey = "/etc/ssh/ssh_host_ed25519_key"; sshKey = "/etc/ssh/ssh_host_ed25519_key";
@@ -46,7 +50,7 @@ lib.mkMerge [
speedFactor = 10; speedFactor = 10;
supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ]; supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ];
}) })
otherBuilders; (builtins.attrValues otherBuilders);
# It is very likely that the builder's internet is faster or just as fast # It is very likely that the builder's internet is faster or just as fast
nix.extraOptions = '' nix.extraOptions = ''

View File

@@ -19,15 +19,6 @@ in
jack.enable = true; jack.enable = true;
}; };
services.pipewire.extraConfig.pipewire."92-fix-wine-audio" = {
context.properties = {
default.clock.rate = 48000;
default.clock.quantum = 256;
default.clock.min-quantum = 256;
default.clock.max-quantum = 2048;
};
};
users.users.googlebot.extraGroups = [ "audio" ]; users.users.googlebot.extraGroups = [ "audio" ];
# bt headset support # bt headset support

View File

@@ -17,6 +17,38 @@ let
"PREFIX=$(out)" "PREFIX=$(out)"
]; ];
}; };
nvidia-vaapi-driver = pkgs.stdenv.mkDerivation rec {
pname = "nvidia-vaapi-driver";
version = "0.0.5";
src = pkgs.fetchFromGitHub {
owner = "elFarto";
repo = pname;
rev = "v${version}";
sha256 = "2bycqKolVoaHK64XYcReteuaON9TjzrFhaG5kty28YY=";
};
patches = [
./use-meson-v57.patch
];
nativeBuildInputs = with pkgs; [
meson
cmake
ninja
pkg-config
];
buildInputs = with pkgs; [
nv-codec-headers-11-1-5-1
libva
gst_all_1.gstreamer
gst_all_1.gst-plugins-bad
libglvnd
];
};
in in
{ {
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
@@ -46,23 +78,27 @@ in
# hardware accelerated video playback (on intel) # hardware accelerated video playback (on intel)
nixpkgs.config.packageOverrides = pkgs: { nixpkgs.config.packageOverrides = pkgs: {
vaapiIntel = pkgs.vaapiIntel.override { enableHybridCodec = true; };
chromium = pkgs.chromium.override { chromium = pkgs.chromium.override {
enableWideVine = true; enableWideVine = true;
# ungoogled = true; # ungoogled = true;
# --enable-native-gpu-memory-buffers # fails on AMD APU # --enable-native-gpu-memory-buffers # fails on AMD APU
# --enable-webrtc-vp9-support # --enable-webrtc-vp9-support
commandLineArgs = "--use-vulkan"; commandLineArgs = "--use-vulkan --use-gl=desktop --enable-zero-copy --enable-hardware-overlays --enable-features=VaapiVideoDecoder,CanvasOopRasterization --ignore-gpu-blocklist --enable-accelerated-mjpeg-decode --enable-accelerated-video --enable-gpu-rasterization";
}; };
}; };
# todo vulkan in chrome # todo vulkan in chrome
# todo video encoding in chrome # todo video encoding in chrome
hardware.graphics = { hardware.opengl = {
enable = true; enable = true;
extraPackages = with pkgs; [ extraPackages = with pkgs; [
intel-media-driver # LIBVA_DRIVER_NAME=iHD intel-media-driver # LIBVA_DRIVER_NAME=iHD
vaapiIntel # LIBVA_DRIVER_NAME=i965 (older but works better for Firefox/Chromium)
# vaapiVdpau
libvdpau-va-gl libvdpau-va-gl
nvidia-vaapi-driver nvidia-vaapi-driver
]; ];
extraPackages32 = with pkgs.pkgsi686Linux; [ vaapiIntel ];
}; };
}; };
} }

View File

@@ -6,18 +6,19 @@ in
{ {
imports = [ imports = [
./kde.nix ./kde.nix
./xfce.nix
./yubikey.nix ./yubikey.nix
./chromium.nix ./chromium.nix
./firefox.nix # ./firefox.nix
./audio.nix ./audio.nix
# ./torbrowser.nix
./pithos.nix ./pithos.nix
./spotify.nix
./vscodium.nix ./vscodium.nix
./discord.nix ./discord.nix
./steam.nix ./steam.nix
./touchpad.nix ./touchpad.nix
./mount-samba.nix ./mount-samba.nix
./udev.nix
./virtualisation.nix
]; ];
options.de = { options.de = {
@@ -25,10 +26,9 @@ in
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; [ # vulkan
# https://github.com/NixOS/nixpkgs/pull/328086#issuecomment-2235384618 hardware.opengl.driSupport = true;
gparted hardware.opengl.driSupport32Bit = true;
];
# Applications # Applications
users.users.googlebot.packages = with pkgs; [ users.users.googlebot.packages = with pkgs; [
@@ -41,22 +41,21 @@ in
mpv mpv
nextcloud-client nextcloud-client
signal-desktop signal-desktop
minecraft
gparted
libreoffice-fresh libreoffice-fresh
thunderbird thunderbird
spotify spotifyd
spotify-qt
arduino arduino
yt-dlp yt-dlp
jellyfin-media-player
joplin-desktop joplin-desktop
config.inputs.deploy-rs.packages.${config.currentSystem}.deploy-rs config.inputs.deploy-rs.packages.${config.currentSystem}.deploy-rs
lxqt.pavucontrol-qt
deskflow
file-roller
android-tools
# For Nix IDE # For Nix IDE
nixpkgs-fmt nixpkgs-fmt
nixd rnix-lsp
nil
]; ];
# Networking # Networking
@@ -70,29 +69,12 @@ in
]; ];
# Printer discovery # Printer discovery
services.avahi.enable = true; services.avahi.enable = true;
services.avahi.nssmdns4 = true; services.avahi.nssmdns = true;
programs.file-roller.enable = true;
# Security # Security
services.gnome.gnome-keyring.enable = true; services.gnome.gnome-keyring.enable = true;
security.pam.services.googlebot.enableGnomeKeyring = true; security.pam.services.googlebot.enableGnomeKeyring = true;
# Mount personal SMB stores
services.mount-samba.enable = true;
# allow building ARM derivations
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
# for luks onlock over tor
services.tor.enable = true;
services.tor.client.enable = true;
# Enable wayland support in various chromium based applications
environment.sessionVariables.NIXOS_OZONE_WL = "1";
fonts.packages = with pkgs; [ nerd-fonts.symbols-only ];
# SSH Ask pass
programs.ssh.enableAskPassword = true;
programs.ssh.askPassword = "${pkgs.kdePackages.ksshaskpass}/bin/ksshaskpass";
}; };
} }

View File

@@ -20,6 +20,31 @@ let
}; };
firefox = pkgs.wrapFirefox somewhatPrivateFF { firefox = pkgs.wrapFirefox somewhatPrivateFF {
desktopName = "Sneed Browser";
nixExtensions = [
(pkgs.fetchFirefoxAddon {
name = "ublock-origin";
url = "https://addons.mozilla.org/firefox/downloads/file/3719054/ublock_origin-1.33.2-an+fx.xpi";
sha256 = "XDpe9vW1R1iVBTI4AmNgAg1nk7BVQdIAMuqd0cnK5FE=";
})
(pkgs.fetchFirefoxAddon {
name = "sponsorblock";
url = "https://addons.mozilla.org/firefox/downloads/file/3720594/sponsorblock_skip_sponsorships_on_youtube-2.0.12.3-an+fx.xpi";
sha256 = "HRtnmZWyXN3MKo4AvSYgNJGkBEsa2RaMamFbkz+YzQg=";
})
(pkgs.fetchFirefoxAddon {
name = "KeePassXC-Browser";
url = "https://addons.mozilla.org/firefox/downloads/file/3720664/keepassxc_browser-1.7.6-fx.xpi";
sha256 = "3K404/eq3amHhIT0WhzQtC892he5I0kp2SvbzE9dbZg=";
})
(pkgs.fetchFirefoxAddon {
name = "https-everywhere";
url = "https://addons.mozilla.org/firefox/downloads/file/3716461/https_everywhere-2021.1.27-an+fx.xpi";
sha256 = "2gSXSLunKCwPjAq4Wsj0lOeV551r3G+fcm1oeqjMKh8=";
})
];
extraPolicies = { extraPolicies = {
CaptivePortal = false; CaptivePortal = false;
DisableFirefoxStudies = true; DisableFirefoxStudies = true;
@@ -49,6 +74,12 @@ let
ExtensionRecommendations = false; ExtensionRecommendations = false;
SkipOnboarding = true; SkipOnboarding = true;
}; };
WebsiteFilter = {
Block = [
"http://paradigminteractive.io/"
"https://paradigminteractive.io/"
];
};
}; };
extraPrefs = '' extraPrefs = ''

View File

@@ -5,17 +5,20 @@ let
in in
{ {
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.displayManager.sddm.enable = true; # kde plasma
services.displayManager.sddm.wayland.enable = true; services.xserver = {
services.desktopManager.plasma6.enable = true; enable = true;
desktopManager.plasma5.enable = true;
displayManager.sddm.enable = true;
};
# kde apps # kde apps
nixpkgs.config.firefox.enablePlasmaBrowserIntegration = true;
users.users.googlebot.packages = with pkgs; [ users.users.googlebot.packages = with pkgs; [
# akonadi # akonadi
# kmail # kmail
# plasma5Packages.kmail-account-wizard # plasma5Packages.kmail-account-wizard
kdePackages.kate kate
kdePackages.kdeconnect-kde
]; ];
}; };
} }

View File

@@ -13,8 +13,6 @@ let
auth_opts = "sec=ntlmv2i,credentials=/run/agenix/smb-secrets"; auth_opts = "sec=ntlmv2i,credentials=/run/agenix/smb-secrets";
version_opts = "vers=3.1.1"; version_opts = "vers=3.1.1";
public_user_opts = "gid=${toString config.users.groups.users.gid}";
opts = "${systemd_opts},${network_opts},${user_opts},${version_opts},${auth_opts}"; opts = "${systemd_opts},${network_opts},${user_opts},${version_opts},${auth_opts}";
in in
{ {
@@ -26,7 +24,7 @@ in
fileSystems."/mnt/public" = { fileSystems."/mnt/public" = {
device = "//s0.koi-bebop.ts.net/public"; device = "//s0.koi-bebop.ts.net/public";
fsType = "cifs"; fsType = "cifs";
options = [ "${opts},${public_user_opts}" ]; options = [ opts ];
}; };
fileSystems."/mnt/private" = { fileSystems."/mnt/private" = {

86
common/pc/spotify.nix Normal file
View File

@@ -0,0 +1,86 @@
{ lib, config, pkgs, ... }:
with lib;
let
cfg = config.services.spotifyd;
toml = pkgs.formats.toml { };
spotifydConf = toml.generate "spotify.conf" cfg.settings;
in
{
disabledModules = [
"services/audio/spotifyd.nix"
];
options = {
services.spotifyd = {
enable = mkEnableOption "spotifyd, a Spotify playing daemon";
settings = mkOption {
default = { };
type = toml.type;
example = { global.bitrate = 320; };
description = ''
Configuration for Spotifyd. For syntax and directives, see
<link xlink:href="https://github.com/Spotifyd/spotifyd#Configuration"/>.
'';
};
users = mkOption {
type = with types; listOf str;
default = [ ];
description = ''
Usernames to be added to the "spotifyd" group, so that they
can start and interact with the userspace daemon.
'';
};
};
};
config = mkIf cfg.enable {
# username specific stuff because i'm lazy...
services.spotifyd.users = [ "googlebot" ];
users.users.googlebot.packages = with pkgs; [
spotify
spotify-tui
];
users.groups.spotifyd = {
members = cfg.users;
};
age.secrets.spotifyd = {
file = ../../secrets/spotifyd.age;
group = "spotifyd";
mode = "0440"; # group can read
};
# spotifyd to read secrets and run as user service
services.spotifyd = {
settings.global = {
username_cmd = "sed '1q;d' /run/agenix/spotifyd";
password_cmd = "sed '2q;d' /run/agenix/spotifyd";
bitrate = 320;
backend = "pulseaudio";
device_name = config.networking.hostName;
device_type = "computer";
# on_song_change_hook = "command_to_run_on_playback_events"
autoplay = true;
};
};
systemd.user.services.spotifyd-daemon = {
enable = true;
wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
description = "spotifyd, a Spotify playing daemon";
environment.SHELL = "/bin/sh";
serviceConfig = {
ExecStart = "${pkgs.spotifyd}/bin/spotifyd --no-daemon --config-path ${spotifydConf}";
Restart = "always";
CacheDirectory = "spotifyd";
};
};
};
}

25
common/pc/torbrowser.nix Normal file
View File

@@ -0,0 +1,25 @@
{ lib, config, pkgs, ... }:
let
cfg = config.de;
in
{
config = lib.mkIf cfg.enable {
nixpkgs.overlays = [
(self: super: {
tor-browser-bundle-bin = super.tor-browser-bundle-bin.overrideAttrs (old: rec {
version = "10.0.10";
lang = "en-US";
src = pkgs.fetchurl {
url = "https://dist.torproject.org/torbrowser/${version}/tor-browser-linux64-${version}_${lang}.tar.xz";
sha256 = "vYWZ+NsGN8YH5O61+zrUjlFv3rieaBqjBQ+a18sQcZg=";
};
});
})
];
users.users.googlebot.packages = with pkgs; [
tor-browser-bundle-bin
];
};
}

View File

@@ -1,11 +1,15 @@
{ lib, config, pkgs, ... }: { lib, config, pkgs, ... }:
let let
cfg = config.de; cfg = config.de.touchpad;
in in
{ {
options.de.touchpad = {
enable = lib.mkEnableOption "enable touchpad";
};
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.libinput.enable = true; services.xserver.libinput.enable = true;
services.libinput.touchpad.naturalScrolling = true; services.xserver.libinput.touchpad.naturalScrolling = true;
}; };
} }

View File

@@ -1,25 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.de;
in
{
config = lib.mkIf cfg.enable {
services.udev.extraRules = ''
# depthai
SUBSYSTEM=="usb", ATTRS{idVendor}=="03e7", MODE="0666"
# Moonlander
# Rules for Oryx web flashing and live training
KERNEL=="hidraw*", ATTRS{idVendor}=="16c0", MODE="0664", GROUP="plugdev"
KERNEL=="hidraw*", ATTRS{idVendor}=="3297", MODE="0664", GROUP="plugdev"
# Wally Flashing rules for the Moonlander and Planck EZ
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE:="0666", SYMLINK+="stm32_dfu"
'';
services.udev.packages = [ pkgs.platformio ];
users.groups.plugdev = {
members = [ "googlebot" ];
};
};
}

View File

@@ -0,0 +1,22 @@
diff --git a/meson.build b/meson.build
index dace367..8c0e290 100644
--- a/meson.build
+++ b/meson.build
@@ -8,7 +8,7 @@ project(
'warning_level=0',
],
license: 'MIT',
- meson_version: '>= 0.58.0',
+ meson_version: '>= 0.57.0',
)
cc = meson.get_compiler('c')
@@ -47,8 +47,3 @@ shared_library(
gnu_symbol_visibility: 'hidden',
)
-meson.add_devenv(environment({
- 'NVD_LOG': '1',
- 'LIBVA_DRIVER_NAME': 'nvidia',
- 'LIBVA_DRIVERS_PATH': meson.project_build_root(),
-}))

View File

@@ -1,23 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.de;
in
{
config = lib.mkIf cfg.enable {
# AppVMs
virtualisation.appvm.enable = true;
virtualisation.appvm.user = "googlebot";
# Use podman instead of docker
virtualisation.podman.enable = true;
virtualisation.podman.dockerCompat = true;
# virt-manager
virtualisation.libvirtd.enable = true;
programs.dconf.enable = true;
virtualisation.spiceUSBRedirection.enable = true;
environment.systemPackages = with pkgs; [ virt-manager ];
users.users.googlebot.extraGroups = [ "libvirtd" "adbusers" ];
};
}

View File

@@ -10,18 +10,12 @@ let
dart-code.flutter dart-code.flutter
golang.go golang.go
jnoortheen.nix-ide jnoortheen.nix-ide
ms-vscode.cpptools
rust-lang.rust-analyzer
vadimcn.vscode-lldb
tauri-apps.tauri-vscode
platformio.platformio-vscode-ide
vue.volar
] ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [ ] ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [
{ {
name = "wgsl-analyzer"; name = "platformio-ide";
publisher = "wgsl-analyzer"; publisher = "platformio";
version = "0.12.105"; version = "3.1.1";
sha256 = "sha256-NheEVNIa8CIlyMebAhxRKS44b1bZiWVt8PgC6r3ExMA="; sha256 = "fwEct7Tj8bfTOLRozSZJGWoLzWRSvYz/KxcnfpO8Usg=";
} }
]; ];

23
common/pc/xfce.nix Normal file
View File

@@ -0,0 +1,23 @@
{ lib, config, pkgs, ... }:
let
cfg = config.de;
in
{
config = lib.mkIf cfg.enable {
services.xserver = {
enable = true;
desktopManager = {
xterm.enable = false;
xfce.enable = true;
};
displayManager.sddm.enable = true;
};
# xfce apps
# TODO for some reason whiskermenu needs to be global for it to work
environment.systemPackages = with pkgs; [
xfce.xfce4-whiskermenu-plugin
];
};
}

View File

@@ -1,16 +0,0 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.actual;
in
{
config = lib.mkIf cfg.enable {
services.actual.settings = {
port = 25448;
};
backup.group."actual-budget".paths = [
"/var/lib/actual"
];
};
}

View File

@@ -10,15 +10,14 @@
./matrix.nix ./matrix.nix
./zerobin.nix ./zerobin.nix
./gitea.nix ./gitea.nix
./gitea-runner.nix
./privatebin/privatebin.nix
./radio.nix
./samba.nix ./samba.nix
./owncast.nix ./owncast.nix
./mailserver.nix ./mailserver.nix
./nextcloud.nix ./nextcloud.nix
./iodine.nix ./iodine.nix
./searx.nix ./searx.nix
./gitea-actions-runner.nix
./librechat.nix
./actualbudget.nix
./unifi.nix
]; ];
} }

View File

@@ -1,133 +0,0 @@
{ config, pkgs, lib, allModules, ... }:
# Gitea Actions Runner. Starts 'host' runner that runs directly on the host inside of a nixos container
# This is useful for providing a real Nix/OS builder to gitea.
# Warning, NixOS containers are not secure. For example, the container shares the /nix/store
# Therefore, this should not be used to run untrusted code.
# To enable, assign a machine the 'gitea-actions-runner' system role
# TODO: skipping running inside of nixos container for now because of issues getting docker/podman running
let
thisMachineIsARunner = config.thisMachine.hasRole."gitea-actions-runner";
containerName = "gitea-runner";
in
{
config = lib.mkIf (thisMachineIsARunner && !config.boot.isContainer) {
# containers.${containerName} = {
# ephemeral = true;
# autoStart = true;
# # for podman
# enableTun = true;
# # privateNetwork = true;
# # hostAddress = "172.16.101.1";
# # localAddress = "172.16.101.2";
# bindMounts =
# {
# "/run/agenix/gitea-actions-runner-token" = {
# hostPath = "/run/agenix/gitea-actions-runner-token";
# isReadOnly = true;
# };
# "/var/lib/gitea-runner" = {
# hostPath = "/var/lib/gitea-runner";
# isReadOnly = false;
# };
# };
# extraFlags = [
# # Allow podman
# ''--system-call-filter=thisystemcalldoesnotexistforsure''
# ];
# additionalCapabilities = [
# "CAP_SYS_ADMIN"
# ];
# config = {
# imports = allModules;
# # speeds up evaluation
# nixpkgs.pkgs = pkgs;
# networking.hostName = lib.mkForce containerName;
# # don't use remote builders
# nix.distributedBuilds = lib.mkForce false;
# environment.systemPackages = with pkgs; [
# git
# # Gitea Actions rely heavily on node. Include it because it would be installed anyway.
# nodejs
# ];
# services.gitea-actions-runner.instances.inst = {
# enable = true;
# name = config.networking.hostName;
# url = "https://git.neet.dev/";
# tokenFile = "/run/agenix/gitea-actions-runner-token";
# labels = [
# "ubuntu-latest:docker://node:18-bullseye"
# "nixos:host"
# ];
# };
# # To allow building on the host, must override the the service's config so it doesn't use a dynamic user
# systemd.services.gitea-runner-inst.serviceConfig.DynamicUser = lib.mkForce false;
# users.users.gitea-runner = {
# home = "/var/lib/gitea-runner";
# group = "gitea-runner";
# isSystemUser = true;
# createHome = true;
# };
# users.groups.gitea-runner = { };
# virtualisation.podman.enable = true;
# boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
# };
# };
# networking.nat.enable = true;
# networking.nat.internalInterfaces = [
# "ve-${containerName}"
# ];
# networking.ip_forward = true;
# don't use remote builders
nix.distributedBuilds = lib.mkForce false;
services.gitea-actions-runner.instances.inst = {
enable = true;
name = config.networking.hostName;
url = "https://git.neet.dev/";
tokenFile = "/run/agenix/gitea-actions-runner-token";
labels = [
"ubuntu-latest:docker://node:18-bullseye"
"nixos:host"
];
};
environment.systemPackages = with pkgs; [
git
# Gitea Actions rely heavily on node. Include it because it would be installed anyway.
nodejs
];
# To allow building on the host, must override the the service's config so it doesn't use a dynamic user
systemd.services.gitea-runner-inst.serviceConfig.DynamicUser = lib.mkForce false;
users.users.gitea-runner = {
home = "/var/lib/gitea-runner";
group = "gitea-runner";
isSystemUser = true;
createHome = true;
};
users.groups.gitea-runner = { };
virtualisation.podman.enable = true;
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
age.secrets.gitea-actions-runner-token.file = ../../secrets/gitea-actions-runner-token.age;
};
}

View File

@@ -0,0 +1,52 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.gitea-runner;
in
{
options.services.gitea-runner = {
enable = lib.mkEnableOption "Enables gitea runner";
dataDir = lib.mkOption {
default = "/var/lib/gitea-runner";
type = lib.types.str;
description = lib.mdDoc "gitea runner data directory.";
};
};
config = lib.mkIf cfg.enable {
virtualisation.docker.enable = true;
users.users.gitea-runner = {
description = "Gitea Runner Service";
home = cfg.dataDir;
useDefaultShell = true;
group = "gitea-runner";
isSystemUser = true;
createHome = true;
extraGroups = [
"docker" # allow creating docker containers
];
};
users.groups.gitea-runner = { };
systemd.services.gitea-runner = {
description = "Gitea Runner";
serviceConfig = {
WorkingDirectory = cfg.dataDir;
User = "gitea-runner";
Group = "gitea-runner";
};
requires = [ "network-online.target" ];
after = [ "network.target" "network-online.target" ];
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ gitea-actions-runner ];
script = ''
exec act_runner daemon
'';
};
};
}

View File

@@ -12,28 +12,23 @@ in
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.gitea = { services.gitea = {
domain = cfg.hostname;
rootUrl = "https://${cfg.hostname}/";
appName = cfg.hostname; appName = cfg.hostname;
lfs.enable = true; # lfs.enable = true;
# dump.enable = true; # dump.enable = true;
settings = { settings = {
server = {
ROOT_URL = "https://${cfg.hostname}/";
DOMAIN = cfg.hostname;
};
other = { other = {
SHOW_FOOTER_VERSION = false; SHOW_FOOTER_VERSION = false;
}; };
ui = { ui = {
DEFAULT_THEME = "gitea-dark"; DEFAULT_THEME = "arc-green";
}; };
service = { service = {
DISABLE_REGISTRATION = true; DISABLE_REGISTRATION = true;
}; };
session = { session = {
COOKIE_SECURE = true; COOKIE_SECURE = true;
PROVIDER = "db";
SESSION_LIFE_TIME = 259200; # 3 days
GC_INTERVAL_TIME = 259200; # 3 days
}; };
mailer = { mailer = {
ENABLED = true; ENABLED = true;
@@ -47,9 +42,6 @@ in
actions = { actions = {
ENABLED = true; ENABLED = true;
}; };
indexer = {
REPO_INDEXER_ENABLED = true;
};
}; };
mailerPasswordFile = "/run/agenix/robots-email-pw"; mailerPasswordFile = "/run/agenix/robots-email-pw";
}; };
@@ -68,7 +60,7 @@ in
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
locations."/" = { locations."/" = {
proxyPass = "http://localhost:${toString cfg.settings.server.HTTP_PORT}"; proxyPass = "http://localhost:${toString cfg.httpPort}";
}; };
}; };
}; };

View File

@@ -1,69 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.librechat-container;
in
{
options.services.librechat-container = {
enable = mkEnableOption "librechat";
port = mkOption {
type = types.int;
default = 3080;
};
host = lib.mkOption {
type = lib.types.str;
example = "example.com";
};
};
config = mkIf cfg.enable {
virtualisation.oci-containers.containers = {
librechat = {
image = "ghcr.io/danny-avila/librechat:v0.8.1";
environment = {
HOST = "0.0.0.0";
MONGO_URI = "mongodb://host.containers.internal:27017/LibreChat";
ENDPOINTS = "openAI,google,bingAI,gptPlugins";
OPENAI_MODELS = lib.concatStringsSep "," [
"gpt-4o-mini"
"o3-mini"
"gpt-4o"
"o1"
];
REFRESH_TOKEN_EXPIRY = toString (1000 * 60 * 60 * 24 * 30); # 30 days
};
environmentFiles = [
"/run/agenix/librechat-env-file"
];
ports = [
"${toString cfg.port}:3080"
];
};
};
age.secrets.librechat-env-file.file = ../../secrets/librechat-env-file.age;
services.mongodb.enable = true;
services.mongodb.bind_ip = "0.0.0.0";
# easier podman maintenance
virtualisation.oci-containers.backend = "podman";
virtualisation.podman.dockerSocket.enable = true;
virtualisation.podman.dockerCompat = true;
# For mongodb access
networking.firewall.trustedInterfaces = [
"podman0" # for librechat
];
services.nginx.virtualHosts.${cfg.host} = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:${toString cfg.port}";
proxyWebsockets = true;
};
};
};
}

View File

@@ -28,6 +28,7 @@ in
indexDir = "/var/lib/mailindex"; indexDir = "/var/lib/mailindex";
enableManageSieve = true; enableManageSieve = true;
fullTextSearch.enable = true; fullTextSearch.enable = true;
fullTextSearch.indexAttachments = true;
fullTextSearch.memoryLimit = 500; fullTextSearch.memoryLimit = 500;
inherit domains; inherit domains;
loginAccounts = { loginAccounts = {
@@ -54,8 +55,6 @@ in
"joslyn@runyan.org" "joslyn@runyan.org"
"damon@runyan.org" "damon@runyan.org"
"jonas@runyan.org" "jonas@runyan.org"
"simon@neet.dev"
"ellen@runyan.org"
]; ];
forwards = { forwards = {
"amazon@runyan.org" = [ "amazon@runyan.org" = [
@@ -63,28 +62,18 @@ in
"cris@runyan.org" "cris@runyan.org"
]; ];
}; };
x509.useACMEHost = config.mailserver.fqdn; # use let's encrypt for certs certificateScheme = 3; # use let's encrypt for certs
stateVersion = 3;
}; };
age.secrets.hashed-email-pw.file = ../../secrets/hashed-email-pw.age; age.secrets.hashed-email-pw.file = ../../secrets/hashed-email-pw.age;
age.secrets.cris-hashed-email-pw.file = ../../secrets/cris-hashed-email-pw.age; age.secrets.cris-hashed-email-pw.file = ../../secrets/cris-hashed-email-pw.age;
age.secrets.hashed-robots-email-pw.file = ../../secrets/hashed-robots-email-pw.age; age.secrets.hashed-robots-email-pw.file = ../../secrets/hashed-robots-email-pw.age;
# Get let's encrypt cert
services.nginx = {
enable = true;
virtualHosts."${config.mailserver.fqdn}" = {
forceSSL = true;
enableACME = true;
};
};
# sendmail to use xxx@domain instead of xxx@mail.domain # sendmail to use xxx@domain instead of xxx@mail.domain
services.postfix.settings.main.myorigin = "$mydomain"; services.postfix.origin = "$mydomain";
# relay sent mail through mailgun # relay sent mail through mailgun
# https://www.howtoforge.com/community/threads/different-smtp-relays-for-different-domains-in-postfix.82711/#post-392620 # https://www.howtoforge.com/community/threads/different-smtp-relays-for-different-domains-in-postfix.82711/#post-392620
services.postfix.settings.main = { services.postfix.config = {
smtp_sasl_auth_enable = "yes"; smtp_sasl_auth_enable = "yes";
smtp_sasl_security_options = "noanonymous"; smtp_sasl_security_options = "noanonymous";
smtp_sasl_password_maps = "hash:/var/lib/postfix/conf/sasl_relay_passwd"; smtp_sasl_password_maps = "hash:/var/lib/postfix/conf/sasl_relay_passwd";
@@ -102,6 +91,7 @@ in
age.secrets.sasl_relay_passwd.file = ../../secrets/sasl_relay_passwd.age; age.secrets.sasl_relay_passwd.file = ../../secrets/sasl_relay_passwd.age;
# webmail # webmail
services.nginx.enable = true;
services.roundcube = { services.roundcube = {
enable = true; enable = true;
hostName = config.mailserver.fqdn; hostName = config.mailserver.fqdn;

View File

@@ -3,44 +3,18 @@
let let
cfg = config.services.nextcloud; cfg = config.services.nextcloud;
nextcloudHostname = "runyan.org";
collaboraOnlineHostname = "collabora.runyan.org";
whiteboardHostname = "whiteboard.runyan.org";
whiteboardPort = 3002; # Seems impossible to change
# Hardcoded public ip of ponyo... I wish I didn't need this...
public_ip_address = "147.135.114.130";
in in
{ {
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.nextcloud = { services.nextcloud = {
https = true; https = true;
package = pkgs.nextcloud32; package = pkgs.nextcloud25;
hostName = nextcloudHostname; hostName = "neet.cloud";
config.dbtype = "sqlite"; config.dbtype = "sqlite";
config.adminuser = "jeremy"; config.adminuser = "jeremy";
config.adminpassFile = "/run/agenix/nextcloud-pw"; config.adminpassFile = "/run/agenix/nextcloud-pw";
# Apps
autoUpdateApps.enable = true; autoUpdateApps.enable = true;
extraAppsEnable = true; enableBrokenCiphersForSSE = false;
extraApps = with config.services.nextcloud.package.packages.apps; {
# Want
inherit end_to_end_encryption mail spreed;
# For file and document editing (collabora online and excalidraw)
inherit richdocuments whiteboard;
# Might use
inherit calendar qownnotesapi;
# Try out
# inherit bookmarks cookbook deck memories maps music news notes phonetrack polls forms;
};
# Allows installing Apps from the UI (might remove later)
appstoreEnable = true;
}; };
age.secrets.nextcloud-pw = { age.secrets.nextcloud-pw = {
file = ../../secrets/nextcloud-pw.age; file = ../../secrets/nextcloud-pw.age;
@@ -56,100 +30,5 @@ in
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
}; };
# collabora-online
# https://diogotc.com/blog/collabora-nextcloud-nixos/
services.collabora-online = {
enable = true;
port = 15972;
settings = {
# Rely on reverse proxy for SSL
ssl = {
enable = false;
termination = true;
};
# Listen on loopback interface only
net = {
listen = "loopback";
post_allow.host = [ "localhost" ];
};
# Restrict loading documents from WOPI Host
storage.wopi = {
"@allow" = true;
host = [ config.services.nextcloud.hostName ];
};
server_name = collaboraOnlineHostname;
};
};
services.nginx.virtualHosts.${config.services.collabora-online.settings.server_name} = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.collabora-online.port}";
proxyWebsockets = true;
};
};
systemd.services.nextcloud-config-collabora =
let
wopi_url = "http://localhost:${toString config.services.collabora-online.port}";
public_wopi_url = "https://${collaboraOnlineHostname}";
wopi_allowlist = lib.concatStringsSep "," [
"127.0.0.1"
"::1"
public_ip_address
];
in
{
wantedBy = [ "multi-user.target" ];
after = [ "nextcloud-setup.service" "coolwsd.service" ];
requires = [ "coolwsd.service" ];
path = [
config.services.nextcloud.occ
];
script = ''
nextcloud-occ -- config:app:set richdocuments wopi_url --value ${lib.escapeShellArg wopi_url}
nextcloud-occ -- config:app:set richdocuments public_wopi_url --value ${lib.escapeShellArg public_wopi_url}
nextcloud-occ -- config:app:set richdocuments wopi_allowlist --value ${lib.escapeShellArg wopi_allowlist}
nextcloud-occ -- richdocuments:setup
'';
serviceConfig = {
Type = "oneshot";
};
};
# Whiteboard
services.nextcloud-whiteboard-server = {
enable = true;
settings.NEXTCLOUD_URL = "https://${nextcloudHostname}";
secrets = [ "/run/agenix/whiteboard-server-jwt-secret" ];
};
systemd.services.nextcloud-config-whiteboard = {
wantedBy = [ "multi-user.target" ];
after = [ "nextcloud-setup.service" ];
requires = [ "coolwsd.service" ];
path = [
config.services.nextcloud.occ
];
script = ''
nextcloud-occ -- config:app:set whiteboard collabBackendUrl --value="https://${whiteboardHostname}"
nextcloud-occ -- config:app:set whiteboard jwt_secret_key --value="$JWT_SECRET_KEY"
'';
serviceConfig = {
Type = "oneshot";
EnvironmentFile = [ "/run/agenix/whiteboard-server-jwt-secret" ];
};
};
age.secrets.whiteboard-server-jwt-secret.file = ../../secrets/whiteboard-server-jwt-secret.age;
services.nginx.virtualHosts.${whiteboardHostname} = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:${toString whiteboardPort}";
proxyWebsockets = true;
};
};
}; };
} }

View File

@@ -4,10 +4,6 @@ let
cfg = config.services.nginx; cfg = config.services.nginx;
in in
{ {
options.services.nginx = {
openFirewall = lib.mkEnableOption "Open firewall ports 80 and 443";
};
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.nginx = { services.nginx = {
recommendedGzipSettings = true; recommendedGzipSettings = true;
@@ -16,8 +12,6 @@ in
recommendedTlsSettings = true; recommendedTlsSettings = true;
}; };
services.nginx.openFirewall = lib.mkDefault true; networking.firewall.allowedTCPPorts = [ 80 443 ];
networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ 80 443 ];
}; };
} }

View File

@@ -0,0 +1,42 @@
;<?php http_response_code(403); /*
[main]
name = "Kode Paste"
discussion = false
opendiscussion = false
password = true
fileupload = false
burnafterreadingselected = false
defaultformatter = "plaintext"
sizelimit = 10485760
template = "bootstrap"
languageselection = false
[expire]
default = "1week"
[expire_options]
5min = 300
10min = 600
1hour = 3600
1day = 86400
1week = 604800
[formatter_options]
plaintext = "Plain Text"
syntaxhighlighting = "Source Code"
markdown = "Markdown"
[traffic]
limit = 10
dir = "/var/lib/privatebin"
[purge]
limit = 300
batchsize = 10
dir = "/var/lib/privatebin"
[model]
class = Filesystem
[model_options]
dir = "/var/lib/privatebin"

View File

@@ -0,0 +1,74 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.privatebin;
privateBinSrc = pkgs.stdenv.mkDerivation {
name = "privatebin";
src = pkgs.fetchFromGitHub {
owner = "privatebin";
repo = "privatebin";
rev = "d65bf02d7819a530c3c2a88f6f9947651fe5258d";
sha256 = "7ttAvEDL1ab0cUZcqZzXFkXwB2rF2t4eNpPxt48ap94=";
};
installPhase = ''
cp -ar $src $out
'';
};
in
{
options.services.privatebin = {
enable = lib.mkEnableOption "enable privatebin";
host = lib.mkOption {
type = lib.types.str;
example = "example.com";
};
};
config = lib.mkIf cfg.enable {
users.users.privatebin = {
description = "privatebin service user";
group = "privatebin";
isSystemUser = true;
};
users.groups.privatebin = { };
services.nginx.enable = true;
services.nginx.virtualHosts.${cfg.host} = {
enableACME = true;
forceSSL = true;
locations."/" = {
root = privateBinSrc;
index = "index.php";
};
locations."~ \.php$" = {
root = privateBinSrc;
extraConfig = ''
fastcgi_pass unix:${config.services.phpfpm.pools.privatebin.socket};
fastcgi_index index.php;
'';
};
};
systemd.tmpfiles.rules = [
"d '/var/lib/privatebin' 0750 privatebin privatebin - -"
];
services.phpfpm.pools.privatebin = {
user = "privatebin";
group = "privatebin";
phpEnv = {
CONFIG_PATH = "${./conf.php}";
};
settings = {
pm = "dynamic";
"listen.owner" = config.services.nginx.user;
"pm.max_children" = 5;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 1;
"pm.max_spare_servers" = 3;
"pm.max_requests" = 500;
};
};
};
}

75
common/server/radio.nix Normal file
View File

@@ -0,0 +1,75 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.radio;
radioPackage = config.inputs.radio.packages.${config.currentSystem}.radio;
in
{
options.services.radio = {
enable = lib.mkEnableOption "enable radio";
user = lib.mkOption {
type = lib.types.str;
default = "radio";
description = ''
The user radio should run as
'';
};
group = lib.mkOption {
type = lib.types.str;
default = "radio";
description = ''
The group radio should run as
'';
};
dataDir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/radio";
description = ''
Path to the radio data directory
'';
};
host = lib.mkOption {
type = lib.types.str;
description = ''
Domain radio is hosted on
'';
};
nginx = lib.mkEnableOption "enable nginx";
};
config = lib.mkIf cfg.enable {
services.icecast = {
enable = true;
hostname = cfg.host;
mount = "stream.mp3";
fallback = "fallback.mp3";
};
services.nginx.virtualHosts.${cfg.host} = lib.mkIf cfg.nginx {
enableACME = true;
forceSSL = true;
locations."/".root = config.inputs.radio-web;
};
users.users.${cfg.user} = {
isSystemUser = true;
group = cfg.group;
home = cfg.dataDir;
createHome = true;
};
users.groups.${cfg.group} = { };
systemd.services.radio = {
enable = true;
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.ExecStart = "${radioPackage}/bin/radio ${config.services.icecast.listen.address}:${toString config.services.icecast.listen.port} ${config.services.icecast.mount} 5500";
serviceConfig.User = cfg.user;
serviceConfig.Group = cfg.group;
serviceConfig.WorkingDirectory = cfg.dataDir;
preStart = ''
mkdir -p ${cfg.dataDir}
chown ${cfg.user} ${cfg.dataDir}
'';
};
};
}

View File

@@ -5,28 +5,30 @@
services.samba = { services.samba = {
openFirewall = true; openFirewall = true;
package = pkgs.sambaFull; # printer sharing package = pkgs.sambaFull; # printer sharing
securityType = "user";
# should this be on? # should this be on?
nsswins = true; nsswins = true;
settings = { extraConfig = ''
global = { workgroup = HOME
security = "user"; server string = smbnix
workgroup = "HOME"; netbios name = smbnix
"server string" = "smbnix"; security = user
"netbios name" = "smbnix"; use sendfile = yes
"use sendfile" = "yes"; min protocol = smb2
"min protocol" = "smb2"; guest account = nobody
"guest account" = "nobody"; map to guest = bad user
"map to guest" = "bad user";
# printing # printing
"load printers" = "yes"; load printers = yes
printing = "cups"; printing = cups
"printcap name" = "cups"; printcap name = cups
"hide files" = "/.nobackup/.DS_Store/._.DS_Store/"; hide files = /.nobackup/.DS_Store/._.DS_Store/
}; '';
shares = {
public = { public = {
path = "/data/samba/Public"; path = "/data/samba/Public";
browseable = "yes"; browseable = "yes";
@@ -75,9 +77,9 @@
# backups # backups
backup.group."samba".paths = [ backup.group."samba".paths = [
config.services.samba.settings.googlebot.path config.services.samba.shares.googlebot.path
config.services.samba.settings.cris.path config.services.samba.shares.cris.path
config.services.samba.settings.public.path config.services.samba.shares.public.path
]; ];
# Windows discovery of samba server # Windows discovery of samba server
@@ -95,7 +97,7 @@
# Printer discovery # Printer discovery
# (is this needed?) # (is this needed?)
services.avahi.enable = true; services.avahi.enable = true;
services.avahi.nssmdns4 = true; services.avahi.nssmdns = true;
# printer sharing # printer sharing
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [

View File

@@ -1,26 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.unifi;
in
{
options.services.unifi = {
# Open select Unifi ports instead of using openFirewall to avoid opening access to unifi's control panel
openMinimalFirewall = lib.mkEnableOption "Open bare minimum firewall ports";
};
config = lib.mkIf cfg.enable {
services.unifi.unifiPackage = pkgs.unifi;
services.unifi.mongodbPackage = pkgs.mongodb-7_0;
networking.firewall = lib.mkIf cfg.openMinimalFirewall {
allowedUDPPorts = [
3478 # STUN
10001 # used for device discovery.
];
allowedTCPPorts = [
8080 # Used for device and application communication.
];
};
};
}

View File

@@ -21,6 +21,8 @@
shellInit = '' shellInit = ''
# disable annoying fish shell greeting # disable annoying fish shell greeting
set fish_greeting set fish_greeting
alias sudo="doas"
''; '';
}; };
@@ -32,8 +34,6 @@
io_seq_write = "${pkgs.fio}/bin/fio --name TEST --eta-newline=5s --filename=temp.file --rw=write --size=2g --io_size=10g --blocksize=1024k --ioengine=libaio --fsync=10000 --iodepth=32 --direct=1 --numjobs=1 --runtime=60 --group_reporting; rm temp.file"; io_seq_write = "${pkgs.fio}/bin/fio --name TEST --eta-newline=5s --filename=temp.file --rw=write --size=2g --io_size=10g --blocksize=1024k --ioengine=libaio --fsync=10000 --iodepth=32 --direct=1 --numjobs=1 --runtime=60 --group_reporting; rm temp.file";
io_rand_read = "${pkgs.fio}/bin/fio --name TEST --eta-newline=5s --filename=temp.file --rw=randread --size=2g --io_size=10g --blocksize=4k --ioengine=libaio --fsync=1 --iodepth=1 --direct=1 --numjobs=32 --runtime=60 --group_reporting; rm temp.file"; io_rand_read = "${pkgs.fio}/bin/fio --name TEST --eta-newline=5s --filename=temp.file --rw=randread --size=2g --io_size=10g --blocksize=4k --ioengine=libaio --fsync=1 --iodepth=1 --direct=1 --numjobs=32 --runtime=60 --group_reporting; rm temp.file";
io_rand_write = "${pkgs.fio}/bin/fio --name TEST --eta-newline=5s --filename=temp.file --rw=randrw --size=2g --io_size=10g --blocksize=4k --ioengine=libaio --fsync=1 --iodepth=1 --direct=1 --numjobs=1 --runtime=60 --group_reporting; rm temp.file"; io_rand_write = "${pkgs.fio}/bin/fio --name TEST --eta-newline=5s --filename=temp.file --rw=randrw --size=2g --io_size=10g --blocksize=4k --ioengine=libaio --fsync=1 --iodepth=1 --direct=1 --numjobs=1 --runtime=60 --group_reporting; rm temp.file";
llsblk = "lsblk -o +uuid,fsType";
}; };
nixpkgs.overlays = [ nixpkgs.overlays = [
@@ -41,9 +41,6 @@
# comma uses the "nix-index" package built into nixpkgs by default. # comma uses the "nix-index" package built into nixpkgs by default.
# That package doesn't use the prebuilt nix-index database so it needs to be changed. # That package doesn't use the prebuilt nix-index database so it needs to be changed.
comma = prev.comma.overrideAttrs (old: { comma = prev.comma.overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs ++ [
prev.makeWrapper
];
postInstall = '' postInstall = ''
wrapProgram $out/bin/comma \ wrapProgram $out/bin/comma \
--prefix PATH : ${lib.makeBinPath [ prev.fzy config.programs.nix-index.package ]} --prefix PATH : ${lib.makeBinPath [ prev.fzy config.programs.nix-index.package ]}

View File

@@ -31,6 +31,8 @@
# TODO: Old ssh keys I will remove some day... # TODO: Old ssh keys I will remove some day...
machines.ssh.userKeys = [ machines.ssh.userKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMVR/R3ZOsv7TZbICGBCHdjh1NDT8SnswUyINeJOC7QG"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0dcqL/FhHmv+a1iz3f9LJ48xubO7MZHy35rW9SZOYM"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHSkKiRUUmnErOKGx81nyge/9KqjkPh8BfDk0D3oP586" # nat "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHSkKiRUUmnErOKGx81nyge/9KqjkPh8BfDk0D3oP586" # nat
]; ];
} }

304
flake.lock generated
View File

@@ -3,22 +3,16 @@
"agenix": { "agenix": {
"inputs": { "inputs": {
"darwin": "darwin", "darwin": "darwin",
"home-manager": [
"home-manager"
],
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
],
"systems": [
"systems"
] ]
}, },
"locked": { "locked": {
"lastModified": 1762618334, "lastModified": 1682101079,
"narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=", "narHash": "sha256-MdAhtjrLKnk2uiqun1FWABbKpLH090oeqCSiWemtuck=",
"owner": "ryantm", "owner": "ryantm",
"repo": "agenix", "repo": "agenix",
"rev": "fcdea223397448d35d9b31f798479227e80183f6", "rev": "2994d002dcff5353ca1ac48ec584c7f6589fe447",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -27,6 +21,29 @@
"type": "github" "type": "github"
} }
}, },
"archivebox": {
"inputs": {
"flake-utils": [
"flake-utils"
],
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1648612759,
"narHash": "sha256-SJwlpD2Wz3zFoX2mIYCQfwIOYHaOdeiWGFeDXsLGM84=",
"ref": "refs/heads/master",
"rev": "39d338b9b24159d8ef3309eecc0d32a2a9f102b5",
"revCount": 2,
"type": "git",
"url": "https://git.neet.dev/zuckerberg/archivebox.git"
},
"original": {
"type": "git",
"url": "https://git.neet.dev/zuckerberg/archivebox.git"
}
},
"blobs": { "blobs": {
"flake": false, "flake": false,
"locked": { "locked": {
@@ -53,17 +70,17 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1739947126, "lastModified": 1651719222,
"narHash": "sha256-JoiddH5H9up8jC/VKU8M7wDlk/bstKoJ3rHj+TkW4Zo=", "narHash": "sha256-p/GY5vOP+HUlxNL4OtEhmBNEVQsedOHXEmjfCGONVmE=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "ea1ad60f1c6662103ef4a3705d8e15aa01219529", "rev": "1290ddd9a2ff2bf2d0f702750768312b80efcd34",
"revCount": 20, "revCount": 19,
"type": "git", "type": "git",
"url": "https://git.neet.dev/zuckerberg/dailybot.git" "url": "https://git.neet.dev/zuckerberg/dailybuild_modules.git"
}, },
"original": { "original": {
"type": "git", "type": "git",
"url": "https://git.neet.dev/zuckerberg/dailybot.git" "url": "https://git.neet.dev/zuckerberg/dailybuild_modules.git"
} }
}, },
"darwin": { "darwin": {
@@ -74,11 +91,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1744478979, "lastModified": 1673295039,
"narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=", "narHash": "sha256-AsdYgE8/GPwcelGgrntlijMg4t3hLFJFCRF3tL5WVjA=",
"owner": "lnl7", "owner": "lnl7",
"repo": "nix-darwin", "repo": "nix-darwin",
"rev": "43975d782b418ebf4969e9ccba82466728c2851b", "rev": "87b9d090ad39b25b2400029c64825fc2a8868943",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -90,22 +107,21 @@
}, },
"deploy-rs": { "deploy-rs": {
"inputs": { "inputs": {
"flake-compat": [ "flake-compat": "flake-compat",
"flake-compat"
],
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
"utils": [ "utils": [
"flake-utils" "simple-nixos-mailserver",
"utils"
] ]
}, },
"locked": { "locked": {
"lastModified": 1766051518, "lastModified": 1683515103,
"narHash": "sha256-znKOwPXQnt3o7lDb3hdf19oDo0BLP4MfBOYiWkEHoik=", "narHash": "sha256-vWlnZ0twW+ekOC6JuAHDfupv+u4QNvWawG7+DaQJ4VA=",
"owner": "serokell", "owner": "serokell",
"repo": "deploy-rs", "repo": "deploy-rs",
"rev": "d5eff7f948535b9c723d60cd8239f8f11ddc90fa", "rev": "64160276cd6569694131ed8864d4d35470a84ec3",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -117,11 +133,11 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1767039857, "lastModified": 1668681692,
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", "narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", "rev": "009399224d5e398d03b22badca40a37ac85412a1",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -132,16 +148,14 @@
}, },
"flake-utils": { "flake-utils": {
"inputs": { "inputs": {
"systems": [ "systems": "systems"
"systems"
]
}, },
"locked": { "locked": {
"lastModified": 1731533236, "lastModified": 1681202837,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -150,75 +164,6 @@
"type": "github" "type": "github"
} }
}, },
"git-hooks": {
"inputs": {
"flake-compat": [
"simple-nixos-mailserver",
"flake-compat"
],
"gitignore": "gitignore",
"nixpkgs": [
"simple-nixos-mailserver",
"nixpkgs"
]
},
"locked": {
"lastModified": 1763988335,
"narHash": "sha256-QlcnByMc8KBjpU37rbq5iP7Cp97HvjRP0ucfdh+M4Qc=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "50b9238891e388c9fdc6a5c49e49c42533a1b5ce",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"simple-nixos-mailserver",
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1768068402,
"narHash": "sha256-bAXnnJZKJiF7Xr6eNW6+PhBf1lg2P1aFUO9+xgWkXfA=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "8bc5473b6bc2b6e1529a9c4040411e1199c43b4c",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "master",
"repo": "home-manager",
"type": "github"
}
},
"nix-index-database": { "nix-index-database": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -226,11 +171,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1765267181, "lastModified": 1683638468,
"narHash": "sha256-d3NBA9zEtBu2JFMnTBqWj7Tmi7R5OikoU2ycrdhQEws=", "narHash": "sha256-tQEaGZfZ2Hpw+XIVEHaJ8FaF1yNQyMDDhUyIQ7LTIEg=",
"owner": "Mic92", "owner": "Mic92",
"repo": "nix-index-database", "repo": "nix-index-database",
"rev": "82befcf7dc77c909b0f2a09f5da910ec95c5b78f", "rev": "219067a5e3cf4b9581c8b4fcfc59ecd5af953d07",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -239,29 +184,13 @@
"type": "github" "type": "github"
} }
}, },
"nixos-hardware": {
"locked": {
"lastModified": 1767185284,
"narHash": "sha256-ljDBUDpD1Cg5n3mJI81Hz5qeZAwCGxon4kQW3Ho3+6Q=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "40b1a28dce561bea34858287fbb23052c3ee63fe",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "master",
"repo": "nixos-hardware",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1768105724, "lastModified": 1683741689,
"narHash": "sha256-0edMCoDc1VpuqDjy0oz8cDa4kjRuhXE3040sac2iZW4=", "narHash": "sha256-VY6gjqAFQe0Xyz+olc979zbsW9dC4VG+mINGffFKVEw=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "4c41b0361812441bf3b4427195e57ab271d5167f", "rev": "f431ee4a85cb985075b4ed27596913e8087f4264",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -271,43 +200,109 @@
"type": "github" "type": "github"
} }
}, },
"root": { "nixpkgs-22_05": {
"inputs": { "locked": {
"agenix": "agenix", "lastModified": 1654936503,
"dailybuild_modules": "dailybuild_modules", "narHash": "sha256-soKzdhI4jTHv/rSbh89RdlcJmrPgH8oMb/PLqiqIYVQ=",
"deploy-rs": "deploy-rs", "owner": "NixOS",
"flake-compat": "flake-compat", "repo": "nixpkgs",
"flake-utils": "flake-utils", "rev": "dab6df51387c3878cdea09f43589a15729cae9f4",
"home-manager": "home-manager", "type": "github"
"nix-index-database": "nix-index-database", },
"nixos-hardware": "nixos-hardware", "original": {
"nixpkgs": "nixpkgs", "id": "nixpkgs",
"simple-nixos-mailserver": "simple-nixos-mailserver", "ref": "nixos-22.05",
"systems": "systems" "type": "indirect"
} }
}, },
"simple-nixos-mailserver": { "nixpkgs-hostapd-pr": {
"flake": false,
"locked": {
"narHash": "sha256-35+g1EJMcDFhb3UP15fyR1aD4AX1ifz2EqaYItITZ7U=",
"type": "file",
"url": "https://github.com/NixOS/nixpkgs/pull/222536.patch"
},
"original": {
"type": "file",
"url": "https://github.com/NixOS/nixpkgs/pull/222536.patch"
}
},
"radio": {
"inputs": { "inputs": {
"blobs": "blobs", "flake-utils": [
"flake-compat": [ "flake-utils"
"flake-compat"
], ],
"git-hooks": "git-hooks",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1766321686, "lastModified": 1631585589,
"narHash": "sha256-icOWbnD977HXhveirqA10zoqvErczVs3NKx8Bj+ikHY=", "narHash": "sha256-q4o/4/2pEuJyaKZwNQC5KHnzG1obClzFB7zWk9XSDfY=",
"ref": "main",
"rev": "5bf607fed977d41a269942a7d1e92f3e6d4f2473",
"revCount": 38,
"type": "git",
"url": "https://git.neet.dev/zuckerberg/radio.git"
},
"original": {
"ref": "main",
"rev": "5bf607fed977d41a269942a7d1e92f3e6d4f2473",
"type": "git",
"url": "https://git.neet.dev/zuckerberg/radio.git"
}
},
"radio-web": {
"flake": false,
"locked": {
"lastModified": 1652121792,
"narHash": "sha256-j1Y9MAjUVNgyFSeGzPoqibAnEysJDjZSXukVfQ7+bsQ=",
"ref": "refs/heads/master",
"rev": "72e7a9e80b780c84ed8d4a6374bfbb242701f900",
"revCount": 5,
"type": "git",
"url": "https://git.neet.dev/zuckerberg/radio-web.git"
},
"original": {
"type": "git",
"url": "https://git.neet.dev/zuckerberg/radio-web.git"
}
},
"root": {
"inputs": {
"agenix": "agenix",
"archivebox": "archivebox",
"dailybuild_modules": "dailybuild_modules",
"deploy-rs": "deploy-rs",
"flake-utils": "flake-utils",
"nix-index-database": "nix-index-database",
"nixpkgs": "nixpkgs",
"nixpkgs-hostapd-pr": "nixpkgs-hostapd-pr",
"radio": "radio",
"radio-web": "radio-web",
"simple-nixos-mailserver": "simple-nixos-mailserver"
}
},
"simple-nixos-mailserver": {
"inputs": {
"blobs": "blobs",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-22_05": "nixpkgs-22_05",
"utils": "utils"
},
"locked": {
"lastModified": 1655930346,
"narHash": "sha256-ht56HHOzEhjeIgAv5ZNFjSVX/in1YlUs0HG9c1EUXTM=",
"owner": "simple-nixos-mailserver", "owner": "simple-nixos-mailserver",
"repo": "nixos-mailserver", "repo": "nixos-mailserver",
"rev": "7d433bf89882f61621f95082e90a4ab91eb0bdd3", "rev": "f535d8123c4761b2ed8138f3d202ea710a334a1d",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
"owner": "simple-nixos-mailserver", "owner": "simple-nixos-mailserver",
"ref": "master", "ref": "nixos-22.05",
"repo": "nixos-mailserver", "repo": "nixos-mailserver",
"type": "gitlab" "type": "gitlab"
} }
@@ -326,6 +321,21 @@
"repo": "default", "repo": "default",
"type": "github" "type": "github"
} }
},
"utils": {
"locked": {
"lastModified": 1605370193,
"narHash": "sha256-YyMTf3URDL/otKdKgtoMChu4vfVL3vCMkRqpGifhUn0=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5021eac20303a61fafe17224c087f5519baed54d",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

114
flake.nix
View File

@@ -1,76 +1,52 @@
{ {
inputs = { inputs = {
# nixpkgs
nixpkgs.url = "github:NixOS/nixpkgs/master"; nixpkgs.url = "github:NixOS/nixpkgs/master";
# nixpkgs-patch-howdy.url = "https://github.com/NixOS/nixpkgs/pull/216245.diff";
# nixpkgs-patch-howdy.flake = false;
# Common Utils Among flake inputs flake-utils.url = "github:numtide/flake-utils";
systems.url = "github:nix-systems/default";
flake-utils = {
url = "github:numtide/flake-utils";
inputs.systems.follows = "systems";
};
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
# NixOS hardware # mail server
nixos-hardware.url = "github:NixOS/nixos-hardware/master"; simple-nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-22.05";
simple-nixos-mailserver.inputs.nixpkgs.follows = "nixpkgs";
# Home Manager # agenix
home-manager = { agenix.url = "github:ryantm/agenix";
url = "github:nix-community/home-manager/master"; agenix.inputs.nixpkgs.follows = "nixpkgs";
inputs.nixpkgs.follows = "nixpkgs";
};
# Mail Server # radio
simple-nixos-mailserver = { radio.url = "git+https://git.neet.dev/zuckerberg/radio.git?ref=main&rev=5bf607fed977d41a269942a7d1e92f3e6d4f2473";
url = "gitlab:simple-nixos-mailserver/nixos-mailserver/master"; radio.inputs.nixpkgs.follows = "nixpkgs";
inputs = { radio.inputs.flake-utils.follows = "flake-utils";
nixpkgs.follows = "nixpkgs"; radio-web.url = "git+https://git.neet.dev/zuckerberg/radio-web.git";
flake-compat.follows = "flake-compat"; radio-web.flake = false;
};
};
# Agenix # drastikbot
agenix = { dailybuild_modules.url = "git+https://git.neet.dev/zuckerberg/dailybuild_modules.git";
url = "github:ryantm/agenix"; dailybuild_modules.inputs.nixpkgs.follows = "nixpkgs";
inputs = { dailybuild_modules.inputs.flake-utils.follows = "flake-utils";
nixpkgs.follows = "nixpkgs";
systems.follows = "systems";
home-manager.follows = "home-manager";
};
};
# Dailybot # archivebox
dailybuild_modules = { archivebox.url = "git+https://git.neet.dev/zuckerberg/archivebox.git";
url = "git+https://git.neet.dev/zuckerberg/dailybot.git"; archivebox.inputs.nixpkgs.follows = "nixpkgs";
inputs = { archivebox.inputs.flake-utils.follows = "flake-utils";
nixpkgs.follows = "nixpkgs";
flake-utils.follows = "flake-utils";
};
};
# NixOS deployment # nixos config deployment
deploy-rs = { deploy-rs.url = "github:serokell/deploy-rs";
url = "github:serokell/deploy-rs"; deploy-rs.inputs.nixpkgs.follows = "nixpkgs";
inputs = { deploy-rs.inputs.utils.follows = "simple-nixos-mailserver/utils";
nixpkgs.follows = "nixpkgs";
flake-compat.follows = "flake-compat";
utils.follows = "flake-utils";
};
};
# Prebuilt nix-index database # prebuilt nix-index database
nix-index-database = { nix-index-database.url = "github:Mic92/nix-index-database";
url = "github:Mic92/nix-index-database"; nix-index-database.inputs.nixpkgs.follows = "nixpkgs";
inputs.nixpkgs.follows = "nixpkgs";
}; nixpkgs-hostapd-pr.url = "https://github.com/NixOS/nixpkgs/pull/222536.patch";
nixpkgs-hostapd-pr.flake = false;
}; };
outputs = { self, nixpkgs, ... }@inputs: outputs = { self, nixpkgs, ... }@inputs:
let let
machineHosts = (import ./common/machine-info/moduleless.nix machines = (import ./common/machine-info/moduleless.nix
{ {
inherit nixpkgs; inherit nixpkgs;
assertionsModule = "${nixpkgs}/nixos/modules/misc/assertions.nix"; assertionsModule = "${nixpkgs}/nixos/modules/misc/assertions.nix";
@@ -84,22 +60,15 @@
simple-nixos-mailserver.nixosModule simple-nixos-mailserver.nixosModule
agenix.nixosModules.default agenix.nixosModules.default
dailybuild_modules.nixosModule dailybuild_modules.nixosModule
archivebox.nixosModule
nix-index-database.nixosModules.nix-index nix-index-database.nixosModules.nix-index
home-manager.nixosModules.home-manager
self.nixosModules.kernel-modules
({ lib, ... }: { ({ lib, ... }: {
config = { config = {
nixpkgs.overlays = [ self.overlays.default ];
environment.systemPackages = [ environment.systemPackages = [
agenix.packages.${system}.agenix agenix.packages.${system}.agenix
]; ];
networking.hostName = hostname; networking.hostName = hostname;
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.users.googlebot = import ./home/googlebot.nix;
}; };
# because nixos specialArgs doesn't work for containers... need to pass in inputs a different way # because nixos specialArgs doesn't work for containers... need to pass in inputs a different way
@@ -117,7 +86,7 @@
name = "nixpkgs-patched"; name = "nixpkgs-patched";
src = nixpkgs; src = nixpkgs;
patches = [ patches = [
./patches/dont-break-nix-serve.patch inputs.nixpkgs-hostapd-pr
]; ];
}; };
patchedNixpkgs = nixpkgs.lib.fix (self: (import "${patchedNixpkgsSrc}/flake.nix").outputs { self = nixpkgs; }); patchedNixpkgs = nixpkgs.lib.fix (self: (import "${patchedNixpkgsSrc}/flake.nix").outputs { self = nixpkgs; });
@@ -129,15 +98,13 @@
specialArgs = { specialArgs = {
inherit allModules; inherit allModules;
lib = self.lib;
nixos-hardware = inputs.nixos-hardware;
}; };
}; };
in in
nixpkgs.lib.mapAttrs nixpkgs.lib.mapAttrs
(hostname: cfg: (hostname: cfg:
mkSystem cfg.arch nixpkgs cfg.configurationPath hostname) mkSystem cfg.arch nixpkgs cfg.configurationPath hostname)
machineHosts; machines;
packages = packages =
let let
@@ -159,9 +126,6 @@
"aarch64-linux"."iso" = mkIso "aarch64-linux"; "aarch64-linux"."iso" = mkIso "aarch64-linux";
}; };
overlays.default = import ./overlays { inherit inputs; };
nixosModules.kernel-modules = import ./overlays/kernel-modules;
deploy.nodes = deploy.nodes =
let let
mkDeploy = configName: arch: hostname: { mkDeploy = configName: arch: hostname: {
@@ -174,10 +138,8 @@
nixpkgs.lib.mapAttrs nixpkgs.lib.mapAttrs
(hostname: cfg: (hostname: cfg:
mkDeploy hostname cfg.arch (builtins.head cfg.hostNames)) mkDeploy hostname cfg.arch (builtins.head cfg.hostNames))
machineHosts; machines;
checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) inputs.deploy-rs.lib; checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) inputs.deploy-rs.lib;
lib = nixpkgs.lib.extend (final: prev: import ./lib { lib = nixpkgs.lib; });
}; };
} }

View File

@@ -1,58 +0,0 @@
{ config, lib, pkgs, osConfig, ... }:
let
# Check if the current machine has the role "personal"
thisMachineIsPersonal = osConfig.thisMachine.hasRole."personal";
in
{
home.username = "googlebot";
home.homeDirectory = "/home/googlebot";
home.stateVersion = "24.11";
programs.home-manager.enable = true;
services.ssh-agent.enable = true;
# System Monitoring
programs.btop.enable = true;
programs.bottom.enable = true;
# Modern "ls" replacement
programs.pls.enable = true;
programs.pls.enableFishIntegration = false;
programs.eza.enable = true;
# Graphical terminal
programs.ghostty.enable = thisMachineIsPersonal;
programs.ghostty.settings = {
theme = "Snazzy";
font-size = 10;
};
# Advanced terminal file explorer
programs.broot.enable = true;
# Shell promt theming
programs.fish.enable = true;
programs.starship.enable = true;
programs.starship.enableFishIntegration = true;
programs.starship.enableInteractive = true;
# programs.oh-my-posh.enable = true;
# programs.oh-my-posh.enableFishIntegration = true;
# Advanced search
programs.ripgrep.enable = true;
# tldr: Simplified, example based and community-driven man pages.
programs.tealdeer.enable = true;
home.shellAliases = {
sudo = "doas";
ls2 = "eza";
explorer = "broot";
};
programs.zed-editor = {
enable = thisMachineIsPersonal;
};
}

View File

@@ -1,56 +0,0 @@
{ lib, ... }:
with lib;
{
# Passthrough trace for debugging
pTrace = v: traceSeq v v;
# find the total sum of a int list
sum = foldr (x: y: x + y) 0;
# splits a list of length two into two params then they're passed to a func
splitPair = f: pair: f (head pair) (last pair);
# Finds the max value in a list
maxList = foldr max 0;
# Sorts a int list. Greatest value first
sortList = sort (x: y: x > y);
# Cuts a list in half and returns the two parts in a list
cutInHalf = l: [ (take (length l / 2) l) (drop (length l / 2) l) ];
# Splits a list into a list of lists with length cnt
chunksOf = cnt: l:
if length l > 0 then
[ (take cnt l) ] ++ chunksOf cnt (drop cnt l)
else [ ];
# same as intersectLists but takes an array of lists to intersect instead of just two
intersectManyLists = ll: foldr intersectLists (head ll) ll;
# converts a boolean to a int (c style)
boolToInt = b: if b then 1 else 0;
# drops the last element of a list
dropLast = l: take (length l - 1) l;
# transposes a matrix
transpose = ll:
let
outerSize = length ll;
innerSize = length (elemAt ll 0);
in
genList (i: genList (j: elemAt (elemAt ll j) i) outerSize) innerSize;
# attriset recursiveUpdate but for a list of attrisets
combineAttrs = foldl recursiveUpdate { };
# visits every single attriset element of an attriset recursively
# and accumulates the result of every visit in a flat list
recurisveVisitAttrs = f: set:
let
visitor = n: v:
if isAttrs v then [ (f n v) ] ++ recurisveVisitAttrs f v
else [ (f n v) ];
in
concatLists (map (name: visitor name set.${name}) (attrNames set));
# merges two lists of the same size (similar to map but both lists are inputs per iteration)
mergeLists = f: a: imap0 (i: f (elemAt a i));
map2D = f: ll:
let
outerSize = length ll;
innerSize = length (elemAt ll 0);
getElem = x: y: elemAt (elemAt ll y) x;
in
genList (y: genList (x: f x y (getElem x y)) innerSize) outerSize;
}

4
lockfile-update.sh Executable file
View File

@@ -0,0 +1,4 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p bash
nix flake update --commit-lock-file

View File

@@ -29,10 +29,10 @@
text = '' text = ''
#!${pkgs.stdenv.shell} #!${pkgs.stdenv.shell}
set -e set -e
${pkgs.kexec-tools}/bin/kexec -l ${image}/kernel --initrd=${image}/initrd --append="init=${builtins.unsafeDiscardStringContext config.system.build.toplevel}/init ${toString config.boot.kernelParams}" ${pkgs.kexectools}/bin/kexec -l ${image}/kernel --initrd=${image}/initrd --append="init=${builtins.unsafeDiscardStringContext config.system.build.toplevel}/init ${toString config.boot.kernelParams}"
sync sync
echo "executing kernel, filesystems will be improperly umounted" echo "executing kernel, filesystems will be improperly umounted"
${pkgs.kexec-tools}/bin/kexec -e ${pkgs.kexectools}/bin/kexec -e
''; '';
}; };
kexec_tarball = pkgs.callPackage (modulesPath + "/../lib/make-system-tarball.nix") { kexec_tarball = pkgs.callPackage (modulesPath + "/../lib/make-system-tarball.nix") {

View File

@@ -7,20 +7,12 @@
../../common/ssh.nix ../../common/ssh.nix
]; ];
boot.initrd.availableKernelModules = [ boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "e1000" "e1000e" "virtio_pci" "r8169" ];
"ata_piix"
"uhci_hcd"
"e1000"
"e1000e"
"virtio_pci"
"r8169"
"sdhci"
"sdhci_pci"
"mmc_core"
"mmc_block"
];
boot.kernelParams = [ boot.kernelParams = [
"panic=30"
"boot.panic_on_fail" # reboot the machine upon fatal boot issues
"console=ttyS0,115200" # enable serial console "console=ttyS0,115200" # enable serial console
"console=tty1"
]; ];
boot.kernel.sysctl."vm.overcommit_memory" = "1"; boot.kernel.sysctl."vm.overcommit_memory" = "1";

View File

@@ -1,57 +0,0 @@
{ config, modulesPath, pkgs, lib, ... }:
let
pinecube-uboot = pkgs.buildUBoot {
defconfig = "pinecube_defconfig";
extraMeta.platforms = [ "armv7l-linux" ];
filesToInstall = [ "u-boot-sunxi-with-spl.bin" ];
};
in
{
imports = [
(modulesPath + "/installer/sd-card/sd-image.nix")
./minimal.nix
];
sdImage.populateFirmwareCommands = "";
sdImage.populateRootCommands = ''
mkdir -p ./files/boot
${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot
'';
sdImage.postBuildCommands = ''
dd if=${pinecube-uboot}/u-boot-sunxi-with-spl.bin of=$img bs=1024 seek=8 conv=notrunc
'';
###
networking.hostName = "pinecube";
boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;
boot.consoleLogLevel = 7;
# cma is 64M by default which is waay too much and we can't even unpack initrd
boot.kernelParams = [ "console=ttyS0,115200n8" "cma=32M" ];
boot.kernelModules = [ "spi-nor" ]; # Not sure why this doesn't autoload. Provides SPI NOR at /dev/mtd0
boot.extraModulePackages = [ config.boot.kernelPackages.rtl8189es ];
zramSwap.enable = true; # 128MB is not much to work with
sound.enable = true;
environment.systemPackages = with pkgs; [
ffmpeg
(v4l_utils.override { withGUI = false; })
usbutils
];
services.getty.autologinUser = lib.mkForce "googlebot";
users.users.googlebot = {
isNormalUser = true;
extraGroups = [ "wheel" "networkmanager" "video" ];
openssh.authorizedKeys.keys = config.machines.ssh.userKeys;
};
networking.wireless.enable = true;
}

View File

@@ -1,70 +0,0 @@
{ config, pkgs, lib, ... }:
{
imports = [
./hardware-configuration.nix
];
# don't use remote builders
nix.distributedBuilds = lib.mkForce false;
nix.gc.automatic = lib.mkForce false;
environment.systemPackages = with pkgs; [
system76-keyboard-configurator
];
services.ollama = {
enable = true;
package = pkgs.ollama-vulkan;
host = "127.0.0.1";
};
services.open-webui = {
enable = true;
host = "127.0.0.1"; # nginx proxy
port = 12831;
environment = {
ANONYMIZED_TELEMETRY = "False";
DO_NOT_TRACK = "True";
SCARF_NO_ANALYTICS = "True";
OLLAMA_API_BASE_URL = "http://localhost:${toString config.services.ollama.port}";
};
};
# nginx
services.nginx = {
enable = true;
openFirewall = false; # All nginx services are internal
virtualHosts =
let
mkHost = external: config:
{
${external} = {
useACMEHost = "fry.neet.dev"; # Use wildcard cert
forceSSL = true;
locations."/" = config;
};
};
mkVirtualHost = external: internal:
mkHost external {
proxyPass = internal;
proxyWebsockets = true;
};
in
lib.mkMerge [
(mkVirtualHost "chat.fry.neet.dev" "http://localhost:${toString config.services.open-webui.port}")
];
};
# Get wildcard cert
security.acme.certs."fry.neet.dev" = {
dnsProvider = "digitalocean";
credentialsFile = "/run/agenix/digitalocean-dns-credentials";
extraDomainNames = [ "*.fry.neet.dev" ];
group = "nginx";
dnsResolver = "1.1.1.1:53";
dnsPropagationCheck = false; # sadly this erroneously fails
};
age.secrets.digitalocean-dns-credentials.file = ../../secrets/digitalocean-dns-credentials.age;
}

View File

@@ -1,50 +0,0 @@
{ config, lib, pkgs, modulesPath, nixos-hardware, ... }:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
nixos-hardware.nixosModules.framework-amd-ai-300-series
];
boot.kernelPackages = pkgs.linuxPackages_latest;
services.fwupd.enable = true;
# boot
boot.loader.systemd-boot.enable = true;
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" "usb_storage" "sd_mod" "r8169" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
# thunderbolt
services.hardware.bolt.enable = true;
# firmware
firmware.x86_64.enable = true;
# disks
remoteLuksUnlock.enable = true;
boot.initrd.luks.devices."enc-pv" = {
device = "/dev/disk/by-uuid/d4f2f25a-5108-4285-968f-b24fb516d4f3";
allowDiscards = true;
};
fileSystems."/" =
{ device = "/dev/disk/by-uuid/a8901bc1-8642-442a-940a-ddd3f428cd0f";
fsType = "btrfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/13E5-C9D4";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};
swapDevices =
[ { device = "/dev/disk/by-uuid/03356a74-33f0-4a2e-b57a-ec9dfc9d85c5"; }
];
# Ensures that dhcp is active during initrd (Network Manager is used post boot)
boot.initrd.network.udhcpc.enable = true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View File

@@ -1,24 +0,0 @@
{
hostNames = [
"fry"
];
arch = "x86_64-linux";
systemRoles = [
"personal"
"dns-challenge"
];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID/Df5lG07Il7fizEgZR/T9bMlR0joESRJ7cqM9BkOyP";
userKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM5/h6YySqNemA4+e+xslhspBp34ulXKembe3RoeZ5av"
];
remoteUnlock = {
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL1RC1lhP4TSL2THvKAQAH7Y/eSGQPo/MjhTsZD6CEES";
clearnetHost = "192.168.1.3";
onionHost = "z7smmigsfrabqfnxqogfogmsu36jhpsyscncmd332w5ioheblw6i4lid.onion";
};
}

View File

@@ -1,12 +0,0 @@
{ config, pkgs, lib, ... }:
{
imports = [
./hardware-configuration.nix
];
# don't use remote builders
nix.distributedBuilds = lib.mkForce false;
nix.gc.automatic = lib.mkForce false;
}

View File

@@ -1,58 +0,0 @@
{ config, lib, pkgs, modulesPath, nixos-hardware, ... }:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
nixos-hardware.nixosModules.framework-13-7040-amd
];
boot.kernelPackages = pkgs.linuxPackages_latest;
hardware.framework.amd-7040.preventWakeOnAC = true;
services.fwupd.enable = true;
# fingerprint reader has initially shown to be more of a nuisance than a help
# it makes sddm log in fail most of the time and take several minutes to finish
services.fprintd.enable = false;
# boot
boot.loader.systemd-boot.enable = true;
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
# thunderbolt
services.hardware.bolt.enable = true;
# firmware
firmware.x86_64.enable = true;
# disks
remoteLuksUnlock.enable = true;
boot.initrd.luks.devices."enc-pv" = {
device = "/dev/disk/by-uuid/2e4a6960-a6b1-40ee-9c2c-2766eb718d52";
allowDiscards = true;
};
fileSystems."/" =
{
device = "/dev/disk/by-uuid/1f62386c-3243-49f5-b72f-df8fc8f39db8";
fsType = "btrfs";
};
fileSystems."/boot" =
{
device = "/dev/disk/by-uuid/F4D9-C5E8";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};
swapDevices =
[{ device = "/dev/disk/by-uuid/5f65cb11-2649-48fe-9c78-3e325b857c53"; }];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp1s0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

View File

@@ -1,22 +0,0 @@
{
hostNames = [
"howl"
];
arch = "x86_64-linux";
systemRoles = [
"personal"
];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEQi3q8jU6vRruExAL60J7GFO1gS8HsmXVJuKRT4ljrG";
userKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKPnLt84bKhUgFxjQf10+Htro9Lo1Pabqm8mGalBUniv"
];
remoteUnlock = {
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN0N80r0Sl2WlJaUqfxZPkOtYyGumFazkIqq7eq3Gd2o";
onionHost = "ll6yjnkh4psmfwmtkmqoutl4gq4elqzbmjxv4s6gpgoavyi3kwhjvnqd.onion";
};
}

View File

@@ -9,4 +9,7 @@
networking.hostName = "nat"; networking.hostName = "nat";
networking.interfaces.ens160.useDHCP = true; networking.interfaces.ens160.useDHCP = true;
de.enable = true;
de.touchpad.enable = true;
} }

View File

@@ -6,4 +6,5 @@
]; ];
networking.hostName = "phil"; networking.hostName = "phil";
services.gitea-runner.enable = true;
} }

View File

@@ -8,6 +8,7 @@
systemRoles = [ systemRoles = [
"server" "server"
"gitea-runner"
"nix-builder" "nix-builder"
]; ];

View File

@@ -5,13 +5,11 @@
./hardware-configuration.nix ./hardware-configuration.nix
]; ];
# system.autoUpgrade.enable = true; system.autoUpgrade.enable = true;
# p2p mesh network # p2p mesh network
services.tailscale.exitNode = true; services.tailscale.exitNode = true;
services.iperf3.enable = true;
# email server # email server
mailserver.enable = true; mailserver.enable = true;
@@ -56,6 +54,29 @@
config.services.drastikbot.dataDir config.services.drastikbot.dataDir
]; ];
# music radio
vpn-container.enable = true;
vpn-container.config = {
services.radio = {
enable = true;
host = "radio.runyan.org";
};
};
pia.wireguard.badPortForwardPorts = [ ];
services.nginx.virtualHosts."radio.runyan.org" = {
enableACME = true;
forceSSL = true;
locations = {
"/stream.mp3" = {
proxyPass = "http://vpn.containers:8001/stream.mp3";
extraConfig = ''
add_header Access-Control-Allow-Origin *;
'';
};
"/".root = config.inputs.radio-web;
};
};
# matrix home server # matrix home server
services.matrix = { services.matrix = {
enable = true; enable = true;
@@ -66,7 +87,7 @@
host = "chat.neet.space"; host = "chat.neet.space";
}; };
jitsi-meet = { jitsi-meet = {
enable = false; # disabled until vulnerable libolm dependency is removed/fixed enable = true;
host = "meet.neet.space"; host = "meet.neet.space";
}; };
turn = { turn = {
@@ -75,13 +96,21 @@
}; };
}; };
# pin postgresql for matrix (will need to migrate eventually) # pin postgresql for matrix (will need to migrate eventually)
services.postgresql.package = pkgs.postgresql_15; services.postgresql.package = pkgs.postgresql_11;
# iodine DNS-based vpn # iodine DNS-based vpn
# services.iodine.server.enable = true; services.iodine.server.enable = true;
# proxied web services # proxied web services
services.nginx.enable = true; services.nginx.enable = true;
services.nginx.virtualHosts."jellyfin.neet.cloud" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://s0.koi-bebop.ts.net";
proxyWebsockets = true;
};
};
services.nginx.virtualHosts."navidrome.neet.cloud" = { services.nginx.virtualHosts."navidrome.neet.cloud" = {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
@@ -95,20 +124,16 @@
root = "/var/www/tmp"; root = "/var/www/tmp";
}; };
# redirect neet.cloud to nextcloud instance on runyan.org # redirect runyan.org to github
services.nginx.virtualHosts."neet.cloud" = { services.nginx.virtualHosts."runyan.org" = {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
extraConfig = '' extraConfig = ''
return 302 https://runyan.org$request_uri; rewrite ^/(.*)$ https://github.com/GoogleBot42 redirect;
''; '';
}; };
# owncast live streaming # owncast live streaming
services.owncast.enable = true; services.owncast.enable = true;
services.owncast.hostname = "live.neet.dev"; services.owncast.hostname = "live.neet.dev";
# librechat
services.librechat-container.enable = true;
services.librechat-container.host = "chat.neet.dev";
} }

View File

@@ -16,7 +16,6 @@
bios = { bios = {
enable = true; enable = true;
device = "/dev/sda"; device = "/dev/sda";
configurationLimit = 3; # Save room in /nix/store
}; };
remoteLuksUnlock.enable = true; remoteLuksUnlock.enable = true;

View File

@@ -15,7 +15,6 @@
"nextcloud" "nextcloud"
"dailybot" "dailybot"
"gitea" "gitea"
"librechat"
]; ];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMBBlTAIp38RhErU1wNNV5MBeb+WGH0mhF/dxh5RsAXN"; hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMBBlTAIp38RhErU1wNNV5MBeb+WGH0mhF/dxh5RsAXN";

55
machines/ray/default.nix Normal file
View File

@@ -0,0 +1,55 @@
{ config, pkgs, lib, ... }:
{
imports = [
./hardware-configuration.nix
];
# for luks onlock over tor
services.tor.enable = true;
services.tor.client.enable = true;
# services.howdy.enable = true;
hardware.openrazer.enable = true;
hardware.openrazer.users = [ "googlebot" ];
hardware.openrazer.devicesOffOnScreensaver = false;
users.users.googlebot.packages = [ pkgs.polychromatic ];
services.udev.extraRules = ''
# depthai
SUBSYSTEM=="usb", ATTRS{idVendor}=="03e7", MODE="0666"
# Moonlander
# Rules for Oryx web flashing and live training
KERNEL=="hidraw*", ATTRS{idVendor}=="16c0", MODE="0664", GROUP="plugdev"
KERNEL=="hidraw*", ATTRS{idVendor}=="3297", MODE="0664", GROUP="plugdev"
# Wally Flashing rules for the Moonlander and Planck EZ
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE:="0666", SYMLINK+="stm32_dfu"
'';
users.groups.plugdev = {
members = [ "googlebot" ];
};
# virt-manager
virtualisation.libvirtd.enable = true;
programs.dconf.enable = true;
virtualisation.spiceUSBRedirection.enable = true;
environment.systemPackages = with pkgs; [ virt-manager ];
users.users.googlebot.extraGroups = [ "libvirtd" ];
# allow building ARM derivations
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
services.spotifyd.enable = true;
virtualisation.docker.enable = true;
virtualisation.appvm.enable = true;
virtualisation.appvm.user = "googlebot";
services.mount-samba.enable = true;
de.enable = true;
de.touchpad.enable = true;
}

View File

@@ -0,0 +1,62 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[
(modulesPath + "/installer/scan/not-detected.nix")
];
# boot
efi.enable = true;
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "usbhid" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
# kernel
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
# firmware
firmware.x86_64.enable = true;
hardware.enableAllFirmware = true;
# gpu
services.xserver.videoDrivers = [ "nvidia" ];
hardware.nvidia = {
modesetting.enable = true; # for nvidia-vaapi-driver
prime = {
reverseSync.enable = true;
offload.enableOffloadCmd = true;
nvidiaBusId = "PCI:1:0:0";
amdgpuBusId = "PCI:4:0:0";
};
};
# disks
remoteLuksUnlock.enable = true;
boot.initrd.luks.devices."enc-pv" = {
device = "/dev/disk/by-uuid/c1822e5f-4137-44e1-885f-954e926583ce";
allowDiscards = true;
};
fileSystems."/" =
{
device = "/dev/vg/root";
fsType = "btrfs";
options = [ "subvol=root" ];
};
fileSystems."/home" =
{
device = "/dev/vg/root";
fsType = "btrfs";
options = [ "subvol=home" ];
};
fileSystems."/boot" =
{
device = "/dev/disk/by-uuid/2C85-2B59";
fsType = "vfat";
};
swapDevices =
[{ device = "/dev/vg/swap"; }];
}

View File

@@ -0,0 +1,22 @@
{
hostNames = [
"ray"
];
arch = "x86_64-linux";
systemRoles = [
"personal"
"deploy"
];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDQM8hwKRgl8cZj7UVYATSLYu4LhG7I0WFJ9m2iWowiB";
userKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFeTK1iARlNIKP/DS8/ObBm9yUM/3L1Ub4XI5A2r9OzP"
];
deployKeys = [
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIEaGIwLiUa6wQLlEF+keQOIYy/tCmJvV6eENzUQjSqW2AAAABHNzaDo="
];
}

View File

@@ -22,7 +22,8 @@
# networking.useDHCP = lib.mkForce true; # networking.useDHCP = lib.mkForce true;
networking.usePredictableInterfaceNames = false; # TODO
# networking.usePredictableInterfaceNames = true;
powerManagement.cpuFreqGovernor = "ondemand"; powerManagement.cpuFreqGovernor = "ondemand";

View File

@@ -10,6 +10,8 @@
# Enable serial output # Enable serial output
boot.kernelParams = [ boot.kernelParams = [
"panic=30"
"boot.panic_on_fail" # reboot the machine upon fatal boot issues
"console=ttyS0,115200n8" # enable serial console "console=ttyS0,115200n8" # enable serial console
]; ];
boot.loader.grub.extraConfig = " boot.loader.grub.extraConfig = "
@@ -21,8 +23,6 @@
# firmware # firmware
firmware.x86_64.enable = true; firmware.x86_64.enable = true;
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;
hardware.enableRedistributableFirmware = true;
hardware.enableAllFirmware = true;
# boot # boot
bios = { bios = {
@@ -31,18 +31,20 @@
}; };
# disks # disks
remoteLuksUnlock.enable = true;
boot.initrd.luks.devices."enc-pv".device = "/dev/disk/by-uuid/9b090551-f78e-45ca-8570-196ed6a4af0c";
fileSystems."/" = fileSystems."/" =
{ {
device = "/dev/disk/by-uuid/6aa7f79e-bef8-4b0f-b22c-9d1b3e8ac94b"; device = "/dev/disk/by-uuid/421c82b9-d67c-4811-8824-8bb57cb10fce";
fsType = "ext4"; fsType = "btrfs";
}; };
fileSystems."/boot" = fileSystems."/boot" =
{ {
device = "/dev/disk/by-uuid/14dfc562-0333-4ddd-b10c-4eeefe1cd05f"; device = "/dev/disk/by-uuid/d97f324f-3a2e-4b84-ae2a-4b3d1209c689";
fsType = "ext3"; fsType = "ext3";
}; };
swapDevices = swapDevices =
[{ device = "/dev/disk/by-uuid/adf37c64-3b54-480c-a9a7-099d61c6eac7"; }]; [{ device = "/dev/disk/by-uuid/45bf58dd-67eb-45e4-9a98-246e23fa7abd"; }];
nixpkgs.hostPlatform = "x86_64-linux"; nixpkgs.hostPlatform = "x86_64-linux";
} }

View File

@@ -1,8 +1,7 @@
{ {
hostNames = [ hostNames = [
"router" "router"
"192.168.6.159" "192.168.1.228"
"192.168.3.1"
]; ];
arch = "x86_64-linux"; arch = "x86_64-linux";
@@ -13,5 +12,10 @@
"router" "router"
]; ];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKDCMhEvWJxFBNyvpyuljv5Uun8AdXCxBK9HvPBRe5x6"; hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFr2IHmWFlaLaLp5dGoSmFEYKA/eg2SwGXAogaOmLsHL";
remoteUnlock = {
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJOw5dTPmtKqiPBH6VKyz5MYBubn8leAh5Eaw7s/O85c";
onionHost = "jxx2exuihlls2t6ncs7rvrjh2dssubjmjtclwr2ysvxtr4t7jv55xmqd.onion";
};
} }

View File

@@ -31,10 +31,8 @@ in
networking.bridges = { networking.bridges = {
br0 = { br0 = {
interfaces = [ interfaces = [
"eth2" "enp2s0"
# "wlp4s0" "wlp4s0"
# "wlan1"
"wlan0"
"wlan1" "wlan1"
]; ];
}; };
@@ -66,173 +64,142 @@ in
services.dnsmasq = { services.dnsmasq = {
enable = true; enable = true;
settings = { extraConfig = ''
# sensible behaviours # sensible behaviours
domain-needed = true; domain-needed
bogus-priv = true; bogus-priv
no-resolv = true; no-resolv
# upstream name servers # upstream name servers
server = [ server=1.1.1.1
"1.1.1.1" server=8.8.8.8
"8.8.8.8"
];
# local domains # local domains
expand-hosts = true; expand-hosts
domain = "home"; domain=home
local = "/home/"; local=/home/
# Interfaces to use DNS on # Interfaces to use DNS on
interface = "br0"; interface=br0
# subnet IP blocks to use DHCP on # subnet IP blocks to use DHCP on
dhcp-range = "${cfg.privateSubnet}.10,${cfg.privateSubnet}.254,24h"; dhcp-range=${cfg.privateSubnet}.10,${cfg.privateSubnet}.254,24h
}; '';
}; };
services.hostapd = { services.hostapd = {
enable = true; enable = true;
radios = { radios = {
# Simple 2.4GHz AP # 2.4GHz
wlan0 = { wlp4s0 = {
hwMode = "g";
noScan = true;
channel = 6;
countryCode = "US"; countryCode = "US";
networks.wlan0 = { wifi4 = {
ssid = "CXNK00BF9176-1"; capabilities = [ "LDPC" "GF" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935" "HT40+" ];
authentication.saePasswords = [{ passwordFile = "/run/agenix/hostapd-pw-CXNK00BF9176"; }];
}; };
wifi5 = {
operatingChannelWidth = "20or40";
capabilities = [ "MAX-A-MPDU-LEN-EXP0" ];
};
wifi6 = {
enable = true;
singleUserBeamformer = true;
singleUserBeamformee = true;
multiUserBeamformer = true;
operatingChannelWidth = "20or40";
};
networks = {
wlp4s0 = {
ssid = "CXNK00BF9176";
authentication.saePasswordsFile = "/run/agenix/hostapd-pw-CXNK00BF9176";
};
# wlp4s0-1 = {
# ssid = "- Experimental 5G Tower by AT&T";
# authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# };
# wlp4s0-2 = {
# ssid = "FBI Surveillance Van 2";
# authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# };
};
extraConfig = ''
he_oper_centr_freq_seg0_idx=8
vht_oper_centr_freq_seg0_idx=8
'';
}; };
# WiFi 5 (5GHz) with two advertised networks # 5GHz
wlan1 = { wlan1 = {
band = "5g"; hwMode = "a";
channel = 0; noScan = true;
channel = 128;
countryCode = "US"; countryCode = "US";
networks.wlan1 = { wifi4 = {
ssid = "CXNK00BF9176-1"; capabilities = [ "LDPC" "GF" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935" "HT40-" ];
authentication.saePasswords = [{ passwordFile = "/run/agenix/hostapd-pw-CXNK00BF9176"; }]; };
}; wifi5 = {
operatingChannelWidth = "160";
capabilities = [ "RXLDPC" "SHORT-GI-80" "SHORT-GI-160" "TX-STBC-2BY1" "SU-BEAMFORMER" "SU-BEAMFORMEE" "MU-BEAMFORMER" "MU-BEAMFORMEE" "RX-ANTENNA-PATTERN" "TX-ANTENNA-PATTERN" "RX-STBC-1" "SOUNDING-DIMENSION-3" "BF-ANTENNA-3" "VHT160" "MAX-MPDU-11454" "MAX-A-MPDU-LEN-EXP7" ];
};
wifi6 = {
enable = true;
singleUserBeamformer = true;
singleUserBeamformee = true;
multiUserBeamformer = true;
operatingChannelWidth = "160";
};
networks = {
wlan1 = {
ssid = "CXNK00BF9176";
authentication.saePasswordsFile = "/run/agenix/hostapd-pw-CXNK00BF9176";
};
# wlan1-1 = {
# ssid = "- Experimental 5G Tower by AT&T";
# authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# };
# wlan1-2 = {
# ssid = "FBI Surveillance Van 5";
# authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# };
};
extraConfig = ''
vht_oper_centr_freq_seg0_idx=114
he_oper_centr_freq_seg0_idx=114
'';
}; };
}; };
}; };
age.secrets.hostapd-pw-experimental-tower.file = ../../secrets/hostapd-pw-experimental-tower.age;
age.secrets.hostapd-pw-CXNK00BF9176.file = ../../secrets/hostapd-pw-CXNK00BF9176.age; age.secrets.hostapd-pw-CXNK00BF9176.file = ../../secrets/hostapd-pw-CXNK00BF9176.age;
# wlan0 5Ghz 00:0a:52:08:38:32 hardware.firmware = [
# wlp4s0 2.4Ghz 00:0a:52:08:38:33 pkgs.mt7916-firmware
];
# services.hostapd = { nixpkgs.overlays = [
# enable = true; (self: super: {
# radios = { mt7916-firmware = pkgs.stdenvNoCC.mkDerivation {
# # 2.4GHz pname = "mt7916-firmware";
# wlp4s0 = { version = "custom-feb-02-23";
# band = "2g"; src = ./firmware/mediatek; # from here https://github.com/openwrt/mt76/issues/720#issuecomment-1413537674
# noScan = true; dontBuild = true;
# channel = 6; installPhase = ''
# countryCode = "US"; for i in \
# wifi4 = { mt7916_eeprom.bin \
# capabilities = [ "LDPC" "GF" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935" "HT40+" ]; mt7916_rom_patch.bin \
# }; mt7916_wa.bin \
# wifi5 = { mt7916_wm.bin;
# operatingChannelWidth = "20or40"; do
# capabilities = [ "MAX-A-MPDU-LEN-EXP0" ]; install -D -pm644 $i $out/lib/firmware/mediatek/$i
# }; done
# wifi6 = { '';
# enable = true; meta = with lib; {
# singleUserBeamformer = true; license = licenses.unfreeRedistributableFirmware;
# singleUserBeamformee = true; };
# multiUserBeamformer = true; };
# operatingChannelWidth = "20or40"; })
# }; ];
# networks = {
# wlp4s0 = {
# ssid = "CXNK00BF9176";
# authentication.saePasswordsFile = "/run/agenix/hostapd-pw-CXNK00BF9176";
# };
# # wlp4s0-1 = {
# # ssid = "- Experimental 5G Tower by AT&T";
# # authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# # };
# # wlp4s0-2 = {
# # ssid = "FBI Surveillance Van 2";
# # authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# # };
# };
# settings = {
# he_oper_centr_freq_seg0_idx = 8;
# vht_oper_centr_freq_seg0_idx = 8;
# };
# };
# # 5GHz
# wlan1 = {
# band = "5g";
# noScan = true;
# channel = 128;
# countryCode = "US";
# wifi4 = {
# capabilities = [ "LDPC" "GF" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935" "HT40-" ];
# };
# wifi5 = {
# operatingChannelWidth = "160";
# capabilities = [ "RXLDPC" "SHORT-GI-80" "SHORT-GI-160" "TX-STBC-2BY1" "SU-BEAMFORMER" "SU-BEAMFORMEE" "MU-BEAMFORMER" "MU-BEAMFORMEE" "RX-ANTENNA-PATTERN" "TX-ANTENNA-PATTERN" "RX-STBC-1" "SOUNDING-DIMENSION-3" "BF-ANTENNA-3" "VHT160" "MAX-MPDU-11454" "MAX-A-MPDU-LEN-EXP7" ];
# };
# wifi6 = {
# enable = true;
# singleUserBeamformer = true;
# singleUserBeamformee = true;
# multiUserBeamformer = true;
# operatingChannelWidth = "160";
# };
# networks = {
# wlan1 = {
# ssid = "CXNK00BF9176";
# authentication.saePasswordsFile = "/run/agenix/hostapd-pw-CXNK00BF9176";
# };
# # wlan1-1 = {
# # ssid = "- Experimental 5G Tower by AT&T";
# # authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# # };
# # wlan1-2 = {
# # ssid = "FBI Surveillance Van 5";
# # authentication.saePasswordsFile = "/run/agenix/hostapd-pw-experimental-tower";
# # };
# };
# settings = {
# vht_oper_centr_freq_seg0_idx = 114;
# he_oper_centr_freq_seg0_idx = 114;
# };
# };
# };
# };
# age.secrets.hostapd-pw-experimental-tower.file = ../../secrets/hostapd-pw-experimental-tower.age;
# age.secrets.hostapd-pw-CXNK00BF9176.file = ../../secrets/hostapd-pw-CXNK00BF9176.age;
# hardware.firmware = [
# pkgs.mt7916-firmware
# ];
# nixpkgs.overlays = [
# (self: super: {
# mt7916-firmware = pkgs.stdenvNoCC.mkDerivation {
# pname = "mt7916-firmware";
# version = "custom-feb-02-23";
# src = ./firmware/mediatek; # from here https://github.com/openwrt/mt76/issues/720#issuecomment-1413537674
# dontBuild = true;
# installPhase = ''
# for i in \
# mt7916_eeprom.bin \
# mt7916_rom_patch.bin \
# mt7916_wa.bin \
# mt7916_wm.bin;
# do
# install -D -pm644 $i $out/lib/firmware/mediatek/$i
# done
# '';
# meta = with lib; {
# license = licenses.unfreeRedistributableFirmware;
# };
# };
# })
# ];
}; };
} }

View File

@@ -1,297 +0,0 @@
{
appConfig = {
theme = "vaporware";
customColors = {
"material-dark-original" = {
primary = "#f36558";
background = "#39434C";
"background-darker" = "#eb615c";
"material-light" = "#f36558";
"item-text-color" = "#ff948a";
"curve-factor" = "5px";
};
};
enableErrorReporting = false;
layout = "auto";
iconSize = "large";
language = "en";
startingView = "default";
defaultOpeningMethod = "sametab";
statusCheck = true;
statusCheckInterval = 20;
faviconApi = "faviconkit";
routingMode = "history";
enableMultiTasking = false;
webSearch = {
disableWebSearch = false;
searchEngine = "duckduckgo";
openingMethod = "sametab";
searchBangs = { };
};
enableFontAwesome = true;
cssThemes = [ ];
externalStyleSheet = [ ];
hideComponents = {
hideHeading = false;
hideNav = false;
hideSearch = false;
hideSettings = false;
hideFooter = false;
hideSplashScreen = false;
};
auth = {
enableGuestAccess = false;
users = [ ];
enableKeycloak = false;
keycloak = { };
};
allowConfigEdit = true;
enableServiceWorker = false;
disableContextMenu = false;
disableUpdateChecks = false;
disableSmartSort = false;
};
pageInfo = {
title = "s0";
description = "s0";
};
sections = [
(
let
# Define the media section items once.
mediaItems = {
jellyfin = {
title = "Jellyfin";
icon = "hl-jellyfin";
url = "https://jellyfin.s0.neet.dev";
target = "sametab";
statusCheck = false;
id = "0_1956_jellyfin";
};
sonarr = {
title = "Sonarr";
description = "Manage TV";
icon = "hl-sonarr";
url = "https://sonarr.s0.neet.dev";
target = "sametab";
statusCheck = false;
id = "1_1956_sonarr";
};
radarr = {
title = "Radarr";
description = "Manage Movies";
icon = "hl-radarr";
url = "https://radarr.s0.neet.dev";
target = "sametab";
statusCheck = false;
id = "2_1956_radarr";
};
lidarr = {
title = "Lidarr";
description = "Manage Music";
icon = "hl-lidarr";
url = "https://lidarr.s0.neet.dev";
target = "sametab";
statusCheck = false;
id = "3_1956_lidarr";
};
prowlarr = {
title = "Prowlarr";
description = "Indexers";
icon = "hl-prowlarr";
url = "https://prowlarr.s0.neet.dev";
target = "sametab";
statusCheck = false;
id = "4_1956_prowlarr";
};
bazarr = {
title = "Bazarr";
description = "Subtitles";
icon = "hl-bazarr";
url = "https://bazarr.s0.neet.dev";
target = "sametab";
statusCheck = false;
id = "5_1956_bazarr";
};
navidrome = {
title = "Navidrome";
description = "Play Music";
icon = "hl-navidrome";
url = "https://music.s0.neet.dev";
target = "sametab";
statusCheck = false;
id = "6_1956_navidrome";
};
transmission = {
title = "Transmission";
description = "Torrenting";
icon = "hl-transmission";
url = "https://transmission.s0.neet.dev";
target = "sametab";
statusCheck = false;
id = "7_1956_transmission";
};
};
# Build the list once.
mediaList = [
mediaItems.jellyfin
mediaItems.sonarr
mediaItems.radarr
mediaItems.lidarr
mediaItems.prowlarr
mediaItems.bazarr
mediaItems.navidrome
mediaItems.transmission
];
in
{
name = "Media & Entertainment";
icon = "fas fa-photo-video";
displayData = {
sortBy = "most-used";
cols = 1;
rows = 1;
collapsed = false;
hideForGuests = false;
};
items = mediaList;
filteredItems = mediaList;
}
)
(
let
networkItems = {
gateway = {
title = "Gateway";
description = "openwrt";
icon = "hl-openwrt";
url = "http://openwrt.lan/";
target = "sametab";
statusCheck = true;
id = "0_746_gateway";
};
wireless = {
title = "Wireless";
description = "openwrt (ish)";
icon = "hl-openwrt";
url = "http://PacketProvocateur.lan";
target = "sametab";
statusCheck = true;
id = "1_746_wireless";
};
};
networkList = [
networkItems.gateway
networkItems.wireless
];
in
{
name = "Network";
icon = "fas fa-network-wired";
items = networkList;
filteredItems = networkList;
displayData = {
sortBy = "default";
rows = 1;
cols = 1;
collapsed = false;
hideForGuests = false;
};
}
)
(
let
servicesItems = {
matrix = {
title = "Matrix";
description = "";
icon = "hl-matrix";
url = "https://chat.neet.space";
target = "sametab";
statusCheck = true;
id = "0_836_matrix";
};
mumble = {
title = "Mumble";
description = "voice.neet.space";
icon = "hl-mumble";
url = "https://voice.neet.space";
target = "sametab";
statusCheck = false;
id = "2_836_mumble";
};
irc = {
title = "IRC";
description = "irc.neet.dev";
icon = "hl-thelounge";
url = "https://irc.neet.dev";
target = "sametab";
statusCheck = true;
id = "3_836_irc";
};
git = {
title = "Git";
description = "git.neet.dev";
icon = "hl-gitea";
url = "https://git.neet.dev";
target = "sametab";
statusCheck = true;
id = "4_836_git";
};
nextcloud = {
title = "Nextcloud";
description = "neet.cloud";
icon = "hl-nextcloud";
url = "https://neet.cloud";
target = "sametab";
statusCheck = true;
id = "5_836_nextcloud";
};
roundcube = {
title = "Roundcube";
description = "mail.neet.dev";
icon = "hl-roundcube";
url = "https://mail.neet.dev";
target = "sametab";
statusCheck = true;
id = "6_836_roundcube";
};
jitsimeet = {
title = "Jitsi Meet";
description = "meet.neet.space";
icon = "hl-jitsimeet";
url = "https://meet.neet.space";
target = "sametab";
statusCheck = true;
id = "7_836_jitsimeet";
};
};
servicesList = [
servicesItems.matrix
servicesItems.mumble
servicesItems.irc
servicesItems.git
servicesItems.nextcloud
servicesItems.roundcube
servicesItems.jitsimeet
];
in
{
name = "Services";
icon = "fas fa-monitor-heart-rate";
items = servicesList;
filteredItems = servicesList;
displayData = {
sortBy = "default";
rows = 1;
cols = 1;
collapsed = false;
hideForGuests = false;
};
}
)
];
}

View File

@@ -3,14 +3,15 @@
{ {
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
./frigate.nix
./home-automation.nix
]; ];
networking.hostName = "s0"; networking.hostName = "s0";
# system.autoUpgrade.enable = true; # system.autoUpgrade.enable = true;
# gitea runner and allow it to build ARM derivations
services.gitea-runner.enable = true;
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
nix.gc.automatic = lib.mkForce false; # allow the nix store to serve as a build cache nix.gc.automatic = lib.mkForce false; # allow the nix store to serve as a build cache
# binary cache # binary cache
@@ -20,13 +21,6 @@
secretKeyFile = "/run/agenix/binary-cache-private-key"; secretKeyFile = "/run/agenix/binary-cache-private-key";
}; };
age.secrets.binary-cache-private-key.file = ../../../secrets/binary-cache-private-key.age; age.secrets.binary-cache-private-key.file = ../../../secrets/binary-cache-private-key.age;
# users.users.cache-push = {
# isNormalUser = true;
# openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINpUZFFL9BpBVqeeU63sFPhR9ewuhEZerTCDIGW1NPSB" ];
# };
# nix.settings = {
# trusted-users = [ "cache-push" ];
# };
services.iperf3.enable = true; services.iperf3.enable = true;
services.iperf3.openFirewall = true; services.iperf3.openFirewall = true;
@@ -41,6 +35,9 @@
# samba # samba
services.samba.enable = true; services.samba.enable = true;
# disable suspend on lid close
services.logind.lidSwitch = "ignore";
# navidrome # navidrome
services.navidrome = { services.navidrome = {
enable = true; enable = true;
@@ -50,6 +47,7 @@
MusicFolder = "/data/samba/Public/Media/Music"; MusicFolder = "/data/samba/Public/Media/Music";
}; };
}; };
networking.firewall.allowedTCPPorts = [ config.services.navidrome.settings.Port ];
# allow access to transmisson data # allow access to transmisson data
users.users.googlebot.extraGroups = [ "transmission" ]; users.users.googlebot.extraGroups = [ "transmission" ];
@@ -75,36 +73,9 @@
services.lidarr.enable = true; services.lidarr.enable = true;
services.lidarr.user = "public_data"; services.lidarr.user = "public_data";
services.lidarr.group = "public_data"; services.lidarr.group = "public_data";
services.recyclarr = {
enable = true;
configuration = {
radarr.radarr_main = {
api_key = {
_secret = "/run/credentials/recyclarr.service/radarr-api-key";
};
base_url = "http://localhost:7878";
quality_definition.type = "movie";
};
sonarr.sonarr_main = {
api_key = {
_secret = "/run/credentials/recyclarr.service/sonarr-api-key";
};
base_url = "http://localhost:8989";
quality_definition.type = "series";
};
};
};
systemd.services.recyclarr.serviceConfig.LoadCredential = [
"radarr-api-key:/run/agenix/radarr-api-key"
"sonarr-api-key:/run/agenix/sonarr-api-key"
];
services.transmission = { services.transmission = {
enable = true; enable = true;
package = pkgs.transmission_4;
performanceNetParameters = true; performanceNetParameters = true;
user = "public_data"; user = "public_data";
group = "public_data"; group = "public_data";
@@ -144,19 +115,13 @@
# "speed-limit-up-enabled" = true; # "speed-limit-up-enabled" = true;
/* seeding limit */ /* seeding limit */
"ratio-limit" = 3; "ratio-limit" = 2;
"ratio-limit-enabled" = true; "ratio-limit-enabled" = true;
"download-queue-enabled" = true; "download-queue-enabled" = true;
"download-queue-size" = 20; # gotta go fast "download-queue-size" = 20; # gotta go fast
}; };
}; };
# https://github.com/NixOS/nixpkgs/issues/258793
systemd.services.transmission.serviceConfig = {
RootDirectoryStartOnly = lib.mkForce (lib.mkForce false);
RootDirectory = lib.mkForce (lib.mkForce "");
};
users.groups.public_data.gid = 994; users.groups.public_data.gid = 994;
users.users.public_data = { users.users.public_data = {
isSystemUser = true; isSystemUser = true;
@@ -172,201 +137,44 @@
8686 # lidarr 8686 # lidarr
9091 # transmission web 9091 # transmission web
]; ];
age.secrets.radarr-api-key.file = ../../../secrets/radarr-api-key.age;
age.secrets.sonarr-api-key.file = ../../../secrets/sonarr-api-key.age;
# jellyfin # jellyfin
# jellyfin cannot run in the vpn container and use hardware encoding # jellyfin cannot run in the vpn container and use hardware encoding
# I could not figure out how to allow the container to access the encoder # I could not figure out how to allow the container to access the encoder
services.jellyfin.enable = true; services.jellyfin.enable = true;
users.users.${config.services.jellyfin.user}.extraGroups = [ "public_data" ]; users.users.${config.services.jellyfin.user}.extraGroups = [ "public_data" ];
hardware.graphics = { nixpkgs.config.packageOverrides = pkgs: {
vaapiIntel = pkgs.vaapiIntel.override { enableHybridCodec = true; };
};
hardware.opengl = {
enable = true; enable = true;
extraPackages = with pkgs; [ extraPackages = with pkgs; [
intel-media-driver intel-media-driver
vaapiIntel
vaapiVdpau
libvdpau-va-gl libvdpau-va-gl
intel-compute-runtime # OpenCL filter support (hardware tonemapping and subtitle burn-in) intel-compute-runtime # OpenCL filter support (hardware tonemapping and subtitle burn-in)
]; ];
}; };
# nginx # nginx
services.nginx = { services.nginx.enable = true;
enable = true; services.nginx.virtualHosts."bazarr.s0".locations."/".proxyPass = "http://vpn.containers:6767";
openFirewall = false; # All nginx services are internal services.nginx.virtualHosts."radarr.s0".locations."/".proxyPass = "http://vpn.containers:7878";
virtualHosts = services.nginx.virtualHosts."lidarr.s0".locations."/".proxyPass = "http://vpn.containers:8686";
let services.nginx.virtualHosts."sonarr.s0".locations."/".proxyPass = "http://vpn.containers:8989";
mkHost = external: config: services.nginx.virtualHosts."prowlarr.s0".locations."/".proxyPass = "http://vpn.containers:9696";
{ services.nginx.virtualHosts."music.s0".locations."/".proxyPass = "http://localhost:4533";
${external} = { services.nginx.virtualHosts."jellyfin.s0".locations."/" = {
useACMEHost = "s0.neet.dev"; # Use wildcard cert proxyPass = "http://localhost:8096";
forceSSL = true;
locations."/" = config;
};
};
mkVirtualHost = external: internal:
mkHost external {
proxyPass = internal;
proxyWebsockets = true; proxyWebsockets = true;
}; };
mkStaticHost = external: static: services.nginx.virtualHosts."jellyfin.neet.cloud".locations."/" = {
mkHost external { proxyPass = "http://localhost:8096";
root = static; proxyWebsockets = true;
tryFiles = "$uri /index.html ";
}; };
in services.nginx.virtualHosts."transmission.s0".locations."/" = {
lib.mkMerge [ proxyPass = "http://vpn.containers:9091";
(mkVirtualHost "bazarr.s0.neet.dev" "http://vpn.containers:6767") proxyWebsockets = true;
(mkVirtualHost "radarr.s0.neet.dev" "http://vpn.containers:7878")
(mkVirtualHost "lidarr.s0.neet.dev" "http://vpn.containers:8686")
(mkVirtualHost "sonarr.s0.neet.dev" "http://vpn.containers:8989")
(mkVirtualHost "prowlarr.s0.neet.dev" "http://vpn.containers:9696")
(mkVirtualHost "transmission.s0.neet.dev" "http://vpn.containers:9091")
(mkVirtualHost "unifi.s0.neet.dev" "https://localhost:8443")
(mkVirtualHost "music.s0.neet.dev" "http://localhost:4533")
(mkVirtualHost "jellyfin.s0.neet.dev" "http://localhost:8096")
(mkStaticHost "s0.neet.dev" config.services.dashy.finalDrv)
{
# Landing page LAN redirect
"s0" = {
default = true;
redirectCode = 302;
globalRedirect = "s0.neet.dev";
}; };
} }
(mkVirtualHost "ha.s0.neet.dev" "http://localhost:${toString config.services.home-assistant.config.http.server_port}")
(mkVirtualHost "esphome.s0.neet.dev" "http://localhost:6052")
(mkVirtualHost "zigbee.s0.neet.dev" "http://localhost:55834")
{
"frigate.s0.neet.dev" = {
# Just configure SSL, frigate module configures the rest of nginx
useACMEHost = "s0.neet.dev";
forceSSL = true;
};
}
(mkVirtualHost "vacuum.s0.neet.dev" "http://192.168.1.125") # valetudo
(mkVirtualHost "sandman.s0.neet.dev" "http://192.168.9.14:3000") # es
(mkVirtualHost "todo.s0.neet.dev" "http://localhost:${toString config.services.vikunja.port}")
(mkVirtualHost "budget.s0.neet.dev" "http://localhost:${toString config.services.actual.settings.port}") # actual budget
(mkVirtualHost "linkwarden.s0.neet.dev" "http://localhost:${toString config.services.linkwarden.port}")
(mkVirtualHost "memos.s0.neet.dev" "http://localhost:${toString config.services.memos.settings.MEMOS_PORT}")
(mkVirtualHost "outline.s0.neet.dev" "http://localhost:${toString config.services.outline.port}")
(mkVirtualHost "languagetool.s0.neet.dev" "http://localhost:${toString config.services.languagetool.port}")
];
tailscaleAuth = {
enable = true;
virtualHosts = [
"bazarr.s0.neet.dev"
"radarr.s0.neet.dev"
"lidarr.s0.neet.dev"
"sonarr.s0.neet.dev"
"prowlarr.s0.neet.dev"
"transmission.s0.neet.dev"
"unifi.s0.neet.dev"
# "music.s0.neet.dev" # messes up navidrome
"jellyfin.s0.neet.dev"
"s0.neet.dev"
# "ha.s0.neet.dev" # messes up home assistant
"esphome.s0.neet.dev"
"zigbee.s0.neet.dev"
"vacuum.s0.neet.dev"
"todo.s0.neet.dev"
"budget.s0.neet.dev"
"linkwarden.s0.neet.dev"
# "memos.s0.neet.dev" # messes up memos /auth route
# "outline.s0.neet.dev" # messes up outline /auth route
"languagetool.s0.neet.dev"
];
expectedTailnet = "koi-bebop.ts.net";
};
};
# Get wildcard cert
security.acme.certs."s0.neet.dev" = {
dnsProvider = "digitalocean";
credentialsFile = "/run/agenix/digitalocean-dns-credentials";
extraDomainNames = [ "*.s0.neet.dev" ];
group = "nginx";
dnsResolver = "1.1.1.1:53";
dnsPropagationCheck = false; # sadly this erroneously fails
};
age.secrets.digitalocean-dns-credentials.file = ../../../secrets/digitalocean-dns-credentials.age;
virtualisation.oci-containers.backend = "podman";
virtualisation.podman.dockerSocket.enable = true; # TODO needed?
services.dashy = {
enable = true;
settings = import ./dashy.nix;
};
services.unifi = {
enable = true;
openMinimalFirewall = true;
};
services.vikunja = {
enable = true;
port = 61473;
frontendScheme = "https";
frontendHostname = "todo.s0.neet.dev";
settings = {
service.enableregistration = false;
};
};
backup.group."vikunja".paths = [
"/var/lib/vikunja"
];
services.actual.enable = true;
services.linkwarden = {
enable = true;
enableRegistration = true;
port = 41709;
environment.NEXTAUTH_URL = "https://linkwarden.s0.neet.dev/api/v1/auth";
environmentFile = "/run/agenix/linkwarden-environment";
};
age.secrets.linkwarden-environment.file = ../../../secrets/linkwarden-environment.age;
services.meilisearch = {
enable = true;
package = pkgs.meilisearch;
};
services.flaresolverr = {
enable = true;
port = 48072;
};
services.memos = {
enable = true;
settings.MEMOS_PORT = "57643";
};
services.outline = {
enable = true;
forceHttps = false; # https through nginx
port = 43933;
publicUrl = "https://outline.s0.neet.dev";
storage.storageType = "local";
smtp = {
secure = true;
fromEmail = "robot@runyan.org";
username = "robot@runyan.org";
replyEmail = "robot@runyan.org";
host = "mail.neet.dev";
port = 465;
passwordFile = "/run/agenix/robots-email-pw";
};
};
age.secrets.robots-email-pw = {
file = ../../../secrets/robots-email-pw.age;
owner = config.services.outline.user;
};
services.languagetool = {
enable = true;
port = 60613;
};
boot.binfmt.emulatedSystems = [ "aarch64-linux" "armv7l-linux" ];
}

View File

@@ -1,159 +0,0 @@
{ config, pkgs, lib, ... }:
let
frigateHostname = "frigate.s0.neet.dev";
mkGo2RtcStream = name: url: withAudio: {
${name} = [
url
"ffmpeg:${name}#video=copy${if withAudio then "#audio=copy" else ""}"
];
};
# Assumes camera is set to output:
# - rtsp
# - H.264 + AAC
# - a downscaled substream for detection
mkCamera = name: primaryUrl: detectUrl: {
# Reference https://docs.frigate.video/configuration/reference/
services.frigate.settings = {
cameras.${name} = {
ffmpeg = {
# Camera feeds are relayed through go2rtc
inputs = [
{
path = "rtsp://127.0.0.1:8554/${name}";
# input_args = "preset-rtsp-restream";
input_args = "preset-rtsp-restream-low-latency";
roles = [ "record" ];
}
{
path = detectUrl;
roles = [ "detect" ];
}
];
output_args = {
record = "preset-record-generic-audio-copy";
};
};
detect = {
width = 1280;
height = 720;
fps = 5;
};
};
};
services.go2rtc.settings.streams = lib.mkMerge [
(mkGo2RtcStream name primaryUrl false)
# Sadly having the detection stream go through go2rpc too makes the stream unreadable by frigate for some reason.
# It might need to be re-encoded to work. But I am not interested in wasting the processing power if only frigate
# need the detection stream anyway. So just let frigate grab the stream directly since it works.
# (mkGo2RtcStream detectName detectUrl false)
];
};
mkDahuaCamera = name: address:
let
# go2rtc and frigate have a slightly different syntax for inserting env vars. So the URLs are not interchangable :(
# - go2rtc: ${VAR}
# - frigate: {VAR}
primaryUrl = "rtsp://admin:\${FRIGATE_RTSP_PASSWORD}@${address}/cam/realmonitor?channel=1&subtype=0";
detectUrl = "rtsp://admin:{FRIGATE_RTSP_PASSWORD}@${address}/cam/realmonitor?channel=1&subtype=3";
in
mkCamera name primaryUrl detectUrl;
mkEsp32Camera = name: address: {
services.frigate.settings.cameras.${name} = {
ffmpeg = {
input_args = "";
inputs = [{
path = "http://${address}:8080";
roles = [ "detect" "record" ];
}];
output_args.record = "-f segment -pix_fmt yuv420p -segment_time 10 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c:v libx264 -preset ultrafast -an ";
};
};
};
in
lib.mkMerge [
(mkDahuaCamera "dog-cam" "192.168.10.31")
# (mkEsp32Camera "dahlia-cam" "dahlia-cam.lan")
{
services.frigate = {
enable = true;
hostname = frigateHostname;
# Sadly this fails because it doesn't support frigate's var substition format
# which is critical... so what's even the point of it then?
checkConfig = false;
settings = {
mqtt = {
enabled = true;
host = "localhost";
port = 1883;
user = "root";
password = "{FRIGATE_MQTT_PASSWORD}";
};
snapshots = {
enabled = true;
bounding_box = true;
};
record = {
enabled = true;
# sync_recordings = true; # detect if recordings were deleted outside of frigate (expensive)
retain = {
days = 7; # Keep video for 7 days
mode = "all";
# mode = "motion";
};
events = {
retain = {
default = 10; # Keep video with detections for 10 days
mode = "motion";
# mode = "active_objects";
};
};
};
# Make frigate aware of the go2rtc streams
go2rtc.streams = config.services.go2rtc.settings.streams;
detect.enabled = false; # :(
objects = {
track = [ "person" "dog" ];
};
};
};
services.go2rtc = {
enable = true;
settings = {
rtsp.listen = ":8554";
webrtc.listen = ":8555";
};
};
# Pass in env file with secrets to frigate/go2rtc
systemd.services.frigate.serviceConfig.EnvironmentFile = "/run/agenix/frigate-credentials";
systemd.services.go2rtc.serviceConfig.EnvironmentFile = "/run/agenix/frigate-credentials";
age.secrets.frigate-credentials.file = ../../../secrets/frigate-credentials.age;
}
{
# hardware encode/decode with amdgpu vaapi
services.frigate.vaapiDriver = "radeonsi";
services.frigate.settings.ffmpeg.hwaccel_args = "preset-vaapi";
}
{
# Coral TPU for frigate
services.frigate.settings.detectors.coral = {
type = "edgetpu";
device = "pci";
};
}
{
# Don't require authentication for frigate
# This is ok because the reverse proxy already requires tailscale access anyway
services.frigate.settings.auth.enabled = false;
}
]

View File

@@ -8,7 +8,6 @@
# boot # boot
boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot.enable = true;
boot.loader.systemd-boot.memtest86.enable = true;
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "uas" "sd_mod" "rtsx_pci_sdmmc" ]; boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "uas" "sd_mod" "rtsx_pci_sdmmc" ];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ]; boot.kernelModules = [ "kvm-intel" ];
@@ -22,6 +21,7 @@
# zfs # zfs
networking.hostId = "5e6791f0"; networking.hostId = "5e6791f0";
boot.supportedFilesystems = [ "zfs" ]; boot.supportedFilesystems = [ "zfs" ];
boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages;
# luks # luks
remoteLuksUnlock.enable = true; remoteLuksUnlock.enable = true;
@@ -31,14 +31,18 @@
boot.initrd.luks.devices."enc-pv4".device = "/dev/disk/by-uuid/e2c7402a-e72c-4c4a-998f-82e4c10187bc"; boot.initrd.luks.devices."enc-pv4".device = "/dev/disk/by-uuid/e2c7402a-e72c-4c4a-998f-82e4c10187bc";
# mounts # mounts
services.zfs.autoScrub.enable = true;
services.zfs.trim.enable = true;
fileSystems."/" = fileSystems."/" =
{ {
device = "rpool/nixos/root"; device = "rpool/nixos/root";
fsType = "zfs"; fsType = "zfs";
options = [ "zfsutil" "X-mount.mkdir" ]; options = [ "zfsutil" "X-mount.mkdir" ];
}; };
fileSystems."/home" =
{
device = "rpool/nixos/home";
fsType = "zfs";
options = [ "zfsutil" "X-mount.mkdir" ];
};
fileSystems."/var/lib" = fileSystems."/var/lib" =
{ {
device = "rpool/nixos/var/lib"; device = "rpool/nixos/var/lib";
@@ -51,6 +55,13 @@
fsType = "zfs"; fsType = "zfs";
options = [ "zfsutil" "X-mount.mkdir" ]; options = [ "zfsutil" "X-mount.mkdir" ];
}; };
fileSystems."/data" =
{
device = "rpool/nixos/data";
fsType = "zfs";
options = [ "zfsutil" "X-mount.mkdir" ];
};
fileSystems."/boot" = fileSystems."/boot" =
{ {
device = "/dev/disk/by-uuid/4FB4-738E"; device = "/dev/disk/by-uuid/4FB4-738E";
@@ -58,48 +69,7 @@
}; };
swapDevices = [ ]; swapDevices = [ ];
### networking ### networking.interfaces.eth0.useDHCP = true;
# systemd.network.enable = true;
networking = {
# useNetworkd = true;
dhcpcd.enable = true;
interfaces."eth0".useDHCP = true;
interfaces."eth1".useDHCP = false;
interfaces."main@eth1".useDHCP = true;
interfaces."iot@eth1".useDHCP = true;
interfaces."management@eth1".useDHCP = true;
vlans = {
main = {
id = 5;
interface = "eth1";
};
iot = {
id = 2;
interface = "eth1";
};
management = {
id = 4;
interface = "eth1";
};
};
# interfaces.eth1.ipv4.addresses = [{
# address = "192.168.1.2";
# prefixLength = 21;
# }];
# interfaces.iot.ipv4.addresses = [{
# address = "192.168.9.8";
# prefixLength = 22;
# }];
defaultGateway = {
# interface = "eth1";
address = "192.168.1.1";
};
# nameservers = [ "1.1.1.1" "8.8.8.8" ];
};
powerManagement.cpuFreqGovernor = "powersave"; powerManagement.cpuFreqGovernor = "powersave";
} }

View File

@@ -1,155 +0,0 @@
{ config, lib, pkgs, ... }:
{
services.esphome.enable = true;
services.mosquitto = {
enable = true;
listeners = [
{
users.root = {
acl = [ "readwrite #" ];
hashedPassword = "$7$101$8+QnkTzCdGizaKqq$lpU4o84n6D/1uwfA9pZDVExr1NDm1D/8tNla2tE9J9HdUqkvu192yYfiySY1MFqVNgUKgWEFu5P1bUKqRnzbUw==";
};
}
];
};
networking.firewall.allowedTCPPorts = [
# mqtt
1883
# Must be exposed so some local devices (such as HA voice preview) can pair with home assistant
config.services.home-assistant.config.http.server_port
# Music assistant (must be exposed so local devices can fetch the audio stream from it)
8095
8097
];
services.zigbee2mqtt = {
enable = true;
settings = {
permit_join = false;
serial = {
adapter = "ember";
port = "/dev/ttyACM0";
};
mqtt = {
server = "mqtt://localhost:1883";
user = "root";
password = "!/run/agenix/zigbee2mqtt.yaml mqtt_password";
};
frontend = {
host = "localhost";
port = 55834;
};
};
};
age.secrets."zigbee2mqtt.yaml" = {
file = ../../../secrets/zigbee2mqtt.yaml.age;
owner = "zigbee2mqtt";
};
services.home-assistant = {
enable = true;
extraComponents = [
"default_config"
"rest_command"
"esphome"
"met"
"radio_browser"
"wled"
"mqtt"
"apple_tv" # why is this even needed? I get `ModuleNotFoundError: No module named 'pyatv'` errors otherwise for some reason.
"unifi"
"digital_ocean"
"downloader"
"mailgun"
"minecraft_server"
"mullvad"
"nextcloud"
"ollama"
"openweathermap"
"jellyfin"
"transmission"
"radarr"
"sonarr"
"syncthing"
"tailscale"
"weather"
"whois"
"youtube"
"homekit_controller"
"zha"
"bluetooth"
"whisper"
"piper"
"wyoming"
"tts"
"music_assistant"
"openai_conversation"
];
config = {
# Includes dependencies for a basic setup
# https://www.home-assistant.io/integrations/default_config/
default_config = { };
homeassistant = {
external_url = "https://ha.s0.neet.dev";
internal_url = "http://192.168.1.2:${toString config.services.home-assistant.config.http.server_port}";
};
# Enable reverse proxy support
http = {
use_x_forwarded_for = true;
trusted_proxies = [
"127.0.0.1"
"::1"
];
};
"automation manual" = [
];
# Allow using automations generated from the UI
"automation ui" = "!include automations.yaml";
"rest_command" = {
json_post_request = {
url = "{{ url }}";
method = "POST";
content_type = "application/json";
payload = "{{ payload | default('{}') }}";
};
};
};
};
services.wyoming.faster-whisper.servers."hass" = {
enable = true;
uri = "tcp://0.0.0.0:45785";
model = "distil-small.en";
language = "en";
};
services.wyoming.piper.servers."hass" = {
enable = true;
uri = "tcp://0.0.0.0:45786";
voice = "en_US-joe-medium";
};
services.music-assistant = {
enable = true;
providers = [
"hass"
"hass_players"
"jellyfin"
"radiobrowser"
"spotify"
];
};
networking.hosts = {
# Workaround for broken spotify api integration
# https://github.com/librespot-org/librespot/issues/1527#issuecomment-3167094158
"0.0.0.0" = [ "apresolve.spotify.com" ];
};
}

View File

@@ -1,7 +1,6 @@
{ {
hostNames = [ hostNames = [
"s0" "s0"
"s0.neet.dev"
]; ];
arch = "x86_64-linux"; arch = "x86_64-linux";
@@ -11,21 +10,12 @@
"server" "server"
"pia" "pia"
"binary-cache" "binary-cache"
"gitea-actions-runner"
"frigate"
"zigbee"
"media-server"
"linkwarden"
"outline"
"dns-challenge"
]; ];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwiXcUFtAvZCayhu4+AIcF+Ktrdgv9ee/mXSIhJbp4q"; hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwiXcUFtAvZCayhu4+AIcF+Ktrdgv9ee/mXSIhJbp4q";
remoteUnlock = { remoteUnlock = {
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFNiceeFMos5ZXcYem4yFxh8PiZNNnuvhlyLbQLrgIZH"; hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFNiceeFMos5ZXcYem4yFxh8PiZNNnuvhlyLbQLrgIZH";
clearnetHost = "192.168.1.2";
onionHost = "r3zvf7f2ppaeithzswigma46pajt3hqytmkg3rshgknbl3jbni455fqd.onion"; onionHost = "r3zvf7f2ppaeithzswigma46pajt3hqytmkg3rshgknbl3jbni455fqd.onion";
}; };
} }

View File

@@ -1,79 +0,0 @@
{ config, pkgs, lib, ... }:
{
imports = [
./hardware-configuration.nix
];
# Login DE Option: Steam
programs.steam.gamescopeSession.enable = true;
# programs.gamescope.capSysNice = true;
# Login DE Option: Kodi
services.xserver.desktopManager.kodi.enable = true;
services.xserver.desktopManager.kodi.package =
(
pkgs.kodi.passthru.withPackages (kodiPackages: with kodiPackages; [
jellyfin
joystick
])
);
services.mount-samba.enable = true;
# wireless xbox controller support
hardware.xone.enable = true;
boot.kernelModules = [ "xone-wired" "xone-dongle" ];
hardware.enableRedistributableFirmware = true;
hardware.enableAllFirmware = true;
# ROCm
hardware.graphics.extraPackages = with pkgs; [
rocmPackages.clr.icd
rocmPackages.clr
];
systemd.tmpfiles.rules = [
"L+ /opt/rocm/hip - - - - ${pkgs.rocmPackages.clr}"
];
services.displayManager.defaultSession = "plasma";
users.users.cris = {
isNormalUser = true;
hashedPassword = "$y$j9T$LMGwHVauFWAcAyWSSmcuS/$BQpDyjDHZZbvj54.ijvNb03tr7IgX9wcjYCuCxjSqf6";
uid = 1001;
packages = with pkgs; [
maestral
maestral-gui
] ++ config.users.users.googlebot.packages;
};
# Dr. John A. Zoidberg
users.users.john = {
isNormalUser = true;
inherit (config.users.users.googlebot) hashedPassword packages;
uid = 1002;
};
# Auto login into Plasma in john zoidberg account
services.displayManager.sddm.settings = {
Autologin = {
Session = "plasma";
User = "john";
};
};
environment.systemPackages = with pkgs; [
config.services.xserver.desktopManager.kodi.package
spotify
];
# Command and Conquer Ports
networking.firewall.allowedUDPPorts = [ 4321 27900 ];
networking.firewall.allowedTCPPorts = [ 6667 28910 29900 29920 ];
services.ollama = {
enable = true;
package = pkgs.ollama-vulkan;
host = "127.0.0.1";
};
}

View File

@@ -1,47 +0,0 @@
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[
(modulesPath + "/installer/scan/not-detected.nix")
];
# boot
boot.loader.systemd-boot.enable = true;
boot.loader.timeout = lib.mkForce 15;
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "usbhid" "sd_mod" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
# kernel
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
boot.kernelPackages = pkgs.linuxPackages_latest;
# luks unlock with clevis
boot.initrd.systemd.enable = true;
boot.initrd.clevis = {
enable = true;
devices."enc-pv".secretFile = "/secret/decrypt.jwe";
};
# disks
boot.initrd.luks.devices."enc-pv" = {
device = "/dev/disk/by-uuid/04231c41-2f13-49c0-8fce-0357eea67990";
allowDiscards = true;
};
fileSystems."/" =
{
device = "/dev/disk/by-uuid/39ee326c-a42f-49f3-84d9-f10091a903cd";
fsType = "btrfs";
};
fileSystems."/boot" =
{
device = "/dev/disk/by-uuid/954B-AB3E";
fsType = "vfat";
};
swapDevices =
[{ device = "/dev/disk/by-uuid/44e36954-9f1c-49ae-af07-72b240f93a95"; }];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View File

@@ -1,14 +0,0 @@
{
hostNames = [
"zoidberg"
];
arch = "x86_64-linux";
systemRoles = [
"personal"
"media-center"
];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHvdC1EiLqSNVmk5L1p7cWRIrrlelbK+NMj6tEBrwqIq";
}

View File

@@ -1,7 +0,0 @@
{ inputs }:
final: prev:
let
system = prev.system;
in
{ }

View File

@@ -1,11 +0,0 @@
{ config, lib, ... }:
# Adds additional kernel modules to the nixos system
# Not actually an overlay but a module. Has to be this way because kernel
# modules are tightly coupled to the kernel version they were built against.
# https://nixos.wiki/wiki/Linux_kernel
let
cfg = config.kernel;
in
{ }

View File

@@ -1,15 +0,0 @@
diff --git a/nixos/modules/services/video/frigate.nix b/nixos/modules/services/video/frigate.nix
index f8d8f64e55da..39326d094118 100644
--- a/nixos/modules/services/video/frigate.nix
+++ b/nixos/modules/services/video/frigate.nix
@@ -609,10 +609,6 @@ in
};
};
extraConfig = ''
- # Frigate wants to connect on 127.0.0.1:5000 for unauthenticated requests
- # https://github.com/NixOS/nixpkgs/issues/370349
- listen 127.0.0.1:5000;
-
# vod settings
vod_base_url "";
vod_segments_base_url "";

Binary file not shown.

View File

@@ -1,11 +1,10 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 hPp1nw qfzeHTN5gk0CDb3Fmwak0InkJkxvlS5foxkuTKIvPTY -> ssh-ed25519 hPp1nw 4fyRGsaEo25EOj/VwPsF0tayghF0URctont4/re6OmY
lEwEcGfpiJQae3mSD2yLfGFm97FZD6K5tOzBHRzT8/Q rs09DCSb2bd/v45a7ABxfLo+Sz3OPLkRzfnP5Tmgi0g
-> ssh-ed25519 ZDy34A uS/CLVSyXkRIWlPEgtFn0NK6QFKZCeLHvT7Z1509Hjg -> ssh-ed25519 dMQYog seRjdySBF1GISaSUWqZNvoW4INDUCxvBKJOgvGeyX1Q
TpW6Y5iRXu7YpDbQV63m+3/LtqIujX54kiXH0ddqF9I fe6JE5f9A48ujVtuc0QZ7e7pWW+Tu0yyQEyexTvQWAQ
-> ssh-ed25519 w3nu8g IEC1wZ/EO+CHOvED3nQHPos7LDuiyivIqo3DKAOqZC4 -> Uqf![<-grease O}' _h*Y~ .@=$H,~W
XAh21OtD2A8psVBsGYXBY9oBf/woIxkIEMv2VMAYucg jDlO5MEGPDjJ44cAWuJaTeADbG+wz5PTqq9Pw75QV3Exrsb8/PNGOrUZKuSTCCl3
-> ssh-ed25519 evqvfg DC9pQv6Jknsi532+px3q5m1HAeYHje0MeZSdPoD0JXA g/z3ZHelBBqHp16ZTc+LSxDYgvnEfWMPZKo4mxgu
rbXOmY3keN63YZL+kfpmZ9sOlOxWa+GVqgYBKURckvk --- GTBCzHJYUKbpcgq7+0HzBpqvo0F7TNSPjFKqdRDUYDk
--- kIbVnf+2GlZRu1BGVi1zlHEIbuBxUX3/jvAHvwNtO88 ÈÚú¡T+ñ—êtµ(פÉF ÆS<C386>/R±+¢¼Н‘âLÃÝcÁ‰·1
Óûy]3â(@Žíº¡äÊÛ2v»ñÀéÔmwãÌП@ñÆPf†Êˆ:[ïÆ‡×¦!ãžQ¦<51>Å Ö<E28099>÷J0²á¸Oþ§KØCþjÐ#;VåWåŽduŒÇ<C592> Äiƒ?×g£c<C2A3><EFBFBD>ˆr>Ïú‹\«¦ü´5@ÓqÙ<71>ÎH22-dË«¸<C2AB>¿ÄPœ5 <20>|>ŒÜu

Binary file not shown.

Binary file not shown.

View File

@@ -1,11 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 hPp1nw MMPi5i5lVf/mcXOraMoErj12pjLWQppVTc18kMFTskM
eez7lnpUwseCP/5MZRxjyPZ11gfLHBYPPGEUXUftrAU
-> ssh-ed25519 ZDy34A dzbWYENdNUIHId+2XUt+gLpnw8xaVsSHrWfIhhBTYBI
NszPXqq/beWLE9pKMhbXYSEB3WDaU2EPy66yPC+oU+Y
-> ssh-ed25519 w3nu8g HjJYUyssutwK+bO120fPZoycsIEdLL0gnX1UDMHJKlY
jjr1bEAD4HHN1Hbdtj8VR6CqfkTHXZ6huJQ1fnp83s4
-> ssh-ed25519 evqvfg nNibZIdrlMqQXZYT+qFPyd8uB1gZgDjPdfIS7RRjJCM
5LNiRyVpkJr4x1CtV+FRsLF+Tk1KUQDFIrTBQVw3N5c
--- 7dJKHwTqDkiiZaojRRK0mpxWopbhLwydPwFXtden9iI
'oºé¹òîÌä<C38C>=1õ¶Bc×°V­d qâÀ=Þÿ¸¸°µï뎀ˆÔjÿ`ǦÎéÏÎ&åÂ@Ûó ½Ç 5RQØ´Ûh™ÞOÉÓÅPŽá£Cv7ü<37>A ûw£s±¸¥QÀR<C380>Ù­O<C2AD>M"Wèí*<2A>s Ýߤâ×a`Æp¬

View File

@@ -1,11 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 hPp1nw CSR2HrrPUfaeOgAa3vt4yuQOrqyu0qnFBmTT2O4Rdnc
nYiiPmn/4Qmrc5VOK+/mmtzKD9xdvEF6SmRiPi/aFqs
-> ssh-ed25519 ZDy34A cmlgkgy5QvYYn6nHymo0u723S470qvUFt0Ubp6ggKj8
8ACCrqGCkVbuFMNoGKMd67oMtZWhQHBigU7Tdqoqy80
-> ssh-ed25519 w3nu8g GWytr1KtsXVQt6CKqqdjH92/Lc7aBjqa2N80oqeOdwU
c9GfCkKIaxMgsKWplXIQjiB5c6UE+UkRd4xlg1I5JSA
-> ssh-ed25519 evqvfg K4Z7DqPilKW9kEfFLDzJ7c2G6PvjRhxhCTEuw0Tw8hU
QsVD2iKObcP7HyVCXn9gPWvewn2Jm/OYLA1Eu6MRP1k
--- DGe/5H+9vk1EGj/mkUnvzk4VC5JVDIwVeaD78EHRiiI
êPŸËÓ²ûªÒÖ duÀÉr†¿"KÇ"©„M¬áÆ©xó3 ®²Æ ú™*J.Y_ÃíT%<25>tµ(ÿYʵ´8/Qa©r]ÍmÑÿÒ¤º

View File

@@ -1,12 +1,10 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 6AT2/g BLyjF65Y/bq9gkAuzl2PZmL7Ge1BTf6MQ/J+04fwwCA -> ssh-ed25519 6AT2/g 93Az2iuqeWL6H/S3XDPXFoEPcrY/n/z9mlSNb5wABkU
mdGmV3lmTPhVmORAVtJucy5EaNmOiCkZqdw+in8r8+E LpMPjpDtBrY2aHpqHwT5AY7vtsYHNcOjpz+LFY4TGCg
-> ssh-ed25519 ZDy34A h7f7GMXKCzuVnoIai84+gNq18XqxOPQLt2a4tmmQSxs -> ssh-ed25519 dMQYog 4qT0aF1IHsTtN1avMPWYG5Az2xmEZhVUhqcwyNFdfU4
RMoh4ecaEFybnE1ObWFZFHJKrIO3SbRynyDBljfSRAY +wD0hE035JqYdDgJmkvNXwJyMzXrquA+RsD8QdK3xP8
-> ssh-ed25519 w3nu8g XubNz2enRmr1uNZlErXBJngZrY52fJC4AUIbsaTh8yE -> !vfM7-grease
w5w3FK30UqLok7VeG8wILcyXeAIrf/Uzbf7AnHPfYAw 7nQGFFUWY9UIjfrb+/VfaG0zJ21zmDnDh5khs/0tioJevrrrlhub9Bz8iM/Jsfxy
-> ssh-ed25519 evqvfg 9UkiG9r2b0ZJwN6DPL+j08YKjBOx2x6jrJlzg+N79lk KUhwV8O8tL/5+30RFSlFRaAB6xPCGg24Yq6E
nmpBD/vZ7h3pAzeL8CO2oABTeA5iujG9Vr4aUgWaO0E --- jVsDtz2xpvK/XCHcdN5JVZx5zSxyEAM6D/xJIgN4YfY
--- 00dECq/aOgxAgnD19UdntMCzn27Iywp4bQoyAaKJ3yw Ñì°ßév.rK,Æ$
»ŽlŸ÷ƒƒÔrñDžgFOí þrÍ=éŒUCR‰wW÷Æ Ô­Ï*þA$÷³åÝÓeV
RH ¶T<01>ISK·é

Binary file not shown.

Binary file not shown.

View File

@@ -1,11 +1,10 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 6AT2/g 3s+reqcb4Hu/3Z7rICFZBOkW02ibISthFAT1sveyLBo -> ssh-ed25519 6AT2/g yTW46JmDIftcOqogIDjheXJf2sw/dG2WEJxfCXU/LDk
Eh5ynxeqqXhNbv/ASWZxzKXAzKX41uI5iJI4KqluHRI 0Co5/Rn22kmdcPr61ZOrmZJbPFHx2wJ8/YkbDjcjqKo
-> ssh-ed25519 ZDy34A cHcA2p0VrGr6jP/CUTOSU4Gef04ujh6wmJjmEWmWNE0 -> ssh-ed25519 dMQYog RtZT0PwVL4kxUHilOhH2GBp8Z9WfyBkaxB62pjKpHA4
wwaQnj7RABFzTbU74awlIJeHHePtO7jihNd2EUkNZPU muMlIt8VYQftMYacfdnQFeejfWpKTEG5gxbFNy97GTc
-> ssh-ed25519 w3nu8g hN/fWUHspXoJmpibR4NAL3EXkKExe2tRjUzmLGK6VnE -> 4|)`7yq-grease P#\5k8 +f
F1KQnGe3M8eD9hjnHLc7hqFTw9iXh7ICz0u421DuFOs jMegn6ATsj2Ai9B5Xmy+tay1nppwxvF1IGJH+hLNanYMsTIDZypM6UsNdzYQ/3mw
-> ssh-ed25519 evqvfg r3AoIJ3KWCYIsV8+RTgYY+Eg+1EcBVNrX+ZRunKaug8 VZ9ooy8TKUgAJ7jsd6IrKw
KSXd4uq1/0ErZzSTPrCmY/66v4TT5PmFqv9LRSHNi9A --- tLaPQWJA0Hh5MrxfhaySURgY02K16IlzvsxKpOWGva0
--- 3bGqZANqdfEgdiUzu38n4dzPOShgGUzQGtO7l2S+hwU 5?lヌ'シ!ケコ<EFBDB9><EFBDBA>キ匪Nxス+<2B>A9゚ムリl/グ諟ホ|旙<>Sオ&コサ、<>Q;_<>K
Ì?\<5C>•Öå¢aÚ'¤¤ÐÚ{˜/}ÉýÝL„:¨|¸G`†Ó+ºMÜÈY$s¸+Uk¥áäg‡ID¾K·

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,21 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 WBT1Hw QyirfN0ibrERO2bNZrb/8xqT5thl8LQmjn+xAFVMryc
bLND1Cb4eO2VAGtM+ehm4YW8jN5Tcki+jc3JxLHSZuo
-> ssh-ed25519 6AT2/g DqNkPFZ/b96oYl8RiUkVxi9vmv8RG0Pbs2y0cqKRGX4
5FLcVYepU/bNRq2Cr9zdHDN/vM9OFO6Q7QlWX+PPa4Q
-> ssh-ed25519 r848+g iSF57inO0hafZ0N6hIWGML1kRE48fN3WooeeHXXIRSs
RdYVTCEwMc31x9yl2VBmRCEJXUGCVeJjBBdO1rAL3A8
-> ssh-ed25519 hPp1nw mhanVdWbVK7OAinjTmEqx1jawd8pTlPe6YTIa/sEckQ
MVBgbEa8uNYIoCCmEBmFzMQR5cO033C57lMze5z+n54
-> ssh-ed25519 ZDy34A su3VVvWZhGKTR11mNKoOLzYjvnBCOG+U4qIeHUY6VXE
DRscTOjNk5BpejadPMVABLeLC+0mB6uAYxsSm5HqUgw
-> ssh-ed25519 w3nu8g kZXxRHeMvnzk96IhW73XUkXo6lM0CfUjgFFcio5e4TA
1vWdp3DVAH74cBd2hUujCz4J4ztQzFseP9SKYk2juAM
-> ssh-ed25519 evqvfg xRV4zs+y8jaqkLH7qMbRsThjptxuokIn1h1S2eIUmXg
6+a1IS7X2qucszKXa1XOeEgVDeNf3PF2HgQMixGPR7s
--- 6gSqjzHmrwlNUz8bmuoeB/2zUIOvQ82RDu77vaCtnvs
]qˆªÓ®ÓñAz}µeÂUª(‡ˆeÿmŸ{^c¤ñ’Þ<1E>ìÖ°)Á7ê¡»ÏÞ[H
ªgK܉Þù#ÞF$ô)ÎÝOE…Á5Œ{³Á6 ÌÖµÓÚQNJ.Î3YN<59>oXS`bZ
W§„ü;*
AÑUÛ¾&¢wîj@BLç/
<¢xËSµH쇅h

Some files were not shown because too many files have changed in this diff Show More