migrate to clan

This commit is contained in:
2025-05-16 15:46:47 +02:00
parent f817ba1405
commit f1ec59c3af
60 changed files with 225 additions and 391 deletions

5
machines/README.md Normal file
View File

@@ -0,0 +1,5 @@
# Hosts
- **crocus**: Hetzner Cloud x86_64 VPS
- **genepi**: Raspberry Pi 4B
- **haze**: ASUS VivoBook Laptop

View File

@@ -0,0 +1,82 @@
{
inputs,
modulesPath,
config,
...
}:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
# ./radicle.nix
../../system
inputs.clan-core.clanModules.state-version
../../modules/remote-builder.nix
../../modules/borgbackup.nix
];
nixpkgs.hostPlatform = "x86_64-linux";
networking.hostName = "crocus";
clan.core.networking.targetHost = "root@crocus.local";
networking.useDHCP = false;
systemd.network.enable = true;
systemd.network.networks."10-wan" = {
matchConfig.Name = "enp1s0";
networkConfig.DHCP = "ipv4";
address = [
"2a01:4f8:1c1e:e415::1/64"
];
routes = [
{ Gateway = "fe80::1"; }
];
};
services.avahi.enable = true;
disko.devices.disk.main.device = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_48353082";
boot.loader.grub = {
efiSupport = true;
efiInstallAsRemovable = true;
};
services.prometheus = {
enable = true;
port = 9001;
exporters = {
node = {
enable = true;
enabledCollectors = [ "systemd" ];
port = 9002;
};
};
scrapeConfigs = [
{
job_name = "crocus";
static_configs = [
{
targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.node.port}" ];
}
];
}
];
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
};
networking.firewall.allowedTCPPorts = [
80
443
];
security.acme = {
acceptTerms = true;
defaults.email = "admin@rpqt.fr";
};
}

42
machines/crocus/disko.nix Normal file
View File

