This commit is contained in:
Finn Linck Ryan 2026-01-11 01:42:54 +00:00
commit aae151cee6
33 changed files with 1351 additions and 0 deletions

9
hosts/makise/.sops.yaml Executable file
View file

@ -0,0 +1,9 @@
keys:
- &host_makise age1pj86dmk8j5tne0r7zu09v3x40xjdae6mhvrzyw5squ9px96z9p0suj89f8
- &user_kurisu age1w3n63wg0pkjy300hsaw6uvd6ell7hpkfpd7knjsp637u2dcjx3nql654fm
creation_rules:
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
key_groups:
- age:
- *host_makise
- *user_kurisu

View file

@ -0,0 +1,30 @@
{ inputs
, pkgs
, ...
}:
{
imports = [
# ./configuration
];
nixpkgs = {
config = {
allowUnfree = true;
};
};
home = {
username = "admin";
homeDirectory = "/home/admin";
# !!! DO NOT TOUCH !!!
stateVersion = "26.05";
};
# Enable essential programs.
programs.home-manager.enable = true;
# Nicely reload user system units when changed.
systemd.user.startServices = "sd-switch";
}

View file

@ -0,0 +1,27 @@
{ outputs
, ...
}:
let
modules = outputs.homeManagerModules;
in
{
imports = [
modules.editors
modules.shells
./git.nix
];
custom = {
editors = {
defaultEditor = "helix";
helix.enable = true;
};
shells = {
fish.enable = true;
direnv.enable = true;
zellij.enable = true;
};
};
}

View file

@ -0,0 +1,27 @@
{ ...
}:
{
programs.git = {
enable = true;
settings = {
user = {
name = "dokkae.cat";
email = "finnliry@gmail.com";
};
init.defaultBranch = "main";
safe.directory = "/etc/nixos";
};
ignores = [
".idea/"
".helix/"
".direnv/"
".envrc"
".ignore"
];
};
}

View file

@ -0,0 +1,30 @@
{ inputs
, pkgs
, ...
}:
{
imports = [
./configuration
];
nixpkgs = {
config = {
allowUnfree = true;
};
};
home = {
username = "kurisu";
homeDirectory = "/home/kurisu";
# !!! DO NOT TOUCH !!!
stateVersion = "26.05";
};
# Enable essential programs.
programs.home-manager.enable = true;
# Nicely reload user system units when changed.
systemd.user.startServices = "sd-switch";
}

View file

