Compare commits

..

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

23 changed files with 109 additions and 436 deletions

View file

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

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
I suppose if you're trying to understand my config you'd need to know where
this stuff is deployed and what for.
- blob
- blobercraft
- 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.
- crayon
@ -21,14 +21,19 @@ that I thought a new user might want to understand as nix is rather poorly
documented.
## 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
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:
- [ ] blob
- [ ] blobercraft
- [ ] add a git backup for everything on crayon (if possible)
- [ ] ff sync server
- [ ] crayon

101
flake.lock generated
View file

@ -22,64 +22,6 @@
"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": {
"inputs": {
"nixpkgs": [
@ -102,24 +44,22 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1764522689,
"narHash": "sha256-SqUuBFjhl/kpDiVaKLQBoD8TLD+/cTUzzgVFoaHrkqY=",
"lastModified": 1762498405,
"narHash": "sha256-Zg/SCgCaAioc0/SVZQJxuECGPJy+OAeBcGeA5okdYDc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8bb5646e0bed5dbd3ab08c7a7cc15b75ab4e1d0f",
"rev": "6faeb062ee4cf4f105989d490831713cc5a43ee1",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-25.11",
"ref": "nixos-25.05",
"type": "indirect"
}
},
"root": {
"inputs": {
"declarative-jellyfin": "declarative-jellyfin",
"deploy-rs": "deploy-rs",
"disko": "disko",
"nid": "nid",
"nixpkgs": "nixpkgs",
"sops-nix": "sops-nix",
@ -160,21 +100,6 @@
"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": {
"inputs": {
"nixpkgs": [
@ -210,24 +135,6 @@
"ref": "nixos-unstable",
"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",

View file

@ -1,7 +1,7 @@
{
description = "Nixos config flake";
inputs = {
nixpkgs.url = "nixpkgs/nixos-25.11";
nixpkgs.url = "nixpkgs/nixos-25.05";
unstable.url = "nixpkgs/nixos-unstable";
nid.url = "github:nix-community/nix-index-database";
@ -12,26 +12,18 @@
declarative-jellyfin.url = "github:Sveske-Juice/declarative-jellyfin";
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
base = [
# I've put these all here so that it's easier to see what's being
# imported by default
./modules/os.nix
./modules/server.nix
./modules/ssh.nix
./modules/time.nix
./modules/pkgs.nix
./modules/unstable.nix
./modules/zmotd.nix
./modules/sops.nix
./modules/wireguard.nix
./modules/users/admin.nix
./overlays
@ -41,8 +33,6 @@
# use comma just in case I need to do some sysadmin stuff
inputs.nid.nixosModules.nix-index
{ programs.nix-index-database.comma.enable = true; }
# disko for completly declarative machines
inputs.disko.nixosModules.disko
];
# ts so DRY it makes me wanna cry
@ -56,35 +46,11 @@
] ++ modules;
}
)) <| 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 {
# define all of my machines
nixosConfigurations = mkHosts {
blob = [];
blobercraft = [];
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")
];
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.kernelModules = [ ];
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
# (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

View file

@ -1,4 +1,4 @@
{ config, ... }:
{ ... }:
{
imports = [
./hardware-configuration.nix # Include the results of the hardware scan.
@ -9,17 +9,4 @@
boot.loader.grub.enable = true;
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 :(
imports = [
(builtins.fetchTarball {
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-25.11/nixos-mailserver-nixos-25.11.tar.gz";
sha256 = "16kanlk74xnj7xgmjsj7pahy31hlxqcbv76xnsg8qbh54b0hwxgq";
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-25.05/nixos-mailserver-nixos-25.05.tar.gz";
sha256 = "0la8v8d9vzhwrnxmmyz3xnb6vm76kihccjyidhfg6qfi3143fiwq";
})
];
mailserver = {
enable = true;
stateVersion = 3;
fqdn = "mail.zacharyscheiman.com";
domains = [ "zacharyscheiman.com" "squi.bid" ];
messageSizeLimit = 2500000000; # 2.5GB

View file

@ -4,7 +4,6 @@
settings = {
experimental-features = [ "nix-command" "flakes" "pipe-operators" ];
auto-optimise-store = true;
trusted-users = [ "@wheel" ];
};
gc = {
dates = "weekly";
@ -19,4 +18,10 @@
enable = true;
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
unzip
zmotd
# mmmm terminfo
foot.terminfo
ghostty.terminfo
kitty.terminfo
termite.terminfo
];
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 = {
"mail/me" = {};
"jellyfin/zachary" = {};
"wireguard/crayon" = {};
};
};
}

View file

@ -20,12 +20,7 @@
services.sshguard.enable = true;
services.openssh = {
enable = true;
settings = {
KbdInteractiveAuthentication = false;
PasswordAuthentication = false;
UseDns = false;
X11Forwarding = false;
};
settings.PasswordAuthentication = false;
};
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]
users:
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:
kms: []
gcp_kms: []
@ -15,41 +13,41 @@ sops:
- recipient: age14d55nfxlzm8t2yzplxpprygxmt99javafz9a8dh5llu87aww4qlswf6g0c
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaZVRGTEpIWW1qRWhPOTR5
STdwVzZzeU1QS2l0TlN2NFNLY1VNZjVCdEhFCmxhejBDSjF5Vk1UQjdEYmpRRFRw
allpajVzcUFpc1h0TVBlUFdaUERPZ3cKLS0tIHc3S0FRbkgwc3BwYUYrWGUrUjZX
QjBLcFY5NnFBZXBJenFYUS8yMXBML0EKkuoDfnc0MnZ0bRQ4Op8GnxC0Mpld9nRE
5tn6why12mT65jDHuaU3+bX2Rg5+NU90KpdA3S88M4tiCD3WSo70eg==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNT0IxYjhWWkZadnVmcGpz
VXB5U2VvTFllYWhJTkNwQmxsWkxEL2drRHcwCksrMGs4SVZoL1pJNU00TUZBeU5V
UFBRcnRFdTlxUjgvcVpSelZIU0NyVWsKLS0tICtnZm8rYnB5cWhIUVBmQzQxSWIr
M29ZRHIwNGZSdi9LYmp5d2xyTWdmRDgKhs6COQa3Vmosiwv7I/IjvYr10Mx83V6z
W2d8PPTHBlRMqPcghpG2UOFsygzP8Y6UlMpCgt25vnFLUwCPlo7ERA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1rjtqzmywfr3zuzz0cn8eqnwp3x8ypzya9gcv6kvtplhudar5eayqq83ey4
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyVEx6VzRNOFBickVjcGFj
UkpGNUpTeTVVUVRGRHJrRTI3UzhrRjIvcXdrCkFSWGE4YS91dEpJbFZEcFNGUmdP
UFJDc0hpTEVvaHZjY2k3Vk5jdTk4NjgKLS0tIDFpU0srRzBMTDFPVGVVblpEMTZk
SEtxQnN6T2lNbkRGWmUwSFdMVUw0dlEKKYe2xCYLQ8Q21p6f3NIIwRMrQHTicSp3
BSIG0SmRGcSrzPlg8agUi4aWQ7du9EECXanQSu98sGhCWkIc/QHWnQ==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXMUFJY2RjSHcrS2Foa2Fo
dUJMSmpEL0NEN1BLYlZDNlA3aUQyQUNkYWxnCnNmV0ZpWTA0ZHUrUEtBV3MyZ3U1
SitYaVFBZklaZ282K2plYUhlVjRVWGMKLS0tIGlOZENMbURDMWR5VEFIVEdyV3k5
S3hQemRLNFd6eDlQY3pvUlkzUVhRUlUKHvdPyCCb0I825u9Hx+Fz+W9ESM2Gxy+N
lUsxP/ngAnG52MSrxxU33PG4TXSvaaYzuGP7gOQF6hB9U79inWzFzg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1pnu4tkdxfcnefntdw262k4m8wuv3qe2894s4e6w5j8yshg8vlu6q9uq5tv
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvaVZxYTFMZDFCYnVTYWM4
QS9Oa1dLa3dVNzArZ0hkKy8yR1Z3UVpRQzJVClo5dzU3dythWGU0NkoySUpYRUQv
MTlQYmJSVG5RNWkzWnlEaDh0YjFxL3MKLS0tIDdySlB3cGxoM09BZWdhN3RwNGtZ
Y1ZUb1Y3ais0dlZrclQyUUZxWkNSVHcKv1Q0VBHE9Y9bU6XyQ84WNf+JTIQq/mPI
tOD6uiS46KgnO5p8oM9rqvBmOPJKoS6bgSLUuEnqjLTtZE3QO0eKzA==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtYTkvaldVWUk1TC94REEr
OHNiUHlqN0l3QWFJbjZ6anZpVTN5OGtibGtNCm9DcVJ6SktQeEFWU2REU0dpRjZu
WnBBaDMrbnRNaVhtR3BqdjVkc2tpZEEKLS0tIHRVdW8yL1JmcDVrVkNaa2lNN2h5
Y0gxSjYrY3gydnBseEVlQTBSSEtJSVEKH4v1Q9kKQaj5vdV9mW2Rsl/GUbq1h/m9
iy6BPmjC9GNtTBJ8VuvkQSvPLD+dsMwYqhmSbTQgDpRP3sQ4a6rWkA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1kardawqarv498rwayadsmnlx62kvjgduvhhg3drx39xacn9u3ajq5d0qra
- recipient: age167gn88rldpmqmjhm9nl0gv05ms4tn37jx2nxwklfvs3xymfp9y7sa8vurh
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwTFR1UU1PaTl0NWZ1dEVk
WTZMUEtGWFFyNm9aTzNmZHh3RkZHOGsvRWowCnYzZ3JlRGlqN2tHbmtIMFFHUVBD
dWNNc2ZqL1UwdlBmMERlNVZGK1ZhdVkKLS0tIGV1RHh5Z0Z3MlNMZHB0K1liTFdr
NTUrY2pDQXJuTnREakRWQkFqckN2M2MKSonhOJsqcY/HDY+d25rEPwKSl3FSOpkW
EJFXcKKTiJB96Ms5yDGRAtUvbqw/oSBbdGTqe7bE7pQhfj3Y8ECz4w==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYcWVDbmhhc1FHRG5WOTEz
emp4Rm9YMlA3aXUvMnpDWElqRElzQjdlMzNRCjducWdqQzliZjkzaWtGdEdUbk9u
MlBCL0lqdWs4TVo0RW9ham5mTExTSzQKLS0tICtJWk15NG9yMWwyVjF6SE1weWFF
NmlybmxKYlJESGxJbFdCazZUKzVjYmMK56j3+CuRfZsbVeYfmESlD2z6GYzIFQYz
f/jpI+8CteDlxbGuUvW10hD7lB8az2+Z+MQX2+koy3PZBkGChPh/Yg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-11-26T18:38:21Z"
mac: ENC[AES256_GCM,data:V3lKQj0ZWIPl2RPpnv7tRBG8sH6W9+rfnPy0z6g+3SZGmKtwhcgqVBG/VPMKhuyseNZ4vxE23lD7Ol44PchMgd/OCJqJF6TUl3A4LIqkK8Ji0m0cPcC3hsFaI8rChkWcLse30qcoQov4NbP7yElpf76Bh/NqBFgOqCjDD0Pp/NU=,iv:897reifxaub96UDCKCsWNxabVCSzYLmsIrrkXCxBgoM=,tag:0d4iQhLA/YxR7wrtUVxXqA==,type:str]
lastmodified: "2025-11-09T02:00:10Z"
mac: ENC[AES256_GCM,data:9Jg3aXMMe8Yhf3CycD+UPqlTg0E619dmOJENRe2sfwROdKxOXhiFqnuI4t262XW3IMpJdCbv3RIblklF6vPaqqJWkPqj4Jt2niF4Bq0oR+cRM+rAElYAZ6vviCWnjTjOhTD/UB2RYPFH77Ce7RQmR4c5H4D6uLaw1g3+9TLJPTE=,iv:p4mF2S1n+mTV+ny3hKbQ+tYqh+4HGURyUP9hiSdMZjs=,tag:dWCa87XTwH3mBHshUMxjiQ==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
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
'';
}