@@ -0,0 +1,42 @@
{
clan-core,
config,
...
}:
let
suffix = config.clan.core.vars.generators.disk-id.files.diskId.value;
in
{
imports = [ clan-core.clanModules.disk-id ];
disko.devices.disk.main = {
name = "main-" + suffix;
type = "disk";
content = {
type = "gpt";
partitions = {
boot = {
type = "EF02";
size = "1M";
};
ESP = {
type = "EF00";
size = "512M";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
}

View File

@@ -0,0 +1,21 @@
{ config, keys, ... }:
{
services.radicle = {
enable = true;
privateKeyFile = config.age.secrets.radicle-private-key.path;
publicKey = keys.services.radicle;
node = {
openFirewall = true;
};
httpd = {
enable = true;
nginx = {
serverName = "radicle.rpqt.fr";
enableACME = true;
forceSSL = true;
};
};
};
age.secrets.radicle-private-key.file = ../../secrets/radicle-private-key.age;
}

21
machines/genepi/acme.nix Normal file
View File

@@ -0,0 +1,21 @@
{ config, ... }:
{
security.acme = {
acceptTerms = true;
defaults.email = "admin@rpqt.fr";
};
age.secrets.gandi.file = ../../secrets/gandi.age;
security.acme = {
certs."home.rpqt.fr" = {
group = config.services.nginx.group;
domain = "home.rpqt.fr";
extraDomainNames = [ "*.home.rpqt.fr" ];
dnsProvider = "gandiv5";
dnsPropagationCheck = true;
environmentFile = config.age.secrets.gandi.path;
};
};
}

19
machines/genepi/boot.nix Normal file
View File

@@ -0,0 +1,19 @@
{ config, ... }:
{
boot.initrd.availableKernelModules = [
"xhci_pci"
"usbhid"
"usb_storage"
];
boot.loader = {
grub.enable = false;
generic-extlinux-compatible.enable = true;
};
boot.supportedFilesystems = [
"btrfs"
"vfat"
];
}

View File

@@ -0,0 +1,11 @@
{ keys, ... }:
{
imports = [
../../modules/remote-builder.nix
];
roles.remote-builder = {
enable = true;
authorizedKeys = [ keys.hosts.haze ];
};
}

View File

@@ -0,0 +1,47 @@
{
inputs,
...
}:
{
imports = [
inputs.agenix.nixosModules.default
inputs.impermanence.nixosModules.impermanence
./acme.nix
./boot.nix
./builder.nix
./dns.nix
./freshrss.nix
./glance.nix
./homeassistant.nix
# ./immich.nix
./monitoring
./mpd.nix
./network.nix
./nginx.nix
./persistence.nix
./syncthing.nix
./taskchampion.nix
../../system
../../modules/borgbackup.nix
inputs.clan-core.clanModules.state-version
inputs.clan-core.clanModules.trusted-nix-caches
inputs.home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.users.rpqt = ./home.nix;
}
];
networking.hostName = "genepi";
clan.core.networking.targetHost = "root@genepi.local";
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
}

86
machines/genepi/disko.nix Normal file
View File

@@ -0,0 +1,86 @@
{
disko.devices.disk.main = {
type = "disk";
device = "/dev/disk/by-id/ata-WD_Green_M.2_2280_480GB_2251E6411147";
content = {
type = "gpt";
partitions = {
ESP = {
priority = 1;
name = "ESP";
start = "1M";
end = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
root = {
end = "-4G";
content = {
type = "btrfs";
extraArgs = [
"-L"
"nixos"
"-f" # Override existing partition
];
subvolumes = {
"/root" = {
mountpoint = "/";
mountOptions = [
"subvol=root"
"compress=zstd"
"noatime"
];
};
"/home" = {
mountpoint = "/home";
mountOptions = [
"subvol=home"
"compress=zstd"
"noatime"
];
};
"/nix" = {
mountpoint = "/nix";
mountOptions = [
"subvol=nix"
"compress=zstd"
"noatime"
];
};
"/persist" = {
mountpoint = "/persist";
mountOptions = [
"subvol=persist"
"compress=zstd"
"noatime"
];
};
"/log" = {
mountpoint = "/var/log";
mountOptions = [
"subvol=log"
"compress=zstd"
"noatime"
];
};
};
};
};
swap = {
size = "100%";
content = {
type = "swap";
};
};
};
};
};
fileSystems."/persist".neededForBoot = true;
fileSystems."/var/log".neededForBoot = true;
}

35
machines/genepi/dns.nix Normal file
View File

@@ -0,0 +1,35 @@
{ config, lib, ... }:
let
domain = "home.rpqt.fr";
genepi = {
ip = "100.83.123.79";
subdomains = [
"glance"
"grafana"
"images"
"rss"
"tw"
];
};
in
{
networking.firewall.interfaces."${config.services.tailscale.interfaceName}" = {
allowedTCPPorts = [ 53 ];
allowedUDPPorts = [ 53 ];
};
services.unbound = {
enable = true;
resolveLocalQueries = false;
settings = {
server = {
interface = [ "${config.services.tailscale.interfaceName}" ];
access-control = [ "100.0.0.0/8 allow" ];
local-zone = lib.map (subdomain: ''"${subdomain}.${domain}." redirect'') genepi.subdomains;
local-data = lib.map (subdomain: ''"${subdomain}.${domain}. IN A ${genepi.ip}"'') genepi.subdomains;
};
};
};
}

View File

@@ -0,0 +1,26 @@
{ config, ... }:
let
domain = "home.rpqt.fr";
subdomain = "rss.${domain}";
in
{
age.secrets.freshrss = {
file = ../../secrets/freshrss.age;
mode = "700";
owner = config.services.freshrss.user;
};
services.freshrss = {
enable = true;
baseUrl = "https://${subdomain}";
virtualHost = "${subdomain}";
defaultUser = "rpqt";
passwordFile = config.age.secrets.freshrss.path;
};
services.nginx.virtualHosts.${config.services.freshrss.virtualHost} = {
forceSSL = true;
useACMEHost = "${domain}";
};
}

View File

@@ -0,0 +1,187 @@
{
theme = {
light = true;
background-color = "0 0 95";
primary-color = "0 0 10";
negative-color = "0 90 50";
};
pages = [
{
name = "Home";
columns = [
{
size = "small";
widgets = [
{
type = "calendar";
first-day-of-week = "monday";
}
{
type = "server-stats";
servers = [
{
type = "local";
name = "Genepi";
}
];
}
];
}
{
size = "full";
widgets = [
{
type = "search";
autofocus = true;
}
{
type = "monitor";
cache = "1m";
title = "Services";
sites = [
{
title = "Immich";
url = "https://images.home.rpqt.fr";
icon = "si:immich";
}
{
title = "Grafana";
url = "https://grafana.home.rpqt.fr";
icon = "si:grafana";
}
{
title = "FreshRSS";
url = "https://rss.home.rpqt.fr";
icon = "si:rss";
}
];
}
];
}
{
size = "small";
widgets = [
{
type = "weather";
location = "Grenoble, France";
units = "metric";
hour-format = "24h";
}
];
}
];
}
{
name = "Feeds";
columns = [
{
size = "small";
widgets = [
{
type = "rss";
title = "Blogs";
limit = 10;
collapse-after = 5;
cache = "12h";
feeds = [
{
url = "https://rss.home.rpqt.fr/api/query.php?user=rpqt&t=74HfeLZ6Wu9h4MmjNR38Rz&f=rss";
}
];
}
{
type = "rss";
title = "Status & Updates";
limit = 3;
cache = "12h";
feeds = [
{
url = "https://status.sr.ht/index.xml";
}
];
}
];
}
{
size = "full";
widgets = [
{
type = "group";
widgets = [
{
type = "hacker-news";
}
{
type = "lobsters";
}
];
}
{
type = "group";
widgets = [
{
type = "reddit";
subreddit = "selfhosted";
show-thumbnails = true;
}
{
type = "reddit";
subreddit = "homelab";
show-thumbnails = true;
}
];
}
{
type = "videos";
channels = [
"UCR-DXc1voovS8nhAvccRZhg"
"UCsBjURrPoezykLs9EqgamOA"
];
}
];
}
{
size = "small";
widgets = [
{
type = "releases";
cache = "1d";
repositories = [
"glanceapp/glance"
];
}
{
type = "custom-api";
title = "Random Fact";
cache = "6h";
url = "https://uselessfacts.jsph.pl/api/v2/facts/random";
template = ''
<p class="size-h4 color-paragraph">{{ .JSON.String "text" }}</p>
'';
}
{
type = "custom-api";
title = "Steam Specials";
cache = "12h";
url = "https://store.steampowered.com/api/featuredcategories?cc=us";
template = ''
<ul class="list list-gap-10 collapsible-container" data-collapse-after="5">
{{ range .JSON.Array "specials.items" }}
<li>
<a class="size-h4 color-highlight block text-truncate" href="https://store.steampowered.com/app/{{ .Int "id" }}/">{{ .String "name" }}</a>
<ul class="list-horizontal-text">
<li>{{ div (.Int "final_price" | toFloat) 100 | printf "$%.2f" }}</li>
{{ $discount := .Int "discount_percent" }}
<li{{ if ge $discount 40 }} class="color-positive"{{ end }}>{{ $discount }}% off</li>
</ul>
</li>
{{ end }}
</ul>
'';
}
];
}
];
}
];
}

View File

@@ -0,0 +1,18 @@
{ config, ... }:
let
domain = "home.rpqt.fr";
subdomain = "glance.${domain}";
in
{
services.glance = {
enable = true;
settings = ./glance-config.nix;
};
services.nginx.virtualHosts.${subdomain} = {
forceSSL = true;
useACMEHost = "${domain}";
locations."/".proxyPass =
"http://127.0.0.1:${toString config.services.glance.settings.server.port}";
};
}

View File

@@ -0,0 +1,23 @@
{ inputs, pkgs, ... }:
{
imports = [
# inputs.nixos-hardware.nixosModules.raspberry-pi-4
];
nixpkgs.hostPlatform = "aarch64-linux";
hardware.enableRedistributableFirmware = true;
# hardware = {
# raspberry-pi."4".apply-overlays-dtmerge.enable = true;
# deviceTree = {
# enable = true;
# filter = "*rpi-4-*.dtb";
# };
# };
environment.systemPackages = with pkgs; [
libraspberrypi
raspberrypi-eeprom
];
}

32
machines/genepi/home.nix Normal file
View File

@@ -0,0 +1,32 @@
{
config,
pkgs,
lib,
...
}:
{
home.username = "rpqt";
home.homeDirectory = lib.mkForce "/home/rpqt";
home.packages = [
pkgs.helix
pkgs.ripgrep
pkgs.eza
];
programs.zsh.enable = true;
programs.starship.enable = true;
programs.atuin.enable = true;
# This value determines the Home Manager release that your configuration is
# compatible with. This helps avoid breakage when a new Home Manager release
# introduces backwards incompatible changes.
#
# You should not change this value, even if you update Home Manager. If you do
# want to update the value, then make sure to first check the Home Manager
# release notes.
home.stateVersion = "24.11";
# Let Home Manager install and manage itself
programs.home-manager.enable = true;
}

View File

@@ -0,0 +1,10 @@
{
virtualisation.oci-containers.containers.homeassistant = {
volumes = [ "home-assistant:/config" ];
environment.TZ = "Europe/Paris";
image = "ghcr.io/home-assistant/home-assistant:stable";
extraOptions = [
"--network=host"
];
};
}

View File

@@ -0,0 +1,30 @@
{ config, ... }:
let
domain = "home.rpqt.fr";
subdomain = "images.${domain}";
in
{
services.immich = {
enable = true;
settings = {
server.externalDomain = "https://${subdomain}";
};
};
services.nginx.virtualHosts.${subdomain} = {
forceSSL = true;
useACMEHost = "${domain}";
locations."/" = {
proxyPass = "http://${toString config.services.immich.host}:${toString config.services.immich.port}";
proxyWebsockets = true;
extraConfig = ''
client_max_body_size 50000M;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
send_timeout 600s;
'';
};
};
clan.core.state.userdata.folders = [ "/var/lib/immich" ];
}

View File

@@ -0,0 +1,6 @@
{
imports = [
./grafana.nix
./prometheus.nix
];
}

View File

@@ -0,0 +1,40 @@
{ config, ... }:
let
domain = "home.rpqt.fr";
in
{
services.grafana = {
enable = true;
settings = {
server = {
http_port = 3000;
domain = "grafana.${domain}";
};
};
provision = {
enable = true;
datasources = {
settings = {
datasources = [
{
name = "Prometheus";
type = "prometheus";
access = "proxy";
url = "http://127.0.0.1:${toString config.services.prometheus.port}";
isDefault = true;
}
];
};
};
};
};
services.nginx.virtualHosts.${config.services.grafana.settings.server.domain} = {
forceSSL = true;
useACMEHost = "${domain}";
locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.grafana.settings.server.http_port}";
proxyWebsockets = true;
};
};
}

View File

@@ -0,0 +1,63 @@
{
lib,
self,
...
}:
let
allHosts = self.nixosConfigurations;
hostInTailnetFilter = k: v: v.config.services.tailscale.enable;
tailnetHosts = lib.filterAttrs hostInTailnetFilter allHosts;
# Explicitly list the exporters as some are deprecated and can't be evaluated
possibleExporterNames = [
"node"
];
getEnabledExporters =
hostname: host:
lib.filterAttrs (k: v: v.enable == true) (
lib.getAttrs possibleExporterNames host.config.services.prometheus.exporters
);
enabledExporters = lib.mapAttrs getEnabledExporters tailnetHosts;
mkScrapeConfigExporter = hostname: exporterName: exporterCfg: {
job_name = "${hostname}-${exporterName}";
static_configs = [ { targets = [ "${hostname}:${toString exporterCfg.port}" ]; } ];
relabel_configs = [
{
target_label = "instance";
replacement = "${hostname}";
}
{
target_label = "job";
replacement = "${exporterName}";
}
];
};
mkScrapeConfigHost = hostname: exporters: lib.mapAttrs (mkScrapeConfigExporter hostname) exporters;
scrapeConfigsByHost = lib.mapAttrs mkScrapeConfigHost enabledExporters;
autogenScrapeConfigs = lib.flatten (
map builtins.attrValues (builtins.attrValues scrapeConfigsByHost)
);
in
{
services.prometheus = {
enable = true;
port = 9001;
scrapeConfigs = autogenScrapeConfigs;
exporters = {
node = {
enable = true;
enabledCollectors = [ "systemd" ];
port = 9002;
};
};
};
clan.core.state.userdata.folders = [ "/var/lib/prometheus2" ];
}

27
machines/genepi/mpd.nix Normal file
View File

@@ -0,0 +1,27 @@
{ config, ... }:
{
services.mpd = {
enable = true;
musicDirectory = "/home/rpqt/Media/Music";
extraConfig = ''
audio_output {
type "pulse"
name "Pulse Audio"
}
'';
network.listenAddress = "any";
};
services.pulseaudio.enable = true;
# Workaround: run PulseAudio system-wide so that the mpd user can access it
services.pulseaudio.systemWide = true;
# Fixes the stutter when changing volume (found this randomly)
services.pulseaudio.daemon.config.flat-volumes = "no";
users.users.${config.services.mpd.user}.extraGroups = [ "pulse-access" ];
users.users.rpqt.homeMode = "755";
}

View File

@@ -0,0 +1,6 @@
{
# Tailscale seems to break when not using resolved
services.resolved.enable = true;
networking.useDHCP = true;
networking.interfaces.tailscale0.useDHCP = false;
}

View File

@@ -0,0 +1,7 @@
{
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
};
}

View File

@@ -0,0 +1,64 @@
{ lib, ... }:
{
environment.persistence."/persist" = {
enable = true;
directories = [
"/var/lib/nixos"
"/var/lib/acme"
"/var/lib/prometheus2"
"/var/lib/immich"
"/var/lib/redis-immich"
"/var/lib/postgresql"
"/var/lib/grafana"
"/var/lib/freshrss"
"/var/lib/tailscale"
];
files = [
# so that systemd doesn't think each boot is the first
"/etc/machine-id"
# ssh host keys
"/etc/ssh/ssh_host_rsa_key"
"/etc/ssh/ssh_host_rsa_key.pub"
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_ed25519_key.pub"
];
users.rpqt = {
directories = [ ];
files = [ ];
home = "/home/rpqt";
};
};
# Empty root and remove snapshots older than 30 days
# boot.initrd.postDeviceCommands = lib.mkAfter ''
# mkdir /btrfs_tmp
# mount /dev/disk/by-label/nixos /btrfs_tmp
# if [[ -e /btrfs_tmp/root ]]; then
# mkdir -p /btrfs_tmp/old_roots
# timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/root)" "+%Y-%m-%-d_%H:%M:%S")
# mv /btrfs_tmp/root "/btrfs_tmp/old_roots/$timestamp"
# fi
# delete_subvolume_recursively() {
# IFS=$'\n'
# for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
# delete_subvolume_recursively "/btrfs_tmp/$i"
# done
# btrfs subvolume delete "$1"
# }
# for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +30); do
# delete_subvolume_recursively "$i"
# done
# btrfs subvolume create /btrfs_tmp/root
# umount /btrfs_tmp
# rmdir /btrfs_tmp
# '';
# Give agenix persistent paths so it can load secrets before the mount
age.identityPaths = [
"/persist/etc/ssh/ssh_host_ed25519_key"
"/persist/etc/ssh/ssh_host_rsa_key"
];
}

View File

@@ -0,0 +1,57 @@
{
config,
...
}:
let
user = "rpqt";
home = config.users.users.${user}.home;
in
{
services.syncthing = {
enable = true;
user = user;
group = "users";
dataDir = home;
configDir = "${home}/.config/syncthing";
openDefaultPorts = true;
overrideDevices = true;
overrideFolders = true;
settings = {
devices = {
"haze" = {
id = "QUX6KGF-7KNFTGD-RAX5OWC-NFQGRNK-S2TC2DQ-DQRWDTK-KMBTQXT-EVNRDQG";
};
"pixel-7a" = {
id = "IZE7B4Z-LKTJY6Q-77NN4JG-ADYRC77-TYPZTXE-Q35BWV2-AEO7Q3R-ZE63IAU";
};
};
folders = {
"Documents" = {
path = "${home}/Documents";
devices = [
"haze"
];
};
"Music" = {
path = "${home}/Media/Music";
devices = [
"haze"
"pixel-7a"
];
};
"Pictures" = {
path = "${home}/Media/Pictures";
devices = [
"haze"
];
};
"Videos" = {
path = "${home}/Media/Videos";
devices = [
"haze"
];
};
};
};
};
}

View File

@@ -0,0 +1,19 @@
{ config, lib, ... }:
let
domain = "home.rpqt.fr";
subdomain = "tw.${domain}";
hasImpermanence = config.environment.persistence."/persist".enable;
in
{
services.taskchampion-sync-server.enable = true;
services.taskchampion-sync-server.dataDir =
(lib.optionalString hasImpermanence "/persist") + "/var/lib/taskchampion-sync-server";
services.nginx.virtualHosts.${subdomain} = {
forceSSL = true;
useACMEHost = "${domain}";
locations."/".proxyPass =
"http://127.0.0.1:${toString config.services.taskchampion-sync-server.port}";
};
}

21
machines/haze/boot.nix Normal file
View File

@@ -0,0 +1,21 @@
{
boot.loader = {
systemd-boot = {
enable = true;
};
efi.canTouchEfiVariables = true;
};
console = {
earlySetup = true;
useXkbConfig = true;
};
services = {
xserver = {
xkb.layout = "fr";
};
};
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
}

8
machines/haze/chat.nix Normal file
View File

@@ -0,0 +1,8 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
beeper
discord
element-desktop
];
}

