diff --git a/hosts/koi/configuration.nix b/hosts/koi/configuration.nix index 694fd0b..38a625a 100755 --- a/hosts/koi/configuration.nix +++ b/hosts/koi/configuration.nix @@ -12,6 +12,7 @@ ./partials/fde.nix + ./services/cage.nix ./services/coredns.nix ./services/sing-box.nix ./services/nginx.nix @@ -20,9 +21,12 @@ ./containers/uxplay.nix ./containers/torrent.nix ./containers/puffer.nix + ./containers/vaultwarden.nix ./containers/sharkey ./containers/pds + ./containers/zond ./vms/hass.nix + ./vms/bnuuy.nix # ./vms/windows.nix ]; @@ -68,11 +72,11 @@ qemu.ovmf.enable = true; allowedBridges = [ "br0" ]; }; - + virtualisation.docker = { enable = true; }; - + boot.extraModprobeConfig = '' options kvm_amd avic=1 nested=0 options kvm ignore_msrs=N report_ignored_msrs=Y diff --git a/hosts/koi/containers/vaultwarden.nix b/hosts/koi/containers/vaultwarden.nix new file mode 100644 index 0000000..54fdb59 --- /dev/null +++ b/hosts/koi/containers/vaultwarden.nix @@ -0,0 +1,55 @@ +{ abs, pkgs, lib, config, ... }@inputs: + +let + containers = import (abs "lib/containers.nix") inputs; + secrets = import (abs "lib/secrets.nix"); + + env = secrets.mount config "vaultwarden-env"; +in { + imports = [ + (secrets.declare [ "vaultwarden-env" ]) + (containers.mkNixosContainer { + name = "vault"; + ip = ".0.7"; + private = true; + + config = { ... }: { + services.vaultwarden = { + enable = true; + config = { + SIGNUPS_ALLOWED = false; + DOMAIN = "https://bw.tei.su"; + WEBSOCKET_ENABLED = true; + ROCKET_ADDRESS = "0.0.0.0"; + ROCKET_PORT = 80; + DATA_FOLDER = "/mnt/vault/data"; + }; + environmentFile = env.path; + }; + + systemd.services.vaultwarden.serviceConfig = { + ReadWritePaths = [ "/mnt/vault" ]; + }; + + networking.firewall.allowedTCPPorts = [ 80 ]; + }; + + mounts = { + "/mnt/vault" = { + hostPath = "/mnt/puffer/vaultwarden-vault"; + isReadOnly = false; + }; + } // (env.mounts); + }) + ]; + + services.nginx.virtualHosts."bw.tei.su" = { + forceSSL = true; + useACMEHost = "tei.su"; + + locations."/" = { + proxyPass = "http://vault.containers/"; + proxyWebsockets = true; + }; + }; +} \ No newline at end of file diff --git a/hosts/koi/containers/zond/default.nix b/hosts/koi/containers/zond/default.nix new file mode 100644 index 0000000..85473d0 --- /dev/null +++ b/hosts/koi/containers/zond/default.nix @@ -0,0 +1,13 @@ +{ ... }: + +{ + # todo - move this from an ad-hoc docker compose to a proper service + services.nginx.virtualHosts."zond.tei.su" = { + forceSSL = true; + useACMEHost = "tei.su"; + + locations."/" = { + proxyPass = "http://umami.umami.docker:3000/"; + }; + }; +} \ No newline at end of file diff --git a/hosts/koi/services/coredns.nix b/hosts/koi/services/coredns.nix index 27bc620..b25f39e 100644 --- a/hosts/koi/services/coredns.nix +++ b/hosts/koi/services/coredns.nix @@ -10,6 +10,7 @@ let 10.42.0.2 hass.stupid.fish 10.42.0.2 very.stupid.fish 10.42.0.5 puffer.stupid.fish + 10.42.0.8 bnuuy.stupid.fish ''; package = coredns.override { diff --git a/hosts/koi/services/nginx.nix b/hosts/koi/services/nginx.nix index 169bb94..43b4b3d 100644 --- a/hosts/koi/services/nginx.nix +++ b/hosts/koi/services/nginx.nix @@ -63,6 +63,7 @@ in { }; security.acme.acceptTerms = true; + security.acme.defaults.dnsResolver = "8.8.8.8:53"; # coredns tends to cache these too much security.acme.certs."stupid.fish" = { email = "alina@tei.su"; group = "nginx"; @@ -73,6 +74,16 @@ in { "CLOUDFLARE_API_KEY_FILE" = config.age.secrets.cloudflare-token.path; }; }; + security.acme.certs."tei.su" = { + email = "alina@tei.su"; + group = "nginx"; + dnsProvider = "cloudflare"; + extraDomainNames = [ "*.tei.su" ]; + credentialFiles = { + "CLOUDFLARE_EMAIL_FILE" = config.age.secrets.cloudflare-email.path; + "CLOUDFLARE_API_KEY_FILE" = config.age.secrets.cloudflare-token.path; + }; + }; networking.firewall.allowedTCPPorts = [ 80 443 ]; } diff --git a/hosts/koi/vms/bnuuy.nix b/hosts/koi/vms/bnuuy.nix new file mode 100644 index 0000000..e49dcf0 --- /dev/null +++ b/hosts/koi/vms/bnuuy.nix @@ -0,0 +1,58 @@ +{ abs, pkgs, ... }@inputs: + +let + qemu = import (abs "lib/qemu.nix") inputs; + + macAddress = "b6:dc:95:aa:21:8e"; + initDisk = qemu.mkCloudInitDisk { + user = { + ssh_pwauth = false; + hostname = "bnuuy"; + users = [ + { + name = "teidesu"; + groups = "users,wheel"; + shell = "/bin/bash"; + sudo = "ALL=(ALL) NOPASSWD:ALL"; + ssh_authorized_keys = [ + (builtins.readFile (abs "ssh/teidesu.pub")) + ]; + } + ]; + }; + network = { + version = 2; + ethernets = { + id0 = { + match = { macaddress = macAddress; }; + wakeonlan = true; + dhcp4 = true; + addresses = [ "10.42.0.8/8" ]; + gateway4 = "10.42.0.2"; + nameservers = { + search = [ "10.42.0.2" ]; + }; + }; + }; + }; + }; +in +{ + # ubuntu vm for random ad-hoc garbage that i don't want to litter my host with + systemd.services.bnuuy = qemu.mkSystemdService { + name = "bnuuy"; + qemuOptions = { + cores = "2"; + disks = [ + { + name = "ubuntu"; + path = "/etc/vms/bnuuy.img"; + } + initDisk + ]; + inherit macAddress; + }; + }; + + networking.firewall.allowedTCPPorts = [ 5901 ]; +} diff --git a/lib/qemu.nix b/lib/qemu.nix index d0faa4b..85250f6 100644 --- a/lib/qemu.nix +++ b/lib/qemu.nix @@ -12,9 +12,10 @@ let name = disk.name; driver = disk.driver or "qcow2"; path = disk.path; + readonly = disk.readonly or false; in builtins.concatStringsSep " " [ - "-blockdev driver=${driver},file.driver=file,file.filename=${path},file.aio=io_uring,discard=unmap,detect-zeroes=unmap,read-only=off,cache.direct=on,node-name=${name}" + "-blockdev driver=${driver},file.driver=file,file.filename=${path},file.aio=io_uring,discard=unmap,detect-zeroes=unmap,read-only=${if readonly then "on" else "off"},cache.direct=on,node-name=${name}" "-device scsi-hd,drive=${name},bus=scsi.0,rotation_rate=1,physical_block_size=512,logical_block_size=512,id=scsi-${name}" ] ) @@ -106,6 +107,40 @@ let "-netdev tap,id=net0,ifname=${tap},script=no,downscript=no" "-device virtio-net-pci,netdev=net0,mac=${macAddress}" ] ++ (mkDiskFlags disks) ++ (mkUsbFlags usbs) ++ extraFlags; + + mkCloudInitImage = { + user ? {}, + meta ? {}, + network ? null, + }: let + toYAML = builtins.toJSON; + + metaYaml = pkgs.writeText "cloud-init-meta.yaml" (toYAML (meta // { + # thx https://gist.github.com/Informatic/0b6b24374b54d09c77b9d25595cdbd47 + dsmode = "local"; + })); + userYaml = pkgs.writeText "cloud-init-user.yaml" '' + #cloud-config + ${toYAML user} + ''; + networkYaml = pkgs.writeText "cloud-init-network.yaml" (toYAML { + inherit network; + }); + + args = [] + ++ pkgs.lib.optionals (network != null) [ + "--network-config" + "${networkYaml}" + ]; + argsText = builtins.concatStringsSep " " args; + in pkgs.stdenvNoCC.mkDerivation { + name = "cloud-init-seed.img"; + buildInputs = [ pkgs.cloud-utils ]; + dontUnpack = true; + buildPhase = '' + cloud-localds ${argsText} $out ${userYaml} ${metaYaml} + ''; + }; in { mkSystemdService = @@ -152,4 +187,12 @@ in ${if (tapName != null) then (tapStopCommands tapName) else ""} ''; }; + + inherit mkCloudInitImage; + mkCloudInitDisk = params: { + name = "init"; + driver = "raw"; + path = mkCloudInitImage params; + readonly = true; + }; } diff --git a/readme.md b/readme.md index 8e28939..c27cd9f 100755 --- a/readme.md +++ b/readme.md @@ -16,6 +16,7 @@ note to self on what needs to be installed on the host manually: ### koi: - ~~`/etc/iso/win11.iso` - iso containing windows 11 installer (e.g. this: [magnet](magnet:?xt=urn:btih:56197d53136ffcecbae5225f0ac761121eacdac6&dn=Win11_22H2_English_x64v1.iso&tr=udp%3a%2f%2ftracker.torrent.eu.org%3a451%2fannounce&tr=udp%3a%2f%2ftracker.tiny-vps.com%3a6969%2fannounce&tr=udp%3a%2f%2fopen.stealth.si%3a80%2fannounce))~~ currently unused - `/etc/vms/haos.img` - qcow2 image for haos vm (can be downloaded from the official website, the KVM/Proxmox image). +- `/etc/vms/bnuuy.img` - qcow2 image of an ubuntu cloud image (e.g. `https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img`) - `/etc/secureboot/keys` - secure boot keys, generated with `sudo nix-shell -p sbctl --run "sbctl create-keys"` - to enroll fde onto tpm: `sudo systemd-cryptenroll /dev/nvme0n1p2 --tpm2-device=auto --tpm2-pcrs=0+2+7` diff --git a/secrets/vaultwarden-env.age b/secrets/vaultwarden-env.age new file mode 100644 index 0000000..50bf45d --- /dev/null +++ b/secrets/vaultwarden-env.age @@ -0,0 +1,5 @@ +age-encryption.org/v1 +-> ssh-ed25519 sj88Xw UnajBSXLcK0Cm9C7gfa6REjgzFXs/fslf7KdNG/xkkA ++QWMJIjp7YWBDiZIjuiQPIa95nQEXf/M5CDlZmkGT5g +--- FqXZVImOJimMwP5Rcbg16qlQCRBgQBm0H8Nsce6W4Pk +f%K `eTwVXﻍQl\QEOebc%mHSΕHejkv \ No newline at end of file