@ -0,0 +1,35 @@
users:
admin:
password_hash: ENC[AES256_GCM,data:xrlPAn4BIbijmhhytipFv+ok/sS5NCn9k+eoSsMXOSRqxwRJCtsv/+DCWg8jd7N3YpgarmDBxcr9LN51KnP+FmzRbmlYt4MDeG1ttvos/W+TEgj+v1bZOOjMoyBj5r1VRdWabbG3g3lTTQ==,iv:Ue8w4NgYgJvpeyEVvmPJODCW30VutJDYe7cSIWchVkc=,tag:3sQX2I+N9BmaxHEK4bMttA==,type:str]
kurisu:
password_hash: ENC[AES256_GCM,data:CeKLgF+zFhoHa6bjzweFbLeElgVGMzPaqxV08ggppHADaDf5cyZ0hg/hattQBppVPYKti907EJMmPewVmo4OfGa0E1gyN9JVAUTaKyG3eNqlij4SpUSx7rIm1JRuWz16QSdRQ/5U5ZFFXw==,iv:Ct6C2MnGg3P6VLv8GIeTDHwq0okdgK1Q/14znEpTqcw=,tag:+ldoe5MiGjcrha052NtkRQ==,type:str]
forgejo:
admin:
dokkae.cat:
password: ENC[AES256_GCM,data:FBmMqD+zROFZ4A==,iv:uh1t3+fMylalXqIQGwzRQoZwoT6kP0xRmkrs3ygVqeA=,tag:tXMNEFcWbPW/kaADN1urow==,type:str]
mailer:
password: ENC[AES256_GCM,data:HoxA9HNIMf0rnltDJrOynvoKzQ==,iv:/9YlRJI2WMjtuyLJJFJInxDpngdiQ1g+L9cel+tISy0=,tag:R3nRPmu23G0zOPEZQkUSug==,type:str]
sops:
age:
- recipient: age1pj86dmk8j5tne0r7zu09v3x40xjdae6mhvrzyw5squ9px96z9p0suj89f8
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0d1IvelNVbUhoUGY4TVRH
Q01zN0thbi9Jc2lZei9NcW5ZcUNTNkxJdVRFCkVscGNUWjVuT1dsMFFBSVRHZGI3
VXZNdUtXaDVVQ0VJUGRlR21tbjZ4K28KLS0tIHhEK2lQRmJud2hDTENUeHpvb29H
ZlJjZkJnbXRBc0JkS3pidG13K1BPS1UKHTUkEfwNtDf+c2UVcp1SInS2e7frvFXd
o4aqAAD8w1/xdjDneus9OmMruwKUbh5bE3Oh0fZGHySVshkLpPhrJg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1w3n63wg0pkjy300hsaw6uvd6ell7hpkfpd7knjsp637u2dcjx3nql654fm
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjRXo0dEphcDVxVU9tUnov
TlRJZTVaZi9iZmVneE92WDZ5WlRHRGhCSWg0CjZES0duazdUOVJrcEFzWCt0UjVt
TEZNNkJEb0VKamFlUkVXWEl5Y01BeDAKLS0tIHMyT28vT09DRVFPdVhzQ0dJL0Rk
MTJWN0R6VUR6c21iVE1tK0VPL2NoYzAKrGwbTolQpUWcFRyJ6M1KVQ3odS4leYvW
KZZUx9n9O6j9LH2tHH6ut1maiDXfLkBTnEeXrogp+oK075QVKXfUBA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-01-10T19:58:26Z"
mac: ENC[AES256_GCM,data:N/eVKWgRdTCHxcTkeKpBUxiVF7OKRdUtpBj+dM2c5uclKxwSHB5jw/GuZjcrq8BQvTjgwZxnH6Q7D05c+tFOl+P1m/LrnZLtIxH/iynqMavFwXsBXFF+1ngY+CwLflsagtiNhKp/JxvIKRSaSlNTxGL7NqX6feeTNQirA0CFs0M=,iv:z0MpIYnONpEIfu90takM398GapmkuuGZGC0y3kFjZP0=,tag:/gz+ngidM0fJPCI7b7ABDw==,type:str]
unencrypted_suffix: _unencrypted
version: 3.11.0

View file

@ -0,0 +1,27 @@
{ outputs
, ...
}:
let
modules = outputs.nixosModules;
in
{
imports = [
modules.shells
./sops.nix
./forgejo.nix
./gc.nix
./postgres.nix
./ssh.nix
./traefik.nix
./users.nix
];
custom = {
shells.fish = {
enable = true;
defaultFor = [ "root" "kurisu" ];
};
};
}

View file

@ -0,0 +1,85 @@
{ config
, lib
, pkgs
, ...
}:
{
networking.firewall.allowedTCPPorts = [ 22 ];
services.traefik.dynamicConfigOptions.http = {
routers.forgejo = {
rule = "Host(`git.dokkae.duckdns.org`)";
service = "forgejo";
entryPoints = [ "websecure" ];
tls = { certResolver = "letsencrypt"; };
};
services.forgejo = {
loadBalancer.servers = [
{ url = "http://localhost:3003"; }
];
};
};
services.forgejo = {
enable = true;
database = {
type = "postgres";
host = "/run/postgresql";
name = "forgejo";
user = "forgejo";
};
lfs.enable = false;
settings = {
server = {
DOMAIN = "localhost";
PROTOCOL = "http";
HTTP_PORT = 3003;
# Used for web-displayed URL references.
ROOT_URL = "https://git.dokkae.duckdns.org/";
# SSH Settings
SSH_DOMAIN = "git.dokkae.duckdns.org";
SSH_PORT = 22;
START_SSH_SERVER = false;
};
services = {
# Can be temporarily disabled to allow registration of an admin user.
# Admin account can manually create new users via web interface.
DISABLE_REGISTRATION = true;
};
actions = {
ENABLED = true;
DEFAULT_ACTIONS_URL = "github";
};
# Optional email server configuration.
# Test mails can be sent via: Profile Picture > Site Administration > Configuration > Mailer Configuration
mailer = {
ENABLED = true;
SMTP_ADDR = "smtp.gmail.com";
FROM = "noreply@git.dokkae.duckdns.org";
USER = "finnliry@gmail.com";
};
};
secrets = {
mailer.PASSWD = config.sops.secrets."forgejo/mailer/password".path;
};
};
systemd.services.forgejo.preStart = let
adminCmd = "${lib.getExe config.services.forgejo.package} admin user";
pwdPath = config.sops.secrets."forgejo/admin/dokkae.cat/password".path;
user = "dokkae.cat";
in ''
PASSWORD="$(cat "${pwdPath}" | tr -d '\n')"
${adminCmd} create --admin --email "finnliry@gmail.com" --username ${user} --password "$PASSWORD" || true
'';
}