View File

@@ -0,0 +1,68 @@
{
inputs,
...
}:
{
imports = [
# inputs.disko.nixosModules.disko
inputs.agenix.nixosModules.default
./boot.nix
./chat.nix
./firefox.nix
./gimp.nix
./gnome.nix
./hibernate.nix
./niri.nix
./ssh.nix
./steam.nix
./thunderbird.nix
./network.nix
./syncthing.nix
./video.nix
../../system
inputs.clan-core.clanModules.state-version
inputs.home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.users.rpqt = ./home.nix;
home-manager.extraSpecialArgs = { inherit inputs; };
}
];
networking.hostName = "haze";
clan.core.networking.targetHost = "rpqt@haze.local";
specialisation = {
hyprland.configuration =
{ ... }:
{
imports = [ ./hyprland.nix ];
disabledModules = [ ./niri.nix ];
};
sway.configuration =
{ ... }:
{
imports = [ ./sway.nix ];
disabledModules = [ ./niri.nix ];
};
};
# Remote builds
nix = {
distributedBuilds = true;
buildMachines = [
{
sshUser = "nixremote";
sshKey = "/etc/ssh/ssh_host_ed25519_key";
systems = [ "aarch64-linux" ];
hostName = "genepi";
}
];
extraOptions = ''
builders-use-substitutes = true
'';
};
}

