Compare commits

..

No commits in common. "c3996f55ceba1ceba82cff368da3aedfde68b19d" and "fbf624a4458ed3d8c138e3dc5bb5ba589a7c964e" have entirely different histories.

23 changed files with 109 additions and 436 deletions

View file

@ -9,10 +9,9 @@ keys:
- &users: - &users:
- &dev age14d55nfxlzm8t2yzplxpprygxmt99javafz9a8dh5llu87aww4qlswf6g0c - &dev age14d55nfxlzm8t2yzplxpprygxmt99javafz9a8dh5llu87aww4qlswf6g0c
- &hosts: - &hosts:
- &dev-vm age1rjtqzmywfr3zuzz0cn8eqnwp3x8ypzya9gcv6kvtplhudar5eayqq83ey4 - &dev-vm age1rjtqzmywfr3zuzz0cn8eqnwp3x8ypzya9gcv6kvtplhudar5eayqq83ey4
- &crayon age1pnu4tkdxfcnefntdw262k4m8wuv3qe2894s4e6w5j8yshg8vlu6q9uq5tv - &crayon age1pnu4tkdxfcnefntdw262k4m8wuv3qe2894s4e6w5j8yshg8vlu6q9uq5tv
- &blob age1kardawqarv498rwayadsmnlx62kvjgduvhhg3drx39xacn9u3ajq5d0qra - &blobercraft age167gn88rldpmqmjhm9nl0gv05ms4tn37jx2nxwklfvs3xymfp9y7sa8vurh
# new-host marker
creation_rules: creation_rules:
- path_regex: secrets.yaml$ - path_regex: secrets.yaml$
key_groups: key_groups:
@ -20,5 +19,4 @@ creation_rules:
- *dev - *dev
- *dev-vm - *dev-vm
- *crayon - *crayon
- *blob - *blobercraft
# new-host ptr marker

25
Makefile Normal file
View file

@ -0,0 +1,25 @@
IP ?=
HOST ?=
deploy:
# push flake config to a remote server
ifeq ($(IP),)
$(error IP not set)
endif
ifeq ($(HOST),)
$(error HOST not set)
endif
ifneq ($(shell git diff),)
git add .
git commit -m "auto commit on build" -m "`PAGER=cat git diff --name-only --cached`"
endif
rsync -azr ./ crown@$(IP):~/flake-config
ssh crown@$(IP) "sudo NIX_CONFIG='experimental-features = flakes pipe-operators' nixos-rebuild switch --flake ~/flake-config#$(HOST)"
sops:
# update sops keys
sops updatekeys secrets.yaml
.DEFAULT_GOAL := default
.PHONY: default deploy sops
default:
# noop

View file

@ -7,7 +7,7 @@ That's it, have fun poking around.
## Systems ## Systems
I suppose if you're trying to understand my config you'd need to know where I suppose if you're trying to understand my config you'd need to know where
this stuff is deployed and what for. this stuff is deployed and what for.
- blob - blobercraft
- This is my main homelab server. It's used for my media (jellyfin) along - This is my main homelab server. It's used for my media (jellyfin) along
with some other stuff that you can find by looking at my config. with some other stuff that you can find by looking at my config.
- crayon - crayon
@ -21,14 +21,19 @@ that I thought a new user might want to understand as nix is rather poorly
documented. documented.
## Maintaining ## Maintaining
I've included a dev shell to keep the system up to date. To enter the shell run: I've included a make file to keep remote systems up to date, here's an example
of what I use to deploy to crayon:
```sh ```sh
nix develop make deploy IP=squi.bid HOST=crayon
``` ```
Once you've entered the shell will give you a rundown on what you can do. This step requires the remote system to have a crown user who can execute sudo
commands without an interactive prompt.
I'll probably end up switching to something more standard once I've got the
time.
## TODO: ## TODO:
- [ ] blob - [ ] blobercraft
- [ ] add a git backup for everything on crayon (if possible) - [ ] add a git backup for everything on crayon (if possible)
- [ ] ff sync server - [ ] ff sync server
- [ ] crayon - [ ] crayon

