From 20dcbdfdc47b099daec0eb4fde2713722a8f2607 Mon Sep 17 00:00:00 2001 From: yukkop Date: Thu, 17 Jul 2025 13:37:33 +0000 Subject: [PATCH] feat: modules --- .gitignore | 1 + flake.lock | 12 +- flake.nix | 382 ++---------------- lib/default.nix | 171 ++++++++ lib/parse-env.nix | 13 + nixos/module/default.nix | 22 + nixos/module/generic/placeholder.nix | 1 + nixos/module/hectic/archetype/base.nix | 37 ++ nixos/module/hectic/archetype/common.nix | 1 + nixos/module/hectic/archetype/dev.nix | 63 +++ .../module/hectic/hardware/hetzner-cloud.nix | 29 ++ .../module/hectic/hardware/lenovo-legion.nix | 37 ++ nixos/system/devvm|manual/default.nix | 19 + nixos/system/devvm|manual/devvm|manual.nix | 89 ++++ overlay/default.nix | 79 ++++ parse-env.nix | 14 - 16 files changed, 593 insertions(+), 377 deletions(-) create mode 100644 lib/default.nix create mode 100644 lib/parse-env.nix create mode 100644 nixos/module/default.nix create mode 100644 nixos/module/generic/placeholder.nix create mode 100644 nixos/module/hectic/archetype/base.nix create mode 100644 nixos/module/hectic/archetype/common.nix create mode 100644 nixos/module/hectic/archetype/dev.nix create mode 100644 nixos/module/hectic/hardware/hetzner-cloud.nix create mode 100644 nixos/module/hectic/hardware/lenovo-legion.nix create mode 100644 nixos/system/devvm|manual/default.nix create mode 100644 nixos/system/devvm|manual/devvm|manual.nix create mode 100644 overlay/default.nix delete mode 100644 parse-env.nix diff --git a/.gitignore b/.gitignore index e571d24..732f8b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .env result +result-man/ rust-toolchain.toml target/ diff --git a/flake.lock b/flake.lock index bb9b8c5..3be354c 100644 --- a/flake.lock +++ b/flake.lock @@ -1,12 +1,12 @@ { "nodes": { - "nixpkgs": { + "nixpkgs-25-05": { "locked": { - "lastModified": 1751211869, - "narHash": "sha256-1Cu92i1KSPbhPCKxoiVG5qnoRiKTgR5CcGSRyLpOd7Y=", + "lastModified": 1752436162, + "narHash": "sha256-Kt1UIPi7kZqkSc5HVj6UY5YLHHEzPBkgpNUByuyxtlw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b43c397f6c213918d6cfe6e3550abfe79b5d1c51", + "rev": "dfcd5b901dbab46c9c6e80b265648481aafb01f8", "type": "github" }, "original": { @@ -18,14 +18,14 @@ }, "root": { "inputs": { - "nixpkgs": "nixpkgs", + "nixpkgs-25-05": "nixpkgs-25-05", "rust-overlay": "rust-overlay" } }, "rust-overlay": { "inputs": { "nixpkgs": [ - "nixpkgs" + "nixpkgs-25-05" ] }, "locked": { diff --git a/flake.nix b/flake.nix index 24f8796..fb13c92 100644 --- a/flake.nix +++ b/flake.nix @@ -1,47 +1,24 @@ { description = "yukkop's nix utilities"; inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05"; + nixpkgs-25-05.url = "github:NixOS/nixpkgs/nixos-25.05"; rust-overlay = { url = "github:oxalica/rust-overlay"; inputs = { - nixpkgs.follows = "nixpkgs"; + nixpkgs.follows = "nixpkgs-25-05"; }; }; }; outputs = { self, - nixpkgs, + nixpkgs-25-05, rust-overlay, - }: let - lib = nixpkgs.lib; - - recursiveUpdate = lib.recursiveUpdate; - - supportedSystems = ["x86_64-linux" "aarch64-linux" "x86_64-darwin"]; - - forSpecSystemsWithPkgs = supportedSystems: pkgOverlays: f: - builtins.foldl' ( - acc: system: let - pkgs = import nixpkgs { - inherit system; - overlays = pkgOverlays; - }; - systemOutputs = f { - system = system; - pkgs = pkgs; - }; - in - recursiveUpdate acc systemOutputs - ) {} - supportedSystems; - - forAllSystemsWithPkgs = pkgOverlays: f: forSpecSystemsWithPkgs supportedSystems pkgOverlays f; - - envErrorMessage = varName: "Error: The ${varName} environment variable is not set."; - - parseEnv = import ./parse-env.nix; + ... + }@inputs: let + flake = ./.; + nixpkgs = nixpkgs-25-05; + self-lib = import ./lib { inherit flake self inputs; }; buildPostgresqlExtension = pkgs: pkgs.callPackage (import (builtins.path { @@ -84,7 +61,7 @@ rev = "6ff3b71e3705e0d4081a51c21ca0379e869ba5fb"; hash = "sha256-wC/2rAsSDO83UITaFhtaf3do3aaOAko4gnKUOzwURc8="; }; - cargo = self.lib.cargoToml src; + cargo = self-lib.cargoToml src; in buildPgrxExtension pkgs { pname = cargo.package.name; @@ -161,22 +138,11 @@ nativeBuildInputs = with pkgs; [pkg-config curl]; }; - dotEnv = builtins.getEnv "DOTENV"; - minorEnvironment = - if dotEnv != "" - then - if builtins.pathExists dotEnv - then parseEnv dotEnv - else throw "${dotEnv} file not exist" - else if builtins.pathExists ./.env - then parseEnv ./.env - else {}; in - forAllSystemsWithPkgs [(import rust-overlay)] ({ + self-lib.forAllSystemsWithPkgs [(import rust-overlay)] ({ system, pkgs, - }: let - in { + }: { packages.${system} = let rust = { nativeBuildInputs = [ @@ -403,96 +369,20 @@ }); }; nixosConfigurations = { - "${system}_manual_test" = nixpkgs.lib.nixosSystem { + "devvm|manual|${system}" = import "./nixos/system/devvm|manual" { inherit flake self inputs; }; + "hemar-test|${system}" = nixpkgs.lib.nixosSystem { inherit system; modules = [ - self.nixosModules."preset.default" - self.nixosModules."hardware.hetzner" - ({modulesPath, pkgs, ...}: { + ({modulesPath, pkgs, lib, ...}: { imports = [ + self.nixosModules.hectic (modulesPath + "/profiles/qemu-guest.nix") ]; - environment.systemPackages = with pkgs; [ - (pkgs.writers.writeMinCBin "minc-hello-world" [""] /*c*/ '' - printf("hello world\n"); - '') - (pkgs.writers.writeMinCBin "minc-env" ["" ""] /*c*/ '' - char *env_name; - if (argc > 1) { - env_name = argv[1]; - } else { - env_name = "HOME"; - } - char *value = getenv(env_name); - if (value) { - printf("%s: %s\n", env_name, value); - } else { - printf("Environment variable %s not found.\n", env_name); - } - '') - (pkgs.writers.writeMinCBin "minc-env-check" ["" ""] /*c*/ '' - char *env_name; - if (argc > 1) { - env_name = argv[1]; - } else { - env_name = "HOME"; - } - - char *value = getenv(env_name); - if (value) { - char buffer[128]; - sprintf(buffer, "echo $%s\n", env_name); - system(buffer); - } else { - printf("Environment variable %s not found.\n", env_name); - } - '') - ]; - - users.users.root.openssh.authorizedKeys.keys = [ - ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrbBG+U07f7OKvOxYIGYCaNvyozzxQF+I9Fb5TYZErK yukkop vm-postgres'' - ]; - - programs.zsh.shellAliases = self.lib.sharedShellAliasesForDevVm; - - virtualisation = { - vmVariant = { - systemd.services.fix-root-perms = { - description = "Fix root directory permissions"; - after = [ "local-fs.target" ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.coreutils}/bin/chmod 755 /"; - }; - }; - virtualisation = { - diskSize = 1024*6; - diskImage = null; - forwardPorts = [ ]; - }; - }; - }; - networking.firewall = { - enable = true; - allowedTCPPorts = [ - 80 - ]; - }; - }) - ]; - pkgs = import nixpkgs {inherit system; overlays = [ self.overlays.default ];}; - }; - "${system}_hemar_test" = nixpkgs.lib.nixosSystem { - inherit system; - modules = [ - self.nixosModules."preset.default" - self.nixosModules."hardware.hetzner" - ({modulesPath, pkgs, ...}: { - imports = [ - (modulesPath + "/profiles/qemu-guest.nix") - ]; + hectic = { + archetype.dev.enable = true; + hardware.hetzner-cloud.enable = true; + }; users.users.root.openssh.authorizedKeys.keys = [ ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrbBG+U07f7OKvOxYIGYCaNvyozzxQF+I9Fb5TYZErK yukkop vm-postgres'' @@ -569,232 +459,10 @@ pkgs = import nixpkgs {inherit system; overlays = [ self.overlays.default ];}; }; }; - }) - // { - nixosModules = { - "preset.default" = { - pkgs, - modulesPath, - ... - }: { - imports = [ - (modulesPath + "/profiles/qemu-guest.nix") - ]; - - services.getty.autologinUser = "root"; - programs.zsh.shellAliases = self.lib.sharedShellAliases; - - programs.zsh.enable = true; - users.defaultUserShell = pkgs.zsh; - - # Enable flakes and new 'nix' command - nix.settings.experimental-features = "nix-command flakes"; - - virtualisation.vmVariant.virtualisation = { - qemu.options = [ - "-nographic" - "-display curses" - "-append console=ttyS0" - "-serial mon:stdio" - "-vga qxl" - ]; - forwardPorts = [ - { - from = "host"; - host.port = 40500; - guest.port = 22; - } - ]; - }; - - services.openssh = { - enable = true; - settings = { - PasswordAuthentication = false; - }; - }; - - networking.firewall = { - enable = true; - allowedTCPPorts = []; - }; - - environment = { - defaultPackages = []; - systemPackages = - (with pkgs; [ - curl - neovim - yq-go - jq - htop-vim - ]) - ++ (with self.packages.${pkgs.system}; [ - prettify-log - nvim-pager - ]); - variables = { - PAGER = with self.packages.${pkgs.system}; "${nvim-pager}/bin/pager"; - }; - }; - - system.stateVersion = "24.11"; - }; - "hardware.hetzner" = { pkgs, ...}: { - boot.loader.grub.device = "/dev/sda"; - boot.initrd.availableKernelModules = [ - "ata_piix" - "uhci_hcd" - "xen_blkfront" - ] ++ (if pkgs.system != "aarch64-linux" then [ "vmw_pvscsi" ] else []); - boot.initrd.kernelModules = ["nvme"]; - fileSystems."/" = { - device = "/dev/sda1"; - fsType = "ext4"; - }; - }; - }; - overlays.default = final: prev: ( - let - hectic-packages = self.packages.${prev.system}; - in { - hectic = hectic-packages; - postgresql_17 = prev.postgresql_17 // {pkgs = prev.postgresql_17.pkgs // { - http = hectic-packages.pg-17-ext-http; - pg_smtp_client = hectic-packages.pg-17-ext-smtp-client; - plhaskell = hectic-packages.pg-17-ext-plhaskell; - plsh = hectic-packages.pg-17-ext-plsh; - hemar = hectic-packages.pg-17-ext-hemar; - };}; - postgresql_16 = prev.postgresql_16 // {pkgs = prev.postgresql_16.pkgs // { - http = hectic-packages.pg-16-ext-http; - pg_smtp_client = hectic-packages.pg-16-ext-smtp-client; - plhaskell = hectic-packages.pg-16-ext-plhaskell; - plsh = hectic-packages.pg-16-ext-plsh; - hemar = hectic-packages.pg-16-ext-hemar; - };}; - postgresql_15 = prev.postgresql_15 // {pkgs = prev.postgresql_15.pkgs // { - http = hectic-packages.pg-15-ext-http; - pg_smtp_client = hectic-packages.pg-15-ext-smtp-client; - plhaskell = hectic-packages.pg-15-ext-plhaskell; - plsh = hectic-packages.pg-15-ext-plsh; - hemar = hectic-packages.pg-15-ext-hemar; - };}; - writers = let - writeC = name: argsOrScript: - if lib.isAttrs argsOrScript && !lib.isDerivation argsOrScript - then - prev.writers.makeBinWriter ( - argsOrScript - // { - compileScript = '' - # Force gcc to treat the input file as C code - ${prev.gcc}/bin/gcc -fsyntax-only -xc $contentPath - if [ $? -ne 0 ]; then - echo "Syntax check failed" - exit 1 - fi - ${prev.gcc}/bin/gcc -xc -o $out $contentPath - ''; - } - ) - name - else - prev.writers.makeBinWriter { - compileScript = '' - # Force gcc to treat the input file as C code - ${prev.gcc}/bin/gcc -fsyntax-only -xc $contentPath - if [ $? -ne 0 ]; then - echo "Syntax check failed" - exit 1 - fi - ${prev.gcc}/bin/gcc -xc -o $out $contentPath - ''; - } - name - argsOrScript; - writeMinC = name: includes: body: - writeC name '' - ${builtins.concatStringsSep "\n" (map (h: "#include " + h) includes)} - - int main(int argc, char *argv[]) { - ${body} - } - ''; - in - prev.writers - // { - writeCBin = name: writeC "/bin/${name}"; - writeC = writeC; - writeMinCBin = name: includes: body: writeMinC "/bin/${name}" includes body; - writeMinC = writeMinC; - }; - } - ); - lib = { - # -- For all systems -- - inherit dotEnv minorEnvironment parseEnv forAllSystemsWithPkgs forSpecSystemsWithPkgs; - - shellModules.logs = '' - RED='\033[0;31m' - GREEN='\033[0;32m' - YELLOW='\033[1;33m' - BLUE='\033[0;34m' - PURPLE='\033[0;35m' - MAGENTA="$PURPLE" - CYAN='\033[0;36m' - WHITE='\033[1;37m' - NC='\033[0m' # No Color - - LOG_PATH="/var/log/hectic/activation.log" - - mkdir -p "$(dirname "$LOG_PATH")" - - log_info() { text=$1; shift; printf "%b ''${text}%b\n" "$BLUE" "$@" "$NC" | tee -a "$LOG_PATH" >&2; } - log_success() { text=$1; shift; printf "%b ''${text}%b\n" "$GREEN" "$@" "$NC" | tee -a "$LOG_PATH" >&2; } - log_warning() { text=$1; shift; printf "%b ''${text}%b\n" "$YELLOW" "$@" "$NC" | tee -a "$LOG_PATH" >&2; } - log_error() { text=$1; shift; printf "%b ''${text}%b\n" "$RED" "$@" "$NC" | tee -a "$LOG_PATH" >&2; } - log_step() { text=$1; shift; printf "%b ''${text}%b\n" "$PURPLE" "$@" "$NC" | tee -a "$LOG_PATH" >&2; } - - log_header() { printf "\n%b=== %s ===%b\n" "$WHITE" "$@" "$NC" | tee -a "$LOG_PATH" >&2; } - ''; - - sharedShellAliases = { - jc = ''journalctl''; - sc = ''journalctl''; - nv = ''nvim''; - }; - - sharedShellAliasesForDevVm = self.lib.sharedShellAliases // { - sd = "shutdown now"; - }; - - readEnvironment = { envVarsToRead, prefix ? "" }: - builtins.listToAttrs - (map (name: { - inherit name; - value = self.lib.getEnv "${prefix}${name}"; - }) - envVarsToRead); - - # -- Env processing -- - getEnv = varName: let - var = builtins.getEnv varName; - in - if var != "" - then var - else if minorEnvironment ? varName - then minorEnvironment."${varName}" - else throw (envErrorMessage varName); - - # -- Cargo.toml -- - cargoToml = src: (builtins.fromTOML (builtins.readFile "${src}/Cargo.toml")); - - ssh.keys = { - hetzner-test = { - yukkop = ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ8scy1tv6zfXX6xyaukhO/fsZwif5rC89DvXNc6XxOf''; - }; - }; - }; - }; + }) // + { + lib = self-lib; + overlays.default = import ./overlay { inherit flake self inputs nixpkgs; }; + nixosModules = import ./nixos/module { inherit flake self inputs nixpkgs; }; + }; } diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 0000000..791cdea --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,171 @@ +{ flake, inputs, self }: let + nixpkgs = inputs.nixpkgs-25-05; + lib = nixpkgs.lib; + recursiveUpdate = nixpkgs.lib.recursiveUpdate; + + envErrorMessage = varName: "Error: The ${varName} environment variable is not set."; + + commonSystems = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + + forSpecSystemsWithPkgs = supportedSystems: pkgOverlays: f: + builtins.foldl' ( + acc: system: let + pkgs = import nixpkgs { + inherit system; + overlays = pkgOverlays; + }; + systemOutputs = f { + system = system; + pkgs = pkgs; + }; + in + recursiveUpdate acc systemOutputs + ) {} + supportedSystems; + + forAllSystemsWithPkgs = pkgOverlays: f: forSpecSystemsWithPkgs commonSystems pkgOverlays f; + + parseEnv = import ./parse-env.nix; + + dotEnv = builtins.getEnv "DOTENV"; + minorEnvironment = + if dotEnv != "" + then + if builtins.pathExists dotEnv + then parseEnv dotEnv + else throw "${dotEnv} file not exist" + else if builtins.pathExists ./.env + then parseEnv ./.env + else {}; +in { + # -- For all systems -- + inherit dotEnv minorEnvironment parseEnv forAllSystemsWithPkgs forSpecSystemsWithPkgs commonSystems; + + shellModules.logs = '' + RED='\033[0;31m' + GREEN='\033[0;32m' + YELLOW='\033[1;33m' + BLUE='\033[0;34m' + PURPLE='\033[0;35m' + MAGENTA="$PURPLE" + CYAN='\033[0;36m' + WHITE='\033[1;37m' + NC='\033[0m' # No Color + + LOG_PATH="/var/log/hectic/activation.log" + + mkdir -p "$(dirname "$LOG_PATH")" + + log_info() { text=$1; shift; printf "%b ''${text}%b\n" "$BLUE" "$@" "$NC" | tee -a "$LOG_PATH" >&2; } + log_success() { text=$1; shift; printf "%b ''${text}%b\n" "$GREEN" "$@" "$NC" | tee -a "$LOG_PATH" >&2; } + log_warning() { text=$1; shift; printf "%b ''${text}%b\n" "$YELLOW" "$@" "$NC" | tee -a "$LOG_PATH" >&2; } + log_error() { text=$1; shift; printf "%b ''${text}%b\n" "$RED" "$@" "$NC" | tee -a "$LOG_PATH" >&2; } + log_step() { text=$1; shift; printf "%b ''${text}%b\n" "$PURPLE" "$@" "$NC" | tee -a "$LOG_PATH" >&2; } + + log_header() { printf "\n%b=== %s ===%b\n" "$WHITE" "$@" "$NC" | tee -a "$LOG_PATH" >&2; } + ''; + + sharedShellAliases = { + jc = ''journalctl''; + sc = ''journalctl''; + nv = ''nvim''; + }; + + sharedShellAliasesForDevVm = self.lib.sharedShellAliases // { + sd = "shutdown now"; + }; + + readEnvironment = { envVarsToRead, prefix ? "" }: + builtins.listToAttrs + (map (name: { + inherit name; + value = self.lib.getEnv "${prefix}${name}"; + }) + envVarsToRead); + + # -- Env processing -- + getEnv = varName: let + var = builtins.getEnv varName; + in + if var != "" + then var + else if minorEnvironment ? varName + then minorEnvironment."${varName}" + else throw (envErrorMessage varName); + + # -- Cargo.toml -- + cargoToml = src: (builtins.fromTOML (builtins.readFile "${src}/Cargo.toml")); + + ssh.keys = { + hetzner-test = { + yukkop = ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ8scy1tv6zfXX6xyaukhO/fsZwif5rC89DvXNc6XxOf''; + }; + }; + + readPackages = callPackage: path: extraArgs: + with lib; + with builtins; + pipe path [ + readDir + (filterAttrs (_: type: type == "directory")) + (filterAttrs (name: _: pathExists "${path}/${name}/default.nix")) + (mapAttrs (name: _: callPackage "${path}/${name}" extraArgs)) + ]; + + # Like readModulesRecursive, but reads module structure as a one-level keys, + # so that it is suited for `nix flake show` + # ```nix + # { + # "foo.bar" = import ./module/foo/bar.nix + # } + # ``` + readModulesRecursive' = path: extraArgs: + with lib; + with builtins; let + paths = pipe "${path}" [ + (filesystem.listFilesRecursive) + (filter (hasSuffix ".nix")) + ]; + pathToName = flip pipe [ + (removePrefix "${path}/") + (replaceStrings ["/" ".nix"] ["." ""]) + (removeSuffix ".nix") + ]; + attrList = + map (path': { + name = pathToName (unsafeDiscardStringContext path'); + value = import path' extraArgs; + }) + paths; + in + listToAttrs attrList; +} // rec { + /* Supplied a directory, reads it's recursive structure into NixOS modules, so + that provided a `./module` dir with `module/foo/bar.nix` in it it outputs + ```nix + { + foo.bar = import ./module/foo/bar.nix + } + ``` + */ + readModulesRecursive = path: + lib.mapAttrs' ( + name: value: let + name' = builtins.replaceStrings [".nix"] [""] name; + in + if value == "regular" + then { + name = name'; + value = import "${path}/${name}"; + } + else { + inherit name; + value = readModulesRecursive "${path}/${name}"; + } + ) (builtins.readDir path); +} diff --git a/lib/parse-env.nix b/lib/parse-env.nix new file mode 100644 index 0000000..ffa6e82 --- /dev/null +++ b/lib/parse-env.nix @@ -0,0 +1,13 @@ + file: let + envText = builtins.readFile file; + envLines = builtins.split "\n" envText; + lines = builtins.filter (line: (builtins.match "^.*=.*" line) != null) envLines; + #attributes = builtins.listToAttrs (builtins.map (line: let + # parts = builtins.split "=" line; + # key = builtins.substring 0 (builtins.stringLength parts[0] - 3) parts[0]; # Remove "var" prefix + # value = parts[1]; + #in { + # name = key; + # value = value; + #}) lines); + in { inherit envLines lines; } diff --git a/nixos/module/default.nix b/nixos/module/default.nix new file mode 100644 index 0000000..8b4d4aa --- /dev/null +++ b/nixos/module/default.nix @@ -0,0 +1,22 @@ +{ + flake, + self, + inputs, + nixpkgs, +}: +with builtins; +with nixpkgs.lib; +with self.lib; +let + # Combine hectic modules into one + hectic.imports = attrValues ( + readModulesRecursive' ./hectic { inherit flake self inputs; } + ); + # Read generic modules seperately + generic = readModulesRecursive' + ./generic + { inherit flake self inputs; }; +in generic // { + inherit hectic; + default = hectic; +} diff --git a/nixos/module/generic/placeholder.nix b/nixos/module/generic/placeholder.nix new file mode 100644 index 0000000..c157af7 --- /dev/null +++ b/nixos/module/generic/placeholder.nix @@ -0,0 +1 @@ +{ ... }: {} diff --git a/nixos/module/hectic/archetype/base.nix b/nixos/module/hectic/archetype/base.nix new file mode 100644 index 0000000..33ddf74 --- /dev/null +++ b/nixos/module/hectic/archetype/base.nix @@ -0,0 +1,37 @@ +{ + inputs, + flake, + self, +}: { + pkgs, + lib, + config, + ... +}: let + cfg = config.hectic.archetype.base; +in { + options.hectic.archetype.base.enable = lib.mkEnableOption "Enable archetupe.dev"; + + config = lib.mkIf cfg.enable { + programs.zsh.shellAliases = self.lib.sharedShellAliases; + programs.zsh.enable = true; + users.defaultUserShell = pkgs.zsh; + + # Enable flakes and new 'nix' command + nix.settings.experimental-features = "nix-command flakes"; + + networking.firewall.enable = true; + + environment = { + defaultPackages = []; + systemPackages = (with self.packages.${pkgs.system}; [ + nvim-pager + ]); + variables = { + PAGER = with self.packages.${pkgs.system}; "${nvim-pager}/bin/pager"; + }; + }; + + system.stateVersion = "25.05"; + }; +} diff --git a/nixos/module/hectic/archetype/common.nix b/nixos/module/hectic/archetype/common.nix new file mode 100644 index 0000000..c157af7 --- /dev/null +++ b/nixos/module/hectic/archetype/common.nix @@ -0,0 +1 @@ +{ ... }: {} diff --git a/nixos/module/hectic/archetype/dev.nix b/nixos/module/hectic/archetype/dev.nix new file mode 100644 index 0000000..253da9f --- /dev/null +++ b/nixos/module/hectic/archetype/dev.nix @@ -0,0 +1,63 @@ +{ + inputs, + flake, + self, +}: { + pkgs, + modulesPath, + lib, + config, + ... +}: let + cfg = config.hectic.archetype.dev; +in { + imports = [ + (modulesPath + "/profiles/qemu-guest.nix") + ]; + + options.hectic.archetype.dev.enable = lib.mkEnableOption "Enable archetupe.dev"; + + config = lib.mkIf cfg.enable { + hectic.archetype.base.enable = true; + + services.getty.autologinUser = "root"; + + virtualisation.vmVariant.virtualisation = { + qemu.options = [ + "-nographic" + "-display curses" + "-append console=ttyS0" + "-serial mon:stdio" + "-vga qxl" + ]; + forwardPorts = [ + { + from = "host"; + host.port = 40500; + guest.port = 22; + } + ]; + }; + + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + }; + }; + + environment = { + systemPackages = + (with pkgs; [ + curl + neovim + yq-go + jq + htop-vim + ]) + ++ (with self.packages.${pkgs.system}; [ + prettify-log + ]); + }; + }; +} diff --git a/nixos/module/hectic/hardware/hetzner-cloud.nix b/nixos/module/hectic/hardware/hetzner-cloud.nix new file mode 100644 index 0000000..1802559 --- /dev/null +++ b/nixos/module/hectic/hardware/hetzner-cloud.nix @@ -0,0 +1,29 @@ +{ + inputs, + flake, + self, +}: +{ + pkgs, + lib, + config, + ... +}: let + cfg = config.hectic.hardware.hetzner-cloud; +in { + options.hectic.hardware.hetzner-cloud.enable = lib.mkEnableOption "Enable hetzner-cloud hardware configurations"; + + config = lib.mkIf cfg.enable { + boot.loader.grub.device = "/dev/sda"; + boot.initrd.availableKernelModules = [ + "ata_piix" + "uhci_hcd" + "xen_blkfront" + ] ++ (if pkgs.system != "aarch64-linux" then [ "vmw_pvscsi" ] else []); + boot.initrd.kernelModules = ["nvme"]; + fileSystems."/" = { + device = "/dev/sda1"; + fsType = "ext4"; + }; + }; +} diff --git a/nixos/module/hectic/hardware/lenovo-legion.nix b/nixos/module/hectic/hardware/lenovo-legion.nix new file mode 100644 index 0000000..600e08b --- /dev/null +++ b/nixos/module/hectic/hardware/lenovo-legion.nix @@ -0,0 +1,37 @@ +{ + ... +}: +{ + inputs, + lib, + config, + ... +}: let + cfg = config.hectic.hardware.lenovo-legion; + hasDisko = false; +in { + options.hectic.hardware.lenovo-legion = { + enable = lib.mkEnableOption "Enable lenovo-legion hardware configurations"; + swapSize = lib.mkOption { + type = lib.types.either (lib.types.enum [ "100%" ]) (lib.types.strMatching "[0-9]+[KMGTP]?"); + default = "0"; + description = '' + Size of the partition, in sgdisk format. + sets end automatically with the + prefix + can be 100% for the whole remaining disk, will be done last in that case. + ''; + }; + device = lib.mkOption { + type = lib.types.str; + default = "0"; + description = '' + Size of the partition, in sgdisk format. + sets end automatically with the + prefix + can be 100% for the whole remaining disk, will be done last in that case. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + }; +} diff --git a/nixos/system/devvm|manual/default.nix b/nixos/system/devvm|manual/default.nix new file mode 100644 index 0000000..e3957b6 --- /dev/null +++ b/nixos/system/devvm|manual/default.nix @@ -0,0 +1,19 @@ +{ + flake, + self, + inputs, + system, + ... +}: let + inherit (self.legacyPackages."${system}") pkgs; + + # Use folder name as name of this system + name = builtins.baseNameOf ./.; + +in pkgs.lib.nixosSystem { + inherit pkgs; + modules = [ + { networking.hostName = name; } + (import ./${name}.nix { inherit flake self inputs; }) + ]; +} diff --git a/nixos/system/devvm|manual/devvm|manual.nix b/nixos/system/devvm|manual/devvm|manual.nix new file mode 100644 index 0000000..7b98441 --- /dev/null +++ b/nixos/system/devvm|manual/devvm|manual.nix @@ -0,0 +1,89 @@ +{ + inputs, + flake, + self, +}: { + lib, + pkgs, + modulesPath, + config, +}: +{ + imports = [ + self.nixosModules.hectic + (modulesPath + "/profiles/qemu-guest.nix") + ]; + + hectic = { + archetype.dev.enable = true; + hardware.hetzner-cloud.enable = true; + }; + + environment.systemPackages = with pkgs.writers; [ + (writeMinCBin "minc-hello-world" [""] /*c*/ '' + printf("hello world\n"); + '') + (writeMinCBin "minc-env" ["" ""] /*c*/ '' + char *env_name; + if (argc > 1) { + env_name = argv[1]; + } else { + env_name = "HOME"; + } + char *value = getenv(env_name); + if (value) { + printf("%s: %s\n", env_name, value); + } else { + printf("Environment variable %s not found.\n", env_name); + } + '') + (writeMinCBin "minc-env-check" ["" ""] /*c*/ '' + char *env_name; + if (argc > 1) { + env_name = argv[1]; + } else { + env_name = "HOME"; + } + + char *value = getenv(env_name); + if (value) { + char buffer[128]; + sprintf(buffer, "echo $%s\n", env_name); + system(buffer); + } else { + printf("Environment variable %s not found.\n", env_name); + } + '') + ]; + + users.users.root.openssh.authorizedKeys.keys = [ + ''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrbBG+U07f7OKvOxYIGYCaNvyozzxQF+I9Fb5TYZErK yukkop vm-postgres'' + ]; + + programs.zsh.shellAliases = self.lib.sharedShellAliasesForDevVm; + + virtualisation = { + vmVariant = { + systemd.services.fix-root-perms = { + description = "Fix root directory permissions"; + after = [ "local-fs.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.coreutils}/bin/chmod 755 /"; + }; + }; + virtualisation = { + diskSize = 1024*6; + diskImage = null; + forwardPorts = [ ]; + }; + }; + }; + networking.firewall = { + enable = true; + allowedTCPPorts = [ + 80 + ]; + }; +} diff --git a/overlay/default.nix b/overlay/default.nix new file mode 100644 index 0000000..0fa4f7d --- /dev/null +++ b/overlay/default.nix @@ -0,0 +1,79 @@ +{ inputs, self, nixpkgs, ... }: let + lib = nixpkgs.lib; +in final: prev: ( + let + hectic-packages = self.packages.${prev.system}; + in { + hectic = hectic-packages; + postgresql_17 = prev.postgresql_17 // {pkgs = prev.postgresql_17.pkgs // { + http = hectic-packages.pg-17-ext-http; + pg_smtp_client = hectic-packages.pg-17-ext-smtp-client; + plhaskell = hectic-packages.pg-17-ext-plhaskell; + plsh = hectic-packages.pg-17-ext-plsh; + hemar = hectic-packages.pg-17-ext-hemar; + };}; + postgresql_16 = prev.postgresql_16 // {pkgs = prev.postgresql_16.pkgs // { + http = hectic-packages.pg-16-ext-http; + pg_smtp_client = hectic-packages.pg-16-ext-smtp-client; + plhaskell = hectic-packages.pg-16-ext-plhaskell; + plsh = hectic-packages.pg-16-ext-plsh; + hemar = hectic-packages.pg-16-ext-hemar; + };}; + postgresql_15 = prev.postgresql_15 // {pkgs = prev.postgresql_15.pkgs // { + http = hectic-packages.pg-15-ext-http; + pg_smtp_client = hectic-packages.pg-15-ext-smtp-client; + plhaskell = hectic-packages.pg-15-ext-plhaskell; + plsh = hectic-packages.pg-15-ext-plsh; + hemar = hectic-packages.pg-15-ext-hemar; + };}; + writers = let + writeC = name: argsOrScript: + if lib.isAttrs argsOrScript && !lib.isDerivation argsOrScript + then + prev.writers.makeBinWriter ( + argsOrScript + // { + compileScript = '' + # Force gcc to treat the input file as C code + ${prev.gcc}/bin/gcc -fsyntax-only -xc $contentPath + if [ $? -ne 0 ]; then + echo "Syntax check failed" + exit 1 + fi + ${prev.gcc}/bin/gcc -xc -o $out $contentPath + ''; + } + ) + name + else + prev.writers.makeBinWriter { + compileScript = '' + # Force gcc to treat the input file as C code + ${prev.gcc}/bin/gcc -fsyntax-only -xc $contentPath + if [ $? -ne 0 ]; then + echo "Syntax check failed" + exit 1 + fi + ${prev.gcc}/bin/gcc -xc -o $out $contentPath + ''; + } + name + argsOrScript; + writeMinC = name: includes: body: + writeC name '' + ${builtins.concatStringsSep "\n" (map (h: "#include " + h) includes)} + + int main(int argc, char *argv[]) { + ${body} + } + ''; + in + prev.writers + // { + writeCBin = name: writeC "/bin/${name}"; + writeC = writeC; + writeMinCBin = name: includes: body: writeMinC "/bin/${name}" includes body; + writeMinC = writeMinC; + }; + } +) diff --git a/parse-env.nix b/parse-env.nix deleted file mode 100644 index 5f404a7..0000000 --- a/parse-env.nix +++ /dev/null @@ -1,14 +0,0 @@ -# TODO: allow multiline -file: let - envText = builtins.readFile file; - envLines = builtins.split "\n" envText; - lines = builtins.filter (line: (builtins.match "^.*=.*" line) != null) envLines; - #attributes = builtins.listToAttrs (builtins.map (line: let - # parts = builtins.split "=" line; - # key = builtins.substring 0 (builtins.stringLength parts[0] - 3) parts[0]; # Remove "var" prefix - # value = parts[1]; - #in { - # name = key; - # value = value; - #}) lines); -in {inherit envLines lines;}