commit d29e6e9b5c9ae675bd0a0c28080d41a10c64319d Author: _cry64 Date: Fri Dec 12 10:33:04 2025 +1000 init diff --git a/cerulean/CeruleanOS/cdesktop.nix b/cerulean/CeruleanOS/cdesktop.nix new file mode 100644 index 0000000..00b7439 --- /dev/null +++ b/cerulean/CeruleanOS/cdesktop.nix @@ -0,0 +1,136 @@ +{ + lib, + config, + pkgs, + pkgs-unstable, + ... +} @ args: let + getModule = name: "../modules/homemanager/${name}.nix"; + getModules = map (x: getModule x); +in { + imports = getModules [ + "term/foot" + "editor/vscode" + + "wm/hyprland" + "wm/hyprland/hyprlock" + + "dm/sddm" + "dm/sddm/themes/corners" + + "apps/firefox" + "apps/thunderbird" + "apps/obsidian" + "apps/rider" + "apps/winbox" + "apps/gitkraken" + "apps/thunar" + + "wm/kanshi" + "wm/mako" + ]; + + home = { + pointerCursor = { + gtk.enable = true; + # x11.enable = true # dont enable since im on hyprland + package = pkgs.bibata-cursors; + name = "Bibata-Modern-Ice"; + size = 16; + }; + + packages = with pkgs; [ + # for services.gnome-keyring + ( + if config.cerulean.isGraphical + then seahorse # gui + else null + ) + + fuzzel + ]; + }; + + gtk = { + enable = true; + font.name = "Victor Mono SemiBold 12"; + theme = { + name = "Dracula"; + package = pkgs.dracula-theme; + }; + iconTheme = { + name = "kora"; + package = pkgs.kora-icon-theme; + }; + # TODO: use a variable to mirror this cursor size + # with the `home.pointerCurser.size` + cursorTheme = { + package = pkgs.bibata-cursors; + name = "Bibata-Modern-Ice"; + size = 16; + }; + }; + + qt = { + enable = true; + platformTheme.name = "gtk2"; + style.name = "gtk2"; + }; + + services = { + # Set display manager (login screen) + displayManager = { + # sddm relies on pkgs.libsForQt5.qt5.qtgraphicaleffects + sddm = { + enable = true; + wayland.enable = true; # experimental + theme = "corners"; + }; + defaultSession = + "hyprland" + + ( + if config.programs.hyprland.withUWSM + then "-uwsm" + else null + ); + }; + + # Multimedia Framework + # With backwards compatability for alsa/pulseaudio/jack + pipewire = { + enable = true; + wireplumber.enable = true; + + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + jack.enable = true; + }; + }; + + # ---- ENVIRONMENT ---- + environment = { + sessionVariables = { + # Hint Electron apps to use support Wayland + NIXOS_OZONE_WL = "1"; + }; + }; + + # ---- SYSTEM PACKAGES ---- + environment.systemPackages = with pkgs; [ + # User Environment + swww + helvum + easyeffects + pavucontrol + hyprpicker # colour picking utility + hyprshot # screenshot utility + qbittorrent + signal-desktop # MAKE THIS ONLY FOR THE DESKTOP FOR END USERS, NOT SERVERS + kdePackages.gwenview # image viewer + libreoffice + wl-clipboard # clipboard for wayland + ]; + + security.rtkit.enable = true; # I *think* this is for pipewire +} diff --git a/cerulean/CeruleanOS/csystem.nix b/cerulean/CeruleanOS/csystem.nix new file mode 100644 index 0000000..fc398f8 --- /dev/null +++ b/cerulean/CeruleanOS/csystem.nix @@ -0,0 +1,309 @@ +{ + inputs, + lib, + config, + pkgs, + pkgs-unstable, + homemanager, + cerulean, + ... +} @ args: let + getModule = name: "../modules/nixos/${name}.nix"; + getModules = map (x: getModule x); + + getHostModule = name: "TODO"; +in { + imports = getModules [ + (getHostModule "hardware-configuration") + (import "${homemanager}/nixos") + + "shell/bash" + "shell/bash/bashistrans.nix" + "shell/zsh" + "shell/fish" + + "cli/git" + "cli/bat" + "cli/btop" + "cli/tmux" + "cli/nvim" + + "lang/asm" + "lang/bash" # TODO: (YES THIS IS DIFFERENT TO shell/bash, this provides language support ie pkgs.shellcheck) + "lang/c-family" + "lang/dotnet" + # "lang/go" + # "lang/haskell" + # "lang/java" + # "lang/nim" + "lang/python" + # "lang/rust" + # "lang/sage" + + "editor/helix" + ]; + + nix.settings = { + experimental-features = [ + "nix-command" + "flakes" + ]; + + download-buffer-size = 524288000; # 500 MiB + + # making wheel group members "trusted users" allows + # them to import packages not signed by a trusted key + # (aka super duper easier to remote deploy) + trusted-users = ["root" "@wheel"]; + }; + + nixpkgs = { + overlays = cerulean.lib.importOverlaysNixOS; + + config = if config.cerulean.allowUnfreeWhitelist != [] + then { + allowUnfreePredicate = + pkg: builtins.elem + (lib.getName pkg) + config.cerulean.allowUnfreeWhitelist; + } + else { + allowUnfree = config.cerulean.allowUnfree; + }; + }; + + # colmena deployment configuration + deployment = { + targetHost = config.cerulean.domain ?? config.cerulean.ip; + targetUser = "cerulean"; + targetPort = "22"; + sshOptions = [ + "-A" # forward ssh-agent + ]; + buildOnTarget = false; # build locally then deploy + }; + + + time.timeZone = config.cerulean.timeZone; + i18n.defaultLocale = "en_US.UTF-8"; + + # Enable initrd hook for virtual console customisation + # aka cool colours when booting yay!! + console = { + enable = true; + earlySetup = true; # initrd pre hook + keyMap = "us"; + font = "Lat2-Terminus16"; + # ANSI 24-bit color definitions (theme: dracula) + colors = [ + "21222c" + "ff5555" + "50fa7b" + "f1fa8c" + "bd93f9" + "ff79c6" + "8be9fd" + "f8f8f2" + "6272a4" + "ff6e6e" + "69ff94" + "ffffa5" + "d6acff" + "ff92df" + "a4ffff" + "ffffff" + ]; + }; + + # super duper minimum grub2 config + boot.loader = { + efi = { + canTouchEfiVariables = true; + efiSysMountPoint = "/boot/efi"; + }; + + grub = { + enable = true; + device = "nodev"; + }; + + # GitHub: vinceliuice/grub2-themes + grub2-theme = { + enable = true; + theme = "whitesur"; # stylish, vimix, or whitesur + footer = true; + # TODO: switch my cables to switch default grub display + customResolution = "3840x2160"; + }; + }; + + networking = { + hostName = config.cerulean.hostname; + networkmanager.enable = true; + + firewall = { + enable = true; + allowedTCPPorts = [ + 22 # sshd + 80 # nginx (http) + 443 # nginx (https) + # 5678 # MikroTik WinBox + ]; + }; + }; + + # ------- USERS ------- + security.sudo.wheelNeedsPassword = true; + users = { + defaultUserShell = pkgs.bash; + + users = cerulean.lib.importUsersNixOS; + }; + + home-manager = { + users = cerulean.lib.importUsersHomeManager; + + extraSpecialArgs = { inherit inputs pkgs pkgs-unstable; }; + sharedModules = []; + }; + + # ---- ENVIRONMENT ---- + environment = { + # always install "dev"/"man" derivation outputs + extraOutputsToInstall = ["dev" "man"]; + + systemPackages = with pkgs; [ + # User Environment + bluetui + + # Shell + bash + fish + shellcheck + grc # colorise command outputs + moreutils + + # Systems Programming & Compilation + qemu # Fellice Bellard's Quick Emulator + # GNU Utils + gnumake + # Binaries + binutils + strace + ltrace + perf-tools # ftrace + perf + radare2 + gdb + # ASM + nasm + (callPackage ../packages/x86-manpages {}) + # C Family + gcc + clang + clang-tools + + # Rust + cargo + rustc + # Go + go + # Nim + nim + nimble + # Haskell + ghc + ghcid + haskell-language-server + ormolu + + # Python + python312 # I use 3.12 since it's in a pretty stable state now + python314 # also 3.14 for latest features + poetry + + openvpn + inetutils + + # security tools + nmap + + httpie + curlie + zoxide + doggo + tldr + btop + eza + yazi + lazygit + ripgrep + viddy # modern `watch` command + thefuck + + # TODO: once upgraded past Nix-24.07 this line won't be necessary (I think) + # helix will support nixd by default + # SOURCE: https://github.com/nix-community/nixd/blob/main/nixd/docs/editor-setup.md#Helix + # nixd # lsp for nix # DEBUG + + # Pretty necessary + nix-prefetch-git + brightnessctl + acpi + powertop + imagemagick + + # "Standard" Unix Commands + vim + file + wget + tree + pstree + unzip + unrar-free + lz4 + man-pages + man-pages-posix + + # Cryptography + gnupg + openssl + libargon2 + ]; + }; + + programs = { + nix-ld.enable = true; + }; + + documentation = { + enable = true; + doc.enable = true; # install /share/doc packages + man.enable = true; # install manpages + info.enable = true; # install GNU info + dev.enable = true; # install docs intended for developers + nixos = { + enable = true; # install NixOS documentation (ie man -k nix, & nixos-help) + options.splitBuild = true; + # includeAllModules = true; + }; + }; + + virtualisation.docker.enable = true; + + + hardware = { + graphics = { + enable = true; + enable32Bit = true; + }; + + bluetooth = let + btSupported = config.cerulean.bluetoothSupported; + in { + enable = btSupported; + powerOnBoot = btSupported; + }; + }; + + system.stateVersion = config.cerulean.stateVersion; # DO NOT MODIFY +} diff --git a/cerulean/CeruleanOS/cuser.nix b/cerulean/CeruleanOS/cuser.nix new file mode 100644 index 0000000..8b26c9f --- /dev/null +++ b/cerulean/CeruleanOS/cuser.nix @@ -0,0 +1,89 @@ +{ + lib, + config, + pkgs, + pkgs-unstable, + ... +} @ args: let + getModule = name: "../modules/homemanager/${name}.nix"; + getModules = map (x: getModule x); +in { + imports = getModules [ + "shell/fish" + + "cli/git" + "cli/bat" + "cli/btop" + "cli/tmux" + + "editor/helix" + ]; + + nixpkgs.config.allowUnfreePredicate = pkg: + builtins.elem (lib.GetName pkg) [ + "vscode-extension-ms-dotnettools-csharp" + ]; + + home = { + stateVersion = config.cerulean.stateVersion; # DO NOT MODIFY + + username = config.cerulean.username; + homeDirectory = "/home/${config.cerulean.username}"; + + shellAliases = { + rg = "batgrep"; # bat + ripgrep + man = "batman"; # bat + man + }; + + sessionVariables = { + NIX_SHELL_PRESERVE_PROMPT = 1; + }; + + packages = with pkgs; [ + # for services.gnome-keyring + gcr # provides org.gnome.keyring.SystemPrompter + speedtest-cli + ]; + }; + + programs = { + home-manager.enable = true; + + zsh = { + enable = true; + enableCompletion = true; + autosuggestion.enable = true; + syntaxHighlighting.enable = true; + + history = { + size = 10000; + ignoreAllDups = true; + path = "$HOME/.zsh_history"; + ignorePatterns = [ + "rm *" + ]; + }; + }; + + # set ssh profiles + # NOTE: (IMPORTANT) this DOES NOT start the ssh-agent + # for that you need to use `services.ssh-agent.enable` + ssh = { + enable = true; + forwardAgent = false; + addKeysToAgent = "no"; + }; + }; + + services = { + # enable OpenSSH private key agent + ssh-agent.enable = true; + + gnome-keyring.enable = true; + }; + + # the ssh-agent won't set this for itself... + systemd.user.sessionVariables.SSH_AUTH_SOCK = "$XDG_RUNTIME_DIR/ssh-agent"; + # Nicely reload system units when changing configs + systemd.user.startServices = "sd-switch"; +} diff --git a/notes.md b/notes.md new file mode 100644 index 0000000..9bc45e1 --- /dev/null +++ b/notes.md @@ -0,0 +1,285 @@ +use `rg -F 'Command::new'` within `~/sandbox/clones/colmena/` + +use `hx $(realpath $(which nixos-rebuild))` to access the bash script + +>[!NOTE] +> The option `--extra-experimental-features "flakes"` is only set +> if `expression.requires_flakes()` where `expression: NixExpression`. + +>[!TODO] +> Also search for nix-store by itself, nix-instantiate, etc. +> And also search for `make_privileged_command(...)` usages. +> or actually maybe `.stdin(...)` or `Stdio::piped(...)`. + + +## `Command::new()` Calls Translated +```rs +command/repl.rs: let mut repl_cmd = Command::new("nix"); +/* +nix repl \ + --experimental-features "nix-command flakes" \ + --file $REPL_EXPRESSION_FILE + */ + +nix/key.rs: let output = Command::new(pathname) +/* +$PATHNAME $ARGS < /dev/null |& ... + */ + +nix/info.rs: let version_cmd = Command::new("nix-instantiate") +/* +# `NixCheck::detect(...)` +# NOTE: Used to detect if Nix is present (and if so, what version) +# NOTE: The version number is used to detect if flakes are supported (NOT enabled though) +# NOTE: You can do the same with nix3 with `nix --version` +nix-instantiate --version + */ + +nix/info.rs: let flake_cmd = Command::new("nix-instantiate") +/* +# `NixCheck::detect(...)` +# NOTE: Used to detect if flakes are enabled +nix-instantiate \ + --eval -E builtins.getFlake \ + &> /dev/null + */ + +nix/flake.rs: let child = Command::new("nix") +/* +# `FlakeMetadata::resolve(flake: &str) -> ColmenaREsult` +nix flake metadata \ + --json \ + --extra-experimental-features "nix-command flakes" + */ + +nix/flake.rs: let status = Command::new("nix") +/* +# `lock_flake_quiet(uri: &str) -> ColmenaResult<()>` +# NOTE: "Quietly locks the dependencies of a flake." +nix flake lock \ + --extra-experimental-features "nix-command flakes" + */ + +nix/profile.rs: let mut command = Command::new("nix-store"); +/* +# `Profile::create_gc_root(&self, path: &Path) -> ColmenaResult<()>` +# NOTE: "Create a GC root for this profile." +# Each Profile struct contains a StorePath object +nix-store \ + --no-build-output \ + --indirect \ + --add-root \ + --realise $STORE_PATH \ + 1>/dev/null + */ + +nix/hive/mod.rs: let mut command = Command::new("nix-instantiate"); +/* +# `NixInstantiate::instantiate(&self) -> Command` +# NOTE: "Instantiation is not supported with DirectFlakeEval" +# NOTE: $EXPRESSION == `self.hive.get_base_expression() + self.expression` +# NOTE: --extra-experimental-features "flakes" only if `self.hive.is_flake()` +nix-instantiate -E $EXPRESSION \ + --no-gc-warning \ + --extra-experimental-features "flakes" + */ + +nix/hive/mod.rs: let mut command = Command::new("nix"); +/* +# `NixInstantiate::eval(self) -> Command` +# NOTE: $FLAGS == `self.hive.nix_flags()` + +# XXX: WARNING: if `self.hive.evaluation_method` is `EvaluationMethod::NixInstantiate` +# XXX: WARNING: then `NixInstantiate::instantiate(...)` (previous) is called +$NIX_INSTANTIATE_COMMAND + --eval + --json + --strict + --read-write-mode # ensures the derivations are instantiated, required for system profile evaluation and IFD + $FLAGS + +# XXX: WARNING: else if `self.hive.evaluation_method` is `EvaluationMethod::DirectFlakeEval` +# XXX: WARNING: then `NixInstantiate::instantiate(...)` (previous) is called +nix eval ${FLAKE_URI}#colmenaHive $FULL_EXPRESSION $FLAGS \ + --json \ + --apply \ + --extra-experimental-features "nix-command flakes" + */ + +nix/evaluator/nix_eval_jobs.rs: let mut command = Command::new(&self.executable); +/* +# `NixEvalJobs::evaluate(&self, expression: &dyn NixExpression, flags: NixFlags) -> ColmenaREsult>>>` +# NOTE: $EXECUTABLE defaults to EXECUTABLE='nix-eval-jobs' +$EXECUTABLE $FLAGS \ + --workers $WORKERS \ + --expr $EXPRESSION \ + --extra-experimental-features "flakes" \ + 2>&1 + */ + +nix/host/local.rs: let mut command = self.make_privileged_command(&["sh", "-c", &key_script]); +/* +# `Local::upload_key(&mut self, name: &str, key: &Key, require_ownership: bool) -> ColmenaResult<()>` +# XXX: NOTE: Same as `Ssh::upload_key()` +sh -c "$KEY_SCRIPT" + */ + + +nix/host/local.rs: let mut command = Command::new("nix-store"); +/* +# `Local::realize_remote(...)` +# XXX: NOTE: Same as `Ssh::realize_remote(...)` +nix-store + --no-gc-warning + --realise $DERIVATION_PATH + */ + +nix/host/local.rs: self.make_privileged_command(&["nix-env", "--profile", SYSTEM_PROFILE, "--set", path]) +/* +# `Local::activate(&mut self, profile: &Profile, goal: Goal) -> ColmenaResult<()>` +# XXX: NOTE: Same as `Ssh::activate(...)` + +# NOTE: This command runs if `goal.should_switch_profile()` +nix-env --profile $SYSTEM+PROFILE + --set $PROFILE_PATH + +# NOTE: Separate command (runs regardless of `goal.should_switch_profile()`) +$ACTIVATION_COMMAND*/ + +nix/host/local.rs: let paths = Command::new("readlink") +/* +# `Local::get_current_system_profile(&mut self) -> ColmenaResult` +# XXX: NOTE: Same as `Ssh::get_current_system_profile(...)` +readlink -e $CURRENT_PROFILE + */ + +nix/host/local.rs: let paths = Command::new("sh") +/* +# `Local::get_main_system_profile(&mut self) -> ColmenaResult` +# XXX: NOTE: Same as `Ssh::get_main_system_profile(...)` +sh -c 'readlink -e "$SYSTEM_PROFILE" | readlink -e "$CURRENT_PROFILE"' + */ + +nix/host/local.rs: let mut result = Command::new(full_command[0]); +/* +# `Local::make_privileged_command>(&self, command: &[S]) -> Command` +$COMMAND + */ + +nix/store.rs: let references = Command::new("nix-store") +/* +# `StorePath::references(...)` +nix-store + --query + --references $STORE_PATH + */ + +nix/host/ssh.rs: let mut cmd = Command::new("ssh"); +/* +# `Ssh::ssh(...)` +# $PRIVESC_COMMAND is privilege_escalation_command from Ssh struct +NIX_SSHOPTS="$SSH_OPTIONS" ssh $SSH_OPTIONS -- $PRIVESC_COMMAND $COMMAND + */ + +nix/host/ssh.rs: let mut command = Command::new("nix"); +/* +# `Ssh::nix_copy_closure(...)` - CONDITION: `if self.use_nix3_copy()` +# NOTE: --builders-use-substitutes "needed due to UX bug in ssh-ng://" +# --derivation is only added if the `path.file_extension() == "drv"` +# --to or --from is used depending on `CopyDirection` +# "?compress=true" is added after ${SSH_TARGET} if `options.gzip` is set +# WARNING: COMMAND EXECUTED OVER SSH (`self.ssh(...)`) +NIX_SSHOPTS="$SSH_OPTIONS" nix copy $CLOSURE_PATH + --no-check-sigs + --substitute-on-destination + --builders-use-substitutes + --derivation + [--to|--from] "ssh-ng://${SSH_TARGET}?compress=true" + --extra-experimental-features "nix-command" + */ + +nix/host/ssh.rs: let mut command = Command::new("nix-copy-closure"); +/* +# `Ssh::nix_copy_closure(...)` - CONDITION: `else` +# --include-outputs if `options.include_outputs` +# --use-substitues if `options.use_substitutes` +# --gzip if `options.gzip` +# WARNING: COMMAND EXECUTED OVER SSH (`self.ssh(...)`) +NIX_SSHOPTS="$SSH_OPTIONS" nix-copy-closure $SSH_TARGET $CLOSURE_PATH + [--to|--from] + --include-outputs + --use-substitues + --gzip + */ + + +nix/host/ssh.rs: let mut command = self.ssh(&["sh", "-c", &key_script]); +/* +# `Ssh::upload_key(...)` +# XXX: NOTE: Same as `Ssh::upload_key()` +# WARNING: COMMAND EXECUTED OVER SSH (`sel.ssh(...)`) +sh -c "$KEY_SCRIPT" + */ + + +nix/host/ssh.rs: let mut command = self.ssh("nix-store"); +/* +# `Ssh::realize_remote(...)` +# XXX: NOTE: Same as `Local::realize_remote(...)` +# WARNING: COMMAND EXECUTED OVER SSH (`self.ssh(...)`) +nix-store + --realise $DERIVATION + --no-gc-warning + */ + +nix/host/ssh.rs: let set_profile = self.ssh(&["nix-env", "--profile", SYSTEM_PROFILE, "--set", path]); +/* +# `Ssh::activate` - activate (switch to) a specific NixOS profile +# XXX: NOTE: Same as `Local::activate(...)` + +# NOTE: This command runs if `goal.should_switch_profile()` +# WARNING: COMMAND EXECUTED OVER SSH (`self.ssh(...)`) +nix-env --profile $SYSTEM+PROFILE + --set $PROFILE_PATH + +# NOTE: Separate command (runs regardless of `goal.should_switch_profile()`) +# WARNING: COMMAND EXECUTED OVER SSH (`self.ssh(...)`) +$ACTIVATION_COMMAND + */ + +nix/host/ssh.rs: let paths = self.ssh(&["readlink", "-e", CURRENT_PROFILE]) +/* +# `Ssh::get_current_system_profile(&mut self) -> ColmenaResult` +# XXX: NOTE: Same as `Local::get_current_system_profile(...)` +readlink -e $CURRENT_PROFILE + */ + +nix/hosts/ssh.rs: let paths = self.ssh(&["sh", "-c", &command]).capture_output().await?; +/* +# `Ssh::get_main_system_profile(...)` +# NOTE: the command executed is the same as in `/nix/host/local.rs` (except for SSH) +# XXX: NOTE: Same as `Local::get_main_system_profile(...)` +# WARNING: COMMAND EXECUTED OVER SSH (`self.ssh(...)`) +sh -c 'readlink -e "$SYSTEM_PROFILE" | readlink -e "$CURRENT_PROFILE"' + */ + +nix/hosts/ssh.rs: self.run_command(self.ssh(&["reboot"])).await +/* +# `Ssh::initiate_reboot` (`initate_reboot` spelt incorrectly... omg, line 408) +# WARNING: NOTE: `Local` doesn't seem to have an alternative to reboot (why?) +reboot + */ +``` + +#### SSH Options +```bash +# === Defined in /nix/host/ssh.rs Ssh::ssh_options() (line 345) === # + +-o StrictHostKeyChecking=accept-new +-o BatchMode=yes +-T +$EXTRA_SSH_OPTIONS # I assume these are set by the user? +-p $SSH_PORT # if self.port is Some +-F $SSH_CONFIG # if self.ssh_config is Some + +```