View file

@ -0,0 +1,13 @@
{ ...
}:
{
nix.gc = {
# Enable automatic garbage collection
automatic = true;
# Run daily at 03:00 AM
dates = "03:00";
# Keep only the latest generations (safety net for rollbacks)
options = "--delete-older-than 7d";
};
}

View file

@ -0,0 +1,31 @@
{ pkgs
, ...
}:
{
services.postgresql = {
enable = true;
package = pkgs.postgresql_18;
ensureDatabases = [
"forgejo"
];
ensureUsers = [
{ name = "forgejo"; ensureDBOwnership = true; }
];
authentication = ''
# Socket connections
local forgejo forgejo peer
# Localhost connections
host forgejo forgejo 127.0.0.1/32 trust
host forgejo forgejo ::1/128 trust
# Deny everything else
host all all 0.0.0.0/0 reject
host all all ::0/0 reject
'';
};
}

View file

@ -0,0 +1,41 @@
{ inputs
, ...
}:
{
imports = [
inputs.sops-nix.nixosModules.sops
];
sops = {
defaultSopsFile = ../../secrets/default.yaml;
defaultSopsFormat = "yaml";
gnupg.sshKeyPaths = [ ];
age.sshKeyPaths = [
"/persist/etc/ssh/ssh_host_ed25519_key"
];
secrets = {
"users/admin/password_hash" = {
owner = "admin";
neededForUsers = true;
};
"users/kurisu/password_hash" = {
owner = "kurisu";
neededForUsers = true;
};
"forgejo/admin/dokkae.cat/password" = {
owner = "forgejo";
group = "forgejo";
mode = "400";
};
"forgejo/mailer/password" = {
owner = "forgejo";
group = "forgejo";
mode = "400";
};
};
};
}

View file

@ -0,0 +1,13 @@
{ ...
}:
{
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "prohibit-password";
PasswordAuthentication = false;
};
};
}

View file

@ -0,0 +1,39 @@
{ ...
}:
{
networking.firewall.allowedTCPPorts = [ 80 443 ];
services.traefik = {
enable = true;
dataDir = "/var/lib/traefik";
staticConfigOptions = {
global = {
checkNewVersion = false;
sendAnonymousUsage = false;
};
entryPoints = {
web = {
address = ":80";
http.redirections.entrypoint = {
to = "websecure";
scheme = "https";
};
};
websecure.address = ":443";
};
certificatesResolvers = {
letsencrypt = {
acme = {
email = "finnliry+acme-cl-00-00@gmail.com";
storage = "/var/lib/traefik/acme.json";
httpChallenge = { entryPoint = "web"; };
};
};
};
};
};
}

View file

@ -0,0 +1,38 @@
{ config
, ...
}:
{
users = {
mutableUsers = false;
users = {
root = {
# Disables password based authentication
hashedPassword = "!";
};
admin = {
isNormalUser = true;
extraGroups = [ "wheel" ];
hashedPasswordFile = config.sops.secrets."users/admin/password_hash".path;
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMZa7mIXvsHouMb3I9gq2uQjNZKsMV43bpWc7yX/RH/X finnliry@gmail.com"
];
};
kurisu = {
isNormalUser = true;
extraGroups = [ "wheel" ];
hashedPasswordFile = config.sops.secrets."users/kurisu/password_hash".path;
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMZa7mIXvsHouMb3I9gq2uQjNZKsMV43bpWc7yX/RH/X finnliry@gmail.com"
];
};
};
};
}