View File

@@ -0,0 +1 @@

76
machines/haze/disko.nix Normal file
View File

@@ -0,0 +1,76 @@
{
disko.devices.disk.main = {
type = "disk";
device = "/dev/nvme0n1";
content = {
type = "gpt";
partitions = {
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
luks = {
size = "100%";
content = {
type = "luks";
name = "crypted";
settings.allowDiscards = true;
content = {
type = "btrfs";
extraArgs = [ "-f" ];
subvolumes = {
"/root" = {
mountpoint = "/";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"/arch-root" = { }; # archlinux root
"/home" = {
mountpoint = "/home";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"/nix" = {
mountpoint = "/nix";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"/persist" = {
mountpoint = "/persist";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"/swap" = {
mountpoint = "/.swapvol";
swap.swapfile.size = "16G";
};
};
postCreateHook = ''
MNTPOINT="$(mktemp -d)"
mount "/dev/mapper/crypted" "$MNTPOINT" -o subvol=/
trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
btrfs subvolume snapshot -r $MNTPOINT/root $MNTPOINT/root-blank
'';
};
};
};
};
};
};
fileSystems."/persist".neededForBoot = true;
}

View File

@@ -0,0 +1,7 @@
{ pkgs, ... }:
{
programs.firefox = {
enable = true;
nativeMessagingHosts.packages = [ pkgs.passff-host ];
};
}

4
machines/haze/gimp.nix Normal file
View File

@@ -0,0 +1,4 @@
{ pkgs, ... }:
{
environment.systemPackages = [ pkgs.gimp ];
}

30
machines/haze/gnome.nix Normal file
View File

@@ -0,0 +1,30 @@
{ pkgs, ... }:
{
services.xserver = {
enable = true;
displayManager.gdm.enable = true;
desktopManager.gnome.enable = true;
xkb.layout = "fr";
};
environment.gnome.excludePackages = (
with pkgs;
[
atomix # puzzle game
cheese # webcam tool
epiphany # web browser
# evince # document viewer
geary # email reader
gedit # text editor
gnome-characters
gnome-music
gnome-photos
gnome-terminal
gnome-tour
hitori # sudoku game
iagno # go game
tali # poker game
totem # video player
]
);
}

View File

@@ -0,0 +1,11 @@
{ config, ... }:
{
nixpkgs.hostPlatform = "x86_64-linux";
hardware.enableRedistributableFirmware = true;
boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "vmd" "nvme" "usb_storage" "sd_mod" "rtsx_usb_sdmmc" ];
boot.kernelModules = [ "kvm-intel" ];
hardware.cpu.intel.updateMicrocode = config.hardware.enableRedistributableFirmware;
}

View File

@@ -0,0 +1,3 @@
{
boot.initrd.systemd.enable = true;
}

17
machines/haze/home.nix Normal file
View File

@@ -0,0 +1,17 @@
{
imports = [
../../home/chat.nix
../../home/cli.nix
../../home/common.nix
../../home/desktop
../../home/dev.nix
../../home/dotfiles.nix
../../home/helix.nix
../../home/mail
../../home/minecraft.nix
../../home/desktop
../../home/desktop/gnome.nix
../../home/desktop/niri.nix
../../home/desktop/sway.nix
];
}

View File

@@ -0,0 +1,3 @@
{
programs.hyprland.enable = true;
}

11
machines/haze/network.nix Normal file
View File

@@ -0,0 +1,11 @@
{ pkgs, ... }:
{
networking.networkmanager = {
enable = true;
wifi.powersave = true;
};
users.users."rpqt".extraGroups = [ "networkmanager" ];
environment.systemPackages = [ pkgs.networkmanager-openconnect ];
}

19
machines/haze/niri.nix Normal file
View File

@@ -0,0 +1,19 @@
{ pkgs, ... }:
{
programs.niri.enable = true;
environment.systemPackages = with pkgs; [
brightnessctl
i3bar-river
mako
pavucontrol
playerctl
swaybg
swaylock
tofi
wl-gammarelay-rs
xwayland-satellite
];
environment.sessionVariables.NIXOS_OZONE_WL = "1";
}

View File

@@ -0,0 +1,13 @@
let
keys = import ../../../parts/keys.nix;
in
{
"syncthing-key.pem.age".publicKeys = [
keys.hosts.haze
keys.rpqt.haze
];
"syncthing-cert.pem.age".publicKeys = [
keys.hosts.haze
keys.rpqt.haze
];
}

Binary file not shown.

View File

@@ -0,0 +1,8 @@
age-encryption.org/v1
-> ssh-ed25519 P3fsag cm2nekzBIMCAb/yXzY4L6jIH/Sa+rSMznT88WJNkP30
DMnRf0An69vywpHLD3RGHwE0dkaa6JIEahhQo14EEDc
--- f/kI+HBhWTQlXoWvCJaLJM70EsOkH4G8/5g9Eeu8uNc
<EFBFBD>T!<21><><12>\Β<>6<16>
<EFBFBD>T<><54>rϵKr<4B>9<EFBFBD><39>w<EFBFBD>̞<EFBFBD>8<04><><EFBFBD><EFBFBD>E<EFBFBD><45><EFBFBD><EFBFBD>,<2C>R.<2E><><EFBFBD><EFBFBD><EFBFBD>i<> <20><><EFBFBD><EFBFBD>_'2<>;i<>ń<EFBFBD>8d<04><><EFBFBD><EFBFBD><EFBFBD>&Dݫq<><71><EFBFBD>xd
<EFBFBD>3<EFBFBD>e<EFBFBD>xn<EFBFBD>g~<7E>/)݇a<DD87><13>W<><57><EFBFBD>G~<1F><><EFBFBD>BNV<4E><56>i<EFBFBD>a<05>{<7B><17><>u<EFBFBD>ە<1B>R=<3D><>M<EFBFBD>O)$HS<48><53>f<EFBFBD>f<<3C><>c<><63>?<3F><01>~*<2A>T<EFBFBD><07><>)Wtʁ<18><><EFBFBD>&<15><>8i<38><69><EFBFBD>z<EFBFBD><7A>:5<><35>[sc"<22><><1A><>& U<><55><EFBFBD>9<EFBFBD><39>'<27><>_<5F><7F>{xkE<6B><45>ؼY<0E>@<40><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>f<EFBFBD>U<EFBFBD>+<2B><>B<EFBFBD>u<EFBFBD>=<3D><>Y4<0F>e3<65>U<01><>QLSl5 U<><1B>!<10>h<EFBFBD><68>W<EFBFBD><57>@}<7D>OW<4F><57><EFBFBD>

3
machines/haze/ssh.nix Normal file
View File

@@ -0,0 +1,3 @@
{
programs.ssh.startAgent = true;
}

8
machines/haze/steam.nix Normal file
View File

@@ -0,0 +1,8 @@
{
programs.steam = {
enable = true;
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
localNetworkGameTransfers.openFirewall = true; # Open ports in the firewall for Steam Local Network Game Transfers
};
}

11
machines/haze/sway.nix Normal file
View File

@@ -0,0 +1,11 @@
{
services.gnome.gnome-keyring.enable = true;
programs.sway = {
enable = true;
wrapperFeatures.gtk = true;
};
users.users."rpqt".extraGroups = [ "video" ];
programs.light.enable = true;
}

View File

@@ -0,0 +1,63 @@
{
config,
...
}:
let
user = "rpqt";
home = config.users.users.${user}.home;
in
{
# age.secrets.syncthing-key.file = ./secrets/syncthing-key.pem.age;
# age.secrets.syncthing-cert.file = ./secrets/syncthing-cert.pem.age;
services.syncthing = {
enable = false;
user = user;
group = "users";
dataDir = home;
configDir = "${home}/.config/syncthing";
key = config.age.secrets.syncthing-key.path;
cert = config.age.secrets.syncthing-cert.path;
openDefaultPorts = true;
overrideDevices = true;
overrideFolders = true;
settings = {
devices = {
"genepi" = {
id = "EA7DC7O-IHB47EQ-AWT2QBJ-AWPDF5S-W4EM66A-KQPCTHI-UX53WKM-QTSAHQ4";
};
"pixel-7a" = {
id = "IZE7B4Z-LKTJY6Q-77NN4JG-ADYRC77-TYPZTXE-Q35BWV2-AEO7Q3R-ZE63IAU";
};
};
folders = {
"Documents" = {
path = "${home}/Documents";
devices = [
"genepi"
"pixel-7a"
];
};
"Music" = {
path = "${home}/Music";
devices = [
"genepi"
"pixel-7a"
];
};
"Pictures" = {
path = "${home}/Pictures";
devices = [
"genepi"
];
};
"Videos" = {
path = "${home}/Videos";
devices = [
"genepi"
];
};
};
};
};
}

View File

@@ -0,0 +1,3 @@
{
programs.thunderbird.enable = true;
}

4
machines/haze/video.nix Normal file
View File

@@ -0,0 +1,4 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ mpv ];
}