101
flake.lock generated
View file

@ -22,64 +22,6 @@
"type": "github" "type": "github"
} }
}, },
"deploy-rs": {
"inputs": {
"flake-compat": "flake-compat",
"nixpkgs": [
"nixpkgs"
],
"utils": "utils"
},
"locked": {
"lastModified": 1762286984,
"narHash": "sha256-9I2H9x5We6Pl+DBYHjR1s3UT8wgwcpAH03kn9CqtdQc=",
"owner": "serokell",
"repo": "deploy-rs",
"rev": "9c870f63e28ec1e83305f7f6cb73c941e699f74f",
"type": "github"
},
"original": {
"owner": "serokell",
"repo": "deploy-rs",
"type": "github"
}
},
"disko": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1764017209,
"narHash": "sha256-RoJGCtKExXXkNCZUmmxezG3eOczEOTBw38DaZGSYJC0=",
"owner": "nix-community",
"repo": "disko",
"rev": "ec8eabe00c4ee9a2ddc50162c125f0ec2a7099e1",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "disko",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1733328505,
"narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"nid": { "nid": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -102,24 +44,22 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1764522689, "lastModified": 1762498405,
"narHash": "sha256-SqUuBFjhl/kpDiVaKLQBoD8TLD+/cTUzzgVFoaHrkqY=", "narHash": "sha256-Zg/SCgCaAioc0/SVZQJxuECGPJy+OAeBcGeA5okdYDc=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "8bb5646e0bed5dbd3ab08c7a7cc15b75ab4e1d0f", "rev": "6faeb062ee4cf4f105989d490831713cc5a43ee1",
"type": "github" "type": "github"
}, },
"original": { "original": {
"id": "nixpkgs", "id": "nixpkgs",
"ref": "nixos-25.11", "ref": "nixos-25.05",
"type": "indirect" "type": "indirect"
} }
}, },
"root": { "root": {
"inputs": { "inputs": {
"declarative-jellyfin": "declarative-jellyfin", "declarative-jellyfin": "declarative-jellyfin",
"deploy-rs": "deploy-rs",
"disko": "disko",
"nid": "nid", "nid": "nid",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"sops-nix": "sops-nix", "sops-nix": "sops-nix",
@ -160,21 +100,6 @@
"type": "indirect" "type": "indirect"
} }
}, },
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"treefmt-nix": { "treefmt-nix": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -210,24 +135,6 @@
"ref": "nixos-unstable", "ref": "nixos-unstable",
"type": "indirect" "type": "indirect"
} }
},
"utils": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -1,7 +1,7 @@
{ {
description = "Nixos config flake"; description = "Nixos config flake";
inputs = { inputs = {
nixpkgs.url = "nixpkgs/nixos-25.11"; nixpkgs.url = "nixpkgs/nixos-25.05";
unstable.url = "nixpkgs/nixos-unstable"; unstable.url = "nixpkgs/nixos-unstable";
nid.url = "github:nix-community/nix-index-database"; nid.url = "github:nix-community/nix-index-database";
@ -12,26 +12,18 @@
declarative-jellyfin.url = "github:Sveske-Juice/declarative-jellyfin"; declarative-jellyfin.url = "github:Sveske-Juice/declarative-jellyfin";
declarative-jellyfin.inputs.nixpkgs.follows = "nixpkgs"; declarative-jellyfin.inputs.nixpkgs.follows = "nixpkgs";
deploy-rs.url = "github:serokell/deploy-rs";
deploy-rs.inputs.nixpkgs.follows = "nixpkgs";
disko.url = "github:nix-community/disko";
disko.inputs.nixpkgs.follows = "nixpkgs";
}; };
outputs = { self, nixpkgs, unstable, ... }@inputs: let outputs = { self, nixpkgs, unstable, ... }@inputs: let
base = [ base = [
# I've put these all here so that it's easier to see what's being # I've put these all here so that it's easier to see what's being
# imported by default # imported by default
./modules/os.nix ./modules/os.nix
./modules/server.nix
./modules/ssh.nix ./modules/ssh.nix
./modules/time.nix ./modules/time.nix
./modules/pkgs.nix ./modules/pkgs.nix
./modules/unstable.nix ./modules/unstable.nix
./modules/zmotd.nix ./modules/zmotd.nix
./modules/sops.nix ./modules/sops.nix
./modules/wireguard.nix
./modules/users/admin.nix ./modules/users/admin.nix
./overlays ./overlays
@ -41,8 +33,6 @@
# use comma just in case I need to do some sysadmin stuff # use comma just in case I need to do some sysadmin stuff
inputs.nid.nixosModules.nix-index inputs.nid.nixosModules.nix-index
{ programs.nix-index-database.comma.enable = true; } { programs.nix-index-database.comma.enable = true; }
# disko for completly declarative machines
inputs.disko.nixosModules.disko
]; ];
# ts so DRY it makes me wanna cry # ts so DRY it makes me wanna cry
@ -56,35 +46,11 @@
] ++ modules; ] ++ modules;
} }
)) <| hosts; )) <| hosts;
mkNodes = nodes:
(builtins.mapAttrs (name: options:
nixpkgs.lib.attrsets.recursiveUpdate {
hostname = name;
profiles.system = {
user = "root";
sshUser = "crown";
path = inputs.deploy-rs.lib."x86_64-linux".activate.nixos self.nixosConfigurations.${name};
};
} options
)) <| nodes;
in { in {
# define all of my machines # define all of my machines
nixosConfigurations = mkHosts { nixosConfigurations = mkHosts {
blob = []; blobercraft = [];
crayon = []; crayon = [];
}; };
# and where they get deployed to
deploy.nodes = mkNodes {
crayon = { hostname = "squi.bid"; };
};
# dev shell to deploy this flake
devShells."x86_64-linux".default = builtins.import ./shell.nix {
pkgs = nixpkgs.legacyPackages."x86_64-linux";
};
checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) inputs.deploy-rs.lib;
}; };
} }

