Restructure

- Restructure
- Add sops+age
This commit is contained in:
aloslider
2026-04-02 21:21:06 +03:00
parent 03548606e4
commit 6a3ff12527
39 changed files with 590 additions and 194 deletions
+8
View File
@@ -0,0 +1,8 @@
keys:
- &users:
- &benq age1tl5hp6v0t38fl8gxuqds40z503mwz885ev22au4jdy5r24aak3zsza23sx
creation_rules:
- path_regex: secrets.yaml$
key_group:
- age:
- *benq
-45
View File
@@ -1,45 +0,0 @@
{ config, lib, pkgs, ... }:
{
imports = [
./home-manager.nix
./modules/system
./hardware-configuration.nix
];
nix.settings.experimental-features = [ "nix-command" "flakes" ];
boot.loader = {
limine = {
enable = true;
};
efi.canTouchEfiVariables = true;
};
time.timeZone = "Europe/Moscow";
i18n = {
defaultLocale = "en_US.UTF-8";
extraLocaleSettings = {
LC_TIME = "en_GB.UTF-8";
};
};
services.xserver.xkb = {
layout = "us,ru";
options = "eurosign:e,caps:escape";
};
services.pipewire = {
enable = true;
pulse.enable = true;
};
environment.systemPackages = with pkgs; [
git
vim
tmux
];
system.stateVersion = "25.05";
}
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/env bash
set -euo pipefail
STATUS=$(bw status | jq -r '.status')
case "$STATUS" in
"unauthenticated")
echo "Unauthenticated. Setting server config..."
read -rp "Enter vault domain: " VAULT_URL
if [[ -z "$VAULT_URL" ]]; then
echo "Error: url cannot be empty"
exit 1
fi
bw config server "https://$VAULT_URL"
export BW_SESSION=$(bw login --raw)
;;
"locked")
export BW_SESSION=$(bw unlock --raw)
;;
"unlocked")
echo "Vault is already unlocked"
;;
*)
echo "Unknown status: $STATUS"
exit 1
;;
esac
echo "Syncing vault..."
bw sync
FILES_DIR="$HOME/nixos-deploy"
rm -rf "$FILES_DIR"
mkdir -p "$FILES_DIR"
AGE_DIR="$FILES_DIR/etc/age"
mkdir -p "$AGE_DIR"
KEY_FILE=$AGE_DIR/key.txt
echo "Writing age key..."
bw get item "age-keys" \
| jq -r '.fields[] | select(.name == "private_key") | .value' \
> "$KEY_FILE"
chmod 700 "$AGE_DIR"
chmod 600 "$KEY_FILE"
if [[ ! -s "$KEY_FILE" ]]; then
echo "Failed to create age key"
exit 1
fi
echo "Copying sops files..."
SOPS_DIR="$FILES_DIR/etc/sops"
mkdir -p "$SOPS_DIR"
cp .sops.yaml secrets.yaml "$SOPS_DIR"
echo "Copying nixos config..."
NIXOS_CFG_DIR="$FILES_DIR/etc/nixos-config"
rsync -r --exclude ".sops.yaml" --exclude "secrets.yaml" ./* "$NIXOS_CFG_DIR"
read -p "Enter IP of the target (user@ip): " TARGET
if [[ -z "$TARGET" ]]; then
echo "Error: TARGET cannot be empty"
exit 1
fi
nix run --extra-experimental-features "nix-command flakes" \
github:nix-community/nixos-anywhere -- \
--flake .#homelab \
--extra-files "$FILES_DIR" \
--target-host "$TARGET"
Generated
+71 -1
View File
@@ -1,5 +1,23 @@
{ {
"nodes": { "nodes": {
"disko": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1773889306,
"narHash": "sha256-PAqwnsBSI9SVC2QugvQ3xeYCB0otOwCacB1ueQj2tgw=",
"owner": "nix-community",
"repo": "disko",
"rev": "5ad85c82cc52264f4beddc934ba57f3789f28347",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "disko",
"type": "github"
}
},
"home-manager": { "home-manager": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -21,6 +39,22 @@
} }
}, },
"nixpkgs": { "nixpkgs": {
"locked": {
"lastModified": 1773628058,
"narHash": "sha256-hpXH0z3K9xv0fHaje136KY872VT2T5uwxtezlAskQgY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f8573b9c935cfaa162dd62cc9e75ae2db86f85df",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1772542754, "lastModified": 1772542754,
"narHash": "sha256-WGV2hy+VIeQsYXpsLjdr4GvHv5eECMISX1zKLTedhdg=", "narHash": "sha256-WGV2hy+VIeQsYXpsLjdr4GvHv5eECMISX1zKLTedhdg=",
@@ -36,10 +70,46 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_3": {
"locked": {
"lastModified": 1775126147,
"narHash": "sha256-J0dZU4atgcfo4QvM9D92uQ0Oe1eLTxBVXjJzdEMQpD0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8d8c1fa5b412c223ffa47410867813290cdedfef",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"disko": "disko",
"home-manager": "home-manager", "home-manager": "home-manager",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs_2",
"sops-nix": "sops-nix"
}
},
"sops-nix": {
"inputs": {
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1775682595,
"narHash": "sha256-0E9PohY/VuESLq0LR4doaH7hTag513sDDW5n5qmHd1Q=",
"owner": "mic92",
"repo": "sops-nix",
"rev": "d2e8438d5886e92bc5e7c40c035ab6cae0c41f76",
"type": "github"
},
"original": {
"owner": "mic92",
"repo": "sops-nix",
"type": "github"
} }
} }
}, },
+20 -6
View File
@@ -1,26 +1,40 @@
{ {
description = "Homelab server flake";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
home-manager = { home-manager = {
url = "github:nix-community/home-manager"; url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
disko.url = "github:nix-community/disko";
sops-nix.url = "github:mic92/sops-nix";
}; };
outputs = { self, nixpkgs, ... }@inputs: outputs = { self, nixpkgs, ... }@inputs:
let let
system = "x86_64-linux"; system = "x86_64-linux";
pkgs = nixpkgs;
customLib = pkgs.lib.extend (
self: super: {
custom = (
import ./lib {
inherit (pkgs) lib;
}
);
}
);
in in
{ {
nixosConfigurations.nixos = nixpkgs.lib.nixosSystem { nixosConfigurations = {
homelab = pkgs.lib.nixosSystem {
inherit system; inherit system;
specialArgs = { inherit inputs; }; specialArgs = {
inherit inputs;
lib = customLib;
};
modules = [ modules = [
./configuration.nix ./hosts/homelab/configuration.nix
inputs.home-manager.nixosModules.home-manager
]; ];
}; };
}; };
};
} }
-30
View File
@@ -1,30 +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 = [ "ahci" "xhci_pci" "virtio_pci" "sr_mod" "virtio_blk" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/5454b429-e268-4399-9eaf-48e16951d1b4";
fsType = "btrfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/F6C1-695C";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
swapDevices = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
-21
View File
@@ -1,21 +0,0 @@
{ config, pkgs, ... }: {
users.users.benq = {
isNormalUser = true;
extraGroups = [ "wheel" ];
};
home-manager = {
imports = [
./modules/home
];
useGlobalPkgs = true;
useUserPackages = true;
users.benq = { pkgs, ... }: {
home.packages = with pkgs; [
lazygit
lazydocker
];
home.stateVersion = "25.05";
};
};
}
+1
View File
@@ -0,0 +1 @@
Home configs per host.
+1
View File
@@ -0,0 +1 @@
Home config for benq user on homelab.
+29
View File
@@ -0,0 +1,29 @@
{
config,
pkgs,
lib,
inputs,
...
}:
{
imports = [
inputs.home-manager.nixosModules.home-manager
];
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
users.benq =
{ pkgs, ... }:
{
imports = lib.flatten [
./packages.nix
(map (f: lib.custom.relativeToRoot "home/common/optional/${f}") [
"git.nix"
])
];
home.stateVersion = "25.05";
};
};
}
+12
View File
@@ -0,0 +1,12 @@
{
config,
pkgs,
...
}:
{
home.packages = with pkgs; [
chezmoi
lazygit
lazydocker
];
}
+29
View File
@@ -0,0 +1,29 @@
{ config, lib, ... }:
with lib;
let
cfg = config.programs.git.options;
in
{
options.programs.git.options = {
username = mkOption {
type = types.str;
default = "aloslider";
};
email = mkOption {
type = types.str;
default = "53711835+aloslider@users.noreply.github.com";
};
};
config = {
programs.git = {
settings = {
user = {
name = cfg.username;
email = cfg.email;
};
init.defaultBranch = "master";
};
};
};
}
+1
View File
@@ -0,0 +1 @@
System config that is required for any host.
+10
View File
@@ -0,0 +1,10 @@
{ config, ... }:
{
imports = [
./disko.nix
./locale.nix
./nix.nix
./packages.nix
./sops.nix
];
}
+62
View File
@@ -0,0 +1,62 @@
{
config,
disko,
lib,
inputs,
...
}:
with lib;
let
cfg = config.disko.cfg;
in
{
imports = [
inputs.disko.nixosModules.disko
];
options.disko.cfg = {
mainDevice = mkOption {
type = types.str;
description = "Main disk name";
};
};
config = {
disko.devices.disk.ssd = {
device = cfg.mainDevice;
type = "disk";
content = {
type = "gpt";
partitions = {
ESP = {
name = "ESP";
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
name = "root";
size = "100%";
content = {
type = "btrfs";
extraArgs = [
"-f"
"-L"
"root"
];
mountpoint = "/";
mountOptions = [
"compress=zstd"
"noatime"
];
};
};
};
};
};
};
}
+16
View File
@@ -0,0 +1,16 @@
{ config, ... }:
{
time.timeZone = "Europe/Moscow";
i18n = {
defaultLocale = "en_US.UTF-8";
extraLocaleSettings = {
LC_TIME = "en_GB.UTF-8";
};
};
services.xserver.xkb = {
layout = "us,ru";
options = "eurosign:e,caps:escape";
};
}
@@ -1,4 +1,10 @@
{ config, ... }: { { config, ... }:
{
nix.settings.experimental-features = [
"nix-command"
"flakes"
];
nix.gc = { nix.gc = {
automatic = true; automatic = true;
dates = "daily"; dates = "daily";
+8
View File
@@ -0,0 +1,8 @@
{ congif, pkgs, ... }:
{
environment.systemPackages = with pkgs; [
git
neovim
tmux
];
}
+17
View File
@@ -0,0 +1,17 @@
{ config, inputs, ... }:
{
imports = [
inputs.sops-nix.nixosModules.sops
];
sops = {
defaultSopsFile = "/etc/sops/secrets.yaml";
age.keyFile = "/etc/age/key.txt";
validateSopsFiles = false;
secrets = {
benq-password = {
neededForUsers = true;
};
};
};
}
+1
View File
@@ -0,0 +1 @@
Optional config that may or not exist on specific host.
+7
View File
@@ -0,0 +1,7 @@
{ config, ... }:
{
services.pipewire = {
enable = true;
pulse.enable = true;
};
}
+8
View File
@@ -0,0 +1,8 @@
{ config, ... }:
{
boot.kernelModules = [ "tcp_bbr" ];
boot.kernel.sysctl = {
"net.ipv4.tcp_congestion_control" = "bbr";
"net.core.deafult_qdisc" = "fq";
};
}
+18
View File
@@ -0,0 +1,18 @@
{ config, pkgs, ... }:
{
virtualisation.docker = {
enable = true;
rootless = {
enable = true;
setSocketVariable = true;
};
};
security.wrappers = {
docker-rootlesskit = {
owner = "root";
group = "root";
capabilities = "cap_net_bind_service+ep";
source = "${pkgs.rootlesskit}/bin/rootlesskit";
};
};
}
+13
View File
@@ -0,0 +1,13 @@
{ config, ... }:
{
services.endlessh = {
enable = true;
port = 22;
openFirewall = true;
};
systemd.services.endlessh = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
};
}
+8
View File
@@ -0,0 +1,8 @@
{ config, ... }:
{
services.fail2ban = {
enable = true;
maxretry = 3;
bantime = "48h";
};
}
+14
View File
@@ -0,0 +1,14 @@
{ config, ... }:
{
services.openssh = {
enable = true;
ports = [ 6969 ];
settings = {
PasswordAuthentication = false;
PermitEmptyPasswords = false;
KbdInteractiveAuthentication = false;
PermitRootLogin = "no";
PubkeyAuthentication = true;
};
};
}
+32
View File
@@ -0,0 +1,32 @@
{
config,
lib,
inputs,
...
}:
with lib;
{
users = {
mutableUsers = false;
users.benq = {
isNormalUser = true;
hashedPasswordFile = config.sops.secrets.benq-password.path;
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAeIuJzR68xA4ugJjtWbwvaWEU852Hg9FAAhXNw8ou43 benq"
];
extraGroups =
let
ifTheyExist = groups: filter (group: hasAttr group config.users.groups) groups;
in
flatten [
"wheel"
(ifTheyExist [
"docker"
"git"
"networkmanager"
"video"
])
];
};
};
}
+7
View File
@@ -0,0 +1,7 @@
{ config, ... }:
{
boot.loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
}
+29
View File
@@ -0,0 +1,29 @@
{
config,
lib,
...
}:
{
imports = lib.flatten [
./boot.nix
./network.nix
./hardware-configuration.nix
(map lib.custom.relativeToRoot (
[
"hosts/common/core"
"hosts/common/users/benq.nix"
"home/benq/homelab.nix"
]
++ (map (f: "hosts/common/optional/${f}") [
"bbr.nix"
"docker.nix"
"endlessh.nix"
"fail2ban.nix"
"openssh.nix"
])
))
];
disko.cfg.mainDevice = "/dev/vda";
system.stateVersion = "26.05";
}
+35
View File
@@ -0,0 +1,35 @@
{
config,
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [
"ahci"
"xhci_pci"
"virtio_pci"
"sr_mod"
"virtio_blk"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
# hdd
fileSystems."/mnt/data" = {
device = "/dev/disk/by-label/data";
fsType = "ext4";
options = [
"noatime"
"nofail"
"x-systemd.device-timeout=5s"
];
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
+26
View File
@@ -0,0 +1,26 @@
{ config, ... }:
{
networking = {
hostName = "homelab";
networkmanager.enable = true;
useDHCP = false;
defaultGateway = "192.168.88.1";
nameservers = [
"192.168.88.1"
];
interfaces.enp1s0 = {
ipv4.addresses = [
{
address = "192.168.88.5";
prefixLength = 24;
}
];
};
firewall.allowedTCPPorts = [
22
80
443
];
firewall.allowedUDPPorts = [ ];
};
}
+4
View File
@@ -0,0 +1,4 @@
{ lib, ... }:
{
relativeToRoot = lib.path.append ../.;
}
-5
View File
@@ -1,5 +0,0 @@
{ config, ... }: {
imports = [
./git.nix
];
}
-12
View File
@@ -1,12 +0,0 @@
{ config, ... }: {
programs.git = {
enable = true;
settings = {
user = {
name = "aloslider";
email = "53711835+aloslider@users.noreply.github.com";
};
init.defaultBranch = "master";
};
};
}
-8
View File
@@ -1,8 +0,0 @@
{ config, ... }: {
imports = [
./docker.nix
./gc.nix
./network.nix
./openssh.nix
];
}
-17
View File
@@ -1,17 +0,0 @@
{ config, pkgs, ... }: {
virtualisation.docker = {
enable = true;
rootless = {
enable = true;
setSocketVariable = true;
};
};
security.wrappers = {
docker-rootlesskit = {
owner = "root";
group = "root";
capabilities = "cap_net_bind_service+ep";
source = "${pkgs.rootlesskit}/bin/rootlesskit";
};
};
}
-13
View File
@@ -1,13 +0,0 @@
{ config, pkgs, ... }: {
networking.hostName = "benq-serv";
networking.networkmanager.enable = true;
networking.firewall.allowedTCPPorts = [ 22 80 443 ];
networking.firewall.allowedUDPPorts = [];
boot.kernelModules = [ "tcp_bbr" ];
boot.kernel.sysctl = {
"net.ipv4.tcp_congestion_control" = "bbr";
"net.core.default_qdisc" = "fq";
};
}
-30
View File
@@ -1,30 +0,0 @@
{ config, pkgs, ... }: {
services.openssh = {
enable = true;
ports = [ 6969 ];
settings = {
PasswordAuthentication = false;
PermitEmptyPasswords = false;
KbdInteractiveAuthentication = false;
PermitRootLogin = "no";
PubkeyAuthentication = true;
};
};
services.fail2ban = {
enable = true;
maxretry = 3;
bantime = "48h";
};
services.endlessh = {
enable = true;
port = 22;
openFirewall = true;
};
systemd.services.endlessh = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
};
}
+16
View File
@@ -0,0 +1,16 @@
benq-password: ENC[AES256_GCM,data:jWOUkdqTtJDvPp3G0uSJDAlzdswT+efZf8keG8rhw5MgiNjWenegiC4eGdQ0ykeS+wQJJaHsrH5wIgpiMI32s18py70JDEqHnrcB0DPQnbE7DzfO7/4BhwdBWHSeEcQaiHjtFhuKr5c8hw==,iv:aA3qcFE5zyBoVMJzuGYkk5J0UyQPu4Xx3fTAl8G4Slw=,tag:IDjwsJ6c1Sm+lbo8qEfJAw==,type:str]
sops:
age:
- recipient: age1tl5hp6v0t38fl8gxuqds40z503mwz885ev22au4jdy5r24aak3zsza23sx
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBDbUpHc0l1Snd4eWVUUWRR
ZWdvVDNlNUp4WWxBVGxxOWdDcjQ3WDM2b2hVCjVqNCs2cThsL2gyckE1K2NsSFdJ
d0ZCamFlcVlnRmFDS05NcldmLzZZN2sKLS0tIDF1U2NhQkhjd1hEazRXbVpocnln
cXhlUUY3a0tzSURRVEdYMDZGNGRmaGcKYknpSmwVYxSFVIde43kjvJFD5zS3hmvq
JMXFAHfa7Nf3deu83gSGsvgQADb61ZI9v78x66lWwvdPKzcZFUriUg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-04-10T20:15:48Z"
mac: ENC[AES256_GCM,data:MinxRU59BGQm3CH/EtvX0LaPLHkU2CsEqbbURqTtcY9H3tkLPTlf6NVJYaA4WtU2W3DZbxcRP4VzCj6o3LNdZ0qnb/CLG4INhIxRNL71SQZ8r5sIAkYHGLYOvI5kXIfFEdeXbK0Y12tb5CFIldERqbO+kcSARmlOqSoNCpFGlgw=,iv:HjwQ8n4yd8Q8Q7S/5tQFgrve960kcelwLpLIfYf6mcU=,tag:jarkIS3EkTTq2H6ZAdp+xg==,type:str]
unencrypted_suffix: _unencrypted
version: 3.12.2