Compare commits
175 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b7549e63f5 | |||
| 306ce8bc3f | |||
| b5dd983ba3 | |||
| 832894edfc | |||
| feb6270952 | |||
| b4dd2d4a92 | |||
| 38c2e5aece | |||
| 0ef689b750 | |||
| e72e19b7e8 | |||
| 03603119e5 | |||
| 71baa09bd2 | |||
| a02775a234 | |||
| 5800359214 | |||
| 0bd42f1850 | |||
| 40f0e5d2ac | |||
| f90b9f85fd | |||
| 5b084fffcc | |||
| 4dd6401f8c | |||
| 260bbc1ffd | |||
| c8132a67d0 | |||
| 3412d5caf9 | |||
| 1065cc4b59 | |||
| 154b37879b | |||
| a34238b3a9 | |||
| 42e2ebd294 | |||
| 378cf47683 | |||
| f68a4f4431 | |||
| 3c683e7b9e | |||
| 68bd70b525 | |||
| 2189ab9a1b | |||
| acbbb8a37a | |||
| d1e6d21d66 | |||
| 1a98e039fe | |||
| 3459ce5058 | |||
| c48b1995f8 | |||
| 53c0e7ba1f | |||
| 820cd392f1 | |||
| 759fe04185 | |||
| db441fcf98 | |||
| 83e9280bb4 | |||
| 478235fe32 | |||
| 440401a391 | |||
| 42c0dcae2d | |||
| 7159868b57 | |||
| ab2cc0cc0a | |||
| aaa1800d0c | |||
| a795c65c32 | |||
| 5ed02e924d | |||
| 1d620372b8 | |||
| 9684a975e2 | |||
| c3c3a9e77f | |||
| ecb6d1ef63 | |||
| a5f7bb8a22 | |||
| cea9b9452b | |||
| 8fb45a7ee5 | |||
| b53f03bb7d | |||
| dee0243268 | |||
| 8b6bc354bd | |||
| aff5611cdb | |||
| c5e7d8b2fe | |||
| 90a3549237 | |||
| 63f2a82ad1 | |||
| 0cc39bfbe0 | |||
| ec54b27d67 | |||
| bba4f27465 | |||
| b5c77611d7 | |||
| 987919417d | |||
| d8dbb12959 | |||
| 3e0cde40b8 | |||
| 2c8576a295 | |||
| 8aecc04d01 | |||
| 9bcf7cc50d | |||
| cb2ac1c1ba | |||
| 7f1e304012 | |||
| 9e3dae4b16 | |||
| c649b04bdd | |||
| 6fce2e1116 | |||
| 3e192b3321 | |||
| bc863de165 | |||
| cfa5c9428e | |||
| abddc5a680 | |||
| 577dc4faaa | |||
| a8b0385c6d | |||
| fc85627bd6 | |||
| f9cadba3eb | |||
| c192c2d52f | |||
| 04c7a9ea51 | |||
| 6f9edd8870 | |||
| 076bdb3ab4 | |||
| fcbd877d06 | |||
| 27f4b5af78 | |||
| 7238d6e6c5 | |||
| 094905a727 | |||
| cf3fa0ff12 | |||
| 7c7b356aab | |||
| c57e4f022f | |||
| f5a9f04cf2 | |||
| 50fd928cda | |||
| 11072c374b | |||
| 60f1235848 | |||
| 55ea5aebc4 | |||
| 2738f6b794 | |||
| ec2b248ed8 | |||
| aa7bbc5932 | |||
| eef574c9f7 | |||
| 25fb7a1645 | |||
| 301fd8462b | |||
| a92800cbcc | |||
| 5e361b2fc8 | |||
| b41e4dc375 | |||
| 7e615f814d | |||
| c560a63182 | |||
| 2f14d07f82 | |||
| a89fde8aa5 | |||
| 1856fe00d6 | |||
| 388599e08c | |||
| 75a33a0b5e | |||
| 918b53e383 | |||
| c643244dab | |||
| 9fc6f816fb | |||
| 63902fcb46 | |||
| 8a1e0b76f1 | |||
| f144bda9e6 | |||
| b8c9278f37 | |||
| 9f45df7903 | |||
| a894a5429e | |||
| dfec18e904 | |||
| 91e38f5866 | |||
| fed1aecd64 | |||
| ec3056f8c1 | |||
| 339eed1f55 | |||
| 5ac5b4551b | |||
| d378a287fa | |||
| d71af55727 | |||
| de05a535ea | |||
| 910af494b5 | |||
| 3d1c078a44 | |||
| c85beff7ed | |||
| 7ab4906710 | |||
| af3af7b2ae | |||
| f627abc649 | |||
| e37878c544 | |||
| 73bbd39c64 | |||
| acbf162ffe | |||
| 516121b26c | |||
| 8742352ea9 | |||
| 61391cc180 | |||
| 60771ea56e | |||
| 2f19903a45 | |||
| 8102981a01 | |||
| d975477c05 | |||
| af9333feff | |||
| 5945310dd4 | |||
| d5d986dd88 | |||
| ffad65d902 | |||
| 2cd7f12a75 | |||
| fe48d7b009 | |||
| 448c3b280a | |||
| ef2ad011cc | |||
| 8267954e3d | |||
| 609f1d416a | |||
| b4dce62d36 | |||
| e15b612b3c | |||
| 6233ce6c0d | |||
| 1a4bdc4a8a | |||
| 73da58f6bf | |||
| 10f054a9d9 | |||
| 3f389e233f | |||
| bece0911b3 | |||
| 5cf1dff4e0 | |||
| 8d9c80d5b7 | |||
| 0b99df46b7 | |||
| fdedd6fe4d | |||
| e8ebcfc2be | |||
| 11600ef4d7 |
@@ -0,0 +1 @@
|
||||
result
|
||||
@@ -0,0 +1,11 @@
|
||||
# My NixOS configurations
|
||||
|
||||
### Source Layout
|
||||
- `/common` - common configuration imported into all `/machines`
|
||||
- `/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
|
||||
- `/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
|
||||
- `/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`
|
||||
- `/secrets` - encrypted shared secrets unlocked through `/machines` ssh host keys
|
||||
@@ -0,0 +1,84 @@
|
||||
# A place for brain dump ideas maybe to be taken off of the shelve one day
|
||||
|
||||
### NixOS webtools
|
||||
- Better options search https://mynixos.com/options/services
|
||||
|
||||
### Interesting ideas for restructuring nixos config
|
||||
- https://github.com/gytis-ivaskevicius/flake-utils-plus
|
||||
- https://github.com/divnix/digga/tree/main/examples/devos
|
||||
- https://digga.divnix.com/
|
||||
- https://nixos.wiki/wiki/Comparison_of_NixOS_setups
|
||||
|
||||
### Housekeeping
|
||||
- Cleanup the line between hardware-configuration.nix and configuration.nix in machine config
|
||||
- remove `options.currentSystem`
|
||||
- allow `hostname` option for webservices to be null to disable configuring nginx
|
||||
|
||||
### NAS
|
||||
- safely turn off NAS on power disconnect
|
||||
|
||||
### Shell Comands
|
||||
- tailexitnode = `sudo tailscale up --exit-node=<exit-node-ip> --exit-node-allow-lan-access=true`
|
||||
|
||||
### Services
|
||||
- setup archivebox
|
||||
- radio https://tildegit.org/tilderadio/site
|
||||
- music
|
||||
- mopidy
|
||||
- use the jellyfin plugin?
|
||||
- navidrome
|
||||
- spotify secrets for navidrome
|
||||
- picard for music tagging
|
||||
- alternative music software
|
||||
- https://www.smarthomebeginner.com/best-music-server-software-options/
|
||||
- https://funkwhale.audio/
|
||||
- https://github.com/epoupon/lms
|
||||
- https://github.com/benkaiser/stretto
|
||||
- https://github.com/blackcandy-org/black_candy
|
||||
- https://github.com/koel/koel
|
||||
- https://airsonic.github.io/
|
||||
- https://ampache.org/
|
||||
- replace nextcloud with seafile
|
||||
|
||||
### Archive
|
||||
- email
|
||||
- https://github.com/Disassembler0/dovecot-archive/blob/main/src/dovecot_archive.py
|
||||
- http://kb.unixservertech.com/software/dovecot/archiveserver
|
||||
|
||||
### Paranoia
|
||||
- https://christine.website/blog/paranoid-nixos-2021-07-18
|
||||
- https://nixos.wiki/wiki/Impermanence
|
||||
|
||||
# Setup CI
|
||||
- CI
|
||||
- hydra
|
||||
- https://docs.cachix.org/continuous-integration-setup/
|
||||
- Binary Cache
|
||||
- Maybe use cachix https://gvolpe.com/blog/nixos-binary-cache-ci/
|
||||
- Self hosted binary cache? https://www.tweag.io/blog/2019-11-21-untrusted-ci/
|
||||
- https://github.com/edolstra/nix-serve
|
||||
- https://nixos.wiki/wiki/Binary_Cache
|
||||
- https://discourse.nixos.org/t/introducing-attic-a-self-hostable-nix-binary-cache-server/24343
|
||||
- Both
|
||||
- https://garnix.io/
|
||||
- https://nixbuild.net
|
||||
|
||||
|
||||
# Secrets
|
||||
- consider using headscale
|
||||
- Replace luks over tor for remote unlock with luks over tailscale using ephemeral keys
|
||||
- Rollover luks FDE passwords
|
||||
- /secrets on personal computers should only be readable using a trusted ssh key, preferably requiring a yubikey
|
||||
- Rollover shared yubikey secrets
|
||||
- offsite backup yubikey, pw db, and ssh key with /secrets access
|
||||
|
||||
### Misc
|
||||
- for automated kernel upgrades on luks systems, need to kexec with initrd that contains luks key
|
||||
- https://github.com/flowztul/keyexec/blob/master/etc/default/kexec-cryptroot
|
||||
- https://github.com/pop-os/system76-scheduler
|
||||
- improve email a little bit https://helloinbox.email
|
||||
- remap razer keys https://github.com/sezanzeb/input-remapper
|
||||
|
||||
### Future Interests (upon merge into nixpkgs)
|
||||
- nixos/thelounge: add users option https://github.com/NixOS/nixpkgs/pull/157477
|
||||
- glorytun: init at 0.3.4 https://github.com/NixOS/nixpkgs/pull/153356
|
||||
+16
-5
@@ -1,14 +1,25 @@
|
||||
{ config, lib, ... }:
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
# Modify auto-update so that it pulls a flake
|
||||
|
||||
let
|
||||
cfg = config.system.autoUpgrade;
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable (lib.mkMerge [
|
||||
{
|
||||
system.autoUpgrade = {
|
||||
flake = "git+https://git.neet.dev/zuckerberg/nix-config.git";
|
||||
flags = [ "--recreate-lock-file" ]; # ignore lock file, just pull the latest
|
||||
};
|
||||
flags = [ "--recreate-lock-file" "--no-write-lock-file" ]; # ignore lock file, just pull the latest
|
||||
|
||||
# dates = "03:40";
|
||||
# kexecWindow = lib.mkDefault { lower = "01:00"; upper = "05:00"; };
|
||||
# randomizedDelaySec = "45min";
|
||||
};
|
||||
|
||||
system.autoUpgrade.allowKexec = lib.mkDefault true;
|
||||
|
||||
luks.enableKexec = cfg.allowKexec && builtins.length config.luks.devices > 0;
|
||||
}
|
||||
]);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.backup;
|
||||
hostname = config.networking.hostName;
|
||||
|
||||
mkRespository = group: "s3:s3.us-west-004.backblazeb2.com/D22TgIt0-main-backup/${group}";
|
||||
|
||||
mkBackup = group: paths: {
|
||||
repository = mkRespository group;
|
||||
inherit paths;
|
||||
|
||||
initialize = true;
|
||||
|
||||
timerConfig = {
|
||||
OnCalendar = "daily";
|
||||
RandomizedDelaySec = "1h";
|
||||
};
|
||||
|
||||
extraBackupArgs = [
|
||||
''--exclude-if-present ".nobackup"''
|
||||
];
|
||||
|
||||
pruneOpts = [
|
||||
"--keep-daily 7" # one backup for each of the last n days
|
||||
"--keep-weekly 5" # one backup for each of the last n weeks
|
||||
"--keep-monthly 12" # one backup for each of the last n months
|
||||
"--keep-yearly 75" # one backup for each of the last n years
|
||||
];
|
||||
|
||||
environmentFile = "/run/agenix/backblaze-s3-backups";
|
||||
passwordFile = "/run/agenix/restic-password";
|
||||
};
|
||||
|
||||
# example usage: "sudo restic_samba unlock" (removes lockfile)
|
||||
mkResticGroupCmd = group: pkgs.writeShellScriptBin "restic_${group}" ''
|
||||
if [ "$EUID" -ne 0 ]
|
||||
then echo "Run as root"
|
||||
exit
|
||||
fi
|
||||
. /run/agenix/backblaze-s3-backups
|
||||
export AWS_SECRET_ACCESS_KEY
|
||||
export AWS_ACCESS_KEY_ID
|
||||
export RESTIC_PASSWORD_FILE=/run/agenix/restic-password
|
||||
export RESTIC_REPOSITORY="${mkRespository group}"
|
||||
exec ${pkgs.restic}/bin/restic "$@"
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.backup = {
|
||||
group = lib.mkOption {
|
||||
default = null;
|
||||
type = lib.types.nullOr (lib.types.attrsOf (lib.types.submodule {
|
||||
options = {
|
||||
paths = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = ''
|
||||
Paths to backup
|
||||
'';
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf (cfg.group != null) {
|
||||
services.restic.backups = lib.concatMapAttrs
|
||||
(group: groupCfg: {
|
||||
${group} = mkBackup group groupCfg.paths;
|
||||
})
|
||||
cfg.group;
|
||||
|
||||
age.secrets.backblaze-s3-backups.file = ../secrets/backblaze-s3-backups.age;
|
||||
age.secrets.restic-password.file = ../secrets/restic-password.age;
|
||||
|
||||
environment.systemPackages = map mkResticGroupCmd (builtins.attrNames cfg.group);
|
||||
};
|
||||
}
|
||||
@@ -3,7 +3,8 @@
|
||||
with lib;
|
||||
let
|
||||
cfg = config.bios;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.bios = {
|
||||
enable = mkEnableOption "enable bios boot";
|
||||
device = mkOption {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
./firmware.nix
|
||||
./efi.nix
|
||||
./bios.nix
|
||||
./kexec-luks.nix
|
||||
./luks.nix
|
||||
./remote-luks-unlock.nix
|
||||
];
|
||||
}
|
||||
+2
-1
@@ -3,7 +3,8 @@
|
||||
with lib;
|
||||
let
|
||||
cfg = config.efi;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.efi = {
|
||||
enable = mkEnableOption "enable efi boot";
|
||||
};
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
with lib;
|
||||
let
|
||||
cfg = config.firmware;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.firmware.x86_64 = {
|
||||
enable = mkEnableOption "enable x86_64 firmware";
|
||||
};
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
# Allows kexec'ing as an alternative to rebooting for machines that
|
||||
# have luks encrypted partitions that need to be mounted at boot.
|
||||
# These luks partitions will be automatically unlocked, no password,
|
||||
# or any interaction needed whatsoever.
|
||||
|
||||
# This is accomplished by fetching the luks key(s) while the system is running,
|
||||
# then building a temporary initrd that contains the luks key(s), and kexec'ing.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.luks = {
|
||||
enableKexec = lib.mkEnableOption "Enable support for transparent passwordless kexec while using luks";
|
||||
};
|
||||
|
||||
config = lib.mkIf config.luks.enableKexec {
|
||||
luks.fallbackToPassword = true;
|
||||
luks.disableKeyring = true;
|
||||
|
||||
boot.initrd.luks.devices = lib.listToAttrs
|
||||
(builtins.map
|
||||
(item:
|
||||
{
|
||||
name = item;
|
||||
value = {
|
||||
masterKeyFile = "/etc/${item}.key";
|
||||
};
|
||||
})
|
||||
config.luks.deviceNames);
|
||||
|
||||
systemd.services.prepare-luks-kexec-image = {
|
||||
description = "Prepare kexec automatic LUKS unlock on kexec reboot without a password";
|
||||
|
||||
wantedBy = [ "kexec.target" ];
|
||||
unitConfig.DefaultDependencies = false;
|
||||
serviceConfig.Type = "oneshot";
|
||||
|
||||
path = with pkgs; [ file kexec-tools coreutils-full cpio findutils gzip xz zstd lvm2 xxd gawk ];
|
||||
|
||||
# based on https://github.com/flowztul/keyexec
|
||||
script = ''
|
||||
system=/nix/var/nix/profiles/system
|
||||
old_initrd=$(readlink -f "$system/initrd")
|
||||
|
||||
umask 0077
|
||||
CRYPTROOT_TMPDIR="$(mktemp -d --tmpdir=/dev/shm)"
|
||||
|
||||
cleanup() {
|
||||
shred -fu "$CRYPTROOT_TMPDIR/initrd_contents/etc/"*.key || true
|
||||
shred -fu "$CRYPTROOT_TMPDIR/new_initrd" || true
|
||||
shred -fu "$CRYPTROOT_TMPDIR/secret/"* || true
|
||||
rm -rf "$CRYPTROOT_TMPDIR"
|
||||
}
|
||||
# trap cleanup INT TERM EXIT
|
||||
|
||||
mkdir -p "$CRYPTROOT_TMPDIR"
|
||||
cd "$CRYPTROOT_TMPDIR"
|
||||
|
||||
# Determine the compression type of the initrd image
|
||||
compression=$(file -b --mime-type "$old_initrd" | awk -F'/' '{print $2}')
|
||||
|
||||
# Decompress the initrd image based on its compression type
|
||||
case "$compression" in
|
||||
gzip)
|
||||
gunzip -c "$old_initrd" > initrd.cpio
|
||||
;;
|
||||
xz)
|
||||
unxz -c "$old_initrd" > initrd.cpio
|
||||
;;
|
||||
zstd)
|
||||
zstd -d -c "$old_initrd" > initrd.cpio
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported compression type: $compression"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Extract the contents of the cpio archive
|
||||
mkdir -p initrd_contents
|
||||
cd initrd_contents
|
||||
cpio -idv < ../initrd.cpio
|
||||
|
||||
# Generate keys and add them to the extracted initrd filesystem
|
||||
luksDeviceNames=(${builtins.concatStringsSep " " config.luks.deviceNames})
|
||||
for item in "''${luksDeviceNames[@]}"; do
|
||||
dmsetup --showkeys table "$item" | cut -d ' ' -f5 | xxd -ps -g1 -r > "./etc/$item.key"
|
||||
done
|
||||
|
||||
# Add normal initrd secrets too
|
||||
${lib.concatStringsSep "\n" (lib.mapAttrsToList (dest: source:
|
||||
let source' = if source == null then dest else builtins.toString source; in
|
||||
''
|
||||
mkdir -p $(dirname "./${dest}")
|
||||
cp -a ${source'} "./${dest}"
|
||||
''
|
||||
) config.boot.initrd.secrets)
|
||||
}
|
||||
|
||||
# Create a new cpio archive with the modified contents
|
||||
find . | cpio -o -H newc -v > ../new_initrd.cpio
|
||||
|
||||
# Compress the new cpio archive using the original compression type
|
||||
cd ..
|
||||
case "$compression" in
|
||||
gzip)
|
||||
gunzip -c new_initrd.cpio > new_initrd
|
||||
;;
|
||||
xz)
|
||||
unxz -c new_initrd.cpio > new_initrd
|
||||
;;
|
||||
zstd)
|
||||
zstd -c new_initrd.cpio > new_initrd
|
||||
;;
|
||||
esac
|
||||
|
||||
kexec --load "$system/kernel" --append "init=$system/init ${builtins.concatStringsSep " " config.boot.kernelParams}" --initrd "$CRYPTROOT_TMPDIR/new_initrd"
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
+60
-87
@@ -1,101 +1,74 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
# Makes it a little easier to configure luks partitions for boot
|
||||
# Additionally, this solves a circular dependency between kexec luks
|
||||
# and NixOS's luks module.
|
||||
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.luks;
|
||||
in {
|
||||
|
||||
deviceCount = builtins.length cfg.devices;
|
||||
|
||||
deviceMap = lib.imap
|
||||
(i: item: {
|
||||
device = item;
|
||||
name =
|
||||
if deviceCount == 1 then "enc-pv"
|
||||
else "enc-pv${builtins.toString (i + 1)}";
|
||||
})
|
||||
cfg.devices;
|
||||
in
|
||||
{
|
||||
options.luks = {
|
||||
enable = lib.mkEnableOption "enable luks root remote decrypt over ssh/tor";
|
||||
device = {
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "enc-pv";
|
||||
};
|
||||
path = lib.mkOption {
|
||||
type = lib.types.either lib.types.str lib.types.path;
|
||||
devices = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
allowDiscards = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
sshHostKeys = lib.mkOption {
|
||||
type = lib.types.listOf (lib.types.either lib.types.str lib.types.path);
|
||||
default = [
|
||||
"/secret/ssh_host_rsa_key"
|
||||
"/secret/ssh_host_ed25519_key"
|
||||
];
|
||||
};
|
||||
sshAuthorizedKeys = lib.mkOption {
|
||||
|
||||
fallbackToPassword = lib.mkEnableOption
|
||||
"Fallback to interactive passphrase prompt if the cannot be found.";
|
||||
|
||||
disableKeyring = lib.mkEnableOption
|
||||
"When opening LUKS2 devices, don't use the kernel keyring";
|
||||
|
||||
# set automatically, don't touch
|
||||
deviceNames = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = config.users.users.googlebot.openssh.authorizedKeys.keys;
|
||||
};
|
||||
onionConfig = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = /secret/onion;
|
||||
};
|
||||
kernelModules = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ "e1000" "e1000e" "virtio_pci" "r8169" ];
|
||||
};
|
||||
};
|
||||
|
||||
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
|
||||
boot.initrd.network.enable = true;
|
||||
boot.initrd.kernelModules = cfg.kernelModules;
|
||||
boot.initrd.network.ssh = {
|
||||
enable = true;
|
||||
port = 22;
|
||||
hostKeys = cfg.sshHostKeys;
|
||||
authorizedKeys = cfg.sshAuthorizedKeys;
|
||||
};
|
||||
|
||||
boot.initrd.postDeviceCommands = ''
|
||||
echo 'waiting for root device to be opened...'
|
||||
mkfifo /crypt-ramfs/passphrase
|
||||
echo /crypt-ramfs/passphrase >> /dev/null
|
||||
config = lib.mkMerge [
|
||||
{
|
||||
assertions = [
|
||||
{
|
||||
assertion = deviceCount == builtins.length (builtins.attrNames config.boot.initrd.luks.devices);
|
||||
message = ''
|
||||
All luks devices must be specified using `luks.devices` not `boot.initrd.luks.devices`.
|
||||
'';
|
||||
|
||||
# Make machine accessable over tor for boot unlock
|
||||
boot.initrd.secrets = {
|
||||
"/etc/tor/onion/bootup" = cfg.onionConfig;
|
||||
};
|
||||
boot.initrd.extraUtilsCommands = ''
|
||||
copy_bin_and_libs ${pkgs.tor}/bin/tor
|
||||
copy_bin_and_libs ${pkgs.haveged}/bin/haveged
|
||||
'';
|
||||
# start tor during boot process
|
||||
boot.initrd.network.postCommands = let
|
||||
torRc = (pkgs.writeText "tor.rc" ''
|
||||
DataDirectory /etc/tor
|
||||
SOCKSPort 127.0.0.1:9050 IsolateDestAddr
|
||||
SOCKSPort 127.0.0.1:9063
|
||||
HiddenServiceDir /etc/tor/onion/bootup
|
||||
HiddenServicePort 22 127.0.0.1:22
|
||||
'');
|
||||
in ''
|
||||
# Add nice prompt for giving LUKS passphrase over ssh
|
||||
echo 'read -s -p "Unlock Passphrase: " passphrase && echo $passphrase > /crypt-ramfs/passphrase && exit' >> /root/.profile
|
||||
|
||||
echo "tor: preparing onion folder"
|
||||
# have to do this otherwise tor does not want to start
|
||||
chmod -R 700 /etc/tor
|
||||
|
||||
echo "make sure localhost is up"
|
||||
ip a a 127.0.0.1/8 dev lo
|
||||
ip link set lo up
|
||||
|
||||
echo "haveged: starting haveged"
|
||||
haveged -F &
|
||||
|
||||
echo "tor: starting tor"
|
||||
tor -f ${torRc} --verify-config
|
||||
tor -f ${torRc} &
|
||||
'';
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
(lib.mkIf (deviceCount != 0) {
|
||||
luks.deviceNames = builtins.map (device: device.name) deviceMap;
|
||||
|
||||
boot.initrd.luks.devices = lib.listToAttrs (
|
||||
builtins.map
|
||||
(item:
|
||||
{
|
||||
name = item.name;
|
||||
value = {
|
||||
device = item.device;
|
||||
allowDiscards = cfg.allowDiscards;
|
||||
fallbackToPassword = cfg.fallbackToPassword;
|
||||
disableKeyring = cfg.disableKeyring;
|
||||
};
|
||||
})
|
||||
deviceMap);
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.remoteLuksUnlock;
|
||||
in
|
||||
{
|
||||
options.remoteLuksUnlock = {
|
||||
enable = lib.mkEnableOption "enable luks root remote decrypt over ssh/tor";
|
||||
enableTorUnlock = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = cfg.enable;
|
||||
description = "Make machine accessable over tor for ssh boot unlock";
|
||||
};
|
||||
sshHostKeys = lib.mkOption {
|
||||
type = lib.types.listOf (lib.types.either lib.types.str lib.types.path);
|
||||
default = [
|
||||
"/secret/ssh_host_rsa_key"
|
||||
"/secret/ssh_host_ed25519_key"
|
||||
];
|
||||
};
|
||||
sshAuthorizedKeys = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = config.users.users.googlebot.openssh.authorizedKeys.keys;
|
||||
};
|
||||
onionConfig = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = /secret/onion;
|
||||
};
|
||||
kernelModules = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ "e1000" "e1000e" "virtio_pci" "r8169" ];
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# Unlock LUKS disk over ssh
|
||||
boot.initrd.network.enable = true;
|
||||
boot.initrd.kernelModules = cfg.kernelModules;
|
||||
boot.initrd.network.ssh = {
|
||||
enable = true;
|
||||
port = 22;
|
||||
hostKeys = cfg.sshHostKeys;
|
||||
authorizedKeys = cfg.sshAuthorizedKeys;
|
||||
};
|
||||
|
||||
boot.initrd.postDeviceCommands = ''
|
||||
echo 'waiting for root device to be opened...'
|
||||
mkfifo /crypt-ramfs/passphrase
|
||||
echo /crypt-ramfs/passphrase >> /dev/null
|
||||
'';
|
||||
|
||||
boot.initrd.secrets = lib.mkIf cfg.enableTorUnlock {
|
||||
"/etc/tor/onion/bootup" = cfg.onionConfig;
|
||||
};
|
||||
boot.initrd.extraUtilsCommands = lib.mkIf cfg.enableTorUnlock ''
|
||||
copy_bin_and_libs ${pkgs.tor}/bin/tor
|
||||
copy_bin_and_libs ${pkgs.haveged}/bin/haveged
|
||||
'';
|
||||
boot.initrd.network.postCommands = lib.mkMerge [
|
||||
(
|
||||
''
|
||||
# Add nice prompt for giving LUKS passphrase over ssh
|
||||
echo 'read -s -p "Unlock Passphrase: " passphrase && echo $passphrase > /crypt-ramfs/passphrase && exit' >> /root/.profile
|
||||
''
|
||||
)
|
||||
|
||||
(
|
||||
let torRc = (pkgs.writeText "tor.rc" ''
|
||||
DataDirectory /etc/tor
|
||||
SOCKSPort 127.0.0.1:9050 IsolateDestAddr
|
||||
SOCKSPort 127.0.0.1:9063
|
||||
HiddenServiceDir /etc/tor/onion/bootup
|
||||
HiddenServicePort 22 127.0.0.1:22
|
||||
''); in
|
||||
lib.mkIf cfg.enableTorUnlock ''
|
||||
echo "tor: preparing onion folder"
|
||||
# have to do this otherwise tor does not want to start
|
||||
chmod -R 700 /etc/tor
|
||||
|
||||
echo "make sure localhost is up"
|
||||
ip a a 127.0.0.1/8 dev lo
|
||||
ip link set lo up
|
||||
|
||||
echo "haveged: starting haveged"
|
||||
haveged -F &
|
||||
|
||||
echo "tor: starting tor"
|
||||
tor -f ${torRc} --verify-config
|
||||
tor -f ${torRc} &
|
||||
''
|
||||
)
|
||||
];
|
||||
};
|
||||
}
|
||||
+35
-11
@@ -2,13 +2,16 @@
|
||||
|
||||
{
|
||||
imports = [
|
||||
./backups.nix
|
||||
./flakes.nix
|
||||
./pia.nix
|
||||
./zerotier.nix
|
||||
./auto-update.nix
|
||||
./shell.nix
|
||||
./network
|
||||
./boot
|
||||
./server
|
||||
./pc
|
||||
./machine-info
|
||||
./ssh.nix
|
||||
];
|
||||
|
||||
nix.flakes.enable = true;
|
||||
@@ -20,17 +23,23 @@
|
||||
networking.firewall.enable = true;
|
||||
networking.firewall.allowPing = true;
|
||||
|
||||
time.timeZone = "America/New_York";
|
||||
time.timeZone = "America/Denver";
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
|
||||
services.openssh.enable = true;
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
};
|
||||
};
|
||||
programs.mosh.enable = true;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
wget
|
||||
kakoune
|
||||
htop
|
||||
git git-lfs
|
||||
git
|
||||
git-lfs
|
||||
dnsutils
|
||||
tmux
|
||||
nethogs
|
||||
@@ -41,6 +50,9 @@
|
||||
screen
|
||||
micro
|
||||
helix
|
||||
lm_sensors
|
||||
picocom
|
||||
lf
|
||||
];
|
||||
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
@@ -53,15 +65,27 @@
|
||||
"dialout" # serial
|
||||
];
|
||||
shell = pkgs.fish;
|
||||
openssh.authorizedKeys.keys = (import ./ssh.nix).users;
|
||||
openssh.authorizedKeys.keys = config.machines.ssh.userKeys;
|
||||
hashedPassword = "$6$TuDO46rILr$gkPUuLKZe3psexhs8WFZMpzgEBGksE.c3Tjh1f8sD0KMC4oV89K2pqAABfl.Lpxu2jVdr5bgvR5cWnZRnji/r/";
|
||||
uid = 1000;
|
||||
};
|
||||
nix.trustedUsers = [ "root" "googlebot" ];
|
||||
users.users.root = {
|
||||
openssh.authorizedKeys.keys = config.machines.ssh.deployKeys;
|
||||
};
|
||||
nix.settings = {
|
||||
trusted-users = [ "root" "googlebot" ];
|
||||
};
|
||||
|
||||
# don't use sudo
|
||||
security.doas.enable = true;
|
||||
security.sudo.enable = false;
|
||||
security.doas.extraRules = [
|
||||
# don't ask for password every time
|
||||
{ groups = [ "wheel" ]; persist = true; }
|
||||
];
|
||||
|
||||
nix.gc.automatic = true;
|
||||
|
||||
programs.fish.enable = true;
|
||||
programs.fish.shellInit = ''
|
||||
set fish_greeting
|
||||
'';
|
||||
security.acme.acceptTerms = true;
|
||||
security.acme.defaults.email = "zuckerberg@neet.dev";
|
||||
}
|
||||
|
||||
+5
-1
@@ -2,7 +2,8 @@
|
||||
with lib;
|
||||
let
|
||||
cfg = config.nix.flakes;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.nix.flakes = {
|
||||
enable = mkEnableOption "use nix flakes";
|
||||
};
|
||||
@@ -16,6 +17,9 @@ in {
|
||||
|
||||
# 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}" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
# Gathers info about each machine to constuct overall configuration
|
||||
# Ex: Each machine already trusts each others SSH fingerprint already
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
machines = config.machines.hosts;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./ssh.nix
|
||||
./roles.nix
|
||||
];
|
||||
|
||||
options.machines = {
|
||||
|
||||
hosts = lib.mkOption {
|
||||
type = lib.types.attrsOf
|
||||
(lib.types.submodule {
|
||||
options = {
|
||||
|
||||
hostNames = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = ''
|
||||
List of hostnames for this machine. The first one is the default so it is the target of deployments.
|
||||
Used for automatically trusting hosts for ssh connections.
|
||||
'';
|
||||
};
|
||||
|
||||
arch = lib.mkOption {
|
||||
type = lib.types.enum [ "x86_64-linux" "aarch64-linux" ];
|
||||
description = ''
|
||||
The architecture of this machine.
|
||||
'';
|
||||
};
|
||||
|
||||
systemRoles = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str; # TODO: maybe use an enum?
|
||||
description = ''
|
||||
The set of roles this machine holds. Affects secrets available. (TODO add service config as well using this info)
|
||||
'';
|
||||
};
|
||||
|
||||
hostKey = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
The system ssh host key of this machine. Used for automatically trusting hosts for ssh connections
|
||||
and for decrypting secrets with agenix.
|
||||
'';
|
||||
};
|
||||
|
||||
remoteUnlock = lib.mkOption {
|
||||
default = null;
|
||||
type = lib.types.nullOr (lib.types.submodule {
|
||||
options = {
|
||||
|
||||
hostKey = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
The system ssh host key of this machine used for luks boot unlocking only.
|
||||
'';
|
||||
};
|
||||
|
||||
clearnetHost = lib.mkOption {
|
||||
default = null;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
description = ''
|
||||
The hostname resolvable over clearnet used to luks boot unlock this machine
|
||||
'';
|
||||
};
|
||||
|
||||
onionHost = lib.mkOption {
|
||||
default = null;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
description = ''
|
||||
The hostname resolvable over tor used to luks boot unlock this machine
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
userKeys = lib.mkOption {
|
||||
default = [ ];
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = ''
|
||||
The list of user keys. Each key here can be used to log into all other systems as `googlebot`.
|
||||
|
||||
TODO: consider auto populating other programs that use ssh keys such as gitea
|
||||
'';
|
||||
};
|
||||
|
||||
deployKeys = lib.mkOption {
|
||||
default = [ ];
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = ''
|
||||
The list of deployment keys. Each key here can be used to log into all other systems as `root`.
|
||||
'';
|
||||
};
|
||||
|
||||
configurationPath = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
The path to this machine's configuration directory.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
assertions = (lib.concatLists (lib.mapAttrsToList
|
||||
(
|
||||
name: cfg: [
|
||||
{
|
||||
assertion = builtins.length cfg.hostNames > 0;
|
||||
message = ''
|
||||
Error with config for ${name}
|
||||
There must be at least one hostname.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = builtins.length cfg.systemRoles > 0;
|
||||
message = ''
|
||||
Error with config for ${name}
|
||||
There must be at least one system role.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = cfg.remoteUnlock == null || cfg.remoteUnlock.hostKey != cfg.hostKey;
|
||||
message = ''
|
||||
Error with config for ${name}
|
||||
Unlock hostkey and hostkey cannot be the same because unlock hostkey is in /boot, unencrypted.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = cfg.remoteUnlock == null || (cfg.remoteUnlock.clearnetHost != null || cfg.remoteUnlock.onionHost != null);
|
||||
message = ''
|
||||
Error with config for ${name}
|
||||
At least one of clearnet host or onion host must be defined.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = cfg.remoteUnlock == null || cfg.remoteUnlock.clearnetHost == null || builtins.elem cfg.remoteUnlock.clearnetHost cfg.hostNames == false;
|
||||
message = ''
|
||||
Error with config for ${name}
|
||||
Clearnet unlock hostname cannot be in the list of hostnames for security reasons.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = cfg.remoteUnlock == null || cfg.remoteUnlock.onionHost == null || lib.strings.hasSuffix ".onion" cfg.remoteUnlock.onionHost;
|
||||
message = ''
|
||||
Error with config for ${name}
|
||||
Tor unlock hostname must be an onion address.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = builtins.elem "personal" cfg.systemRoles || builtins.length cfg.userKeys == 0;
|
||||
message = ''
|
||||
Error with config for ${name}
|
||||
There must be at least one userkey defined for personal machines.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = builtins.elem "deploy" cfg.systemRoles || builtins.length cfg.deployKeys == 0;
|
||||
message = ''
|
||||
Error with config for ${name}
|
||||
Only deploy machines are allowed to have deploy keys for security reasons.
|
||||
'';
|
||||
}
|
||||
]
|
||||
)
|
||||
machines));
|
||||
|
||||
# Set per machine properties automatically using each of their `properties.nix` files respectively
|
||||
machines.hosts =
|
||||
let
|
||||
properties = dir: lib.concatMapAttrs
|
||||
(name: path: {
|
||||
${name} =
|
||||
import path
|
||||
//
|
||||
{ configurationPath = builtins.dirOf path; };
|
||||
})
|
||||
(propertiesFiles dir);
|
||||
propertiesFiles = dir:
|
||||
lib.foldl (lib.mergeAttrs) { } (propertiesFiles' dir);
|
||||
propertiesFiles' = dir:
|
||||
let
|
||||
propFiles = lib.filter (p: baseNameOf p == "properties.nix") (lib.filesystem.listFilesRecursive dir);
|
||||
dirName = path: builtins.baseNameOf (builtins.dirOf path);
|
||||
in
|
||||
builtins.map (p: { "${dirName p}" = p; }) propFiles;
|
||||
in
|
||||
properties ../../machines;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# Allows getting machine-info outside the scope of nixos configuration
|
||||
|
||||
{ nixpkgs ? import <nixpkgs> { }
|
||||
, assertionsModule ? <nixpkgs/nixos/modules/misc/assertions.nix>
|
||||
}:
|
||||
|
||||
{
|
||||
machines =
|
||||
(nixpkgs.lib.evalModules {
|
||||
modules = [
|
||||
./default.nix
|
||||
assertionsModule
|
||||
];
|
||||
}).config.machines;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
# Maps roles to their hosts
|
||||
|
||||
{
|
||||
options.machines.roles = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.listOf lib.types.str);
|
||||
};
|
||||
|
||||
config = {
|
||||
machines.roles = lib.zipAttrs
|
||||
(lib.mapAttrsToList
|
||||
(host: cfg:
|
||||
lib.foldl (lib.mergeAttrs) { }
|
||||
(builtins.map (role: { ${role} = host; })
|
||||
cfg.systemRoles))
|
||||
config.machines.hosts);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
machines = config.machines;
|
||||
|
||||
sshkeys = keyType: lib.foldl (l: cfg: l ++ cfg.${keyType}) [ ] (builtins.attrValues machines.hosts);
|
||||
in
|
||||
{
|
||||
options.machines.ssh = {
|
||||
userKeys = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = ''
|
||||
List of user keys aggregated from all machines.
|
||||
'';
|
||||
};
|
||||
|
||||
deployKeys = lib.mkOption {
|
||||
default = [ ];
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = ''
|
||||
List of deploy keys aggregated from all machines.
|
||||
'';
|
||||
};
|
||||
|
||||
hostKeysByRole = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.listOf lib.types.str);
|
||||
description = ''
|
||||
Machine host keys divided into their roles.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
machines.ssh.userKeys = sshkeys "userKeys";
|
||||
machines.ssh.deployKeys = sshkeys "deployKeys";
|
||||
|
||||
machines.ssh.hostKeysByRole = lib.mapAttrs
|
||||
(role: hosts:
|
||||
builtins.map
|
||||
(host: machines.hosts.${host}.hostKey)
|
||||
hosts)
|
||||
machines.roles;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIHqzCCBZOgAwIBAgIJAJ0u+vODZJntMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYD
|
||||
VQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNV
|
||||
BAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIElu
|
||||
dGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3Mx
|
||||
IDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkB
|
||||
FiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzQw
|
||||
MzNaFw0zNDA0MTIxNzQwMzNaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
|
||||
EzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQg
|
||||
QWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UE
|
||||
AxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50
|
||||
ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVy
|
||||
bmV0YWNjZXNzLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALVk
|
||||
hjumaqBbL8aSgj6xbX1QPTfTd1qHsAZd2B97m8Vw31c/2yQgZNf5qZY0+jOIHULN
|
||||
De4R9TIvyBEbvnAg/OkPw8n/+ScgYOeH876VUXzjLDBnDb8DLr/+w9oVsuDeFJ9K
|
||||
V2UFM1OYX0SnkHnrYAN2QLF98ESK4NCSU01h5zkcgmQ+qKSfA9Ny0/UpsKPBFqsQ
|
||||
25NvjDWFhCpeqCHKUJ4Be27CDbSl7lAkBuHMPHJs8f8xPgAbHRXZOxVCpayZ2SND
|
||||
fCwsnGWpWFoMGvdMbygngCn6jA/W1VSFOlRlfLuuGe7QFfDwA0jaLCxuWt/BgZyl
|
||||
p7tAzYKR8lnWmtUCPm4+BtjyVDYtDCiGBD9Z4P13RFWvJHw5aapx/5W/CuvVyI7p
|
||||
Kwvc2IT+KPxCUhH1XI8ca5RN3C9NoPJJf6qpg4g0rJH3aaWkoMRrYvQ+5PXXYUzj
|
||||
tRHImghRGd/ydERYoAZXuGSbPkm9Y/p2X8unLcW+F0xpJD98+ZI+tzSsI99Zs5wi
|
||||
jSUGYr9/j18KHFTMQ8n+1jauc5bCCegN27dPeKXNSZ5riXFL2XX6BkY68y58UaNz
|
||||
meGMiUL9BOV1iV+PMb7B7PYs7oFLjAhh0EdyvfHkrh/ZV9BEhtFa7yXp8XR0J6vz
|
||||
1YV9R6DYJmLjOEbhU8N0gc3tZm4Qz39lIIG6w3FDAgMBAAGjggFUMIIBUDAdBgNV
|
||||
HQ4EFgQUrsRtyWJftjpdRM0+925Y6Cl08SUwggEfBgNVHSMEggEWMIIBEoAUrsRt
|
||||
yWJftjpdRM0+925Y6Cl08SWhge6kgeswgegxCzAJBgNVBAYTAlVTMQswCQYDVQQI
|
||||
EwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRl
|
||||
cm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAw
|
||||
HgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0
|
||||
ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRl
|
||||
aW50ZXJuZXRhY2Nlc3MuY29tggkAnS7684Nkme0wDAYDVR0TBAUwAwEB/zANBgkq
|
||||
hkiG9w0BAQ0FAAOCAgEAJsfhsPk3r8kLXLxY+v+vHzbr4ufNtqnL9/1Uuf8NrsCt
|
||||
pXAoyZ0YqfbkWx3NHTZ7OE9ZRhdMP/RqHQE1p4N4Sa1nZKhTKasV6KhHDqSCt/dv
|
||||
Em89xWm2MVA7nyzQxVlHa9AkcBaemcXEiyT19XdpiXOP4Vhs+J1R5m8zQOxZlV1G
|
||||
tF9vsXmJqWZpOVPmZ8f35BCsYPvv4yMewnrtAC8PFEK/bOPeYcKN50bol22QYaZu
|
||||
LfpkHfNiFTnfMh8sl/ablPyNY7DUNiP5DRcMdIwmfGQxR5WEQoHL3yPJ42LkB5zs
|
||||
6jIm26DGNXfwura/mi105+ENH1CaROtRYwkiHb08U6qLXXJz80mWJkT90nr8Asj3
|
||||
5xN2cUppg74nG3YVav/38P48T56hG1NHbYF5uOCske19F6wi9maUoto/3vEr0rnX
|
||||
JUp2KODmKdvBI7co245lHBABWikk8VfejQSlCtDBXn644ZMtAdoxKNfR2WTFVEwJ
|
||||
iyd1Fzx0yujuiXDROLhISLQDRjVVAvawrAtLZWYK31bY7KlezPlQnl/D9Asxe85l
|
||||
8jO5+0LdJ6VyOs/Hd4w52alDW/MFySDZSfQHMTIc30hLBJ8OnCEIvluVQQ2UQvoW
|
||||
+no177N9L2Y+M9TcTA62ZyMXShHQGeh20rb4kK8f+iFX8NxtdHVSkxMEFSfDDyQ=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,23 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.networking;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./pia-openvpn.nix
|
||||
./pia-wireguard.nix
|
||||
./ping.nix
|
||||
./tailscale.nix
|
||||
./vpn.nix
|
||||
];
|
||||
|
||||
options.networking.ip_forward = mkEnableOption "Enable ip forwarding";
|
||||
|
||||
config = mkIf cfg.ip_forward {
|
||||
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
|
||||
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.pia.openvpn;
|
||||
vpnfailsafe = pkgs.stdenv.mkDerivation {
|
||||
pname = "vpnfailsafe";
|
||||
version = "0.0.1";
|
||||
src = ./.;
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp vpnfailsafe.sh $out/vpnfailsafe.sh
|
||||
sed -i 's|getent|${pkgs.getent}/bin/getent|' $out/vpnfailsafe.sh
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
options.pia.openvpn = {
|
||||
enable = lib.mkEnableOption "Enable private internet access";
|
||||
server = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "us-washingtondc.privacy.network";
|
||||
example = "swiss.privacy.network";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.openvpn = {
|
||||
servers = {
|
||||
pia = {
|
||||
config = ''
|
||||
client
|
||||
dev tun
|
||||
proto udp
|
||||
remote ${cfg.server} 1198
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
cipher aes-128-cbc
|
||||
auth sha1
|
||||
tls-client
|
||||
remote-cert-tls server
|
||||
|
||||
auth-user-pass
|
||||
compress
|
||||
verb 1
|
||||
reneg-sec 0
|
||||
<crl-verify>
|
||||
-----BEGIN X509 CRL-----
|
||||
MIICWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQI
|
||||
EwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRl
|
||||
cm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAw
|
||||
HgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0
|
||||
ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRl
|
||||
aW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZa
|
||||
MCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG
|
||||
9w0BAQ0FAAOCAQEAQZo9X97ci8EcPYu/uK2HB152OZbeZCINmYyluLDOdcSvg6B5
|
||||
jI+ffKN3laDvczsG6CxmY3jNyc79XVpEYUnq4rT3FfveW1+Ralf+Vf38HdpwB8EW
|
||||
B4hZlQ205+21CALLvZvR8HcPxC9KEnev1mU46wkTiov0EKc+EdRxkj5yMgv0V2Re
|
||||
ze7AP+NQ9ykvDScH4eYCsmufNpIjBLhpLE2cuZZXBLcPhuRzVoU3l7A9lvzG9mjA
|
||||
5YijHJGHNjlWFqyrn1CfYS6koa4TGEPngBoAziWRbDGdhEgJABHrpoaFYaL61zqy
|
||||
MR6jC0K2ps9qyZAN74LEBedEfK7tBOzWMwr58A==
|
||||
-----END X509 CRL-----
|
||||
</crl-verify>
|
||||
|
||||
<ca>
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFqzCCBJOgAwIBAgIJAKZ7D5Yv87qDMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYD
|
||||
VQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNV
|
||||
BAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIElu
|
||||
dGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3Mx
|
||||
IDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkB
|
||||
FiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzM1
|
||||
MThaFw0zNDA0MTIxNzM1MThaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
|
||||
EzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQg
|
||||
QWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UE
|
||||
AxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50
|
||||
ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVy
|
||||
bmV0YWNjZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPXD
|
||||
L1L9tX6DGf36liA7UBTy5I869z0UVo3lImfOs/GSiFKPtInlesP65577nd7UNzzX
|
||||
lH/P/CnFPdBWlLp5ze3HRBCc/Avgr5CdMRkEsySL5GHBZsx6w2cayQ2EcRhVTwWp
|
||||
cdldeNO+pPr9rIgPrtXqT4SWViTQRBeGM8CDxAyTopTsobjSiYZCF9Ta1gunl0G/
|
||||
8Vfp+SXfYCC+ZzWvP+L1pFhPRqzQQ8k+wMZIovObK1s+nlwPaLyayzw9a8sUnvWB
|
||||
/5rGPdIYnQWPgoNlLN9HpSmsAcw2z8DXI9pIxbr74cb3/HSfuYGOLkRqrOk6h4RC
|
||||
OfuWoTrZup1uEOn+fw8CAwEAAaOCAVQwggFQMB0GA1UdDgQWBBQv63nQ/pJAt5tL
|
||||
y8VJcbHe22ZOsjCCAR8GA1UdIwSCARYwggESgBQv63nQ/pJAt5tLy8VJcbHe22ZO
|
||||
sqGB7qSB6zCB6DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpM
|
||||
b3NBbmdlbGVzMSAwHgYDVQQKExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4G
|
||||
A1UECxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAMTF1ByaXZhdGUg
|
||||
SW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQpExdQcml2YXRlIEludGVybmV0IEFjY2Vz
|
||||
czEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5j
|
||||
b22CCQCmew+WL/O6gzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQAn
|
||||
a5PgrtxfwTumD4+3/SYvwoD66cB8IcK//h1mCzAduU8KgUXocLx7QgJWo9lnZ8xU
|
||||
ryXvWab2usg4fqk7FPi00bED4f4qVQFVfGfPZIH9QQ7/48bPM9RyfzImZWUCenK3
|
||||
7pdw4Bvgoys2rHLHbGen7f28knT2j/cbMxd78tQc20TIObGjo8+ISTRclSTRBtyC
|
||||
GohseKYpTS9himFERpUgNtefvYHbn70mIOzfOJFTVqfrptf9jXa9N8Mpy3ayfodz
|
||||
1wiqdteqFXkTYoSDctgKMiZ6GdocK9nMroQipIQtpnwd4yBDWIyC6Bvlkrq5TQUt
|
||||
YDQ8z9v+DMO6iwyIDRiU
|
||||
-----END CERTIFICATE-----
|
||||
</ca>
|
||||
|
||||
disable-occ
|
||||
auth-user-pass /run/agenix/pia-login.conf
|
||||
'';
|
||||
autoStart = true;
|
||||
up = "${vpnfailsafe}/vpnfailsafe.sh";
|
||||
down = "${vpnfailsafe}/vpnfailsafe.sh";
|
||||
};
|
||||
};
|
||||
};
|
||||
age.secrets."pia-login.conf".file = ../../secrets/pia-login.age;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,357 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
# Server list:
|
||||
# https://serverlist.piaservers.net/vpninfo/servers/v6
|
||||
# Reference materials:
|
||||
# https://github.com/pia-foss/manual-connections
|
||||
# https://github.com/thrnz/docker-wireguard-pia/blob/master/extra/wg-gen.sh
|
||||
|
||||
# TODO handle potential errors (or at least print status, success, and failures to the console)
|
||||
# TODO parameterize names of systemd services so that multiple wg VPNs could coexist in theory easier
|
||||
# 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 verify signatures of PIA responses
|
||||
|
||||
with builtins;
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.pia.wireguard;
|
||||
|
||||
getPIAToken = ''
|
||||
PIA_USER=`sed '1q;d' /run/agenix/pia-login.conf`
|
||||
PIA_PASS=`sed '2q;d' /run/agenix/pia-login.conf`
|
||||
# PIA_TOKEN only lasts 24hrs
|
||||
PIA_TOKEN=`curl -s -u "$PIA_USER:$PIA_PASS" https://www.privateinternetaccess.com/gtoken/generateToken | jq -r '.token'`
|
||||
'';
|
||||
|
||||
chooseWireguardServer = ''
|
||||
servers=$(mktemp)
|
||||
servers_json=$(mktemp)
|
||||
curl -s "https://serverlist.piaservers.net/vpninfo/servers/v6" > "$servers"
|
||||
# extract json part only
|
||||
head -n 1 "$servers" | tr -d '\n' > "$servers_json"
|
||||
|
||||
echo "Available location ids:" && jq '.regions | .[] | {name, id, port_forward}' "$servers_json"
|
||||
|
||||
# Some locations have multiple servers available. Pick a random one.
|
||||
totalservers=$(jq -r '.regions | .[] | select(.id=="'${cfg.serverLocation}'") | .servers.wg | length' "$servers_json")
|
||||
if ! [[ "$totalservers" =~ ^[0-9]+$ ]] || [ "$totalservers" -eq 0 ] 2>/dev/null; then
|
||||
echo "Location \"${cfg.serverLocation}\" not found."
|
||||
exit 1
|
||||
fi
|
||||
serverindex=$(( RANDOM % totalservers))
|
||||
WG_HOSTNAME=$(jq -r '.regions | .[] | select(.id=="'${cfg.serverLocation}'") | .servers.wg | .['$serverindex'].cn' "$servers_json")
|
||||
WG_SERVER_IP=$(jq -r '.regions | .[] | select(.id=="'${cfg.serverLocation}'") | .servers.wg | .['$serverindex'].ip' "$servers_json")
|
||||
WG_SERVER_PORT=$(jq -r '.groups.wg | .[0] | .ports | .[0]' "$servers_json")
|
||||
|
||||
# write chosen server
|
||||
rm -f /tmp/${cfg.interfaceName}-server.conf
|
||||
touch /tmp/${cfg.interfaceName}-server.conf
|
||||
chmod 700 /tmp/${cfg.interfaceName}-server.conf
|
||||
echo "$WG_HOSTNAME" >> /tmp/${cfg.interfaceName}-server.conf
|
||||
echo "$WG_SERVER_IP" >> /tmp/${cfg.interfaceName}-server.conf
|
||||
echo "$WG_SERVER_PORT" >> /tmp/${cfg.interfaceName}-server.conf
|
||||
|
||||
rm $servers_json $servers
|
||||
'';
|
||||
|
||||
getChosenWireguardServer = ''
|
||||
WG_HOSTNAME=`sed '1q;d' /tmp/${cfg.interfaceName}-server.conf`
|
||||
WG_SERVER_IP=`sed '2q;d' /tmp/${cfg.interfaceName}-server.conf`
|
||||
WG_SERVER_PORT=`sed '3q;d' /tmp/${cfg.interfaceName}-server.conf`
|
||||
'';
|
||||
|
||||
refreshPIAPort = ''
|
||||
${getChosenWireguardServer}
|
||||
signature=`sed '1q;d' /tmp/${cfg.interfaceName}-port-renewal`
|
||||
payload=`sed '2q;d' /tmp/${cfg.interfaceName}-port-renewal`
|
||||
bind_port_response=`curl -Gs -m 5 --connect-to "$WG_HOSTNAME::$WG_SERVER_IP:" --cacert "${./ca.rsa.4096.crt}" --data-urlencode "payload=$payload" --data-urlencode "signature=$signature" "https://$WG_HOSTNAME:19999/bindPort"`
|
||||
'';
|
||||
|
||||
portForwarding = cfg.forwardPortForTransmission || cfg.forwardedPort != null;
|
||||
|
||||
containerServiceName = "container@${config.vpn-container.containerName}.service";
|
||||
in
|
||||
{
|
||||
options.pia.wireguard = {
|
||||
enable = mkEnableOption "Enable private internet access";
|
||||
badPortForwardPorts = mkOption {
|
||||
type = types.listOf types.port;
|
||||
description = ''
|
||||
Ports that will not be accepted from PIA.
|
||||
If PIA assigns a port from this list, the connection is aborted since we cannot ask for a different port.
|
||||
This is used to guarantee we are not assigned a port that is used by a service we do not want exposed.
|
||||
'';
|
||||
};
|
||||
wireguardListenPort = mkOption {
|
||||
type = types.port;
|
||||
description = "The port wireguard listens on for this VPN connection";
|
||||
default = 51820;
|
||||
};
|
||||
serverLocation = mkOption {
|
||||
type = types.str;
|
||||
default = "swiss";
|
||||
};
|
||||
interfaceName = mkOption {
|
||||
type = types.str;
|
||||
default = "piaw";
|
||||
};
|
||||
forwardedPort = mkOption {
|
||||
type = types.nullOr types.port;
|
||||
description = "The port to redirect port forwarded TCP VPN traffic too";
|
||||
default = null;
|
||||
};
|
||||
forwardPortForTransmission = mkEnableOption "PIA port forwarding for transmission should be performed.";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.forwardPortForTransmission != (cfg.forwardedPort != null);
|
||||
message = ''
|
||||
The PIA forwarded port cannot simultaneously be used by transmission and redirected to another port.
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
# mounts used to pass the connection parameters to the container
|
||||
# the container doesn't have internet until it uses these parameters so it cannot fetch them itself
|
||||
vpn-container.mounts = [
|
||||
"/tmp/${cfg.interfaceName}.conf"
|
||||
"/tmp/${cfg.interfaceName}-server.conf"
|
||||
"/tmp/${cfg.interfaceName}-address.conf"
|
||||
];
|
||||
|
||||
# The container takes ownership of the wireguard interface on its startup
|
||||
containers.vpn.interfaces = [ cfg.interfaceName ];
|
||||
|
||||
# TODO: while this is much better than "loose" networking, it seems to have issues with firewall restarts
|
||||
# allow traffic for wireguard interface to pass since wireguard trips up rpfilter
|
||||
# networking.firewall = {
|
||||
# extraCommands = ''
|
||||
# ip46tables -t raw -I nixos-fw-rpfilter -p udp -m udp --sport ${toString cfg.wireguardListenPort} -j RETURN
|
||||
# ip46tables -t raw -I nixos-fw-rpfilter -p udp -m udp --dport ${toString cfg.wireguardListenPort} -j RETURN
|
||||
# '';
|
||||
# extraStopCommands = ''
|
||||
# ip46tables -t raw -D nixos-fw-rpfilter -p udp -m udp --sport ${toString cfg.wireguardListenPort} -j RETURN || true
|
||||
# ip46tables -t raw -D nixos-fw-rpfilter -p udp -m udp --dport ${toString cfg.wireguardListenPort} -j RETURN || true
|
||||
# '';
|
||||
# };
|
||||
networking.firewall.checkReversePath = "loose";
|
||||
|
||||
systemd.services.pia-vpn-wireguard-init = {
|
||||
description = "Creates PIA VPN Wireguard Interface";
|
||||
|
||||
requires = [ "network-online.target" ];
|
||||
after = [ "network.target" "network-online.target" ];
|
||||
before = [ containerServiceName ];
|
||||
requiredBy = [ containerServiceName ];
|
||||
partOf = [ containerServiceName ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
path = with pkgs; [ wireguard-tools jq curl iproute ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
|
||||
# restart once a month; PIA forwarded port expires after two months
|
||||
# because the container is "PartOf" this unit, it gets restarted too
|
||||
RuntimeMaxSec = "30d";
|
||||
};
|
||||
|
||||
script = ''
|
||||
# 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
|
||||
# issue but is not ideal because then leaking network outside of the VPN is more likely.
|
||||
|
||||
${chooseWireguardServer}
|
||||
|
||||
${getPIAToken}
|
||||
|
||||
# generate wireguard keys
|
||||
privKey=$(wg genkey)
|
||||
pubKey=$(echo "$privKey" | wg pubkey)
|
||||
|
||||
# authorize our WG keys with the PIA server we are about to connect to
|
||||
wireguard_json=`curl -s -G --connect-to "$WG_HOSTNAME::$WG_SERVER_IP:" --cacert "${./ca.rsa.4096.crt}" --data-urlencode "pt=$PIA_TOKEN" --data-urlencode "pubkey=$pubKey" https://$WG_HOSTNAME:$WG_SERVER_PORT/addKey`
|
||||
|
||||
# create wg-quick config file
|
||||
rm -f /tmp/${cfg.interfaceName}.conf /tmp/${cfg.interfaceName}-address.conf
|
||||
touch /tmp/${cfg.interfaceName}.conf /tmp/${cfg.interfaceName}-address.conf
|
||||
chmod 700 /tmp/${cfg.interfaceName}.conf /tmp/${cfg.interfaceName}-address.conf
|
||||
echo "
|
||||
[Interface]
|
||||
# Address = $(echo "$wireguard_json" | jq -r '.peer_ip')
|
||||
PrivateKey = $privKey
|
||||
ListenPort = ${toString cfg.wireguardListenPort}
|
||||
[Peer]
|
||||
PersistentKeepalive = 25
|
||||
PublicKey = $(echo "$wireguard_json" | jq -r '.server_key')
|
||||
AllowedIPs = 0.0.0.0/0
|
||||
Endpoint = $WG_SERVER_IP:$(echo "$wireguard_json" | jq -r '.server_port')
|
||||
" >> /tmp/${cfg.interfaceName}.conf
|
||||
|
||||
# create file storing the VPN ip address PIA assigned to us
|
||||
echo "$wireguard_json" | jq -r '.peer_ip' >> /tmp/${cfg.interfaceName}-address.conf
|
||||
|
||||
# Create wg interface now so it inherits from the namespace with internet access
|
||||
# the container will handle actually connecting the interface since that info is
|
||||
# not preserved upon moving into the container's networking namespace
|
||||
# Roughly following this guide https://www.wireguard.com/netns/#ordinary-containerization
|
||||
[[ -z $(ip link show dev ${cfg.interfaceName} 2>/dev/null) ]] || exit
|
||||
ip link add ${cfg.interfaceName} type wireguard
|
||||
'';
|
||||
|
||||
preStop = ''
|
||||
# cleanup wireguard interface
|
||||
ip link del ${cfg.interfaceName}
|
||||
rm -f /tmp/${cfg.interfaceName}.conf /tmp/${cfg.interfaceName}-address.conf
|
||||
'';
|
||||
};
|
||||
|
||||
vpn-container.config.systemd.services.pia-vpn-wireguard = {
|
||||
description = "Initializes the PIA VPN WireGuard Tunnel";
|
||||
|
||||
requires = [ "network-online.target" ];
|
||||
after = [ "network.target" "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
path = with pkgs; [ wireguard-tools iproute curl jq iptables ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
|
||||
script = ''
|
||||
# pseudo calls wg-quick
|
||||
# Near equivalent of "wg-quick up /tmp/${cfg.interfaceName}.conf"
|
||||
# cannot actually call wg-quick because the interface has to be already
|
||||
# created before the container taken ownership of the interface
|
||||
# Thus, assumes wg interface was already created:
|
||||
# ip link add ${cfg.interfaceName} type wireguard
|
||||
|
||||
${getChosenWireguardServer}
|
||||
|
||||
myaddress=`cat /tmp/${cfg.interfaceName}-address.conf`
|
||||
|
||||
wg setconf ${cfg.interfaceName} /tmp/${cfg.interfaceName}.conf
|
||||
ip -4 address add $myaddress dev ${cfg.interfaceName}
|
||||
ip link set mtu 1420 up dev ${cfg.interfaceName}
|
||||
wg set ${cfg.interfaceName} fwmark ${toString cfg.wireguardListenPort}
|
||||
ip -4 route add 0.0.0.0/0 dev ${cfg.interfaceName} table ${toString cfg.wireguardListenPort}
|
||||
|
||||
# TODO is this needed?
|
||||
ip -4 rule add not fwmark ${toString cfg.wireguardListenPort} table ${toString cfg.wireguardListenPort}
|
||||
ip -4 rule add table main suppress_prefixlength 0
|
||||
|
||||
# The rest of the script is only for only for port forwarding skip if not needed
|
||||
if [ ${boolToString portForwarding} == false ]; then exit 0; fi
|
||||
|
||||
# Reserve port
|
||||
${getPIAToken}
|
||||
payload_and_signature=`curl -s -m 5 --connect-to "$WG_HOSTNAME::$WG_SERVER_IP:" --cacert "${./ca.rsa.4096.crt}" -G --data-urlencode "token=$PIA_TOKEN" "https://$WG_HOSTNAME:19999/getSignature"`
|
||||
signature=$(echo "$payload_and_signature" | jq -r '.signature')
|
||||
payload=$(echo "$payload_and_signature" | jq -r '.payload')
|
||||
port=$(echo "$payload" | base64 -d | jq -r '.port')
|
||||
|
||||
# Check if the port is acceptable
|
||||
notallowed=(${concatStringsSep " " (map toString cfg.badPortForwardPorts)})
|
||||
if [[ " ''${notallowed[*]} " =~ " $port " ]]; then
|
||||
# the port PIA assigned is not allowed, kill the connection
|
||||
wg-quick down /tmp/${cfg.interfaceName}.conf
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# write reserved port to file readable for all users
|
||||
echo $port > /tmp/${cfg.interfaceName}-port
|
||||
chmod 644 /tmp/${cfg.interfaceName}-port
|
||||
|
||||
# write payload and signature info needed to allow refreshing allocated forwarded port
|
||||
rm -f /tmp/${cfg.interfaceName}-port-renewal
|
||||
touch /tmp/${cfg.interfaceName}-port-renewal
|
||||
chmod 700 /tmp/${cfg.interfaceName}-port-renewal
|
||||
echo $signature >> /tmp/${cfg.interfaceName}-port-renewal
|
||||
echo $payload >> /tmp/${cfg.interfaceName}-port-renewal
|
||||
|
||||
# Block all traffic from VPN interface except for traffic that is from the forwarded port
|
||||
iptables -I nixos-fw -p tcp --dport $port -j nixos-fw-accept -i ${cfg.interfaceName}
|
||||
iptables -I nixos-fw -p udp --dport $port -j nixos-fw-accept -i ${cfg.interfaceName}
|
||||
|
||||
# The first port refresh triggers the port to be actually allocated
|
||||
${refreshPIAPort}
|
||||
|
||||
${optionalString (cfg.forwardedPort != null) ''
|
||||
# redirect the fowarded port
|
||||
iptables -A INPUT -i ${cfg.interfaceName} -p tcp --dport $port -j ACCEPT
|
||||
iptables -A INPUT -i ${cfg.interfaceName} -p udp --dport $port -j ACCEPT
|
||||
iptables -A INPUT -i ${cfg.interfaceName} -p tcp --dport ${toString cfg.forwardedPort} -j ACCEPT
|
||||
iptables -A INPUT -i ${cfg.interfaceName} -p udp --dport ${toString cfg.forwardedPort} -j ACCEPT
|
||||
iptables -A PREROUTING -t nat -i ${cfg.interfaceName} -p tcp --dport $port -j REDIRECT --to-port ${toString cfg.forwardedPort}
|
||||
iptables -A PREROUTING -t nat -i ${cfg.interfaceName} -p udp --dport $port -j REDIRECT --to-port ${toString cfg.forwardedPort}
|
||||
''}
|
||||
|
||||
${optionalString cfg.forwardPortForTransmission ''
|
||||
# assumes no auth needed for transmission
|
||||
curlout=$(curl localhost:9091/transmission/rpc 2>/dev/null)
|
||||
regex='X-Transmission-Session-Id\: (\w*)'
|
||||
if [[ $curlout =~ $regex ]]; then
|
||||
sessionId=''${BASH_REMATCH[1]}
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# set the port in transmission
|
||||
data='{"method": "session-set", "arguments": { "peer-port" :'$port' } }'
|
||||
curl http://localhost:9091/transmission/rpc -d "$data" -H "X-Transmission-Session-Id: $sessionId"
|
||||
''}
|
||||
'';
|
||||
|
||||
preStop = ''
|
||||
wg-quick down /tmp/${cfg.interfaceName}.conf
|
||||
|
||||
# The rest of the script is only for only for port forwarding skip if not needed
|
||||
if [ ${boolToString portForwarding} == false ]; then exit 0; fi
|
||||
|
||||
${optionalString (cfg.forwardedPort != null) ''
|
||||
# stop redirecting the forwarded port
|
||||
iptables -D INPUT -i ${cfg.interfaceName} -p tcp --dport $port -j ACCEPT
|
||||
iptables -D INPUT -i ${cfg.interfaceName} -p udp --dport $port -j ACCEPT
|
||||
iptables -D INPUT -i ${cfg.interfaceName} -p tcp --dport ${toString cfg.forwardedPort} -j ACCEPT
|
||||
iptables -D INPUT -i ${cfg.interfaceName} -p udp --dport ${toString cfg.forwardedPort} -j ACCEPT
|
||||
iptables -D PREROUTING -t nat -i ${cfg.interfaceName} -p tcp --dport $port -j REDIRECT --to-port ${toString cfg.forwardedPort}
|
||||
iptables -D PREROUTING -t nat -i ${cfg.interfaceName} -p udp --dport $port -j REDIRECT --to-port ${toString cfg.forwardedPort}
|
||||
''}
|
||||
'';
|
||||
};
|
||||
|
||||
vpn-container.config.systemd.services.pia-vpn-wireguard-forward-port = {
|
||||
enable = portForwarding;
|
||||
description = "PIA VPN WireGuard Tunnel Port Forwarding";
|
||||
after = [ "pia-vpn-wireguard.service" ];
|
||||
requires = [ "pia-vpn-wireguard.service" ];
|
||||
|
||||
path = with pkgs; [ curl ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
};
|
||||
|
||||
script = refreshPIAPort;
|
||||
};
|
||||
|
||||
vpn-container.config.systemd.timers.pia-vpn-wireguard-forward-port = {
|
||||
enable = portForwarding;
|
||||
partOf = [ "pia-vpn-wireguard-forward-port.service" ];
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "*:0/10"; # 10 minutes
|
||||
RandomizedDelaySec = "1m"; # vary by 1 min to give PIA servers some relief
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets."pia-login.conf".file = ../../secrets/pia-login.age;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
# keeps peer to peer connections alive with a periodic ping
|
||||
|
||||
with lib;
|
||||
with builtins;
|
||||
|
||||
# todo auto restart
|
||||
|
||||
let
|
||||
cfg = config.keepalive-ping;
|
||||
|
||||
serviceTemplate = host:
|
||||
{
|
||||
"keepalive-ping@${host}" = {
|
||||
description = "Periodic ping keep alive for ${host} connection";
|
||||
|
||||
requires = [ "network-online.target" ];
|
||||
after = [ "network.target" "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig.Restart = "always";
|
||||
|
||||
path = with pkgs; [ iputils ];
|
||||
|
||||
script = ''
|
||||
ping -i ${cfg.delay} ${host} &>/dev/null
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
combineAttrs = foldl recursiveUpdate { };
|
||||
|
||||
serviceList = map serviceTemplate cfg.hosts;
|
||||
|
||||
services = combineAttrs serviceList;
|
||||
in
|
||||
{
|
||||
options.keepalive-ping = {
|
||||
enable = mkEnableOption "Enable keep alive ping task";
|
||||
hosts = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Hosts to ping periodically
|
||||
'';
|
||||
};
|
||||
delay = mkOption {
|
||||
type = types.str;
|
||||
default = "60";
|
||||
description = ''
|
||||
Ping interval in seconds of periodic ping per host being pinged
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services = services;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.tailscale;
|
||||
in
|
||||
{
|
||||
options.services.tailscale.exitNode = mkEnableOption "Enable exit node support";
|
||||
|
||||
config.services.tailscale.enable = mkDefault (!config.boot.isContainer);
|
||||
|
||||
# MagicDNS
|
||||
config.networking.nameservers = mkIf cfg.enable [ "1.1.1.1" "8.8.8.8" ];
|
||||
config.networking.search = mkIf cfg.enable [ "koi-bebop.ts.net" ];
|
||||
|
||||
# exit node
|
||||
config.networking.firewall.checkReversePath = mkIf cfg.exitNode "loose";
|
||||
config.networking.ip_forward = mkIf cfg.exitNode true;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
{ config, pkgs, lib, allModules, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.vpn-container;
|
||||
in
|
||||
{
|
||||
options.vpn-container = {
|
||||
enable = mkEnableOption "Enable VPN container";
|
||||
|
||||
containerName = mkOption {
|
||||
type = types.str;
|
||||
default = "vpn";
|
||||
description = ''
|
||||
Name of the VPN container.
|
||||
'';
|
||||
};
|
||||
|
||||
mounts = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ "/var/lib" ];
|
||||
example = "/home/example";
|
||||
description = ''
|
||||
List of mounts on the host to bind to the vpn container.
|
||||
'';
|
||||
};
|
||||
|
||||
useOpenVPN = mkEnableOption "Uses OpenVPN instead of wireguard for PIA VPN connection";
|
||||
|
||||
config = mkOption {
|
||||
type = types.anything;
|
||||
default = { };
|
||||
example = ''
|
||||
{
|
||||
services.nginx.enable = true;
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
NixOS config for the vpn container.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
pia.wireguard.enable = !cfg.useOpenVPN;
|
||||
pia.wireguard.forwardPortForTransmission = !cfg.useOpenVPN;
|
||||
|
||||
containers.${cfg.containerName} = {
|
||||
ephemeral = true;
|
||||
autoStart = true;
|
||||
|
||||
bindMounts = mkMerge ([{
|
||||
"/run/agenix" = {
|
||||
hostPath = "/run/agenix";
|
||||
isReadOnly = true;
|
||||
};
|
||||
}] ++ (lists.forEach cfg.mounts (mount:
|
||||
{
|
||||
"${mount}" = {
|
||||
hostPath = mount;
|
||||
isReadOnly = false;
|
||||
};
|
||||
}
|
||||
)));
|
||||
|
||||
enableTun = cfg.useOpenVPN;
|
||||
privateNetwork = true;
|
||||
hostAddress = "172.16.100.1";
|
||||
localAddress = "172.16.100.2";
|
||||
|
||||
config = {
|
||||
imports = allModules ++ [ cfg.config ];
|
||||
|
||||
# speeds up evaluation
|
||||
nixpkgs.pkgs = pkgs;
|
||||
|
||||
# networking.firewall.enable = mkForce false;
|
||||
networking.firewall.trustedInterfaces = [
|
||||
# completely trust internal interface to host
|
||||
"eth0"
|
||||
];
|
||||
|
||||
pia.openvpn.enable = cfg.useOpenVPN;
|
||||
pia.openvpn.server = "swiss.privacy.network"; # swiss vpn
|
||||
|
||||
# TODO fix so it does run it's own resolver again
|
||||
# run it's own DNS resolver
|
||||
networking.useHostResolvConf = false;
|
||||
# services.resolved.enable = true;
|
||||
networking.nameservers = [ "1.1.1.1" "8.8.8.8" ];
|
||||
};
|
||||
};
|
||||
|
||||
# load secrets the container needs
|
||||
age.secrets = config.containers.${cfg.containerName}.config.age.secrets;
|
||||
|
||||
# forwarding for vpn container (only for OpenVPN)
|
||||
networking.nat.enable = mkIf cfg.useOpenVPN true;
|
||||
networking.nat.internalInterfaces = mkIf cfg.useOpenVPN [
|
||||
"ve-${cfg.containerName}"
|
||||
];
|
||||
networking.ip_forward = mkIf cfg.useOpenVPN true;
|
||||
|
||||
# assumes only one potential interface
|
||||
networking.usePredictableInterfaceNames = false;
|
||||
networking.nat.externalInterface = "eth0";
|
||||
};
|
||||
}
|
||||
@@ -81,26 +81,6 @@ update_routes() {
|
||||
fi
|
||||
}
|
||||
|
||||
# $@ := "up" | "down"
|
||||
update_resolv() {
|
||||
case "$@" in
|
||||
up) local domains="" ns=""
|
||||
for opt in ${!foreign_option_*}; do
|
||||
case "${!opt}" in
|
||||
dhcp-option\ DOMAIN*) domains+=" ${!opt##* }";;
|
||||
dhcp-option\ DNS\ *) ns+=" ${!opt##* }";;
|
||||
*) ;;
|
||||
esac
|
||||
done
|
||||
if [[ -n "$ns" ]]; then
|
||||
echo -e "${domains/ /search }\\n${ns// /$'\n'nameserver }"|resolvconf -xa "$dev"
|
||||
else
|
||||
echo "$0: WARNING: no DNS was pushed by the VPN server, this could cause a DNS leak" >&2
|
||||
fi;;
|
||||
down) resolvconf -fd "$dev" 2>/dev/null || true;;
|
||||
esac
|
||||
}
|
||||
|
||||
# $@ := ""
|
||||
update_firewall() {
|
||||
# $@ := "INPUT" | "OUTPUT" | "FORWARD"
|
||||
@@ -198,7 +178,7 @@ trap 'err_msg "$LINENO" "$?"' ERR
|
||||
# $@ := ""
|
||||
main() {
|
||||
case "${script_type:-down}" in
|
||||
up) for f in hosts routes resolv firewall; do "update_$f" up; done;;
|
||||
up) for f in hosts routes firewall; do "update_$f" up; done;;
|
||||
down) update_routes down
|
||||
update_resolv down;;
|
||||
esac
|
||||
+2
-40
@@ -2,7 +2,8 @@
|
||||
|
||||
let
|
||||
cfg = config.de;
|
||||
in {
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
# enable pulseaudio support for packages
|
||||
nixpkgs.config.pulseaudio = true;
|
||||
@@ -16,45 +17,6 @@ in {
|
||||
alsa.support32Bit = true;
|
||||
pulse.enable = true;
|
||||
jack.enable = true;
|
||||
|
||||
# use the example session manager (no others are packaged yet so this is enabled by default,
|
||||
# no need to redefine it in your config for now)
|
||||
#media-session.enable = true;
|
||||
|
||||
config.pipewire = {
|
||||
"context.objects" = [
|
||||
{
|
||||
# A default dummy driver. This handles nodes marked with the "node.always-driver"
|
||||
# properyty when no other driver is currently active. JACK clients need this.
|
||||
factory = "spa-node-factory";
|
||||
args = {
|
||||
"factory.name" = "support.node.driver";
|
||||
"node.name" = "Dummy-Driver";
|
||||
"priority.driver" = 8000;
|
||||
};
|
||||
}
|
||||
{
|
||||
factory = "adapter";
|
||||
args = {
|
||||
"factory.name" = "support.null-audio-sink";
|
||||
"node.name" = "Microphone-Proxy";
|
||||
"node.description" = "Microphone";
|
||||
"media.class" = "Audio/Source/Virtual";
|
||||
"audio.position" = "MONO";
|
||||
};
|
||||
}
|
||||
{
|
||||
factory = "adapter";
|
||||
args = {
|
||||
"factory.name" = "support.null-audio-sink";
|
||||
"node.name" = "Main-Output-Proxy";
|
||||
"node.description" = "Main Output";
|
||||
"media.class" = "Audio/Sink";
|
||||
"audio.position" = "FL,FR";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
users.users.googlebot.extraGroups = [ "audio" ];
|
||||
|
||||
@@ -49,7 +49,8 @@ let
|
||||
];
|
||||
};
|
||||
|
||||
in {
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
# chromium with specific extensions + settings
|
||||
programs.chromium = {
|
||||
@@ -60,9 +61,9 @@ in {
|
||||
"oboonakemofpalcgghocfoadofidjkkk" # keepassxc plugin
|
||||
"cimiefiiaegbelhefglklhhakcgmhkai" # plasma integration
|
||||
"hkgfoiooedgoejojocmhlaklaeopbecg" # picture in picture
|
||||
"fihnjjcciajhdojfnbdddfaoknhalnja" # I don't care about cookies
|
||||
"mnjggcdmjocbbbhaepdhchncahnbgone" # SponsorBlock
|
||||
"dhdgffkkebhmkfjojejmpbldmpobfkfo" # Tampermonkey
|
||||
# "ehpdicggenhgapiikfpnmppdonadlnmp" # Disable Scroll Jacking
|
||||
];
|
||||
extraOpts = {
|
||||
"BrowserSignin" = 0;
|
||||
@@ -79,7 +80,6 @@ in {
|
||||
nixpkgs.config.packageOverrides = pkgs: {
|
||||
vaapiIntel = pkgs.vaapiIntel.override { enableHybridCodec = true; };
|
||||
chromium = pkgs.chromium.override {
|
||||
gnomeKeyringSupport = true;
|
||||
enableWideVine = true;
|
||||
# ungoogled = true;
|
||||
# --enable-native-gpu-memory-buffers # fails on AMD APU
|
||||
|
||||
+12
-4
@@ -2,7 +2,8 @@
|
||||
|
||||
let
|
||||
cfg = config.de;
|
||||
in {
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./kde.nix
|
||||
./xfce.nix
|
||||
@@ -17,6 +18,7 @@ in {
|
||||
./discord.nix
|
||||
./steam.nix
|
||||
./touchpad.nix
|
||||
./mount-samba.nix
|
||||
];
|
||||
|
||||
options.de = {
|
||||
@@ -41,16 +43,20 @@ in {
|
||||
nextcloud-client
|
||||
signal-desktop
|
||||
minecraft
|
||||
sauerbraten
|
||||
gnome.file-roller
|
||||
gparted
|
||||
lm_sensors
|
||||
libreoffice-fresh
|
||||
thunderbird
|
||||
spotifyd
|
||||
spotify-qt
|
||||
arduino
|
||||
yt-dlp
|
||||
jellyfin-media-player
|
||||
joplin-desktop
|
||||
config.inputs.deploy-rs.packages.${config.currentSystem}.deploy-rs
|
||||
|
||||
# For Nix IDE
|
||||
nixpkgs-fmt
|
||||
rnix-lsp
|
||||
];
|
||||
|
||||
# Networking
|
||||
@@ -66,6 +72,8 @@ in {
|
||||
services.avahi.enable = true;
|
||||
services.avahi.nssmdns = true;
|
||||
|
||||
programs.file-roller.enable = true;
|
||||
|
||||
# Security
|
||||
services.gnome.gnome-keyring.enable = true;
|
||||
security.pam.services.googlebot.enableGnomeKeyring = true;
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
let
|
||||
cfg = config.de;
|
||||
in {
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
users.users.googlebot.packages = [
|
||||
pkgs.discord
|
||||
|
||||
+2
-1
@@ -2,7 +2,8 @@
|
||||
|
||||
let
|
||||
cfg = config.de;
|
||||
in {
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
# kde plasma
|
||||
services.xserver = {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# mounts the samba share on s0 over tailscale
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.mount-samba;
|
||||
|
||||
# prevents hanging on network split and other similar niceties to ensure a stable connection
|
||||
network_opts = "nostrictsync,cache=strict,handlecache,handletimeout=30000,rwpidforward,mapposix,soft,resilienthandles,echo_interval=10,noblocksend,fsc";
|
||||
|
||||
systemd_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
|
||||
user_opts = "uid=${toString config.users.users.googlebot.uid},file_mode=0660,dir_mode=0770,user";
|
||||
auth_opts = "sec=ntlmv2i,credentials=/run/agenix/smb-secrets";
|
||||
version_opts = "vers=3.1.1";
|
||||
|
||||
opts = "${systemd_opts},${network_opts},${user_opts},${version_opts},${auth_opts}";
|
||||
in
|
||||
{
|
||||
options.services.mount-samba = {
|
||||
enable = lib.mkEnableOption "enable mounting samba shares";
|
||||
};
|
||||
|
||||
config = lib.mkIf (cfg.enable && config.services.tailscale.enable) {
|
||||
fileSystems."/mnt/public" = {
|
||||
device = "//s0.koi-bebop.ts.net/public";
|
||||
fsType = "cifs";
|
||||
options = [ opts ];
|
||||
};
|
||||
|
||||
fileSystems."/mnt/private" = {
|
||||
device = "//s0.koi-bebop.ts.net/googlebot";
|
||||
fsType = "cifs";
|
||||
options = [ opts ];
|
||||
};
|
||||
|
||||
age.secrets.smb-secrets.file = ../../secrets/smb-secrets.age;
|
||||
|
||||
environment.shellAliases = {
|
||||
# remount storage
|
||||
remount_public = "sudo systemctl restart mnt-public.mount";
|
||||
remount_private = "sudo systemctl restart mnt-private.mount";
|
||||
|
||||
# Encrypted Vault
|
||||
vault_unlock = "${pkgs.gocryptfs}/bin/gocryptfs /mnt/private/.vault/ /mnt/vault/";
|
||||
vault_lock = "umount /mnt/vault/";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
let
|
||||
cfg = config.de;
|
||||
in {
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
nixpkgs.overlays = [
|
||||
(self: super: {
|
||||
|
||||
+2
-1
@@ -2,7 +2,8 @@
|
||||
|
||||
let
|
||||
cfg = config.de;
|
||||
in {
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
programs.steam.enable = true;
|
||||
hardware.steam-hardware.enable = true; # steam controller
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
let
|
||||
cfg = config.de;
|
||||
in {
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
nixpkgs.overlays = [
|
||||
(self: super: {
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
let
|
||||
cfg = config.de.touchpad;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.de.touchpad = {
|
||||
enable = lib.mkEnableOption "enable touchpad";
|
||||
};
|
||||
|
||||
+2
-1
@@ -2,7 +2,8 @@
|
||||
|
||||
let
|
||||
cfg = config.de;
|
||||
in {
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.xserver = {
|
||||
enable = true;
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
let
|
||||
cfg = config.de;
|
||||
in {
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
# yubikey
|
||||
services.pcscd.enable = true;
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.pia;
|
||||
in
|
||||
{
|
||||
options.pia = {
|
||||
enable = lib.mkEnableOption "Enable private internet access";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.openvpn = {
|
||||
servers = {
|
||||
us-east = {
|
||||
config = ''
|
||||
client
|
||||
dev tun
|
||||
proto udp
|
||||
remote us-washingtondc.privacy.network 1198
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
cipher aes-128-cbc
|
||||
auth sha1
|
||||
tls-client
|
||||
remote-cert-tls server
|
||||
|
||||
auth-user-pass
|
||||
compress
|
||||
verb 1
|
||||
reneg-sec 0
|
||||
<crl-verify>
|
||||
-----BEGIN X509 CRL-----
|
||||
MIICWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQI
|
||||
EwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRl
|
||||
cm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAw
|
||||
HgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0
|
||||
ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRl
|
||||
aW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZa
|
||||
MCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG
|
||||
9w0BAQ0FAAOCAQEAQZo9X97ci8EcPYu/uK2HB152OZbeZCINmYyluLDOdcSvg6B5
|
||||
jI+ffKN3laDvczsG6CxmY3jNyc79XVpEYUnq4rT3FfveW1+Ralf+Vf38HdpwB8EW
|
||||
B4hZlQ205+21CALLvZvR8HcPxC9KEnev1mU46wkTiov0EKc+EdRxkj5yMgv0V2Re
|
||||
ze7AP+NQ9ykvDScH4eYCsmufNpIjBLhpLE2cuZZXBLcPhuRzVoU3l7A9lvzG9mjA
|
||||
5YijHJGHNjlWFqyrn1CfYS6koa4TGEPngBoAziWRbDGdhEgJABHrpoaFYaL61zqy
|
||||
MR6jC0K2ps9qyZAN74LEBedEfK7tBOzWMwr58A==
|
||||
-----END X509 CRL-----
|
||||
</crl-verify>
|
||||
|
||||
<ca>
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFqzCCBJOgAwIBAgIJAKZ7D5Yv87qDMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYD
|
||||
VQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNV
|
||||
BAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIElu
|
||||
dGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3Mx
|
||||
IDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkB
|
||||
FiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzM1
|
||||
MThaFw0zNDA0MTIxNzM1MThaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
|
||||
EzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQg
|
||||
QWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UE
|
||||
AxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50
|
||||
ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVy
|
||||
bmV0YWNjZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPXD
|
||||
L1L9tX6DGf36liA7UBTy5I869z0UVo3lImfOs/GSiFKPtInlesP65577nd7UNzzX
|
||||
lH/P/CnFPdBWlLp5ze3HRBCc/Avgr5CdMRkEsySL5GHBZsx6w2cayQ2EcRhVTwWp
|
||||
cdldeNO+pPr9rIgPrtXqT4SWViTQRBeGM8CDxAyTopTsobjSiYZCF9Ta1gunl0G/
|
||||
8Vfp+SXfYCC+ZzWvP+L1pFhPRqzQQ8k+wMZIovObK1s+nlwPaLyayzw9a8sUnvWB
|
||||
/5rGPdIYnQWPgoNlLN9HpSmsAcw2z8DXI9pIxbr74cb3/HSfuYGOLkRqrOk6h4RC
|
||||
OfuWoTrZup1uEOn+fw8CAwEAAaOCAVQwggFQMB0GA1UdDgQWBBQv63nQ/pJAt5tL
|
||||
y8VJcbHe22ZOsjCCAR8GA1UdIwSCARYwggESgBQv63nQ/pJAt5tLy8VJcbHe22ZO
|
||||
sqGB7qSB6zCB6DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpM
|
||||
b3NBbmdlbGVzMSAwHgYDVQQKExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4G
|
||||
A1UECxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAMTF1ByaXZhdGUg
|
||||
SW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQpExdQcml2YXRlIEludGVybmV0IEFjY2Vz
|
||||
czEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5j
|
||||
b22CCQCmew+WL/O6gzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQAn
|
||||
a5PgrtxfwTumD4+3/SYvwoD66cB8IcK//h1mCzAduU8KgUXocLx7QgJWo9lnZ8xU
|
||||
ryXvWab2usg4fqk7FPi00bED4f4qVQFVfGfPZIH9QQ7/48bPM9RyfzImZWUCenK3
|
||||
7pdw4Bvgoys2rHLHbGen7f28knT2j/cbMxd78tQc20TIObGjo8+ISTRclSTRBtyC
|
||||
GohseKYpTS9himFERpUgNtefvYHbn70mIOzfOJFTVqfrptf9jXa9N8Mpy3ayfodz
|
||||
1wiqdteqFXkTYoSDctgKMiZ6GdocK9nMroQipIQtpnwd4yBDWIyC6Bvlkrq5TQUt
|
||||
YDQ8z9v+DMO6iwyIDRiU
|
||||
-----END CERTIFICATE-----
|
||||
</ca>
|
||||
|
||||
disable-occ
|
||||
auth-user-pass /run/agenix/pia-login.conf
|
||||
'';
|
||||
autoStart = true;
|
||||
up = "${./vpnfailsafe.sh}";
|
||||
down = "${./vpnfailsafe.sh}";
|
||||
};
|
||||
};
|
||||
};
|
||||
age.secrets."pia-login.conf".file = ../secrets/pia-login.conf;
|
||||
};
|
||||
}
|
||||
@@ -3,9 +3,9 @@
|
||||
with lib;
|
||||
let
|
||||
cfg = config.ceph;
|
||||
in {
|
||||
options.ceph = {
|
||||
};
|
||||
in
|
||||
{
|
||||
options.ceph = { };
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# ceph.enable = true;
|
||||
|
||||
@@ -10,8 +10,14 @@
|
||||
./matrix.nix
|
||||
./zerobin.nix
|
||||
./gitea.nix
|
||||
./gitea-runner.nix
|
||||
./privatebin/privatebin.nix
|
||||
./radio.nix
|
||||
./samba.nix
|
||||
./owncast.nix
|
||||
./mailserver.nix
|
||||
./nextcloud.nix
|
||||
./iodine.nix
|
||||
./searx.nix
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
{ 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.";
|
||||
};
|
||||
instanceUrl = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
registrationTokenFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
};
|
||||
};
|
||||
|
||||
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 = { };
|
||||
|
||||
# registration token
|
||||
services.gitea-runner.registrationTokenFile = "/run/agenix/gitea-runner-registration-token";
|
||||
age.secrets.gitea-runner-registration-token = {
|
||||
file = ../../secrets/gitea-runner-registration-token.age;
|
||||
owner = "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 ];
|
||||
|
||||
# based on https://gitea.com/gitea/act_runner/src/branch/main/run.sh
|
||||
script = ''
|
||||
. ${cfg.registrationTokenFile}
|
||||
|
||||
if [[ ! -s .runner ]]; then
|
||||
try=$((try + 1))
|
||||
success=0
|
||||
|
||||
LOGFILE="$(mktemp)"
|
||||
|
||||
# The point of this loop is to make it simple, when running both act_runner and gitea in docker,
|
||||
# for the act_runner to wait a moment for gitea to become available before erroring out. Within
|
||||
# the context of a single docker-compose, something similar could be done via healthchecks, but
|
||||
# this is more flexible.
|
||||
while [[ $success -eq 0 ]] && [[ $try -lt ''${10:-10} ]]; do
|
||||
act_runner register \
|
||||
--instance "${cfg.instanceUrl}" \
|
||||
--token "$GITEA_RUNNER_REGISTRATION_TOKEN" \
|
||||
--name "${config.networking.hostName}" \
|
||||
--no-interactive > $LOGFILE 2>&1
|
||||
|
||||
cat $LOGFILE
|
||||
|
||||
cat $LOGFILE | grep 'Runner registered successfully' > /dev/null
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo "SUCCESS"
|
||||
success=1
|
||||
else
|
||||
echo "Waiting to retry ..."
|
||||
sleep 5
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
exec act_runner daemon
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
+33
-6
@@ -1,8 +1,9 @@
|
||||
{ lib, config, ... }:
|
||||
{ lib, pkgs, config, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.gitea;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.services.gitea = {
|
||||
hostname = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
@@ -14,11 +15,8 @@ in {
|
||||
domain = cfg.hostname;
|
||||
rootUrl = "https://${cfg.hostname}/";
|
||||
appName = cfg.hostname;
|
||||
ssh.enable = true;
|
||||
# lfs.enable = true;
|
||||
dump.enable = true;
|
||||
cookieSecure = true;
|
||||
disableRegistration = true;
|
||||
# dump.enable = true;
|
||||
settings = {
|
||||
other = {
|
||||
SHOW_FOOTER_VERSION = false;
|
||||
@@ -26,8 +24,37 @@ in {
|
||||
ui = {
|
||||
DEFAULT_THEME = "arc-green";
|
||||
};
|
||||
service = {
|
||||
DISABLE_REGISTRATION = true;
|
||||
};
|
||||
session = {
|
||||
COOKIE_SECURE = true;
|
||||
};
|
||||
mailer = {
|
||||
ENABLED = true;
|
||||
MAILER_TYPE = "smtp";
|
||||
SMTP_ADDR = "mail.neet.dev";
|
||||
SMTP_PORT = "465";
|
||||
IS_TLS_ENABLED = true;
|
||||
USER = "robot@runyan.org";
|
||||
FROM = "no-reply@neet.dev";
|
||||
};
|
||||
actions = {
|
||||
ENABLED = true;
|
||||
};
|
||||
};
|
||||
mailerPasswordFile = "/run/agenix/robots-email-pw";
|
||||
};
|
||||
age.secrets.robots-email-pw = {
|
||||
file = ../../secrets/robots-email-pw.age;
|
||||
owner = config.services.gitea.user;
|
||||
};
|
||||
|
||||
# backups
|
||||
backup.group."gitea".paths = [
|
||||
config.services.gitea.stateDir
|
||||
];
|
||||
|
||||
services.nginx.enable = true;
|
||||
services.nginx.virtualHosts.${cfg.hostname} = {
|
||||
enableACME = true;
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
|
||||
let
|
||||
cfg = config.services.icecast;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.services.icecast = {
|
||||
mount = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.iodine.server;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
# iodine DNS-based vpn
|
||||
services.iodine.server = {
|
||||
ip = "192.168.99.1";
|
||||
domain = "tun.neet.dev";
|
||||
passwordFile = "/run/agenix/iodine";
|
||||
};
|
||||
age.secrets.iodine.file = ../../secrets/iodine.age;
|
||||
networking.firewall.allowedUDPPorts = [ 53 ];
|
||||
|
||||
networking.nat.internalInterfaces = [
|
||||
"dns0" # iodine
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with builtins;
|
||||
|
||||
let
|
||||
cfg = config.mailserver;
|
||||
domains = [
|
||||
"neet.space"
|
||||
"neet.dev"
|
||||
"neet.cloud"
|
||||
"runyan.org"
|
||||
"runyan.rocks"
|
||||
"thunderhex.com"
|
||||
"tar.ninja"
|
||||
"bsd.ninja"
|
||||
"bsd.rocks"
|
||||
];
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
# kresd doesn't work with tailscale MagicDNS
|
||||
mailserver.localDnsResolver = false;
|
||||
services.resolved.enable = true;
|
||||
|
||||
mailserver = {
|
||||
fqdn = "mail.neet.dev";
|
||||
dkimKeyBits = 2048;
|
||||
indexDir = "/var/lib/mailindex";
|
||||
enableManageSieve = true;
|
||||
fullTextSearch.enable = true;
|
||||
fullTextSearch.indexAttachments = true;
|
||||
fullTextSearch.memoryLimit = 500;
|
||||
inherit domains;
|
||||
loginAccounts = {
|
||||
"jeremy@runyan.org" = {
|
||||
hashedPasswordFile = "/run/agenix/hashed-email-pw";
|
||||
# catchall for all domains
|
||||
aliases = map (domain: "@${domain}") domains;
|
||||
};
|
||||
"robot@runyan.org" = {
|
||||
aliases = [
|
||||
"no-reply@neet.dev"
|
||||
"robot@neet.dev"
|
||||
];
|
||||
sendOnly = true;
|
||||
hashedPasswordFile = "/run/agenix/hashed-robots-email-pw";
|
||||
};
|
||||
};
|
||||
rejectRecipients = [
|
||||
"george@runyan.org"
|
||||
"joslyn@runyan.org"
|
||||
"damon@runyan.org"
|
||||
"jonas@runyan.org"
|
||||
];
|
||||
certificateScheme = 3; # use let's encrypt for certs
|
||||
};
|
||||
age.secrets.hashed-email-pw.file = ../../secrets/hashed-email-pw.age;
|
||||
age.secrets.hashed-robots-email-pw.file = ../../secrets/hashed-robots-email-pw.age;
|
||||
|
||||
# sendmail to use xxx@domain instead of xxx@mail.domain
|
||||
services.postfix.origin = "$mydomain";
|
||||
|
||||
# relay sent mail through mailgun
|
||||
# https://www.howtoforge.com/community/threads/different-smtp-relays-for-different-domains-in-postfix.82711/#post-392620
|
||||
services.postfix.config = {
|
||||
smtp_sasl_auth_enable = "yes";
|
||||
smtp_sasl_security_options = "noanonymous";
|
||||
smtp_sasl_password_maps = "hash:/var/lib/postfix/conf/sasl_relay_passwd";
|
||||
smtp_use_tls = "yes";
|
||||
sender_dependent_relayhost_maps = "hash:/var/lib/postfix/conf/sender_relay";
|
||||
smtp_sender_dependent_authentication = "yes";
|
||||
};
|
||||
services.postfix.mapFiles.sender_relay =
|
||||
let
|
||||
relayHost = "[smtp.mailgun.org]:587";
|
||||
in
|
||||
pkgs.writeText "sender_relay"
|
||||
(concatStringsSep "\n" (map (domain: "@${domain} ${relayHost}") domains));
|
||||
services.postfix.mapFiles.sasl_relay_passwd = "/run/agenix/sasl_relay_passwd";
|
||||
age.secrets.sasl_relay_passwd.file = ../../secrets/sasl_relay_passwd.age;
|
||||
|
||||
# webmail
|
||||
services.nginx.enable = true;
|
||||
services.roundcube = {
|
||||
enable = true;
|
||||
hostName = config.mailserver.fqdn;
|
||||
extraConfig = ''
|
||||
# starttls needed for authentication, so the fqdn required to match the certificate
|
||||
$config['smtp_server'] = "tls://${config.mailserver.fqdn}";
|
||||
$config['smtp_user'] = "%u";
|
||||
$config['smtp_pass'] = "%p";
|
||||
'';
|
||||
};
|
||||
|
||||
# backups
|
||||
backup.group."email".paths = [
|
||||
config.mailserver.mailDirectory
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -3,7 +3,8 @@
|
||||
let
|
||||
cfg = config.services.matrix;
|
||||
certs = config.security.acme.certs;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.services.matrix = {
|
||||
enable = lib.mkEnableOption "enable matrix";
|
||||
element-web = {
|
||||
@@ -59,10 +60,11 @@ in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.matrix-synapse = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server_name = cfg.host;
|
||||
enable_registration = cfg.enable_registration;
|
||||
listeners = [{
|
||||
bind_address = "127.0.0.1";
|
||||
bind_addresses = [ "127.0.0.1" ];
|
||||
port = cfg.port;
|
||||
tls = false;
|
||||
resources = [{
|
||||
@@ -77,6 +79,7 @@ in {
|
||||
turn_shared_secret = cfg.turn.secret;
|
||||
turn_user_lifetime = "1h";
|
||||
};
|
||||
};
|
||||
|
||||
services.coturn = {
|
||||
enable = true;
|
||||
@@ -135,7 +138,8 @@ in {
|
||||
];
|
||||
locations."/".proxyPass = "http://localhost:${toString cfg.port}";
|
||||
};
|
||||
virtualHosts.${cfg.turn.host} = { # get TLS cert for TURN server
|
||||
virtualHosts.${cfg.turn.host} = {
|
||||
# get TLS cert for TURN server
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
let
|
||||
cfg = config.services.murmur;
|
||||
certs = config.security.acme.certs;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.services.murmur.domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
|
||||
let
|
||||
cfg = config.services.nextcloud;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.nextcloud = {
|
||||
https = true;
|
||||
package = pkgs.nextcloud25;
|
||||
hostName = "neet.cloud";
|
||||
config.dbtype = "sqlite";
|
||||
config.adminuser = "jeremy";
|
||||
config.adminpassFile = "/run/agenix/nextcloud-pw";
|
||||
autoUpdateApps.enable = true;
|
||||
enableBrokenCiphersForSSE = false;
|
||||
};
|
||||
age.secrets.nextcloud-pw = {
|
||||
file = ../../secrets/nextcloud-pw.age;
|
||||
owner = "nextcloud";
|
||||
};
|
||||
|
||||
# backups
|
||||
backup.group."nextcloud".paths = [
|
||||
config.services.nextcloud.home
|
||||
];
|
||||
|
||||
services.nginx.virtualHosts.${config.services.nextcloud.hostName} = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -5,7 +5,8 @@ let
|
||||
nginxWithRTMP = pkgs.nginx.override {
|
||||
modules = [ pkgs.nginxModules.rtmp ];
|
||||
};
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.services.nginx.stream = {
|
||||
enable = lib.mkEnableOption "enable nginx rtmp/hls/dash video streaming";
|
||||
port = lib.mkOption {
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
let
|
||||
cfg = config.services.nginx;
|
||||
in {
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.nginx = {
|
||||
recommendedGzipSettings = true;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
{ lib, config, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.owncast;
|
||||
in
|
||||
{
|
||||
options.services.owncast = {
|
||||
hostname = lib.mkOption {
|
||||
type = types.str;
|
||||
example = "example.com";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.owncast.listen = "127.0.0.1";
|
||||
services.owncast.port = 62419; # random port
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ cfg.rtmp-port ];
|
||||
|
||||
services.nginx.enable = true;
|
||||
services.nginx.virtualHosts.${cfg.hostname} = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:${toString cfg.port}";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -14,7 +14,8 @@ let
|
||||
cp -ar $src $out
|
||||
'';
|
||||
};
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.services.privatebin = {
|
||||
enable = lib.mkEnableOption "enable privatebin";
|
||||
host = lib.mkOption {
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
let
|
||||
cfg = config.services.radio;
|
||||
radioPackage = config.inputs.radio.packages.${config.currentSystem}.radio;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.services.radio = {
|
||||
enable = lib.mkEnableOption "enable radio";
|
||||
user = lib.mkOption {
|
||||
|
||||
+43
-11
@@ -24,6 +24,8 @@
|
||||
load printers = yes
|
||||
printing = cups
|
||||
printcap name = cups
|
||||
|
||||
hide files = /.nobackup/.DS_Store/._.DS_Store/
|
||||
'';
|
||||
|
||||
shares = {
|
||||
@@ -31,22 +33,34 @@
|
||||
path = "/data/samba/Public";
|
||||
browseable = "yes";
|
||||
"read only" = "no";
|
||||
"guest ok" = "yes";
|
||||
"create mask" = "0644";
|
||||
"directory mask" = "0755";
|
||||
"force user" = "googlebot";
|
||||
"force group" = "public_data";
|
||||
};
|
||||
private = {
|
||||
path = "/data/samba/Private";
|
||||
browseable = "yes";
|
||||
"read only" = "no";
|
||||
"guest ok" = "no";
|
||||
"create mask" = "0644";
|
||||
"directory mask" = "0755";
|
||||
"force user" = "public_data";
|
||||
"force group" = "public_data";
|
||||
};
|
||||
googlebot = {
|
||||
path = "/data/samba/googlebot";
|
||||
browseable = "yes";
|
||||
"read only" = "no";
|
||||
"guest ok" = "no";
|
||||
"valid users" = "googlebot";
|
||||
"create mask" = "0644";
|
||||
"directory mask" = "0755";
|
||||
"force user" = "googlebot";
|
||||
"force group" = "users";
|
||||
};
|
||||
cris = {
|
||||
path = "/data/samba/cris";
|
||||
browseable = "yes";
|
||||
"read only" = "no";
|
||||
"guest ok" = "no";
|
||||
"valid users" = "cris";
|
||||
"create mask" = "0644";
|
||||
"directory mask" = "0755";
|
||||
"force user" = "root";
|
||||
"force group" = "users";
|
||||
};
|
||||
printers = {
|
||||
comment = "All Printers";
|
||||
path = "/var/spool/samba";
|
||||
@@ -61,6 +75,13 @@
|
||||
};
|
||||
};
|
||||
|
||||
# backups
|
||||
backup.group."samba".paths = [
|
||||
config.services.samba.shares.googlebot.path
|
||||
config.services.samba.shares.cris.path
|
||||
config.services.samba.shares.public.path
|
||||
];
|
||||
|
||||
# Windows discovery of samba server
|
||||
services.samba-wsdd = {
|
||||
enable = true;
|
||||
@@ -83,6 +104,17 @@
|
||||
"d /var/spool/samba 1777 root root -"
|
||||
];
|
||||
|
||||
users.groups.public_data = {};
|
||||
users.groups.public_data.gid = 994;
|
||||
users.users.public_data = {
|
||||
isSystemUser = true;
|
||||
group = "public_data";
|
||||
uid = 994;
|
||||
};
|
||||
users.users.googlebot.extraGroups = [ "public_data" ];
|
||||
|
||||
# samba user for share
|
||||
users.users.cris.isSystemUser = true;
|
||||
users.users.cris.group = "cris";
|
||||
users.groups.cris = { };
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.searx;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.searx = {
|
||||
environmentFile = "/run/agenix/searx";
|
||||
settings = {
|
||||
server.port = 43254;
|
||||
server.secret_key = "@SEARX_SECRET_KEY@";
|
||||
engines = [{
|
||||
name = "wolframalpha";
|
||||
shortcut = "wa";
|
||||
api_key = "@WOLFRAM_API_KEY@";
|
||||
engine = "wolframalpha_api";
|
||||
}];
|
||||
};
|
||||
};
|
||||
services.nginx.virtualHosts."search.neet.space" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:${toString config.services.searx.settings.server.port}";
|
||||
};
|
||||
};
|
||||
age.secrets.searx.file = ../../secrets/searx.age;
|
||||
};
|
||||
}
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
let
|
||||
cfg = config.services.thelounge;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.services.thelounge = {
|
||||
fileUploadBaseUrl = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
@@ -23,7 +24,7 @@ in {
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.thelounge = {
|
||||
private = true;
|
||||
public = false;
|
||||
extraConfig = {
|
||||
reverseProxy = true;
|
||||
maxHistory = -1;
|
||||
@@ -42,6 +43,10 @@ in {
|
||||
};
|
||||
};
|
||||
|
||||
backup.group."thelounge".paths = [
|
||||
"/var/lib/thelounge/"
|
||||
];
|
||||
|
||||
# the lounge client
|
||||
services.nginx.virtualHosts.${cfg.host} = {
|
||||
enableACME = true;
|
||||
|
||||
@@ -79,8 +79,11 @@ in
|
||||
"${toStr webrtc-peer-lower-port}-${toStr webrtc-peer-upper-port}:${toStr webrtc-peer-lower-port}-${toStr webrtc-peer-upper-port}/udp"
|
||||
];
|
||||
cmd = [
|
||||
"lightspeed-webrtc" "--addr=0.0.0.0" "--ip=${domain}"
|
||||
"--ports=${toStr webrtc-peer-lower-port}-${toStr webrtc-peer-upper-port}" "run"
|
||||
"lightspeed-webrtc"
|
||||
"--addr=0.0.0.0"
|
||||
"--ip=${domain}"
|
||||
"--ports=${toStr webrtc-peer-lower-port}-${toStr webrtc-peer-upper-port}"
|
||||
"run"
|
||||
];
|
||||
# imageFile = pkgs.dockerTools.pullImage {
|
||||
# imageName = "projectlightspeed/webrtc";
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
let
|
||||
cfg = config.services.zerobin;
|
||||
in {
|
||||
in
|
||||
{
|
||||
options.services.zerobin = {
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
# Improvements to the default shell
|
||||
# - use nix-index for command-not-found
|
||||
# - disable fish's annoying greeting message
|
||||
# - add some handy shell commands
|
||||
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
comma
|
||||
];
|
||||
|
||||
# nix-index
|
||||
programs.nix-index.enable = true;
|
||||
programs.nix-index.enableFishIntegration = true;
|
||||
programs.command-not-found.enable = false;
|
||||
|
||||
programs.fish = {
|
||||
enable = true;
|
||||
|
||||
shellInit = ''
|
||||
# disable annoying fish shell greeting
|
||||
set fish_greeting
|
||||
|
||||
alias sudo="doas"
|
||||
'';
|
||||
};
|
||||
|
||||
environment.shellAliases = {
|
||||
myip = "dig +short myip.opendns.com @resolver1.opendns.com";
|
||||
|
||||
# https://linuxreviews.org/HOWTO_Test_Disk_I/O_Performance
|
||||
io_seq_read = "${pkgs.fio}/bin/fio --name TEST --eta-newline=5s --filename=temp.file --rw=read --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_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";
|
||||
};
|
||||
|
||||
nixpkgs.overlays = [
|
||||
(final: prev: {
|
||||
# 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.
|
||||
comma = prev.comma.overrideAttrs (old: {
|
||||
postInstall = ''
|
||||
wrapProgram $out/bin/comma \
|
||||
--prefix PATH : ${lib.makeBinPath [ prev.fzy config.programs.nix-index.package ]}
|
||||
ln -s $out/bin/comma $out/bin/,
|
||||
'';
|
||||
});
|
||||
})
|
||||
];
|
||||
}
|
||||
+33
-56
@@ -1,61 +1,38 @@
|
||||
rec {
|
||||
users = [
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
programs.ssh.knownHosts = lib.filterAttrs (n: v: v != null) (lib.concatMapAttrs
|
||||
(host: cfg: {
|
||||
${host} = {
|
||||
hostNames = cfg.hostNames;
|
||||
publicKey = cfg.hostKey;
|
||||
};
|
||||
"${host}-remote-unlock" =
|
||||
if cfg.remoteUnlock != null then {
|
||||
hostNames = builtins.filter (h: h != null) [ cfg.remoteUnlock.clearnetHost cfg.remoteUnlock.onionHost ];
|
||||
publicKey = cfg.remoteUnlock.hostKey;
|
||||
} else null;
|
||||
})
|
||||
config.machines.hosts);
|
||||
|
||||
# prebuilt cmds for easy ssh LUKS unlock
|
||||
environment.shellAliases =
|
||||
let
|
||||
unlockHosts = unlockType: lib.concatMapAttrs
|
||||
(host: cfg:
|
||||
if cfg.remoteUnlock != null && cfg.remoteUnlock.${unlockType} != null then {
|
||||
${host} = cfg.remoteUnlock.${unlockType};
|
||||
} else { })
|
||||
config.machines.hosts;
|
||||
in
|
||||
lib.concatMapAttrs (host: addr: { "unlock-over-tor_${host}" = "torsocks ssh root@${addr}"; }) (unlockHosts "onionHost")
|
||||
//
|
||||
lib.concatMapAttrs (host: addr: { "unlock_${host}" = "ssh root@${addr}"; }) (unlockHosts "clearnetHost");
|
||||
|
||||
# TODO: Old ssh keys I will remove some day...
|
||||
machines.ssh.userKeys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMVR/R3ZOsv7TZbICGBCHdjh1NDT8SnswUyINeJOC7QG"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0dcqL/FhHmv+a1iz3f9LJ48xubO7MZHy35rW9SZOYM"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO0VFnn3+Mh0nWeN92jov81qNE9fpzTAHYBphNoY7HUx" # reg
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHSkKiRUUmnErOKGx81nyge/9KqjkPh8BfDk0D3oP586" # nat
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFeTK1iARlNIKP/DS8/ObBm9yUM/3L1Ub4XI5A2r9OzP" # ray
|
||||
];
|
||||
system = {
|
||||
liza = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDY/pNyWedEfU7Tq9ikGbriRuF1ZWkHhegGS17L0Vcdl";
|
||||
ray = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDQM8hwKRgl8cZj7UVYATSLYu4LhG7I0WFJ9m2iWowiB";
|
||||
s0 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHkTQNPzrIhsKk3OpTHq8b7slIp9LktB49r1w/DKb/5b";
|
||||
n1 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPWlhd1Oid5Xf2zdcBrcdrR0TlhObutwcJ8piobRTpRt";
|
||||
n2 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ7bRiRutnI7Bmyt/I238E3Fp5DqiClIXiVibsccipOr";
|
||||
n3 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+rJEaRrFDGirQC2UoWQkmpzLg4qgTjGJgVqiipWiU5";
|
||||
n4 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINYm2ROIfCeGz6QtDwqAmcj2DX9tq2CZn0eLhskdvB4Z";
|
||||
n5 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE5Qhvwq3PiHEKf+2/4w5ZJkSMNzFLhIRrPOR98m7wW4";
|
||||
n6 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID/P/pa9+qhKAPfvvd8xSO2komJqDW0M1nCK7ZrP6PO7";
|
||||
n7 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPtOlOvTlMX2mxPaXDJ6VlMe5rmroUXpKmJVNxgV32xL";
|
||||
};
|
||||
|
||||
# groups
|
||||
systems = with system; [
|
||||
liza
|
||||
ray
|
||||
s0
|
||||
n1
|
||||
n2
|
||||
n3
|
||||
n4
|
||||
n5
|
||||
n6
|
||||
n7
|
||||
];
|
||||
personal = with system; [
|
||||
ray
|
||||
];
|
||||
servers = with system; [
|
||||
liza
|
||||
s0
|
||||
n1
|
||||
n2
|
||||
n3
|
||||
n4
|
||||
n5
|
||||
n6
|
||||
n7
|
||||
];
|
||||
compute = with system; [
|
||||
n1
|
||||
n2
|
||||
n3
|
||||
n4
|
||||
n5
|
||||
n6
|
||||
n7
|
||||
];
|
||||
storage = with system; [
|
||||
s0
|
||||
];
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{ lib, config, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.zerotierone;
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.zerotierone.joinNetworks = [
|
||||
"565799d8f6d654c0"
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
9993
|
||||
];
|
||||
};
|
||||
}
|
||||
Generated
+150
-71
@@ -2,16 +2,17 @@
|
||||
"nodes": {
|
||||
"agenix": {
|
||||
"inputs": {
|
||||
"darwin": "darwin",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1648942457,
|
||||
"narHash": "sha256-i29Z1t3sVfCNfpp+KAfeExvpqHQSbLO1KWylTtfradU=",
|
||||
"lastModified": 1682101079,
|
||||
"narHash": "sha256-MdAhtjrLKnk2uiqun1FWABbKpLH090oeqCSiWemtuck=",
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"rev": "0d5e59ed645e4c7b60174bc6f6aac6a203dc0b01",
|
||||
"rev": "2994d002dcff5353ca1ac48ec584c7f6589fe447",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -32,7 +33,7 @@
|
||||
"locked": {
|
||||
"lastModified": 1648612759,
|
||||
"narHash": "sha256-SJwlpD2Wz3zFoX2mIYCQfwIOYHaOdeiWGFeDXsLGM84=",
|
||||
"ref": "master",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "39d338b9b24159d8ef3309eecc0d32a2a9f102b5",
|
||||
"revCount": 2,
|
||||
"type": "git",
|
||||
@@ -61,8 +62,6 @@
|
||||
},
|
||||
"dailybuild_modules": {
|
||||
"inputs": {
|
||||
"drastikbot": "drastikbot",
|
||||
"drastikbot_modules": "drastikbot_modules",
|
||||
"flake-utils": [
|
||||
"flake-utils"
|
||||
],
|
||||
@@ -71,60 +70,92 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1648509055,
|
||||
"narHash": "sha256-y8AXfcbkAqn9UcfnfQz1MisT4YIXxj2I6P7uMnqMn9E=",
|
||||
"lastModified": 1651719222,
|
||||
"narHash": "sha256-p/GY5vOP+HUlxNL4OtEhmBNEVQsedOHXEmjfCGONVmE=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "1290ddd9a2ff2bf2d0f702750768312b80efcd34",
|
||||
"revCount": 19,
|
||||
"type": "git",
|
||||
"url": "https://git.neet.dev/zuckerberg/dailybuild_modules.git"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://git.neet.dev/zuckerberg/dailybuild_modules.git"
|
||||
}
|
||||
},
|
||||
"darwin": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"agenix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1673295039,
|
||||
"narHash": "sha256-AsdYgE8/GPwcelGgrntlijMg4t3hLFJFCRF3tL5WVjA=",
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "87b9d090ad39b25b2400029c64825fc2a8868943",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "lnl7",
|
||||
"ref": "master",
|
||||
"rev": "82f4cddc27be4370f321a8d758db1b35c2ce28e5",
|
||||
"revCount": 11,
|
||||
"type": "git",
|
||||
"url": "https://git.neet.dev/zuckerberg/dailybuild_modules.git"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://git.neet.dev/zuckerberg/dailybuild_modules.git"
|
||||
}
|
||||
},
|
||||
"drastikbot": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1596211584,
|
||||
"narHash": "sha256-1L8vTE1YEhFWzY5RYb+s5Hb4LrVJNN2leKlZEugEyRU=",
|
||||
"owner": "olagood",
|
||||
"repo": "drastikbot",
|
||||
"rev": "ef72e3afe7602d95c8b014202e220f04796900ab",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "olagood",
|
||||
"ref": "v2.1",
|
||||
"repo": "drastikbot",
|
||||
"repo": "nix-darwin",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"drastikbot_modules": {
|
||||
"flake": false,
|
||||
"deploy-rs": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"utils": [
|
||||
"simple-nixos-mailserver",
|
||||
"utils"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1619214744,
|
||||
"narHash": "sha256-w1164FkRkeyWnx6a95WDbwEUvNkNwFWa/6mhKtgVw0c=",
|
||||
"owner": "olagood",
|
||||
"repo": "drastikbot_modules",
|
||||
"rev": "3af549a8c3f6e55b63758a61a751bebb1b2db3a3",
|
||||
"lastModified": 1682063650,
|
||||
"narHash": "sha256-VaDHh2z6xlnTHaONlNVHP7qEMcK5rZ8Js3sT6mKb2XY=",
|
||||
"owner": "serokell",
|
||||
"repo": "deploy-rs",
|
||||
"rev": "c2ea4e642dc50fd44b537e9860ec95867af30d39",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "olagood",
|
||||
"ref": "v2.1",
|
||||
"repo": "drastikbot_modules",
|
||||
"owner": "serokell",
|
||||
"repo": "deploy-rs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1668681692,
|
||||
"narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "009399224d5e398d03b22badca40a37ac85412a1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1648297722,
|
||||
"narHash": "sha256-W+qlPsiZd8F3XkzXOzAoR+mpFqzm3ekQkJNa+PIh1BQ=",
|
||||
"lastModified": 1681202837,
|
||||
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade",
|
||||
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -133,37 +164,69 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-index-database": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1681591833,
|
||||
"narHash": "sha256-lW+xOELafAs29yw56FG4MzNOFkh8VHC/X/tRs1wsGn8=",
|
||||
"owner": "Mic92",
|
||||
"repo": "nix-index-database",
|
||||
"rev": "68ec961c51f48768f72d2bbdb396ce65a316677e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Mic92",
|
||||
"repo": "nix-index-database",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1649117019,
|
||||
"narHash": "sha256-ID7nw/8MDgqj/cbJ0wy6AtQ9wp58hSnE6+weZwuHnso=",
|
||||
"lastModified": 1682133240,
|
||||
"narHash": "sha256-s6yRsI/7V+k/+rckp0+/2cs/UXnea3SEfMpy95QiGcc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ccb90fb9e11459aeaf83cc28d5f8910816d90dd0",
|
||||
"rev": "8dafae7c03d6aa8c2ae0a0612fbcb47e994e3fb8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-21.11",
|
||||
"ref": "master",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-21_05": {
|
||||
"nixpkgs-22_05": {
|
||||
"locked": {
|
||||
"lastModified": 1625692408,
|
||||
"narHash": "sha256-e9L3TLLDVIJpMnHtiNHJE62oOh6emRtSZ244bgYJUZs=",
|
||||
"lastModified": 1654936503,
|
||||
"narHash": "sha256-soKzdhI4jTHv/rSbh89RdlcJmrPgH8oMb/PLqiqIYVQ=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c06613c25df3fe1dd26243847a3c105cf6770627",
|
||||
"rev": "dab6df51387c3878cdea09f43589a15729cae9f4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-21.05",
|
||||
"ref": "nixos-22.05",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs-hostapd-pr": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"narHash": "sha256-1rGQKcB1jeRPc1n021ulyOVkA6L6xmNYKmeqQ94+iRc=",
|
||||
"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": {
|
||||
"flake-utils": [
|
||||
@@ -174,16 +237,17 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1633288285,
|
||||
"narHash": "sha256-pL8oEB1AoghvFTsSLLKA1zhV8Z8TM8vcAkeodS6/IZs=",
|
||||
"lastModified": 1631585589,
|
||||
"narHash": "sha256-q4o/4/2pEuJyaKZwNQC5KHnzG1obClzFB7zWk9XSDfY=",
|
||||
"ref": "main",
|
||||
"rev": "eb95b31089f5a107cb7efe0c55d45beb1399ebbb",
|
||||
"revCount": 51,
|
||||
"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"
|
||||
}
|
||||
@@ -191,11 +255,11 @@
|
||||
"radio-web": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1629918655,
|
||||
"narHash": "sha256-sDVM1K1r2y4T37tvdu3mtjiswJ7/PrVGsDQrHzrNfac=",
|
||||
"ref": "master",
|
||||
"rev": "585ce4e3d09d1618d61358902a4231e91e15e1de",
|
||||
"revCount": 4,
|
||||
"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"
|
||||
},
|
||||
@@ -209,8 +273,11 @@
|
||||
"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"
|
||||
@@ -222,27 +289,39 @@
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-21_05": "nixpkgs-21_05",
|
||||
"nixpkgs-21_11": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-22_05": "nixpkgs-22_05",
|
||||
"utils": "utils"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1638911354,
|
||||
"narHash": "sha256-hNhzLOp+dApEY15vwLAQZu+sjEQbJcOXCaSfAT6lpsQ=",
|
||||
"lastModified": 1655930346,
|
||||
"narHash": "sha256-ht56HHOzEhjeIgAv5ZNFjSVX/in1YlUs0HG9c1EUXTM=",
|
||||
"owner": "simple-nixos-mailserver",
|
||||
"repo": "nixos-mailserver",
|
||||
"rev": "6e3a7b2ea6f0d68b82027b988aa25d3423787303",
|
||||
"rev": "f535d8123c4761b2ed8138f3d202ea710a334a1d",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"owner": "simple-nixos-mailserver",
|
||||
"ref": "nixos-21.11",
|
||||
"ref": "nixos-22.05",
|
||||
"repo": "nixos-mailserver",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"utils": {
|
||||
"locked": {
|
||||
"lastModified": 1605370193,
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-21.11";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/master";
|
||||
# nixpkgs-patch-howdy.url = "https://github.com/NixOS/nixpkgs/pull/216245.diff";
|
||||
# nixpkgs-patch-howdy.flake = false;
|
||||
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
|
||||
# mail server
|
||||
simple-nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-21.11";
|
||||
simple-nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-22.05";
|
||||
simple-nixos-mailserver.inputs.nixpkgs.follows = "nixpkgs";
|
||||
simple-nixos-mailserver.inputs.nixpkgs-21_11.follows = "nixpkgs";
|
||||
|
||||
# agenix
|
||||
agenix.url = "github:ryantm/agenix";
|
||||
agenix.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
# radio
|
||||
radio.url = "git+https://git.neet.dev/zuckerberg/radio.git?ref=main";
|
||||
radio.url = "git+https://git.neet.dev/zuckerberg/radio.git?ref=main&rev=5bf607fed977d41a269942a7d1e92f3e6d4f2473";
|
||||
radio.inputs.nixpkgs.follows = "nixpkgs";
|
||||
radio.inputs.flake-utils.follows = "flake-utils";
|
||||
radio-web.url = "git+https://git.neet.dev/zuckerberg/radio-web.git";
|
||||
@@ -29,22 +30,46 @@
|
||||
archivebox.url = "git+https://git.neet.dev/zuckerberg/archivebox.git";
|
||||
archivebox.inputs.nixpkgs.follows = "nixpkgs";
|
||||
archivebox.inputs.flake-utils.follows = "flake-utils";
|
||||
|
||||
# nixos config deployment
|
||||
deploy-rs.url = "github:serokell/deploy-rs";
|
||||
deploy-rs.inputs.nixpkgs.follows = "nixpkgs";
|
||||
deploy-rs.inputs.utils.follows = "simple-nixos-mailserver/utils";
|
||||
|
||||
# prebuilt nix-index database
|
||||
nix-index-database.url = "github:Mic92/nix-index-database";
|
||||
nix-index-database.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
nixpkgs-hostapd-pr.url = "https://github.com/NixOS/nixpkgs/pull/222536.patch";
|
||||
nixpkgs-hostapd-pr.flake = false;
|
||||
};
|
||||
|
||||
outputs = inputs: {
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs:
|
||||
let
|
||||
machines = (import ./common/machine-info/moduleless.nix
|
||||
{
|
||||
inherit nixpkgs;
|
||||
assertionsModule = "${nixpkgs}/nixos/modules/misc/assertions.nix";
|
||||
}).machines.hosts;
|
||||
in
|
||||
{
|
||||
nixosConfigurations =
|
||||
let
|
||||
nixpkgs = inputs.nixpkgs;
|
||||
|
||||
modules = system: [
|
||||
modules = system: hostname: with inputs; [
|
||||
./common
|
||||
inputs.simple-nixos-mailserver.nixosModule
|
||||
inputs.agenix.nixosModule
|
||||
inputs.dailybuild_modules.nixosModule
|
||||
inputs.archivebox.nixosModule
|
||||
simple-nixos-mailserver.nixosModule
|
||||
agenix.nixosModules.default
|
||||
dailybuild_modules.nixosModule
|
||||
archivebox.nixosModule
|
||||
nix-index-database.nixosModules.nix-index
|
||||
({ lib, ... }: {
|
||||
config.environment.systemPackages = [ inputs.agenix.defaultPackage.${system} ];
|
||||
config = {
|
||||
environment.systemPackages = [
|
||||
agenix.packages.${system}.agenix
|
||||
];
|
||||
|
||||
networking.hostName = hostname;
|
||||
};
|
||||
|
||||
# because nixos specialArgs doesn't work for containers... need to pass in inputs a different way
|
||||
options.inputs = lib.mkOption { default = inputs; };
|
||||
@@ -52,70 +77,70 @@
|
||||
})
|
||||
];
|
||||
|
||||
mkVpnContainer = system: pkgs: mount: config: {
|
||||
ephemeral = true;
|
||||
autoStart = true;
|
||||
bindMounts = {
|
||||
"/var/lib" = {
|
||||
hostPath = "/var/lib/";
|
||||
isReadOnly = false;
|
||||
};
|
||||
"/run/agenix" = {
|
||||
hostPath = "/run/agenix";
|
||||
isReadOnly = true;
|
||||
};
|
||||
"/dev/fuse" = {
|
||||
hostPath = "/dev/fuse";
|
||||
isReadOnly = false;
|
||||
};
|
||||
"${mount}" = {
|
||||
hostPath = mount;
|
||||
isReadOnly = false;
|
||||
};
|
||||
};
|
||||
enableTun = true;
|
||||
privateNetwork = true;
|
||||
hostAddress = "172.16.100.1";
|
||||
localAddress = "172.16.100.2";
|
||||
mkSystem = system: nixpkgs: path: hostname:
|
||||
let
|
||||
allModules = modules system hostname;
|
||||
|
||||
config = { lib, ... }: {
|
||||
imports = (modules system) ++ [config];
|
||||
|
||||
nixpkgs.pkgs = pkgs;
|
||||
|
||||
networking.firewall.enable = lib.mkForce false;
|
||||
pia.enable = true;
|
||||
|
||||
# run it's own DNS resolver
|
||||
networking.useHostResolvConf = false;
|
||||
services.resolved.enable = true;
|
||||
};
|
||||
# allow patching nixpkgs, remove this hack once this is solved: https://github.com/NixOS/nix/issues/3920
|
||||
patchedNixpkgsSrc = nixpkgs.legacyPackages.${system}.applyPatches {
|
||||
name = "nixpkgs-patched";
|
||||
src = nixpkgs;
|
||||
patches = [
|
||||
inputs.nixpkgs-hostapd-pr
|
||||
./patches/kexec-luks.patch
|
||||
];
|
||||
};
|
||||
patchedNixpkgs = nixpkgs.lib.fix (self: (import "${patchedNixpkgsSrc}/flake.nix").outputs { self = nixpkgs; });
|
||||
|
||||
mkSystem = system: nixpkgs: path:
|
||||
nixpkgs.lib.nixosSystem {
|
||||
in
|
||||
patchedNixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = (modules system) ++ [path];
|
||||
modules = allModules ++ [ path ];
|
||||
|
||||
specialArgs = {
|
||||
mkVpnContainer = (mkVpnContainer system);
|
||||
inherit allModules;
|
||||
};
|
||||
};
|
||||
in
|
||||
nixpkgs.lib.mapAttrs
|
||||
(hostname: cfg:
|
||||
mkSystem cfg.arch nixpkgs cfg.configurationPath hostname)
|
||||
machines;
|
||||
|
||||
packages =
|
||||
let
|
||||
mkKexec = system:
|
||||
(nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [ ./machines/ephemeral/kexec.nix ];
|
||||
}).config.system.build.kexec_tarball;
|
||||
mkIso = system:
|
||||
(nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [ ./machines/ephemeral/iso.nix ];
|
||||
}).config.system.build.isoImage;
|
||||
in
|
||||
{
|
||||
"reg" = mkSystem "x86_64-linux" nixpkgs ./machines/reg/configuration.nix;
|
||||
"ray" = mkSystem "x86_64-linux" nixpkgs ./machines/ray/configuration.nix;
|
||||
"nat" = mkSystem "aarch64-linux" nixpkgs ./machines/nat/configuration.nix;
|
||||
"neetdev" = mkSystem "x86_64-linux" nixpkgs ./machines/neet.dev/configuration.nix;
|
||||
"liza" = mkSystem "x86_64-linux" nixpkgs ./machines/liza/configuration.nix;
|
||||
"s0" = mkSystem "aarch64-linux" nixpkgs ./machines/storage/s0/configuration.nix;
|
||||
"n1" = mkSystem "aarch64-linux" nixpkgs ./machines/compute/n1/configuration.nix;
|
||||
"n2" = mkSystem "aarch64-linux" nixpkgs ./machines/compute/n2/configuration.nix;
|
||||
"n3" = mkSystem "aarch64-linux" nixpkgs ./machines/compute/n3/configuration.nix;
|
||||
"n4" = mkSystem "aarch64-linux" nixpkgs ./machines/compute/n4/configuration.nix;
|
||||
"n5" = mkSystem "aarch64-linux" nixpkgs ./machines/compute/n5/configuration.nix;
|
||||
"n6" = mkSystem "aarch64-linux" nixpkgs ./machines/compute/n6/configuration.nix;
|
||||
"n7" = mkSystem "aarch64-linux" nixpkgs ./machines/compute/n7/configuration.nix;
|
||||
"x86_64-linux"."kexec" = mkKexec "x86_64-linux";
|
||||
"x86_64-linux"."iso" = mkIso "x86_64-linux";
|
||||
"aarch64-linux"."kexec" = mkKexec "aarch64-linux";
|
||||
"aarch64-linux"."iso" = mkIso "aarch64-linux";
|
||||
};
|
||||
|
||||
deploy.nodes =
|
||||
let
|
||||
mkDeploy = configName: arch: hostname: {
|
||||
inherit hostname;
|
||||
magicRollback = false;
|
||||
sshUser = "root";
|
||||
profiles.system.path = inputs.deploy-rs.lib.${arch}.activate.nixos self.nixosConfigurations.${configName};
|
||||
};
|
||||
in
|
||||
nixpkgs.lib.mapAttrs
|
||||
(hostname: cfg:
|
||||
mkDeploy hostname cfg.arch (builtins.head cfg.hostNames))
|
||||
machines;
|
||||
|
||||
checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) inputs.deploy-rs.lib;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
# NixOS wants to enable GRUB by default
|
||||
boot.loader.grub.enable = false;
|
||||
# Enables the generation of /boot/extlinux/extlinux.conf
|
||||
boot.loader.generic-extlinux-compatible.enable = true;
|
||||
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "/dev/disk/by-label/NIXOS_SD";
|
||||
fsType = "ext4";
|
||||
};
|
||||
};
|
||||
|
||||
system.autoUpgrade.enable = true;
|
||||
|
||||
networking.interfaces.eth0.useDHCP = true;
|
||||
|
||||
hardware.deviceTree.enable = true;
|
||||
hardware.deviceTree.overlays = [
|
||||
./sopine-baseboard-ethernet.dtbo # fix pine64 clusterboard ethernet
|
||||
];
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
../common.nix
|
||||
];
|
||||
|
||||
networking.hostName = "n1";
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
../common.nix
|
||||
];
|
||||
|
||||
networking.hostName = "n2";
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
../common.nix
|
||||
];
|
||||
|
||||
networking.hostName = "n3";
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
../common.nix
|
||||
];
|
||||
|
||||
networking.hostName = "n4";
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
../common.nix
|
||||
];
|
||||
|
||||
networking.hostName = "n5";
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
../common.nix
|
||||
];
|
||||
|
||||
networking.hostName = "n6";
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
../common.nix
|
||||
];
|
||||
|
||||
networking.hostName = "n7";
|
||||
}
|
||||
Binary file not shown.
@@ -1,15 +0,0 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
model = "SoPine with baseboard";
|
||||
compatible = "pine64,sopine-baseboard\0pine64,sopine\0allwinner,sun50i-a64";
|
||||
|
||||
fragment@0 {
|
||||
/* target = <ðernet@1c30000>; */
|
||||
target-path = "/soc/ethernet@1c30000";
|
||||
__overlay__ {
|
||||
allwinner,tx-delay-ps = <500>;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
{ modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/installer/cd-dvd/iso-image.nix")
|
||||
./minimal.nix
|
||||
];
|
||||
|
||||
isoImage.makeUsbBootable = true;
|
||||
|
||||
networking.hostName = "iso";
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
# From https://mdleom.com/blog/2021/03/09/nixos-oracle/#Build-a-kexec-tarball
|
||||
# Builds a kexec img
|
||||
|
||||
{ config, pkgs, modulesPath, ... }:
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/installer/netboot/netboot.nix")
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
./minimal.nix
|
||||
];
|
||||
|
||||
networking.hostName = "kexec";
|
||||
|
||||
# stripped down version of https://github.com/cleverca22/nix-tests/tree/master/kexec
|
||||
system.build = rec {
|
||||
image = pkgs.runCommand "image" { buildInputs = [ pkgs.nukeReferences ]; } ''
|
||||
mkdir $out
|
||||
if [ -f ${config.system.build.kernel}/bzImage ]; then
|
||||
cp ${config.system.build.kernel}/bzImage $out/kernel
|
||||
else
|
||||
cp ${config.system.build.kernel}/Image $out/kernel
|
||||
fi
|
||||
cp ${config.system.build.netbootRamdisk}/initrd $out/initrd
|
||||
nuke-refs $out/kernel
|
||||
'';
|
||||
kexec_script = pkgs.writeTextFile {
|
||||
executable = true;
|
||||
name = "kexec-nixos";
|
||||
text = ''
|
||||
#!${pkgs.stdenv.shell}
|
||||
set -e
|
||||
${pkgs.kexectools}/bin/kexec -l ${image}/kernel --initrd=${image}/initrd --append="init=${builtins.unsafeDiscardStringContext config.system.build.toplevel}/init ${toString config.boot.kernelParams}"
|
||||
sync
|
||||
echo "executing kernel, filesystems will be improperly umounted"
|
||||
${pkgs.kexectools}/bin/kexec -e
|
||||
'';
|
||||
};
|
||||
kexec_tarball = pkgs.callPackage (modulesPath + "/../lib/make-system-tarball.nix") {
|
||||
storeContents = [
|
||||
{
|
||||
object = config.system.build.kexec_script;
|
||||
symlink = "/kexec_nixos";
|
||||
}
|
||||
];
|
||||
contents = [ ];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
{ config, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/installer/cd-dvd/channel.nix")
|
||||
../../common/machine-info
|
||||
../../common/ssh.nix
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "e1000" "e1000e" "virtio_pci" "r8169" ];
|
||||
boot.kernelParams = [
|
||||
"panic=30"
|
||||
"boot.panic_on_fail" # reboot the machine upon fatal boot issues
|
||||
"console=ttyS0,115200" # enable serial console
|
||||
"console=tty1"
|
||||
];
|
||||
boot.kernel.sysctl."vm.overcommit_memory" = "1";
|
||||
|
||||
boot.kernelPackages = pkgs.linuxPackages_latest;
|
||||
|
||||
system.stateVersion = "21.11";
|
||||
|
||||
# hardware.enableAllFirmware = true;
|
||||
# nixpkgs.config.allowUnfree = true;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
cryptsetup
|
||||
btrfs-progs
|
||||
git
|
||||
git-lfs
|
||||
wget
|
||||
htop
|
||||
dnsutils
|
||||
pciutils
|
||||
usbutils
|
||||
lm_sensors
|
||||
];
|
||||
|
||||
environment.variables.GC_INITIAL_HEAP_SIZE = "1M";
|
||||
|
||||
networking.useDHCP = true;
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings = {
|
||||
KbdInteractiveAuthentication = false;
|
||||
PasswordAuthentication = false;
|
||||
};
|
||||
};
|
||||
|
||||
services.getty.autologinUser = "root";
|
||||
users.users.root.openssh.authorizedKeys.keys = config.machines.ssh.userKeys;
|
||||
}
|
||||
@@ -1,273 +0,0 @@
|
||||
{ config, pkgs, lib, mkVpnContainer, ... }:
|
||||
|
||||
let
|
||||
mta-sts-web = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."=/.well-known/mta-sts.txt".alias = pkgs.writeText "mta-sts.txt" ''
|
||||
version: STSv1
|
||||
mode: none
|
||||
mx: mail.neet.dev
|
||||
max_age: 86400
|
||||
'';
|
||||
};
|
||||
in {
|
||||
imports =[
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
# 5synsrjgvfzywruomjsfvfwhhlgxqhyofkzeqt2eisyijvjvebnu2xyd.onion
|
||||
|
||||
firmware.x86_64.enable = true;
|
||||
bios = {
|
||||
enable = true;
|
||||
device = "/dev/sda";
|
||||
};
|
||||
|
||||
luks = {
|
||||
enable = true;
|
||||
device.path = "/dev/disk/by-uuid/2f736fba-8a0c-4fb5-8041-c849fb5e1297";
|
||||
};
|
||||
|
||||
system.autoUpgrade.enable = true;
|
||||
|
||||
networking.hostName = "liza";
|
||||
|
||||
networking.interfaces.enp1s0.useDHCP = true;
|
||||
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
hostname = "git.neet.dev";
|
||||
disableRegistration = true;
|
||||
};
|
||||
|
||||
services.peertube = {
|
||||
enable = true;
|
||||
localDomain = "tube.neet.space";
|
||||
listenHttp = 9000;
|
||||
listenWeb = 443;
|
||||
enableWebHttps = true;
|
||||
# dataDirs
|
||||
serviceEnvironmentFile = "/run/agenix/peertube-init";
|
||||
# settings
|
||||
database = {
|
||||
createLocally = true;
|
||||
passwordFile = "/run/agenix/peertube-db-pw";
|
||||
};
|
||||
redis = {
|
||||
createLocally = true;
|
||||
passwordFile = "/run/agenix/peertube-redis-pw";
|
||||
};
|
||||
smtp = {
|
||||
createLocally = false;
|
||||
passwordFile = "/run/agenix/peertube-smtp";
|
||||
};
|
||||
};
|
||||
services.nginx.virtualHosts."tube.neet.space" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:${toString config.services.peertube.listenHttp}";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
age.secrets.peertube-init.file = ../../secrets/peertube-init.age;
|
||||
age.secrets.peertube-db-pw.file = ../../secrets/peertube-db-pw.age;
|
||||
age.secrets.peertube-redis-pw.file = ../../secrets/peertube-redis-pw.age;
|
||||
age.secrets.peertube-smtp.file = ../../secrets/peertube-smtp.age;
|
||||
networking.firewall.allowedTCPPorts = [ 1935 ];
|
||||
|
||||
services.searx = {
|
||||
enable = true;
|
||||
environmentFile = "/run/agenix/searx";
|
||||
settings = {
|
||||
server.port = 43254;
|
||||
server.secret_key = "@SEARX_SECRET_KEY@";
|
||||
engines = [ {
|
||||
name = "wolframalpha";
|
||||
shortcut = "wa";
|
||||
api_key = "@WOLFRAM_API_KEY@";
|
||||
engine = "wolframalpha_api";
|
||||
} ];
|
||||
};
|
||||
};
|
||||
services.nginx.virtualHosts."search.neet.space" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:${toString config.services.searx.settings.server.port}";
|
||||
};
|
||||
};
|
||||
age.secrets.searx.file = ../../secrets/searx.age;
|
||||
|
||||
services.minecraft-server = {
|
||||
enable = true;
|
||||
jvmOpts = "-Xms2048M -Xmx4092M -XX:+UseG1GC -XX:ParallelGCThreads=2 -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=10";
|
||||
eula = true;
|
||||
declarative = true;
|
||||
serverProperties = {
|
||||
motd = "Welcome :)";
|
||||
server-port = 38358;
|
||||
white-list = false;
|
||||
};
|
||||
openFirewall = true;
|
||||
package = pkgs.minecraft-server.overrideAttrs (old: {
|
||||
version = "1.17";
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://launcher.mojang.com/v1/objects/0a269b5f2c5b93b1712d0f5dc43b6182b9ab254e/server.jar";
|
||||
sha1 = "0a269b5f2c5b93b1712d0f5dc43b6182b9ab254e";
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
# wrap radio in a VPN
|
||||
containers.vpn = mkVpnContainer pkgs "/dev/null" {
|
||||
services.radio = {
|
||||
enable = true;
|
||||
host = "radio.neet.space";
|
||||
};
|
||||
};
|
||||
# containers cannot unlock their own secrets right now. unlock it here
|
||||
age.secrets."pia-login.conf".file = ../../secrets/pia-login.conf;
|
||||
|
||||
services.drastikbot = {
|
||||
enable = true;
|
||||
wolframAppIdFile = "/run/agenix/wolframalpha";
|
||||
};
|
||||
age.secrets.wolframalpha = {
|
||||
file = ../../secrets/wolframalpha.age;
|
||||
owner = config.services.drastikbot.user;
|
||||
};
|
||||
|
||||
# icecast endpoint + website
|
||||
services.nginx.virtualHosts."radio.neet.space" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations = {
|
||||
"/stream.mp3" = {
|
||||
proxyPass = "http://172.16.100.2:8001/stream.mp3";
|
||||
extraConfig = ''
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
'';
|
||||
};
|
||||
"/".root = config.inputs.radio-web;
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."paradigminteractive.agency" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/".root = builtins.fetchTarball {
|
||||
url = "https://git.neet.dev/zuckerberg/paradigminteractive.agency/archive/b91f3ea2884ddd902461a8acb47f20ae04bc28ee.tar.gz";
|
||||
sha256 = "1x1fpsd1qr0004hfcxk6j4c4n3wwxykzhnv47gmrdnx5hq1nbzq4";
|
||||
};
|
||||
};
|
||||
|
||||
services.matrix = {
|
||||
enable = true;
|
||||
host = "neet.space";
|
||||
enable_registration = false;
|
||||
element-web = {
|
||||
enable = true;
|
||||
host = "chat.neet.space";
|
||||
};
|
||||
jitsi-meet = {
|
||||
enable = true;
|
||||
host = "meet.neet.space";
|
||||
};
|
||||
turn = {
|
||||
host = "turn.neet.space";
|
||||
secret = "a8369a0e96922abf72494bb888c85831b";
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."tmp.neet.dev" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
root = "/var/www/tmp";
|
||||
};
|
||||
|
||||
mailserver = {
|
||||
enable = true;
|
||||
fqdn = "mail.neet.dev";
|
||||
dkimKeyBits = 2048;
|
||||
indexDir = "/var/lib/mailindex";
|
||||
enableManageSieve = true;
|
||||
fullTextSearch.enable = true;
|
||||
fullTextSearch.indexAttachments = true;
|
||||
fullTextSearch.memoryLimit = 500;
|
||||
domains = [
|
||||
"neet.space" "neet.dev" "neet.cloud"
|
||||
"runyan.org" "runyan.rocks"
|
||||
"thunderhex.com" "tar.ninja"
|
||||
"bsd.ninja" "bsd.rocks"
|
||||
"paradigminteractive.agency"
|
||||
];
|
||||
loginAccounts = {
|
||||
"jeremy@runyan.org" = {
|
||||
hashedPasswordFile = "/run/agenix/email-pw";
|
||||
aliases = [
|
||||
"@neet.space" "@neet.cloud" "@neet.dev"
|
||||
"@runyan.org" "@runyan.rocks"
|
||||
"@thunderhex.com" "@tar.ninja"
|
||||
"@bsd.ninja" "@bsd.rocks"
|
||||
"@paradigminteractive.agency"
|
||||
];
|
||||
};
|
||||
};
|
||||
rejectRecipients = [
|
||||
"george@runyan.org"
|
||||
"joslyn@runyan.org"
|
||||
"damon@runyan.org"
|
||||
"jonas@runyan.org"
|
||||
];
|
||||
certificateScheme = 3; # use let's encrypt for certs
|
||||
};
|
||||
age.secrets.email-pw.file = ../../secrets/email-pw.age;
|
||||
services.nginx.virtualHosts."mta-sts.runyan.org" = mta-sts-web;
|
||||
services.nginx.virtualHosts."mta-sts.runyan.rocks" = mta-sts-web;
|
||||
services.nginx.virtualHosts."mta-sts.thunderhex.com" = mta-sts-web;
|
||||
services.nginx.virtualHosts."mta-sts.tar.ninja" = mta-sts-web;
|
||||
services.nginx.virtualHosts."mta-sts.bsd.ninja" = mta-sts-web;
|
||||
services.nginx.virtualHosts."mta-sts.bsd.rocks" = mta-sts-web;
|
||||
|
||||
services.nextcloud = {
|
||||
enable = true;
|
||||
https = true;
|
||||
package = pkgs.nextcloud22;
|
||||
hostName = "neet.cloud";
|
||||
config.dbtype = "sqlite";
|
||||
config.adminuser = "jeremy";
|
||||
config.adminpassFile = "/run/agenix/nextcloud-pw";
|
||||
autoUpdateApps.enable = true;
|
||||
};
|
||||
age.secrets.nextcloud-pw = {
|
||||
file = ../../secrets/nextcloud-pw.age;
|
||||
owner = "nextcloud";
|
||||
};
|
||||
services.nginx.virtualHosts.${config.services.nextcloud.hostName} = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
|
||||
# iodine DNS-based vpn
|
||||
services.iodine.server = {
|
||||
enable = true;
|
||||
ip = "192.168.99.1";
|
||||
domain = "tun.neet.dev";
|
||||
passwordFile = "/run/agenix/iodine";
|
||||
};
|
||||
age.secrets.iodine.file = ../../secrets/iodine.age;
|
||||
networking.firewall.allowedUDPPorts = [ 53 ];
|
||||
|
||||
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
|
||||
networking.nat.enable = true;
|
||||
networking.nat.internalInterfaces = [
|
||||
"dns0" # iodine
|
||||
"ve-vpn" # vpn container
|
||||
];
|
||||
networking.nat.externalInterface = "enp1s0";
|
||||
|
||||
security.acme.acceptTerms = true;
|
||||
security.acme.email = "zuckerberg@neet.dev";
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
# 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 + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "ata_piix" "virtio_pci" "floppy" "sr_mod" "virtio_blk" ];
|
||||
boot.initrd.kernelModules = [ "dm-snapshot" ];
|
||||
boot.kernelModules = [ ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-uuid/b90eaf3c-2f91-499a-a066-861e0f4478df";
|
||||
fsType = "btrfs";
|
||||
};
|
||||
|
||||
fileSystems."/home" =
|
||||
{ device = "/dev/disk/by-uuid/b90eaf3c-2f91-499a-a066-861e0f4478df";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=home" ];
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/2b8f6f6d-9358-4d30-8341-7426574e0819";
|
||||
fsType = "ext3";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[ { device = "/dev/disk/by-uuid/ef7a83db-4b33-41d1-85fc-cff69e480352"; }
|
||||
];
|
||||
|
||||
}
|
||||
@@ -10,8 +10,6 @@
|
||||
networking.hostName = "nat";
|
||||
networking.interfaces.ens160.useDHCP = true;
|
||||
|
||||
services.zerotierone.enable = true;
|
||||
|
||||
de.enable = true;
|
||||
de.touchpad.enable = true;
|
||||
}
|
||||
|
||||
@@ -12,12 +12,14 @@
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-uuid/02a8c0c7-fd4e-4443-a83c-2d0b63848779";
|
||||
{
|
||||
device = "/dev/disk/by-uuid/02a8c0c7-fd4e-4443-a83c-2d0b63848779";
|
||||
fsType = "btrfs";
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/0C95-1290";
|
||||
{
|
||||
device = "/dev/disk/by-uuid/0C95-1290";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
imports =[
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
# wt6nczjfvtba6pvjt2qtevwjpq4gcbz46bwjz4hboehgecyqmzqgwnqd.onion
|
||||
|
||||
firmware.x86_64.enable = true;
|
||||
bios = {
|
||||
enable = true;
|
||||
device = "/dev/sda";
|
||||
};
|
||||
|
||||
luks = {
|
||||
enable = true;
|
||||
device.path = "/dev/disk/by-uuid/06f6b0bf-fe79-4b89-a549-b464c2b162a1";
|
||||
};
|
||||
|
||||
networking.hostName = "neetdev";
|
||||
|
||||
system.autoUpgrade.enable = true;
|
||||
|
||||
networking.interfaces.eno1.useDHCP = true;
|
||||
|
||||
services.nginx.enable = true;
|
||||
security.acme.acceptTerms = true;
|
||||
security.acme.email = "letsencrypt+5@tar.ninja";
|
||||
|
||||
services.thelounge = {
|
||||
enable = true;
|
||||
port = 9000;
|
||||
fileUploadBaseUrl = "https://files.neet.cloud/irc/";
|
||||
host = "irc.neet.dev";
|
||||
fileHost = {
|
||||
host = "files.neet.cloud";
|
||||
path = "/irc";
|
||||
};
|
||||
};
|
||||
|
||||
services.murmur = {
|
||||
enable = true;
|
||||
port = 23563;
|
||||
domain = "voice.neet.space";
|
||||
};
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
# 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.initrd.availableKernelModules = [ "ahci" ];
|
||||
boot.initrd.kernelModules = [ "dm-snapshot" ];
|
||||
boot.kernelModules = [ "kvm-intel" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-uuid/35ca3392-548a-45ef-9e72-392cddfcea1b";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=root" ];
|
||||
};
|
||||
|
||||
fileSystems."/home" =
|
||||
{ device = "/dev/disk/by-uuid/35ca3392-548a-45ef-9e72-392cddfcea1b";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=home" ];
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/d1d3cc19-980f-42ea-9784-a223ea71f435";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[ { device = "/dev/disk/by-uuid/86fdcded-3f0e-4ee0-81bc-c1c92cb96ab1"; }
|
||||
];
|
||||
|
||||
powerManagement.cpuFreqGovernor = lib.mkDefault "performance";
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
services.gitea-runner = {
|
||||
enable = true;
|
||||
instanceUrl = "https://git.neet.dev";
|
||||
};
|
||||
|
||||
system.autoUpgrade.enable = true;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
# 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 + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
# because grub just doesn't work for some reason
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
|
||||
remoteLuksUnlock.enable = true;
|
||||
remoteLuksUnlock.enableTorUnlock = false;
|
||||
|
||||
boot.initrd.availableKernelModules = [ "xhci_pci" ];
|
||||
boot.initrd.kernelModules = [ "dm-snapshot" ];
|
||||
boot.kernelModules = [ ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
luks.devices = [ "/dev/disk/by-uuid/d26c1820-4c39-4615-98c2-51442504e194" ];
|
||||
|
||||
fileSystems."/" =
|
||||
{
|
||||
device = "/dev/disk/by-uuid/851bfde6-93cd-439e-9380-de28aa87eda9";
|
||||
fsType = "btrfs";
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{
|
||||
device = "/dev/disk/by-uuid/F185-C4E5";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[{ device = "/dev/disk/by-uuid/d809e3a1-3915-405a-a200-4429c5efdf87"; }];
|
||||
|
||||
networking.interfaces.enp0s6.useDHCP = lib.mkDefault true;
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
hostNames = [
|
||||
"phil"
|
||||
"phil.neet.dev"
|
||||
];
|
||||
|
||||
arch = "aarch64-linux";
|
||||
|
||||
systemRoles = [
|
||||
"server"
|
||||
"gitea-runner"
|
||||
];
|
||||
|
||||
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlgRPpuUkZqe8/lHugRPm/m2vcN9psYhh5tENHZt9I2";
|
||||
|
||||
remoteUnlock = {
|
||||
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK0RodotOXLMy/w70aa096gaNqPBnfgiXR5ZAH4+wGzd";
|
||||
clearnetHost = "unlock.phil.neet.dev";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
system.autoUpgrade.enable = true;
|
||||
# I want to manually trigger kexec updates for now on ponyo
|
||||
system.autoUpgrade.allowKexec = false;
|
||||
luks.enableKexec = true;
|
||||
|
||||
# p2p mesh network
|
||||
services.tailscale.exitNode = true;
|
||||
|
||||
# email server
|
||||
mailserver.enable = true;
|
||||
|
||||
# nextcloud
|
||||
services.nextcloud.enable = true;
|
||||
|
||||
# git
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
hostname = "git.neet.dev";
|
||||
};
|
||||
|
||||
# IRC
|
||||
services.thelounge = {
|
||||
enable = true;
|
||||
port = 9000;
|
||||
fileUploadBaseUrl = "https://files.neet.cloud/irc/";
|
||||
host = "irc.neet.dev";
|
||||
fileHost = {
|
||||
host = "files.neet.cloud";
|
||||
path = "/irc";
|
||||
};
|
||||
};
|
||||
|
||||
# mumble
|
||||
services.murmur = {
|
||||
enable = true;
|
||||
port = 23563;
|
||||
domain = "voice.neet.space";
|
||||
};
|
||||
|
||||
# IRC bot
|
||||
services.drastikbot = {
|
||||
enable = true;
|
||||
wolframAppIdFile = "/run/agenix/wolframalpha";
|
||||
};
|
||||
age.secrets.wolframalpha = {
|
||||
file = ../../secrets/wolframalpha.age;
|
||||
owner = config.services.drastikbot.user;
|
||||
};
|
||||
backup.group."dailybot".paths = [
|
||||
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
|
||||
services.matrix = {
|
||||
enable = true;
|
||||
host = "neet.space";
|
||||
enable_registration = false;
|
||||
element-web = {
|
||||
enable = true;
|
||||
host = "chat.neet.space";
|
||||
};
|
||||
jitsi-meet = {
|
||||
enable = true;
|
||||
host = "meet.neet.space";
|
||||
};
|
||||
turn = {
|
||||
host = "turn.neet.space";
|
||||
secret = "a8369a0e96922abf72494bb888c85831b";
|
||||
};
|
||||
};
|
||||
# pin postgresql for matrix (will need to migrate eventually)
|
||||
services.postgresql.package = pkgs.postgresql_11;
|
||||
|
||||
# iodine DNS-based vpn
|
||||
services.iodine.server.enable = true;
|
||||
|
||||
# proxied web services
|
||||
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" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/".proxyPass = "http://s0.koi-bebop.ts.net:4533";
|
||||
};
|
||||
|
||||
# TODO replace with a proper file hosting service
|
||||
services.nginx.virtualHosts."tmp.neet.dev" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
root = "/var/www/tmp";
|
||||
};
|
||||
|
||||
# redirect runyan.org to github
|
||||
services.nginx.virtualHosts."runyan.org" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
extraConfig = ''
|
||||
rewrite ^/(.*)$ https://github.com/GoogleBot42 redirect;
|
||||
'';
|
||||
};
|
||||
|
||||
# owncast live streaming
|
||||
services.owncast.enable = true;
|
||||
services.owncast.hostname = "live.neet.dev";
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-intel" "nvme" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
firmware.x86_64.enable = true;
|
||||
|
||||
bios = {
|
||||
enable = true;
|
||||
device = "/dev/sda";
|
||||
};
|
||||
|
||||
remoteLuksUnlock.enable = true;
|
||||
|
||||
luks.devices = [
|
||||
"/dev/disk/by-uuid/4cc36be4-dbff-4afe-927d-69bf4637bae2"
|
||||
"/dev/disk/by-uuid/e52b01b3-81c8-4bb2-ae7e-a3d9c793cb00"
|
||||
];
|
||||
|
||||
fileSystems."/" =
|
||||
{
|
||||
device = "/dev/mapper/enc-pv1";
|
||||
fsType = "btrfs";
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{
|
||||
device = "/dev/disk/by-uuid/d3a3777d-1e70-47fa-a274-804dc70ee7fd";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
swapDevices = [
|
||||
{
|
||||
device = "/dev/disk/by-partuuid/b14668b8-9026-b041-8b71-f302b6b291bf";
|
||||
randomEncryption.enable = true;
|
||||
}
|
||||
];
|
||||
|
||||
networking.interfaces.eth0.useDHCP = true;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
hostNames = [
|
||||
"ponyo"
|
||||
"ponyo.neet.dev"
|
||||
"git.neet.dev"
|
||||
];
|
||||
|
||||
arch = "x86_64-linux";
|
||||
|
||||
systemRoles = [
|
||||
"server"
|
||||
"email-server"
|
||||
"iodine"
|
||||
"pia"
|
||||
"nextcloud"
|
||||
"dailybot"
|
||||
"gitea"
|
||||
];
|
||||
|
||||
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMBBlTAIp38RhErU1wNNV5MBeb+WGH0mhF/dxh5RsAXN";
|
||||
|
||||
remoteUnlock = {
|
||||
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC9LQuuImgWlkjDhEEIbM1wOd+HqRv1RxvYZuLXPSdRi";
|
||||
|
||||
clearnetHost = "unlock.ponyo.neet.dev";
|
||||
onionHost = "cfamr6artx75qvt7ho3rrbsc7mkucmv5aawebwflsfuorusayacffryd.onion";
|
||||
};
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
disabledModules = [
|
||||
"hardware/video/nvidia.nix"
|
||||
];
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
./nvidia.nix
|
||||
];
|
||||
|
||||
firmware.x86_64.enable = true;
|
||||
efi.enable = true;
|
||||
|
||||
boot.initrd.luks.devices."enc-pv" = {
|
||||
device = "/dev/disk/by-uuid/c1822e5f-4137-44e1-885f-954e926583ce";
|
||||
allowDiscards = true;
|
||||
};
|
||||
|
||||
networking.hostName = "ray";
|
||||
|
||||
hardware.enableAllFirmware = true;
|
||||
|
||||
# newer kernel for wifi
|
||||
boot.kernelPackages = pkgs.linuxPackages_latest;
|
||||
|
||||
# gpu
|
||||
services.xserver.videoDrivers = [ "nvidia" ];
|
||||
services.xserver.logFile = "/var/log/Xorg.0.log";
|
||||
hardware.nvidia = {
|
||||
modesetting.enable = true; # for nvidia-vaapi-driver
|
||||
prime = {
|
||||
#reverse_sync.enable = true;
|
||||
offload.enable = true;
|
||||
offload.enableOffloadCmd = true;
|
||||
#sync.enable = true;
|
||||
nvidiaBusId = "PCI:1:0:0";
|
||||
amdgpuBusId = "PCI:4:0:0";
|
||||
};
|
||||
powerManagement = {
|
||||
# enable = true;
|
||||
# finegrained = true;
|
||||
coarsegrained = true;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
virtualisation.docker.enable = true;
|
||||
|
||||
services.zerotierone.enable = true;
|
||||
|
||||
de.enable = true;
|
||||
de.touchpad.enable = true;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -5,37 +5,55 @@
|
||||
|
||||
{
|
||||
imports =
|
||||
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||
[
|
||||
(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;
|
||||
luks.devices = [ "/dev/disk/by-uuid/c1822e5f-4137-44e1-885f-954e926583ce" ];
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/vg/root";
|
||||
{
|
||||
device = "/dev/vg/root";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=root" ];
|
||||
};
|
||||
|
||||
fileSystems."/home" =
|
||||
{ device = "/dev/vg/root";
|
||||
{
|
||||
device = "/dev/vg/root";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=home" ];
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/2C85-2B59";
|
||||
{
|
||||
device = "/dev/disk/by-uuid/2C85-2B59";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[ { device = "/dev/vg/swap"; }
|
||||
];
|
||||
|
||||
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
|
||||
# high-resolution display
|
||||
hardware.video.hidpi.enable = lib.mkDefault true;
|
||||
[{ device = "/dev/vg/swap"; }];
|
||||
}
|
||||
|
||||
@@ -1,485 +0,0 @@
|
||||
# This module provides the proprietary NVIDIA X11 / OpenGL drivers.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
nvidia_x11 = let
|
||||
drivers = config.services.xserver.videoDrivers;
|
||||
isDeprecated = str: (hasPrefix "nvidia" str) && (str != "nvidia");
|
||||
hasDeprecated = drivers: any isDeprecated drivers;
|
||||
in if (hasDeprecated drivers) then
|
||||
throw ''
|
||||
Selecting an nvidia driver has been modified for NixOS 19.03. The version is now set using `hardware.nvidia.package`.
|
||||
''
|
||||
else if (elem "nvidia" drivers) then cfg.package else null;
|
||||
|
||||
enabled = nvidia_x11 != null;
|
||||
cfg = config.hardware.nvidia;
|
||||
|
||||
pCfg = cfg.prime;
|
||||
syncCfg = pCfg.sync;
|
||||
offloadCfg = pCfg.offload;
|
||||
reverseSyncCfg = pCfg.reverse_sync;
|
||||
primeEnabled = syncCfg.enable || reverseSyncCfg.enable || offloadCfg.enable;
|
||||
nvidiaPersistencedEnabled = cfg.nvidiaPersistenced;
|
||||
nvidiaSettings = cfg.nvidiaSettings;
|
||||
in
|
||||
|
||||
{
|
||||
imports =
|
||||
[
|
||||
(mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "enable" ] [ "hardware" "nvidia" "prime" "sync" "enable" ])
|
||||
(mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "allowExternalGpu" ] [ "hardware" "nvidia" "prime" "allowExternalGpu" ])
|
||||
(mkRenamedOptionModule [ "hardware" "nvidia" "prime" "sync" "allowExternalGpu" ] [ "hardware" "nvidia" "prime" "allowExternalGpu" ])
|
||||
(mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "nvidiaBusId" ] [ "hardware" "nvidia" "prime" "nvidiaBusId" ])
|
||||
(mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "intelBusId" ] [ "hardware" "nvidia" "prime" "intelBusId" ])
|
||||
];
|
||||
|
||||
options = {
|
||||
hardware.nvidia.powerManagement.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Experimental power management through systemd. For more information, see
|
||||
the NVIDIA docs, on Chapter 21. Configuring Power Management Support.
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.powerManagement.finegrained = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Experimental power management of PRIME offload. For more information, see
|
||||
the NVIDIA docs, chapter 22. PCI-Express runtime power management.
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.powerManagement.coarsegrained = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Experimental power management of PRIME offload. For more information, see
|
||||
the NVIDIA docs, chapter 22. PCI-Express runtime power management.
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.modesetting.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Enable kernel modesetting when using the NVIDIA proprietary driver.
|
||||
|
||||
Enabling this fixes screen tearing when using Optimus via PRIME (see
|
||||
<option>hardware.nvidia.prime.sync.enable</option>. This is not enabled
|
||||
by default because it is not officially supported by NVIDIA and would not
|
||||
work with SLI.
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.prime.nvidiaBusId = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "PCI:1:0:0";
|
||||
description = ''
|
||||
Bus ID of the NVIDIA GPU. You can find it using lspci; for example if lspci
|
||||
shows the NVIDIA GPU at "01:00.0", set this option to "PCI:1:0:0".
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.prime.intelBusId = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "PCI:0:2:0";
|
||||
description = ''
|
||||
Bus ID of the Intel GPU. You can find it using lspci; for example if lspci
|
||||
shows the Intel GPU at "00:02.0", set this option to "PCI:0:2:0".
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.prime.amdgpuBusId = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "PCI:4:0:0";
|
||||
description = ''
|
||||
Bus ID of the AMD APU. You can find it using lspci; for example if lspci
|
||||
shows the AMD APU at "04:00.0", set this option to "PCI:4:0:0".
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.prime.sync.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Enable NVIDIA Optimus support using the NVIDIA proprietary driver via PRIME.
|
||||
If enabled, the NVIDIA GPU will be always on and used for all rendering,
|
||||
while enabling output to displays attached only to the integrated Intel/AMD
|
||||
GPU without a multiplexer.
|
||||
|
||||
Note that this option only has any effect if the "nvidia" driver is specified
|
||||
in <option>services.xserver.videoDrivers</option>, and it should preferably
|
||||
be the only driver there.
|
||||
|
||||
If this is enabled, then the bus IDs of the NVIDIA and Intel/AMD GPUs have to
|
||||
be specified (<option>hardware.nvidia.prime.nvidiaBusId</option> and
|
||||
<option>hardware.nvidia.prime.intelBusId</option> or
|
||||
<option>hardware.nvidia.prime.amdgpuBusId</option>).
|
||||
|
||||
If you enable this, you may want to also enable kernel modesetting for the
|
||||
NVIDIA driver (<option>hardware.nvidia.modesetting.enable</option>) in order
|
||||
to prevent tearing.
|
||||
|
||||
Note that this configuration will only be successful when a display manager
|
||||
for which the <option>services.xserver.displayManager.setupCommands</option>
|
||||
option is supported is used.
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.prime.allowExternalGpu = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Configure X to allow external NVIDIA GPUs when using Prime [Reverse] Sync.
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.prime.offload.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Enable render offload support using the NVIDIA proprietary driver via PRIME.
|
||||
|
||||
If this is enabled, then the bus IDs of the NVIDIA and Intel/AMD GPUs have to
|
||||
be specified (<option>hardware.nvidia.prime.nvidiaBusId</option> and
|
||||
<option>hardware.nvidia.prime.intelBusId</option> or
|
||||
<option>hardware.nvidia.prime.amdgpuBusId</option>).
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.prime.offload.enableOffloadCmd = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Adds a `nvidia-offload` convenience script to <option>environment.systemPackages</option>
|
||||
for offloading programs to an nvidia device. To work, should have also enabled
|
||||
<option>hardware.nvidia.prime.offload.enable</option> or <option>hardware.nvidia.prime.reverse_sync.enable</option>
|
||||
|
||||
Example usage `nvidia-offload sauerbraten_client`
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.prime.reverse_sync.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Warning: This feature is relatively new, depending on your system this might
|
||||
work poorly. AMD support, especially so.
|
||||
See: https://forums.developer.nvidia.com/t/the-all-new-outputsink-feature-aka-reverse-prime/129828
|
||||
|
||||
Enable NVIDIA Optimus support using the NVIDIA proprietary driver via reverse
|
||||
PRIME. If enabled, the Intel/AMD GPU will be used for all rendering, while
|
||||
enabling output to displays attached only to the NVIDIA GPU without a
|
||||
multiplexer.
|
||||
|
||||
Note that this option only has any effect if the "nvidia" driver is specified
|
||||
in <option>services.xserver.videoDrivers</option>, and it should preferably
|
||||
be the only driver there.
|
||||
|
||||
If this is enabled, then the bus IDs of the NVIDIA and Intel/AMD GPUs have to
|
||||
be specified (<option>hardware.nvidia.prime.nvidiaBusId</option> and
|
||||
<option>hardware.nvidia.prime.intelBusId</option> or
|
||||
<option>hardware.nvidia.prime.amdgpuBusId</option>).
|
||||
|
||||
If you enable this, you may want to also enable kernel modesetting for the
|
||||
NVIDIA driver (<option>hardware.nvidia.modesetting.enable</option>) in order
|
||||
to prevent tearing.
|
||||
|
||||
Note that this configuration will only be successful when a display manager
|
||||
for which the <option>services.xserver.displayManager.setupCommands</option>
|
||||
option is supported is used.
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.nvidiaSettings = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Whether to add nvidia-settings, NVIDIA's GUI configuration tool, to
|
||||
systemPackages.
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.nvidiaPersistenced = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Update for NVIDA GPU headless mode, i.e. nvidia-persistenced. It ensures all
|
||||
GPUs stay awake even during headless mode.
|
||||
'';
|
||||
};
|
||||
|
||||
hardware.nvidia.package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = config.boot.kernelPackages.nvidiaPackages.stable;
|
||||
defaultText = literalExpression "config.boot.kernelPackages.nvidiaPackages.stable";
|
||||
description = ''
|
||||
The NVIDIA X11 derivation to use.
|
||||
'';
|
||||
example = literalExpression "config.boot.kernelPackages.nvidiaPackages.legacy_340";
|
||||
};
|
||||
};
|
||||
|
||||
config = let
|
||||
igpuDriver = if pCfg.intelBusId != "" then "modesetting" else "amdgpu";
|
||||
igpuBusId = if pCfg.intelBusId != "" then pCfg.intelBusId else pCfg.amdgpuBusId;
|
||||
in mkIf enabled {
|
||||
assertions = [
|
||||
{
|
||||
assertion = primeEnabled -> pCfg.intelBusId == "" || pCfg.amdgpuBusId == "";
|
||||
message = ''
|
||||
You cannot configure both an Intel iGPU and an AMD APU. Pick the one corresponding to your processor.
|
||||
'';
|
||||
}
|
||||
|
||||
{
|
||||
assertion = offloadCfg.enableOffloadCmd -> offloadCfg.enable || reverseSyncCfg.enable;
|
||||
message = ''
|
||||
Offload command requires offloading or reverse prime sync to be enabled.
|
||||
'';
|
||||
}
|
||||
|
||||
{
|
||||
assertion = primeEnabled -> pCfg.nvidiaBusId != "" && (pCfg.intelBusId != "" || pCfg.amdgpuBusId != "");
|
||||
message = ''
|
||||
When NVIDIA PRIME is enabled, the GPU bus IDs must configured.
|
||||
'';
|
||||
}
|
||||
|
||||
{
|
||||
assertion = offloadCfg.enable -> versionAtLeast nvidia_x11.version "435.21";
|
||||
message = "NVIDIA PRIME render offload is currently only supported on versions >= 435.21.";
|
||||
}
|
||||
|
||||
{
|
||||
assertion = (reverseSyncCfg.enable && pCfg.amdgpuBusId != "") -> versionAtLeast nvidia_x11.version "470.0";
|
||||
message = "NVIDIA PRIME render offload for AMD APUs is currently only supported on versions >= 470 beta.";
|
||||
}
|
||||
|
||||
{
|
||||
assertion = !(syncCfg.enable && offloadCfg.enable);
|
||||
message = "PRIME Sync and Offload cannot be both enabled";
|
||||
}
|
||||
|
||||
{
|
||||
assertion = !(syncCfg.enable && reverseSyncCfg.enable);
|
||||
message = "PRIME Sync and PRIME Reverse Sync cannot be both enabled";
|
||||
}
|
||||
|
||||
{
|
||||
assertion = !(syncCfg.enable && cfg.powerManagement.finegrained && cfg.powerManagement.coarsegrained);
|
||||
message = "Sync precludes powering down the NVIDIA GPU.";
|
||||
}
|
||||
|
||||
{
|
||||
assertion = cfg.powerManagement.finegrained -> offloadCfg.enable;
|
||||
message = "Fine-grained power management requires offload to be enabled.";
|
||||
}
|
||||
|
||||
{
|
||||
assertion = cfg.powerManagement.coarsegrained -> offloadCfg.enable;
|
||||
message = "Coarse-grained power management requires offload to be enabled.";
|
||||
}
|
||||
|
||||
{
|
||||
assertion = cfg.powerManagement.enable -> (
|
||||
builtins.pathExists (cfg.package.out + "/bin/nvidia-sleep.sh") &&
|
||||
builtins.pathExists (cfg.package.out + "/lib/systemd/system-sleep/nvidia")
|
||||
);
|
||||
message = "Required files for driver based power management don't exist.";
|
||||
}
|
||||
];
|
||||
|
||||
# If Optimus/PRIME is enabled, we:
|
||||
# - Specify the configured NVIDIA GPU bus ID in the Device section for the
|
||||
# "nvidia" driver.
|
||||
# - Add the AllowEmptyInitialConfiguration option to the Screen section for the
|
||||
# "nvidia" driver, in order to allow the X server to start without any outputs.
|
||||
# - Add a separate Device section for the Intel GPU, using the "modesetting"
|
||||
# driver and with the configured BusID.
|
||||
# - OR add a separate Device section for the AMD APU, using the "amdgpu"
|
||||
# driver and with the configures BusID.
|
||||
# - Reference that Device section from the ServerLayout section as an inactive
|
||||
# device.
|
||||
# - Configure the display manager to run specific `xrandr` commands which will
|
||||
# configure/enable displays connected to the Intel iGPU / AMD APU.
|
||||
|
||||
services.xserver.useGlamor = mkDefault offloadCfg.enable;
|
||||
|
||||
# reverse sync implies offloading
|
||||
hardware.nvidia.prime.offload.enable = mkDefault reverseSyncCfg.enable;
|
||||
|
||||
services.xserver.drivers = optional primeEnabled {
|
||||
name = igpuDriver;
|
||||
display = !syncCfg.enable;
|
||||
modules = optional (igpuDriver == "amdgpu") [ pkgs.xorg.xf86videoamdgpu ];
|
||||
deviceSection = ''
|
||||
BusID "${igpuBusId}"
|
||||
${optionalString (syncCfg.enable && igpuDriver != "amdgpu") ''Option "AccelMethod" "none"''}
|
||||
'';
|
||||
} ++ singleton {
|
||||
name = "nvidia";
|
||||
modules = [ nvidia_x11.bin ];
|
||||
display = syncCfg.enable;
|
||||
deviceSection = optionalString primeEnabled ''
|
||||
BusID "${pCfg.nvidiaBusId}"
|
||||
${optionalString pCfg.allowExternalGpu "Option \"AllowExternalGpus\""}
|
||||
'';
|
||||
};
|
||||
|
||||
services.xserver.serverLayoutSection = optionalString syncCfg.enable ''
|
||||
Inactive "Device-${igpuDriver}[0]"
|
||||
'' + optionalString reverseSyncCfg.enable ''
|
||||
Inactive "Device-nvidia[0]"
|
||||
'' + optionalString offloadCfg.enable ''
|
||||
Option "AllowNVIDIAGPUScreens"
|
||||
'';
|
||||
|
||||
services.xserver.displayManager.setupCommands = let
|
||||
gpuProviderName = if igpuDriver == "amdgpu" then
|
||||
# find the name of the provider if amdgpu
|
||||
"`${pkgs.xorg.xrandr}/bin/xrandr --listproviders | ${pkgs.gnugrep}/bin/grep -i AMD | ${pkgs.gnused}/bin/sed -n 's/^.*name://p'`"
|
||||
else
|
||||
igpuDriver;
|
||||
providerCmdParams = if syncCfg.enable then "\"${gpuProviderName}\" NVIDIA-0" else "NVIDIA-G0 \"${gpuProviderName}\"";
|
||||
in optionalString (syncCfg.enable || reverseSyncCfg.enable) ''
|
||||
# Added by nvidia configuration module for Optimus/PRIME.
|
||||
${pkgs.xorg.xrandr}/bin/xrandr --setprovideroutputsource ${providerCmdParams}
|
||||
${pkgs.xorg.xrandr}/bin/xrandr --auto
|
||||
'';
|
||||
|
||||
environment.etc."nvidia/nvidia-application-profiles-rc" = mkIf nvidia_x11.useProfiles {
|
||||
source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";
|
||||
};
|
||||
|
||||
# 'nvidia_x11' installs it's files to /run/opengl-driver/...
|
||||
environment.etc."egl/egl_external_platform.d".source =
|
||||
"/run/opengl-driver/share/egl/egl_external_platform.d/";
|
||||
|
||||
hardware.opengl.extraPackages = [
|
||||
nvidia_x11.out
|
||||
# pkgs.nvidia-vaapi-driver
|
||||
];
|
||||
hardware.opengl.extraPackages32 = [
|
||||
nvidia_x11.lib32
|
||||
# pkgs.pkgsi686Linux.nvidia-vaapi-driver
|
||||
];
|
||||
|
||||
environment.systemPackages = [ nvidia_x11.bin ]
|
||||
++ optionals cfg.nvidiaSettings [ nvidia_x11.settings ]
|
||||
++ optionals nvidiaPersistencedEnabled [ nvidia_x11.persistenced ]
|
||||
++ optionals offloadCfg.enableOffloadCmd [
|
||||
(pkgs.writeShellScriptBin "nvidia-offload" ''
|
||||
export __NV_PRIME_RENDER_OFFLOAD=1
|
||||
export __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0
|
||||
export __GLX_VENDOR_LIBRARY_NAME=nvidia
|
||||
export __VK_LAYER_NV_optimus=NVIDIA_only
|
||||
exec -a "$0" "$@"
|
||||
'')
|
||||
];
|
||||
|
||||
systemd.packages = optional cfg.powerManagement.enable nvidia_x11.out;
|
||||
|
||||
systemd.services = let
|
||||
baseNvidiaService = state: {
|
||||
description = "NVIDIA system ${state} actions";
|
||||
|
||||
path = with pkgs; [ kbd ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${nvidia_x11.out}/bin/nvidia-sleep.sh '${state}'";
|
||||
};
|
||||
};
|
||||
|
||||
nvidiaService = sleepState: (baseNvidiaService sleepState) // {
|
||||
before = [ "systemd-${sleepState}.service" ];
|
||||
requiredBy = [ "systemd-${sleepState}.service" ];
|
||||
};
|
||||
|
||||
services = (builtins.listToAttrs (map (t: nameValuePair "nvidia-${t}" (nvidiaService t)) ["hibernate" "suspend"]))
|
||||
// {
|
||||
nvidia-resume = (baseNvidiaService "resume") // {
|
||||
after = [ "systemd-suspend.service" "systemd-hibernate.service" ];
|
||||
requiredBy = [ "systemd-suspend.service" "systemd-hibernate.service" ];
|
||||
};
|
||||
};
|
||||
in optionalAttrs cfg.powerManagement.enable services
|
||||
// optionalAttrs nvidiaPersistencedEnabled {
|
||||
"nvidia-persistenced" = mkIf nvidiaPersistencedEnabled {
|
||||
description = "NVIDIA Persistence Daemon";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "forking";
|
||||
Restart = "always";
|
||||
PIDFile = "/var/run/nvidia-persistenced/nvidia-persistenced.pid";
|
||||
ExecStart = "${nvidia_x11.persistenced}/bin/nvidia-persistenced --verbose";
|
||||
ExecStopPost = "${pkgs.coreutils}/bin/rm -rf /var/run/nvidia-persistenced";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = optional config.virtualisation.docker.enableNvidia
|
||||
"L+ /run/nvidia-docker/bin - - - - ${nvidia_x11.bin}/origBin"
|
||||
++ optional (nvidia_x11.persistenced != null && config.virtualisation.docker.enableNvidia)
|
||||
"L+ /run/nvidia-docker/extras/bin/nvidia-persistenced - - - - ${nvidia_x11.persistenced}/origBin/nvidia-persistenced";
|
||||
|
||||
boot.extraModulePackages = [ nvidia_x11.bin ];
|
||||
|
||||
# nvidia-uvm is required by CUDA applications.
|
||||
boot.kernelModules = [ "nvidia-uvm" ] ++
|
||||
optionals config.services.xserver.enable [ "nvidia" "nvidia_modeset" "nvidia_drm" ];
|
||||
|
||||
# If requested enable modesetting via kernel parameter.
|
||||
boot.kernelParams = optional (offloadCfg.enable || cfg.modesetting.enable) "nvidia-drm.modeset=1"
|
||||
++ optional cfg.powerManagement.enable "nvidia.NVreg_PreserveVideoMemoryAllocations=1";
|
||||
|
||||
services.udev.extraRules =
|
||||
''
|
||||
# Create /dev/nvidia-uvm when the nvidia-uvm module is loaded.
|
||||
KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidiactl c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) 255'"
|
||||
KERNEL=="nvidia_modeset", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-modeset c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) 254'"
|
||||
KERNEL=="card*", SUBSYSTEM=="drm", DRIVERS=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia%n c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) %n'"
|
||||
KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 0'"
|
||||
KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 0'"
|
||||
'' + optionalString (cfg.powerManagement.finegrained || cfg.powerManagement.coarsegrained) ''
|
||||
# Remove NVIDIA USB xHCI Host Controller devices, if present
|
||||
ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{remove}="1"
|
||||
|
||||
# Remove NVIDIA USB Type-C UCSI devices, if present
|
||||
ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c8000", ATTR{remove}="1"
|
||||
|
||||
# Remove NVIDIA Audio devices, if present
|
||||
ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x040300", ATTR{remove}="1"
|
||||
|
||||
# Enable runtime PM for NVIDIA VGA/3D controller devices on driver bind
|
||||
ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="auto"
|
||||
ACTION=="bind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="auto"
|
||||
|
||||
# Disable runtime PM for NVIDIA VGA/3D controller devices on driver unbind
|
||||
ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030000", TEST=="power/control", ATTR{power/control}="on"
|
||||
ACTION=="unbind", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x030200", TEST=="power/control", ATTR{power/control}="on"
|
||||
'';
|
||||
|
||||
boot.extraModprobeConfig = optionalString cfg.powerManagement.finegrained ''
|
||||
options nvidia "NVreg_DynamicPowerManagement=0x02"
|
||||
'' + optionalString cfg.powerManagement.coarsegrained ''
|
||||
options nvidia "NVreg_DynamicPowerManagement=0x01"
|
||||
'';
|
||||
|
||||
boot.blacklistedKernelModules = [ "nouveau" "nvidiafb" ];
|
||||
|
||||
services.acpid.enable = true;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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="
|
||||
];
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
{ config, pkgs, fetchurl, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
# smcxui7kwoyxpswwage4fkcppxnqzpw33xcmxmlhxvk5gcp5s6lrtfad.onion
|
||||
|
||||
boot.kernelPackages = pkgs.linuxPackages_5_12;
|
||||
|
||||
firmware.x86_64.enable = true;
|
||||
efi.enable = true;
|
||||
|
||||
luks = {
|
||||
enable = true;
|
||||
device = {
|
||||
path = "/dev/disk/by-uuid/975d8427-2c6a-440d-a1d2-18dd15ba5bc2";
|
||||
allowDiscards = true;
|
||||
};
|
||||
};
|
||||
|
||||
networking.hostName = "reg";
|
||||
|
||||
de.enable = true;
|
||||
de.touchpad.enable = true;
|
||||
|
||||
services.zerotierone.enable = true;
|
||||
|
||||
# VNC
|
||||
networking.firewall.allowedTCPPorts = [ 5900 ];
|
||||
|
||||
networking.interfaces.enp57s0f1.useDHCP = true;
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
# 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.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ];
|
||||
boot.initrd.kernelModules = [ "dm-snapshot" ];
|
||||
boot.kernelModules = [ "kvm-intel" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-uuid/b3a2906b-e9a5-45bd-aac5-960297437fe9";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=root" "noatime" "nodiratime" "discard" ];
|
||||
};
|
||||
|
||||
fileSystems."/home" =
|
||||
{ device = "/dev/disk/by-uuid/b3a2906b-e9a5-45bd-aac5-960297437fe9";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=home" "noatime" "nodiratime" "discard" ];
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/6C41-24A0";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[ { device = "/dev/disk/by-uuid/34ec322f-79c3-4993-a073-ef1da3c6ef51"; }
|
||||
];
|
||||
|
||||
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
./router.nix
|
||||
];
|
||||
|
||||
# https://dataswamp.org/~solene/2022-08-03-nixos-with-live-usb-router.html
|
||||
# https://github.com/mdlayher/homelab/blob/391cfc0de06434e4dee0abe2bec7a2f0637345ac/nixos/routnerr-2/configuration.nix
|
||||
# https://github.com/skogsbrus/os/blob/master/sys/router.nix
|
||||
# http://trac.gateworks.com/wiki/wireless/wifi
|
||||
|
||||
system.autoUpgrade.enable = true;
|
||||
|
||||
services.tailscale.exitNode = true;
|
||||
|
||||
router.enable = true;
|
||||
router.privateSubnet = "192.168.3";
|
||||
|
||||
services.iperf3.enable = true;
|
||||
|
||||
# networking.useDHCP = lib.mkForce true;
|
||||
|
||||
# TODO
|
||||
# networking.usePredictableInterfaceNames = true;
|
||||
|
||||
powerManagement.cpuFreqGovernor = "ondemand";
|
||||
|
||||
|
||||
services.irqbalance.enable = true;
|
||||
|
||||
# services.miniupnpd = {
|
||||
# enable = true;
|
||||
# externalInterface = "eth0";
|
||||
# internalIPs = [ "br0" ];
|
||||
# };
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user