View file

@ -1,27 +0,0 @@
{ modulesPath, ... }:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
(modulesPath + "/profiles/qemu-guest.nix")
./disko.nix
./hardware-configuration.nix # Include the results of the hardware scan.
./jellyfin.nix
./minecraft.nix
./gatus.nix
./ai.nix
];
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# ai.enable = true;
jellyfin.enable = true;
minecraft.enable = true;
# This value determines the NixOS release with which your system is to be
# compatible, in order to avoid breaking some software such as database
# servers. You should change this only after NixOS release notes say you
# should.
system.stateVersion = "25.05"; # Did you read the comment?
}

View file

@ -1,36 +0,0 @@
{ lib, ... }:
{
disko.devices = {
disk.main = {
device = lib.mkDefault "/dev/sda";
type = "disk";
content = {
type = "gpt";
partitions = {
boot = {
size = "1M";
type = "EF02"; # for grub MBR
};
ESP = {
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
};
}

View file

@ -0,0 +1,17 @@
{ ... }:
{
imports = [
./hardware-configuration.nix # Include the results of the hardware scan.
./jellyfin.nix
./minecraft.nix
./gatus.nix
./ai.nix
];
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# ai.enable = true;
jellyfin.enable = true;
minecraft.enable = true;
}

View file

@ -8,11 +8,24 @@
[ (modulesPath + "/installer/scan/not-detected.nix") [ (modulesPath + "/installer/scan/not-detected.nix")
]; ];
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" ];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ]; boot.kernelModules = [ ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/59b4c37b-b8c6-4b95-96af-e343161381bb";
fsType = "ext4";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/E8A3-780D";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
swapDevices = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's # (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction # still possible to use this option, but it's recommended to use it in conjunction

View file

@ -1,4 +1,4 @@
{ config, ... }: { ... }:
{ {
imports = [ imports = [
./hardware-configuration.nix # Include the results of the hardware scan. ./hardware-configuration.nix # Include the results of the hardware scan.
@ -9,17 +9,4 @@
boot.loader.grub.enable = true; boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/vda"; boot.loader.grub.device = "/dev/vda";
wireguard = {
enable = true;
# pub: gq0/fX4EF/3jUNJSW5C3ythZjMVAWYqQdAVRw1eUC1Y=
privateKeyFile = config.sops.secrets."wireguard/crayon".path;
externalInterface = "enp1s0";
};
# This value determines the NixOS release with which your system is to be
# compatible, in order to avoid breaking some software such as database
# servers. You should change this only after NixOS release notes say you
# should.
system.stateVersion = "25.05"; # Did you read the comment?
} }

View file

@ -4,14 +4,13 @@
# working :( # working :(
imports = [ imports = [
(builtins.fetchTarball { (builtins.fetchTarball {
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-25.11/nixos-mailserver-nixos-25.11.tar.gz"; url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-25.05/nixos-mailserver-nixos-25.05.tar.gz";
sha256 = "16kanlk74xnj7xgmjsj7pahy31hlxqcbv76xnsg8qbh54b0hwxgq"; sha256 = "0la8v8d9vzhwrnxmmyz3xnb6vm76kihccjyidhfg6qfi3143fiwq";
}) })
]; ];
mailserver = { mailserver = {
enable = true; enable = true;
stateVersion = 3;
fqdn = "mail.zacharyscheiman.com"; fqdn = "mail.zacharyscheiman.com";
domains = [ "zacharyscheiman.com" "squi.bid" ]; domains = [ "zacharyscheiman.com" "squi.bid" ];
messageSizeLimit = 2500000000; # 2.5GB messageSizeLimit = 2500000000; # 2.5GB

View file

@ -4,7 +4,6 @@
settings = { settings = {
experimental-features = [ "nix-command" "flakes" "pipe-operators" ]; experimental-features = [ "nix-command" "flakes" "pipe-operators" ];
auto-optimise-store = true; auto-optimise-store = true;
trusted-users = [ "@wheel" ];
}; };
gc = { gc = {
dates = "weekly"; dates = "weekly";
@ -19,4 +18,10 @@
enable = true; enable = true;
dates = "weekly"; dates = "weekly";
}; };
# This value determines the NixOS release with which your system is to be
# compatible, in order to avoid breaking some software such as database
# servers. You should change this only after NixOS release notes say you
# should.
system.stateVersion = "25.05"; # Did you read the comment?
} }

View file

@ -11,12 +11,6 @@
tree tree
unzip unzip
zmotd zmotd
# mmmm terminfo
foot.terminfo
ghostty.terminfo
kitty.terminfo
termite.terminfo
]; ];
security.sudo.execWheelOnly = true; security.sudo.execWheelOnly = true;

View file

@ -1,20 +0,0 @@
# Most of this has been yoinked from nix-community/srvos, the only reason I'm
# not using it is because I want absolute control over my nix settings and using
# it would mean I would have to disable options that they enabled
{
# Given that our systems are headless, emergency mode is useless.
# We prefer the system to attempt to continue booting so
# that we can hopefully still access it remotely.
systemd.enableEmergencyMode = false;
# No need for fonts on a server
fonts.fontconfig.enable = false;
# Ensure that basic bugs in systemd services are caught.
systemd.enableStrictShellChecks = true;
# Make builds to be more likely killed than important services.
# 100 is the default for user slices and 500 is systemd-coredumpd@
# We rather want a build to be killed than our precious user sessions as builds can be easily restarted.
systemd.services.nix-daemon.serviceConfig.OOMScoreAdjust = 250;
}

View file

@ -16,7 +16,6 @@
secrets = { secrets = {
"mail/me" = {}; "mail/me" = {};
"jellyfin/zachary" = {}; "jellyfin/zachary" = {};
"wireguard/crayon" = {};
}; };
}; };
} }