View file

@ -0,0 +1,124 @@
{ inputs
, lib
, ...
}:
{
imports = [
inputs.disko.nixosModules.disko
];
# !!! DANGER !!!
# You have to carefully configure your partitions here.
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/roots.old
timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/root)" "+%Y-%m-%-d_%H:%M:%S")
mv /btrfs_tmp/root "/btrfs_tmp/roots.old/$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/roots.old/ -maxdepth 1 -mtime +7); do
delete_subvolume_recursively "$i"
done
btrfs subvolume create /btrfs_tmp/root
umount /btrfs_tmp
'';
disko.devices = {
disk = {
main = {
type = "disk";
device = "/dev/sda";
content = {
type = "gpt";
partitions = {
boot = {
name = "boot";
size = "1M";
type = "EF02";
priority = 1;
};
esp = {
name = "ESP";
end = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
root = {
size = "100%";
content = {
type = "btrfs";
extraArgs = [ "-L" "nixos" "-f" ]; # Override existing partition
# Subvolumes must set a mountpoint in order to be mounted,
# unless their parent is mounted
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" ];
};
"/var-lib" = {
mountpoint = "/var/lib";
mountOptions = [ "subvol=var-lib" "compress=zstd" "noatime" ];
};
"/var-log" = {
mountpoint = "/var/log";
mountOptions = [ "subvol=var-log" "compress=zstd" "noatime" ];
};
"/var-tmp" = {
mountpoint = "/var/tmp";
mountOptions = [ "subvol=var-tmp" "compress=zstd" "noatime" ];
};
"/swap" = {
mountpoint = "/.swap";
swap.swapfile.size = "4G";
};
};
};
};
};
};
};
};
};
fileSystems = {
# /, /nix/, /nix/store, /var, /var/log, /var/lib, /var/lib/nixos, /etc, /usr
# are all automatically mounted marked as needed for boot.
"/boot".neededForBoot = true;
"/persist".neededForBoot = true;
# Possibly not required
"/home".neededForBoot = true;
};
}

View file

@ -0,0 +1,49 @@
{ lib
, modulesPath
, ...
}:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot = {
loader = {
grub = {
enable = true;
efiSupport = true;
efiInstallAsRemovable = true;
};
limine = {
enable = false;
efiSupport = true;
efiInstallAsRemovable = true;
};
};
initrd = {
availableKernelModules = [
"ahci"
"xhci_pci"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
kernelModules = [ ];
};
kernelModules = [ ];
extraModulePackages = [ ];
};
swapDevices = [ ];
networking.useDHCP = lib.mkDefault true;
networking.hostName = "cl-00-00";
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

View file

@ -0,0 +1,24 @@
{ inputs
, ...
}:
{
imports = [
inputs.impermanence.nixosModules.impermanence
];
environment.persistence."/persist" = {
enable = true;
hideMounts = true;
directories = [
"/root/.ssh"
"/etc/nixos"
"/etc/ssh"
];
files = [
"/etc/machine-id"
];
};
}

53
hosts/makise/system/system.nix Executable file
View file

@ -0,0 +1,53 @@
{ inputs
, pkgs
, lib
, ...
}:
{
imports = [
./disk-configuration.nix
./hardware-configuration.nix
./impermanence-configuration.nix
./configuration
];
nixpkgs = {
overlays = [ ];
config = {
allowUnfree = true;
};
};
nix = let
flakeInputs = lib.filterAttrs (_: lib.isType "flake") inputs;
in {
settings = {
# Enable flakes and new 'nix' command
experimental-features = "nix-command flakes";
# Disable global registry
flake-registry = "";
trusted-users = ["root" "@wheel"];
};
# Disable channels in favor of flakes
channel.enable = false;
# Make flake registry and nix path match flake inputs
registry = lib.mapAttrs (_: flake: {inherit flake;}) flakeInputs;
nixPath = lib.mapAttrsToList (n: _: "${n}=flake:${n}") flakeInputs;
};
# Relevant core programs
environment.systemPackages = with pkgs; [
home-manager
nix
];
# !!! DO NOT TOUCH !!!
system.stateVersion = "26.05";
}