View file

@ -20,12 +20,7 @@
services.sshguard.enable = true; services.sshguard.enable = true;
services.openssh = { services.openssh = {
enable = true; enable = true;
settings = { settings.PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PasswordAuthentication = false;
UseDns = false;
X11Forwarding = false;
};
}; };
users.users.root.openssh.authorizedKeys.keys = config.ssh.keys; users.users.root.openssh.authorizedKeys.keys = config.ssh.keys;

View file

@ -1,60 +0,0 @@
{ pkgs, lib, config, ... }:
{
options.wireguard = {
enable = lib.mkEnableOption "wireguard";
port = lib.mkOption {
default = 51820;
description = "The port for wireguard to use.";
type = lib.types.int;
};
externalInterface = lib.mkOption {
description = "The external networking interface for wireguard to use.";
type = lib.types.str;
};
internalInterface = lib.mkOption {
default = "wg0";
description = "The networking interface for wireguard to use.";
type = lib.types.str;
};
privateKeyFile = lib.mkOption {
description = "The path to the private key of the wireguard server.";
type = lib.types.path;
};
};
config = lib.mkIf config.wireguard.enable {
networking.nat.enable = true;
networking.nat.externalInterface = config.wireguard.externalInterface;
networking.nat.internalInterfaces = [ config.wireguard.internalInterface ];
networking.firewall.allowedUDPPorts = [ config.wireguard.port ];
networking.wireguard.interfaces = {
${config.wireguard.internalInterface} = {
# Determines the IP address and subnet of the server's end of the tunnel interface.
ips = [ "10.100.0.1/24" ];
listenPort = config.wireguard.port;
# This allows the wireguard server to route your traffic to the internet and hence be like a VPN
# For this to work you have to set the dnsserver IP of your router (or dnsserver of choice) in your clients
postSetup = ''
${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.100.0.0/24 -o eth0 -j MASQUERADE
'';
# This undoes the above command
postShutdown = ''
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.100.0.0/24 -o eth0 -j MASQUERADE
'';
# Path to the servers private key file.
privateKeyFile = config.wireguard.privateKeyFile;
# TODO: add config option?
peers = [
{
publicKey = "L+NlTn0E9pgCoEoTYs4aDewZSMmyeyC1Os9DCdwYTjY=";
allowedIPs = [ "10.100.0.2/32" ];
}
];
};
};
};
}

View file

@ -4,8 +4,6 @@ jellyfin:
zachary: ENC[AES256_GCM,data:GIDgfsxhU4fZVjP/cTmTvIA1aeP4lbd3Fz6tbPLdyL37KD+IKERgkxJmGwtt9GNwnJBsHE/xpH8ZAvloS1DykZZtEaqB0H6wuA==,iv:FM0d4tiQPzyoEiqEQF5YvNeClHXOhP+q+TaKGeyg/TE=,tag:v+sYDwQiCX7o+g7plcnQFg==,type:str] zachary: ENC[AES256_GCM,data:GIDgfsxhU4fZVjP/cTmTvIA1aeP4lbd3Fz6tbPLdyL37KD+IKERgkxJmGwtt9GNwnJBsHE/xpH8ZAvloS1DykZZtEaqB0H6wuA==,iv:FM0d4tiQPzyoEiqEQF5YvNeClHXOhP+q+TaKGeyg/TE=,tag:v+sYDwQiCX7o+g7plcnQFg==,type:str]
users: users:
crown: ENC[AES256_GCM,data:6UAYcafxflvbsTXC1N3Ff0hAlWGjveYDUzbcXPSGfPX0uXg++bfjRwYo3JFgfJpJ/KN4MODPSxgjFAFnoZOnkyxk0UDSppDagQ==,iv:PWmxuj2caqRLASjftbl0tovNq2t1WoDoviJXs/OO8yI=,tag:EwJhROsHfj5cPkpxUCy+uw==,type:str] crown: ENC[AES256_GCM,data:6UAYcafxflvbsTXC1N3Ff0hAlWGjveYDUzbcXPSGfPX0uXg++bfjRwYo3JFgfJpJ/KN4MODPSxgjFAFnoZOnkyxk0UDSppDagQ==,iv:PWmxuj2caqRLASjftbl0tovNq2t1WoDoviJXs/OO8yI=,tag:EwJhROsHfj5cPkpxUCy+uw==,type:str]
wireguard:
crayon: ENC[AES256_GCM,data:pQ4nOzcON+yCqgisBQO8LIdfi9GmXE9YcPzBRgu9Fdzx0R6p4dEK+DVBuDg=,iv:vq0uDgZlLwXVZMwE3xTWZDP20uaAcT4I0D7qLS61ApI=,tag:btVyZREPAgfcC694/Wusmg==,type:str]
sops: sops:
kms: [] kms: []
gcp_kms: [] gcp_kms: []
@ -15,41 +13,41 @@ sops:
- recipient: age14d55nfxlzm8t2yzplxpprygxmt99javafz9a8dh5llu87aww4qlswf6g0c - recipient: age14d55nfxlzm8t2yzplxpprygxmt99javafz9a8dh5llu87aww4qlswf6g0c
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaZVRGTEpIWW1qRWhPOTR5 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNT0IxYjhWWkZadnVmcGpz
STdwVzZzeU1QS2l0TlN2NFNLY1VNZjVCdEhFCmxhejBDSjF5Vk1UQjdEYmpRRFRw VXB5U2VvTFllYWhJTkNwQmxsWkxEL2drRHcwCksrMGs4SVZoL1pJNU00TUZBeU5V
allpajVzcUFpc1h0TVBlUFdaUERPZ3cKLS0tIHc3S0FRbkgwc3BwYUYrWGUrUjZX UFBRcnRFdTlxUjgvcVpSelZIU0NyVWsKLS0tICtnZm8rYnB5cWhIUVBmQzQxSWIr
QjBLcFY5NnFBZXBJenFYUS8yMXBML0EKkuoDfnc0MnZ0bRQ4Op8GnxC0Mpld9nRE M29ZRHIwNGZSdi9LYmp5d2xyTWdmRDgKhs6COQa3Vmosiwv7I/IjvYr10Mx83V6z
5tn6why12mT65jDHuaU3+bX2Rg5+NU90KpdA3S88M4tiCD3WSo70eg== W2d8PPTHBlRMqPcghpG2UOFsygzP8Y6UlMpCgt25vnFLUwCPlo7ERA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1rjtqzmywfr3zuzz0cn8eqnwp3x8ypzya9gcv6kvtplhudar5eayqq83ey4 - recipient: age1rjtqzmywfr3zuzz0cn8eqnwp3x8ypzya9gcv6kvtplhudar5eayqq83ey4
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyVEx6VzRNOFBickVjcGFj YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXMUFJY2RjSHcrS2Foa2Fo
UkpGNUpTeTVVUVRGRHJrRTI3UzhrRjIvcXdrCkFSWGE4YS91dEpJbFZEcFNGUmdP dUJMSmpEL0NEN1BLYlZDNlA3aUQyQUNkYWxnCnNmV0ZpWTA0ZHUrUEtBV3MyZ3U1
UFJDc0hpTEVvaHZjY2k3Vk5jdTk4NjgKLS0tIDFpU0srRzBMTDFPVGVVblpEMTZk SitYaVFBZklaZ282K2plYUhlVjRVWGMKLS0tIGlOZENMbURDMWR5VEFIVEdyV3k5
SEtxQnN6T2lNbkRGWmUwSFdMVUw0dlEKKYe2xCYLQ8Q21p6f3NIIwRMrQHTicSp3 S3hQemRLNFd6eDlQY3pvUlkzUVhRUlUKHvdPyCCb0I825u9Hx+Fz+W9ESM2Gxy+N
BSIG0SmRGcSrzPlg8agUi4aWQ7du9EECXanQSu98sGhCWkIc/QHWnQ== lUsxP/ngAnG52MSrxxU33PG4TXSvaaYzuGP7gOQF6hB9U79inWzFzg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1pnu4tkdxfcnefntdw262k4m8wuv3qe2894s4e6w5j8yshg8vlu6q9uq5tv - recipient: age1pnu4tkdxfcnefntdw262k4m8wuv3qe2894s4e6w5j8yshg8vlu6q9uq5tv
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvaVZxYTFMZDFCYnVTYWM4 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtYTkvaldVWUk1TC94REEr
QS9Oa1dLa3dVNzArZ0hkKy8yR1Z3UVpRQzJVClo5dzU3dythWGU0NkoySUpYRUQv OHNiUHlqN0l3QWFJbjZ6anZpVTN5OGtibGtNCm9DcVJ6SktQeEFWU2REU0dpRjZu
MTlQYmJSVG5RNWkzWnlEaDh0YjFxL3MKLS0tIDdySlB3cGxoM09BZWdhN3RwNGtZ WnBBaDMrbnRNaVhtR3BqdjVkc2tpZEEKLS0tIHRVdW8yL1JmcDVrVkNaa2lNN2h5
Y1ZUb1Y3ais0dlZrclQyUUZxWkNSVHcKv1Q0VBHE9Y9bU6XyQ84WNf+JTIQq/mPI Y0gxSjYrY3gydnBseEVlQTBSSEtJSVEKH4v1Q9kKQaj5vdV9mW2Rsl/GUbq1h/m9
tOD6uiS46KgnO5p8oM9rqvBmOPJKoS6bgSLUuEnqjLTtZE3QO0eKzA== iy6BPmjC9GNtTBJ8VuvkQSvPLD+dsMwYqhmSbTQgDpRP3sQ4a6rWkA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1kardawqarv498rwayadsmnlx62kvjgduvhhg3drx39xacn9u3ajq5d0qra - recipient: age167gn88rldpmqmjhm9nl0gv05ms4tn37jx2nxwklfvs3xymfp9y7sa8vurh
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwTFR1UU1PaTl0NWZ1dEVk YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYcWVDbmhhc1FHRG5WOTEz
WTZMUEtGWFFyNm9aTzNmZHh3RkZHOGsvRWowCnYzZ3JlRGlqN2tHbmtIMFFHUVBD emp4Rm9YMlA3aXUvMnpDWElqRElzQjdlMzNRCjducWdqQzliZjkzaWtGdEdUbk9u
dWNNc2ZqL1UwdlBmMERlNVZGK1ZhdVkKLS0tIGV1RHh5Z0Z3MlNMZHB0K1liTFdr MlBCL0lqdWs4TVo0RW9ham5mTExTSzQKLS0tICtJWk15NG9yMWwyVjF6SE1weWFF
NTUrY2pDQXJuTnREakRWQkFqckN2M2MKSonhOJsqcY/HDY+d25rEPwKSl3FSOpkW NmlybmxKYlJESGxJbFdCazZUKzVjYmMK56j3+CuRfZsbVeYfmESlD2z6GYzIFQYz
EJFXcKKTiJB96Ms5yDGRAtUvbqw/oSBbdGTqe7bE7pQhfj3Y8ECz4w== f/jpI+8CteDlxbGuUvW10hD7lB8az2+Z+MQX2+koy3PZBkGChPh/Yg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-11-26T18:38:21Z" lastmodified: "2025-11-09T02:00:10Z"
mac: ENC[AES256_GCM,data:V3lKQj0ZWIPl2RPpnv7tRBG8sH6W9+rfnPy0z6g+3SZGmKtwhcgqVBG/VPMKhuyseNZ4vxE23lD7Ol44PchMgd/OCJqJF6TUl3A4LIqkK8Ji0m0cPcC3hsFaI8rChkWcLse30qcoQov4NbP7yElpf76Bh/NqBFgOqCjDD0Pp/NU=,iv:897reifxaub96UDCKCsWNxabVCSzYLmsIrrkXCxBgoM=,tag:0d4iQhLA/YxR7wrtUVxXqA==,type:str] mac: ENC[AES256_GCM,data:9Jg3aXMMe8Yhf3CycD+UPqlTg0E619dmOJENRe2sfwROdKxOXhiFqnuI4t262XW3IMpJdCbv3RIblklF6vPaqqJWkPqj4Jt2niF4Bq0oR+cRM+rAElYAZ6vviCWnjTjOhTD/UB2RYPFH77Ce7RQmR4c5H4D6uLaw1g3+9TLJPTE=,iv:p4mF2S1n+mTV+ny3hKbQ+tYqh+4HGURyUP9hiSdMZjs=,tag:dWCa87XTwH3mBHshUMxjiQ==,type:str]
pgp: [] pgp: []
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.9.1 version: 3.9.1

View file

@ -1,92 +0,0 @@
{
pkgs ?
# If pkgs is not defined, instantiate nixpkgs from locked commit
# yoinked from (github.com/EmergentMind/nix-config)
let
lock = (builtins.fromJSON (builtins.readFile ./flake.lock)).nodes.nixpkgs.locked;
nixpkgs = builtins.fetchTarball {
url = "https://github.com/${lock.owner}/${lock.repo}/archive/${lock.rev}.tar.gz";
sha256 = lock.narHash;
};
in
builtins.import nixpkgs { overlays = [ ]; },
...
}:
pkgs.mkShell {
nativeBuildInputs = with pkgs.buildPackages; [
git
openssh
ssh-to-age
nixos-anywhere
(pkgs.writeShellScriptBin "-commit" ''
# there shall be no impurity
if [ -n "$(git diff)" ]; then
git add .
git commit -m "auto commit on build" -m "`PAGER=cat git diff --name-only --cached`"
fi
'')
(pkgs.writeShellScriptBin "-sops" "sops updatekeys secrets.yaml")
(pkgs.writeShellScriptBin "-init" ''
USER="root"
if [ -z "$1" ] || [ -z "$2" ]; then
echo "the 1st argument must be the ip address"
echo "the 2nd argument must be the new hostname (the nix flake host)"
echo "the 3rd argument may be the user to ssh with if unset the default is root"
exit 0
fi
IP=$1
HOST=$2
if [ -n "$3" ]; then
USER=$3
fi
# get the remote systems ssh key
key=$(ssh $(USER)@$(IP) 'cat /etc/ssh/ssh_host_ed25519_key.pub' | ssh-to-age)
if [ -z "$key" ]; then
echo "failed to get the remote systems ssh pubkey"
exit 1
fi
# add the new sops key to the .sops.yaml
sed -i '/# new-host marker/i\ - &$(HOST) $(key)' .sops.yaml
sed -i '/# new-host ptr marker/i\ - *$(HOST)' .sops.yaml
# update the keys
sops updatekeys secrets.yaml
-commit
# push the flake to the remote system
nixos-anywhere\
--flake .#$HOST\
--build-on remote\
--copy-host-keys\
--generate-hardware-config nixos-generate-config ./hosts/$HOST/hardware-configuration.nix\
--target-host $USER@$IP
'')
(pkgs.writeShellScriptBin "-deploy" ''
-commit
# push flake config to a remote server(s)
nix run github:serokell/deploy-rs . # this needs to be the same version that the flake is using
'')
];
shellHook = ''
cat << EOF
# This is my tiny nix shell to create new machines and update existing ones
# it requires you to have nix and sops installed to correctly setup a new
# system and nix to deploy to an existing one.
#
# Available commands:
# '-sops' -> updates your sops secret file
# '-init' -> initializes a new system with nix-anywhere
# '-deploy' -> deploys the existing flake to all nodes using deploy-rs
EOF
'';
}