#+title: NixOS Configuration #+AUTHOR: Preston Pan #+DESCRIPTION: My NixOS system, written entirely in a literate configuration #+html_head: * Introduction This is my NixOS configuration. It is a part of my monorepo, and this file automatically tangles to all the under the nix/ directory in my monorepo [[https://ret2pop.net/gitweb/monorepo.git][git repository]]. My monorepo also stores my website, as my website stores my [[file:elfeed.org][elfeed]] and [[file:emacs.org][emacs]] configurations. Additionally, I want to track my emacs configuration with my Nix configuration. Having them in one repository means that my emacs configuration is pinned to my flake. Hence, my monorepo serves a dual purpose, as do many of the files within my monorepo. They are often data files used in my configuration (i.e. emacs, elfeed, org-roam, agenda, journal, etc...) and they are webpages as well. This page is one such example of this concept. * Configurables We start with some configurable variables (you can change these if you want to use this configuration yourself): #+begin_src nix :tangle ../nix/flakevars.nix let # I'm ret2pop! What's your name? internetName = "ret2pop"; in { # Name of spontaneity box remoteHost = "${internetName}.net"; # Your internet name internetName = internetName; # Name of your organization orgHost = "nullring.xyz"; # Hostnames of my systems hostnames = [ "affinity" "continuity" "spontaneity" "installer" ]; } #+end_src * Flake.nix The flake is the entry point of the NixOS configuration. Here, I have a list of all the systems that I use with all the modules that they use. My NixOS configuration is heavily modularized, so that adding new configurations that add modifications is made simple. and now for the main flake: #+begin_src nix :tangle ../nix/flake.nix { description = "Emacs centric configurations for a complete networked system"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nur.url = "github:nix-community/NUR"; sops-nix.url = "github:Mic92/sops-nix"; scripts.url = "github:ret2pop/scripts"; wallpapers.url = "github:ret2pop/wallpapers"; sounds.url = "github:ret2pop/sounds"; deep-research.url = "github:ret2pop/ollama-deep-researcher"; impermanence.url = "github:nix-community/impermanence"; nix-topology = { url = "github:oddlama/nix-topology"; inputs.nixpkgs.follows = "nixpkgs"; }; home-manager = { url = "github:nix-community/home-manager/release-25.05"; inputs.nixpkgs.follows = "nixpkgs"; }; disko = { url = "github:nix-community/disko"; inputs.nixpkgs.follows = "nixpkgs"; }; lanzaboote = { url = "github:nix-community/lanzaboote/v0.4.1"; inputs.nixpkgs.follows = "nixpkgs"; }; nixos-dns = { url = "github:Janik-Haag/nixos-dns"; inputs.nixpkgs.follows = "nixpkgs"; }; }; outputs = { self, nixpkgs, home-manager, nur, disko, lanzaboote, sops-nix, nix-topology, nixos-dns, deep-research, impermanence, ... } @attrs: let vars = import ./flakevars.nix; system = "x86_64-linux"; pkgs = import nixpkgs { inherit system; }; generate = nixos-dns.utils.generate nixpkgs.legacyPackages."${system}"; dnsConfig = { inherit (self) nixosConfigurations; extraConfig = import ./dns/default.nix; }; # function that generates all systems from hostnames mkConfigs = map (hostname: {name = "${hostname}"; value = nixpkgs.lib.nixosSystem { inherit system; specialArgs = attrs; modules = if (hostname == "installer") then [ (./. + "/systems/${hostname}/default.nix") { networking.hostName = "${hostname}"; } nix-topology.nixosModules.default ] else [ { environment.systemPackages = with nixpkgs.lib; [ deep-research.packages."${system}".deep-research ]; } impermanence.nixosModules.impermanence nix-topology.nixosModules.default lanzaboote.nixosModules.lanzaboote disko.nixosModules.disko home-manager.nixosModules.home-manager sops-nix.nixosModules.sops nixos-dns.nixosModules.dns { nixpkgs.overlays = [ nur.overlays.default ]; home-manager.extraSpecialArgs = attrs // { systemHostName = "${hostname}"; }; networking.hostName = "${hostname}"; } (./. + "/systems/${hostname}/default.nix") ]; }; }); mkDiskoFiles = map (hostname: { name = "${hostname}"; value = self.nixosConfigurations."${hostname}".config.monorepo.vars.diskoSpec; }); in { nixosConfigurations = builtins.listToAttrs (mkConfigs vars.hostnames); evalDisko = builtins.listToAttrs (mkDiskoFiles (builtins.filter (x: x != "installer") vars.hostnames)); topology."${system}" = import nix-topology { pkgs = import nixpkgs { inherit system; overlays = [ nix-topology.overlays.default ]; }; modules = [ ./topology/default.nix { nixosConfigurations = self.nixosConfigurations; } ]; }; devShell."${system}" = with pkgs; mkShell { buildInputs = [ fira-code python3 poetry statix deadnix ]; }; packages."${system}" = { zoneFiles = generate.zoneFiles dnsConfig; octodns = generate.octodnsConfig { inherit dnsConfig; config = { providers = { cloudflare = { class = "octodns_cloudflare.CloudflareProvider"; token = "env/CLOUDFLARE_TOKEN"; }; config = { check_origin = false; }; }; }; zones = { "${vars.remoteHost}." = nixos-dns.utils.octodns.generateZoneAttrs [ "cloudflare" ]; "${vars.orgHost}." = nixos-dns.utils.octodns.generateZoneAttrs [ "cloudflare" ]; }; }; }; }; } #+end_src Note that the configurations are automatically generated with he mkConfigs function, and the final disko output is automatically generated with mkDiskoFiles. * Sops Configuration In order to use the sops configuration, you must change the age public key to the one that you own: #+begin_src yaml :tangle ../nix/.sops.yaml keys: - &primary age165ul43e8rc0qwzz2f2q9cw02psm2mkudsrwavq2e0pxs280p64yqy2z0dr creation_rules: - path_regex: secrets/secrets.yaml$ key_groups: - age: - *primary #+end_src also note that you will have to write your own secrets.yaml file, with an entry called ~mail~, which is used for the imaps and smtps password. * Nix DNS #+begin_src nix :tangle ../nix/dns/default.nix { defaultTTL = 120; } #+end_src * Nix Topology Nix Topology generates a nice graph of all my hosts. You can view this graph by running ~nix build .#topology.x86_64-linux.config.output~. #+begin_src nix :tangle ../nix/topology/default.nix { config, ... }: let inherit (config.lib.topology); in { nodes = { spontaneity = { interfaces.wan.network = "remote"; }; installer = { interfaces.lan.network = "home"; }; affinity = { interfaces.lan = { network = "home"; physicalConnections = [ { node = "spontaneity"; interface = "wan"; } { node = "installer"; interface = "lan"; } ]; }; }; continuity = { interfaces.lan = { network = "home"; physicalConnections = [ { node = "spontaneity"; interface = "wan"; } { node = "affinity"; interface = "lan"; } ]; }; }; }; networks = { home = { name = "Home Network"; cidrv4 = "192.168.1.1/24"; }; remote = { name = "Remote Network"; cidrv4 = "144.202.27.169/32"; }; }; } #+end_src * Modules ** Vars Variables used for regular configuration in your system ~default.nix~ file. The options are largely self-documenting. #+begin_src nix :tangle ../nix/modules/vars.nix { lib, ... }: let vars = import ../flakevars.nix; in { options.monorepo.vars = { device = lib.mkOption { type = lib.types.str; default = "/dev/sda"; example = "/dev/nvme0n1"; description = "device that NixOS is installed to"; }; internetName = lib.mkOption { type = lib.types.str; default = "${vars.internetName}"; example = "myinternetname"; description = "Internet name to be used for internet usernames"; }; repoName = lib.mkOption { type = lib.types.str; default = "monorepo"; example = "myreponame"; description = "Name of this repository"; }; fileSystem = lib.mkOption { type = lib.types.str; default = "ext4"; example = "btrfs"; description = "filesystem to install with disko"; }; diskoSpec = lib.mkOption { type = lib.types.attrs; description = "retains a copy of the disko spec for reflection"; }; userName = lib.mkOption { type = lib.types.str; default = "preston"; example = "myUser"; description = "system username"; }; fullName = lib.mkOption { type = lib.types.str; default = "Preston Pan"; example = "John Doe"; description = "Full Name"; }; gpgKey = lib.mkOption { type = lib.types.str; default = "AEC273BF75B6F54D81343A1AC1FE6CED393AE6C1"; example = "1234567890ABCDEF..."; description = "GPG key fingerprint"; }; remoteHost = lib.mkOption { type = lib.types.str; default = "${vars.remoteHost}"; example = "example.com"; description = "Address to push to and pull from for website and git repos"; }; orgHost = lib.mkOption { type = lib.types.str; default = "${vars.orgHost}"; example = "orgname.org"; description = "Domain name of your organization"; }; timeZone = lib.mkOption { type = lib.types.str; default = "America/Vancouver"; example = "America/Chicago"; description = "Linux timezone"; }; monitors = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ "HDMI-A-1" "eDP-1" "DP-2" "DP-3" "DP-4" "LVDS-1" ]; example = []; description = "Monitors that waybar will use"; }; }; } #+end_src ** Default Profile Again, these are self documenting variables that you may see used below. These are to be used under ~default.nix~ in the ~systems~ folder. #+begin_src nix :tangle ../nix/modules/default.nix { lib, config, pkgs, ... }: { imports = [ ./configuration.nix ./vars.nix ]; options = { monorepo = { profiles = { cuda.enable = lib.mkEnableOption "Enables CUDA support"; documentation.enable = lib.mkEnableOption "Enables documentation on system."; secureBoot.enable = lib.mkEnableOption "Enables secure boot. See sbctl."; pipewire.enable = lib.mkEnableOption "Enables pipewire low latency audio setup"; tor.enable = lib.mkEnableOption "Enables tor along with torsocks"; home.enable = lib.mkEnableOption "Enables home user"; server.enable = lib.mkEnableOption "Enables server services"; ttyonly.enable = lib.mkEnableOption "TTY only, no xserver"; grub.enable = lib.mkEnableOption "Enables grub instead of systemd-boot"; workstation.enable = lib.mkEnableOption "Enables workstation services"; impermanence.enable = lib.mkEnableOption "Enables imperamanence"; }; }; }; config = { environment.systemPackages = lib.mkIf config.monorepo.profiles.documentation.enable ((with pkgs; [ linux-manual man-pages man-pages-posix iproute2 silver-searcher ripgrep ]) ++ (if (config.monorepo.vars.fileSystem == "btrfs") then with pkgs; [ btrfs-progs btrfs-snap btrfs-list btrfs-heatmap ] else [])); boot.loader.grub = lib.mkIf config.monorepo.profiles.grub.enable { enable = true; }; monorepo = { profiles = { documentation.enable = lib.mkDefault true; pipewire.enable = lib.mkDefault true; tor.enable = lib.mkDefault true; home.enable = lib.mkDefault true; impermanence.enable = lib.mkDefault false; }; }; }; } #+end_src ** X11 My Xorg configuration is used as a backup for when wayland applications don't work. Note that using this configuration is extremely inefficient and my i3 configuration is unoptimized. Still, it is suitable for using Krita. #+begin_src nix :tangle ../nix/modules/xserver.nix { lib, config, pkgs, ... }: { services.xserver = { enable = (! config.monorepo.profiles.ttyonly.enable); displayManager = { startx.enable = (! config.monorepo.profiles.ttyonly.enable); }; windowManager = { i3 = { enable = ! config.monorepo.profiles.ttyonly.enable; package = pkgs.i3-gaps; }; }; desktopManager = { runXdgAutostartIfNone = true; }; xkb = { layout = "us"; variant = ""; options = "caps:escape"; }; videoDrivers = (if config.monorepo.profiles.cuda.enable then [ "nvidia" ] else []); }; } #+end_src You should add your own video drivers in a custom machine configuration. ** Containers In order to run docker/podman containers, I need this file: #+begin_src nix :tangle ../nix/modules/docker.nix { lib, config, vars, ... }: { virtualisation = { oci-containers = { backend = "podman"; containers = {}; }; containers.enable = true; podman = { enable = true; dockerCompat = true; defaultNetwork.settings.dns_enabled = true; }; }; } #+end_src ** Pipewire My low latency pipewire configuration is used for music production, as well as for regular desktop usage. Pipewire is much better than pulseaudio because it supports jack with the same underlying interface and it breaks significantly less often. #+begin_src nix :tangle ../nix/modules/pipewire.nix { lib, config, ... }: { services.pipewire = { enable = lib.mkDefault config.monorepo.profiles.pipewire.enable; alsa = { enable = true; support32Bit = true; }; pulse.enable = true; jack.enable = true; wireplumber.enable = true; extraConfig = { pipewire."92-low-latency" = { "context.properties" = { "default.clock.rate" = 48000; "default.clock.quantum" = 256; "default.clock.min-quantum" = 32; "default.clock.max-quantum" = 512; }; pipewire-pulse."92-low-latency" = { "context.properties" = [ { name = "libpipewire-module-protocol-pulse"; args = { }; } ]; "pulse.properties" = { "pulse.min.req" = "32/48000"; "pulse.default.req" = "32/48000"; "pulse.max.req" = "32/48000"; "pulse.min.quantum" = "32/48000"; "pulse.max.quantum" = "32/48000"; }; "stream.properties" = { "node.latency" = "32/48000"; "resample.quality" = 1; }; }; }; }; }; } #+end_src ** SSH My SSH daemon configuration. #+begin_src nix :tangle ../nix/modules/ssh.nix { config, lib, ... }: { services.openssh = { enable = true; settings = { PasswordAuthentication = lib.mkDefault (! config.monorepo.profiles.server.enable); AllowUsers = [ config.monorepo.vars.userName "root" "git" ]; PermitRootLogin = "prohibit-password"; KbdInteractiveAuthentication = false; }; }; } #+end_src ** Tor This is my tor configuration, used for my cryptocurrency wallets and whatever else I want it to do. #+begin_src nix :tangle ../nix/modules/tor.nix { config, lib, ... }: { services.tor = { enable = lib.mkDefault config.monorepo.profiles.tor.enable; openFirewall = true; client = { enable = lib.mkDefault config.monorepo.profiles.tor.enable; socksListenAddress = { IsolateDestAddr = true; addr = "127.0.0.1"; port = 9050; }; dns.enable = true; }; torsocks = { enable = lib.mkDefault config.monorepo.profiles.tor.enable; server = "127.0.0.1:9050"; }; }; } #+end_src ** Kubo IPFS I use IPFS for my website and also for my ISOs for truly declarative and deterministic configuration. NixOS might be moving to IPFS for binary cache distribution and package distribution soon, and I'm waiting on that. #+begin_src nix :tangle ../nix/modules/kubo.nix { config, pkgs, lib, ... }: { services.kubo = { enable = lib.mkDefault config.monorepo.profiles.workstation.enable; }; } #+end_src ** TODO Murmur #+begin_src nix :tangle ../nix/modules/murmur.nix { lib, config, ... }: { services.murmur = { enable = lib.mkDefault config.monorepo.profiles.server.enable; logFile = "/var/log/murmur.log"; openFirewall = true; hostName = "0.0.0.0"; welcometext = "Wecome to the Null Murmur instance!"; registerName = "nullring"; registerHostname = "${config.monorepo.vars.orgHost}"; sslCert = "/var/lib/acme/${config.monorepo.vars.orgHost}/fullchain.pem"; sslKey = "/var/lib/acme/${config.monorepo.vars.orgHost}/sslKey.pem"; }; } #+end_src ** TODO i2pd I use i2p for some p2p connections. We enable it with the server profile: #+begin_src nix :tangle ../nix/modules/i2pd.nix { config, lib, ... }: { services.i2pd = { enable = lib.mkDefault config.monorepo.profiles.server.enable; address = "0.0.0.0"; inTunnels = { }; outTunnels = { }; }; } #+end_src ** TODO Icecast This is an internet radio which will host a ton of music. #+begin_src nix :tangle ../nix/modules/icecast.nix { lib, config, ... }: { services.icecast = { enable = lib.mkDefault config.monorepo.profiles.server.enable; listen.address = "0.0.0.0"; extraConfig = '' 0 /stream.m3u 3600
''; }; admin.password = "changeme"; } #+end_src ** IRC A great protocol. It's the most widely usable by any netizen, as it is just pure plaintext and the operating costs are trivial. *** NgIRCD I run my own IRC server to bridge with my Matrix server and my discord guild. #+begin_src nix :tangle ../nix/modules/ngircd.nix { lib, config, ... }: { services.ngircd = { enable = lib.mkDefault config.monorepo.profiles.server.enable; config = '' [Global] Name = ${config.monorepo.vars.orgHost} Info = NullRing IRC Instance Listen = 0.0.0.0 MotdFile = /etc/motd.txt Network = NullRing Ports = 6667 [Options] PAM = no [SSL] CertFile = /var/lib/acme/${config.monorepo.vars.orgHost}/fullchain.pem CipherList = HIGH:!aNULL:@STRENGTH:!SSLv3 KeyFile = /var/lib/acme/${config.monorepo.vars.orgHost}/key.pem Ports = 6697 ''; }; environment.etc."motd.txt" = { source = ../data/motd.txt; mode = "644"; user = "ngircd"; group = "ngircd"; }; } #+end_src *** MOTD I also have a MOTD file that I want to add, which displays when users connect to the server: #+begin_src fundamental :tangle ../nix/data/motd.txt Welcome to the NullRing experience! The main channel is #nullring; we're glad to have you! Rules: 1. Don't be annoying. 2. No illegal content. And if you're here to have constructive, philisophical and theoretical conversations, this is the place for you! #+end_src *** ZNC I want to be able to create some sort of identity persistence on IRC for users: #+begin_src nix :tangle ../nix/modules/znc.nix { lib, config, ... }: { services.znc = { enable = lib.mkDefault config.monorepo.profiles.server.enable; openFirewall = true; confOptions = { useSSL = true; passBlock = '' Method = sha256 Hash = d4abdd69aa24de69693885c5bd83a4a0e9ee989e1a69a905041b0dad9abc06ea Salt = sDY,?H5AxC-!gH3a.:)D ''; modules = [ "partyline" "webadmin" "adminlog" "log" ]; networks = { "libera" = { server = "irc.libera.chat"; port = 6697; useSSL = true; modules = [ "simple_away" ]; }; }; }; }; } #+end_src Note that the password hash and whatnot is completely random so there is almost no point to cracking it with hashcat. ** Conduit This is a modern matrix server that is meant to be lightweight while still federating and hosting the same protocol. #+begin_src nix :tangle ../nix/modules/conduit.nix { config, lib, ... }: { services.matrix-conduit = { enable = lib.mkDefault config.monorepo.profiles.server.enable; settings.global = { server_name = "matrix.${config.monorepo.vars.orgHost}"; trusted_servers = [ "matrix.org" "nixos.org" "conduit.rs" ]; address = "0.0.0.0"; port = 6167; allow_registration = false; }; }; } #+end_src ** Honk In order to connect to activitypub: #+begin_src nix :tangle ../nix/modules/honk.nix { lib, config, ... }: { services.honk = { enable = config.monorepo.vars.ttyonly; servername = "ret2pop.net"; username = "ret2pop"; }; } #+end_src ** Matterbridge I want to connect IRC to discord with matterbridge. #+begin_src nix :tangle ../nix/modules/matterbridge.nix { lib, config, ... }: { services.matterbridge = { enable = lib.mkDefault config.monorepo.profiles.server.enable; configPath = "/etc/matterbridge.toml"; }; } #+end_src *** Mautrix I use this bridge to bridge myself from Matrix to Discord and vise versa, because Matterbridge is not maintained very well and therefore does not support conduit at the moment. Note that this is not fully declarative and requires that you add ~/var/lib/mautrix-discord/discord-registration.yaml~ as an appservice to conduit. #+begin_src nix :tangle ../nix/modules/mautrix.nix { lib, config, ... }: { services.mautrix-discord = { enable = lib.mkDefault config.monorepo.profiles.server.enable; environmentFile = "/etc/mautrix"; settings = { bridge = { animated_sticker = { args = { fps = 25; height = 320; width = 320; }; target = "webp"; }; autojoin_thread_on_open = true; avatar_proxy_key = "generate"; backfill = { forward_limits = { initial = { channel = 0; dm = 0; thread = 0; }; max_guild_members = -1; missed = { channel = 0; dm = 0; thread = 0; }; }; }; cache_media = "unencrypted"; channel_name_template = "{{if or (eq .Type 3) (eq .Type 4)}}{{.Name}}{{else}}#{{.Name}}{{end}}"; command_prefix = "!discord"; custom_emoji_reactions = true; delete_guild_on_leave = true; delete_portal_on_channel_delete = false; delivery_receipts = false; direct_media = { allow_proxy = true; enabled = false; server_key = "generate"; }; displayname_template = "{{if .Webhook}}Webhook{{else}}{{or .GlobalName .Username}}{{if .Bot}} (bot){{end}}{{end}}"; double_puppet_allow_discovery = true; double_puppet_server_map = { }; embed_fields_as_tables = true; enable_webhook_avatars = true; encryption = { allow = false; allow_key_sharing = false; appservice = false; default = false; delete_keys = { delete_fully_used_on_decrypt = false; delete_on_device_delete = false; delete_outbound_on_ack = false; delete_outdated_inbound = false; delete_prev_on_new_session = false; dont_store_outbound = false; periodically_delete_expired = false; ratchet_on_decrypt = false; }; msc4190 = false; plaintext_mentions = false; require = false; rotation = { disable_device_change_key_rotation = false; enable_custom = false; messages = 100; milliseconds = 604800000; }; verification_levels = { receive = "unverified"; send = "unverified"; share = "cross-signed-tofu"; }; }; federate_rooms = true; guild_name_template = "{{.Name}}"; login_shared_secret_map = { }; management_room_text = { additional_help = ""; welcome = "Hello, I'm a Discord bridge bot."; welcome_connected = "Use `help` for help."; welcome_unconnected = "Use `help` for help or `login` to log in."; }; message_error_notices = true; message_status_events = false; mute_channels_on_create = false; permissions = { "@${config.monorepo.vars.internetName}:matrix.${config.monorepo.vars.orgHost}" = "admin"; "*" = "user"; }; portal_message_buffer = 128; prefix_webhook_messages = true; private_chat_portal_meta = "default"; provisioning = { debug_endpoints = false; prefix = "/_matrix/provision"; shared_secret = "generate"; }; public_address = null; resend_bridge_info = false; restricted_rooms = false; startup_private_channel_create_limit = 5; sync_direct_chat_list = false; use_discord_cdn_upload = true; username_template = "discord_{{.}}"; }; appservice = { address = "http://localhost:29334"; hostname = "0.0.0.0"; port = 29334; id = "discord"; bot = { username = "discordbot"; displayname = "Discord bridge bot"; avatar = "mxc://maunium.net/nIdEykemnwdisvHbpxflpDlC"; }; ephemeral_events = true; async_transactions = false; database = { type = "sqlite3"; uri = "file:${config.services.mautrix-discord.dataDir}/mautrix-discord.db?_txlock=immediate"; max_open_conns = 20; max_idle_conns = 2; max_conn_idle_time = null; max_conn_lifetime = null; }; as_token = "$MAUTRIX_DISCORD_APPSERVICE_AS_TOKEN"; hs_token = "$MAUTRIX_DISCORD_APPSERVICE_HS_TOKEN"; }; dataDir = "/var/lib/mautrix-discord"; homeserver = { async_media = false; message_send_checkpoint_endpoint = null; ping_interval_seconds = 0; software = "standard"; status_endpoint = null; websocket = false; domain = "matrix.${config.monorepo.vars.orgHost}"; address = "http://localhost:6167"; }; }; }; } #+end_src ** Ollama Use ollama for serving large language models to my other computers. #+begin_src nix :tangle ../nix/modules/ollama.nix { config, lib, ... }: { services.ollama = { enable = lib.mkDefault (!config.monorepo.profiles.server.enable); acceleration = if (config.monorepo.profiles.workstation.enable) then "cuda" else null; loadModels = if (config.monorepo.profiles.workstation.enable) then [ "qwen3:30b" "qwen3-coder:latest" "qwen2.5-coder:latest" "gemma3:12b-it-qat" ] else [ "qwen3:0.6b" "qwen2.5-coder:0.5b" ]; host = "0.0.0.0"; openFirewall = true; }; } #+end_src ** Bitcoind #+begin_src nix :tangle ../nix/modules/bitcoin.nix { config, lib, ... }: { services.bitcoind."${config.monorepo.vars.userName}" = { enable = lib.mkDefault config.monorepo.profiles.workstation.enable; prune = 10000; }; } #+end_src ** Git Server I run my own git server in order to have a mirror in case github goes down. #+begin_src nix :tangle ../nix/modules/git-daemon.nix { config, lib, ... }: { services.gitDaemon = { enable = lib.mkDefault config.monorepo.profiles.server.enable; exportAll = true; basePath = "/srv/git"; }; } #+end_src ** Nginx These are all my virtual hosts. For many of these servers we have to have a reverse proxy in order to expose the locally running instances to the outside world under a domain. #+begin_src nix :tangle ../nix/modules/nginx.nix { config, lib, services, ... }: { services.nginx = { enable = lib.mkDefault config.monorepo.profiles.server.enable; user = "nginx"; # Use recommended settings recommendedGzipSettings = true; recommendedOptimisation = true; recommendedProxySettings = true; recommendedTlsSettings = true; appendHttpConfig = ''''; gitweb = { enable = true; virtualHost = "${config.monorepo.vars.remoteHost}"; }; virtualHosts = { "matrix.${config.monorepo.vars.orgHost}" = { enableACME = true; forceSSL = true; listen = [ { addr = "0.0.0.0"; port = 443; ssl = true; } { addr = "[::]"; port = 443; ssl = true; } { addr = "0.0.0.0"; port = 8448; ssl = true; } { addr = "[::]"; port = 8448; ssl = true; } ]; locations."/_matrix/" = { proxyPass = "http://127.0.0.1:6167"; extraConfig = '' proxy_set_header Host $host; proxy_buffers 32 16k; proxy_read_timeout 5m; ''; }; extraConfig = '' merge_slashes off; ''; }; "${config.monorepo.vars.remoteHost}" = { serverName = "${config.monorepo.vars.remoteHost}"; serverAliases = [ "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" ]; root = "/var/www/${config.monorepo.vars.internetName}-website/"; addSSL = true; enableACME = true; }; "${config.monorepo.vars.orgHost}" = { serverName = "${config.monorepo.vars.orgHost}"; root = "/var/www/nullring/"; addSSL = true; enableACME = true; }; "mail.${config.monorepo.vars.remoteHost}" = { serverName = "mail.${config.monorepo.vars.remoteHost}"; root = "/var/www/dummy"; addSSL = true; enableACME = true; }; }; }; } #+end_src ** Git Web Interface I enable the git web interface to show off my git repos to the world. This was the easiest frontend to set up on NixOS. #+begin_src nix :tangle ../nix/modules/gitweb.nix { lib, config, ... }: { services.gitweb = { gitwebTheme = true; projectroot = "/srv/git/"; }; } #+end_src ** Nvidia I have an Nvidia GPU on my computer. #+begin_src nix :tangle ../nix/modules/nvidia.nix { config, lib, pkgs, ... }: { hardware = { graphics.extraPackages = (if config.monorepo.profiles.cuda.enable then with pkgs; [ vaapiVdpau libvdpau-va-gl nvidia-vaapi-driver ] else []); nvidia = { modesetting.enable = lib.mkDefault config.monorepo.profiles.cuda.enable; powerManagement = { enable = lib.mkDefault config.monorepo.profiles.cuda.enable; finegrained = false; }; nvidiaSettings = lib.mkDefault config.monorepo.profiles.cuda.enable; open = lib.mkDefault false; package = config.boot.kernelPackages.nvidiaPackages.stable; }; }; } #+end_src ** CUDA I need CUDA on some computers because I run local LLMs. #+begin_src nix :tangle ../nix/modules/cuda.nix { config, lib, pkgs, ... }: { environment.systemPackages = (if config.monorepo.profiles.cuda.enable then with pkgs; [ cudatoolkit cudaPackages.cudnn cudaPackages.libcublas linuxPackages.nvidia_x11 ] else []); } #+end_src ** TODO Maddy #+begin_src nix :tangle ../nix/modules/maddy.nix { lib, config, options, ... }: { services.maddy = { enable = lib.mkDefault config.monorepo.profiles.server.enable; openFirewall = true; hostName = "${config.monorepo.vars.remoteHost}"; primaryDomain = "mail.${config.monorepo.vars.remoteHost}"; tls = { loader = "acme"; }; config = builtins.replaceStrings [ "imap tcp://0.0.0.0:143" "submission tcp://0.0.0.0:587" ] [ "imap tls://0.0.0.0:993 tcp://0.0.0.0:143" "submission tls://0.0.0.0:465 tcp://0.0.0.0:587" ] options.services.maddy.config.default; ensureCredentials = { "${config.monorepo.vars.userName}@localhost" = { passwordFile = "/secrets/${config.monorepo.vars.userName}-localhost"; }; }; }; } #+end_src ** Impermanence This is my impermanence profile, which removes all files on reboot except for the ones listed below. #+begin_src nix :tangle ../nix/modules/impermanence.nix { lib, config, ... }: { assertions = [ { assertion = (! (config.monorepo.profiles.impermanence.enable && (! (config.monorepo.vars.fileSystem == "btrfs")))); message = "Impermanence requires btrfs filesystem."; } ]; boot.initrd.postResumeCommands = (if config.monorepo.profiles.impermanence.enable then lib.mkAfter '' mkdir /btrfs_tmp mount /dev/root_vg/root /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 '' else ""); fileSystems = if (config.monorepo.profiles.impermanence.enable) then { "/persistent" = { neededForBoot = true; }; } else {}; environment.persistence."/persistent" = { enable = config.monorepo.profiles.impermanence.enable; hideMounts = true; directories = [ "/var/log" "/var/lib/bluetooth" "/var/lib/nixos" "/var/lib/systemd/coredump" "/etc/NetworkManager/system-connections" ]; files = [ "/etc/machine-id" "/etc/matterbridge.toml" { file = "/var/keys/secret_file"; parentDirectory = { mode = "u=rwx,g=,o="; }; } ]; users."${config.monorepo.vars.userName}" = { directories = [ "Downloads" "music" "Pictures" "Documents" "Videos" "Monero" "org" "monorepo" "soundfont" "website_html" "ardour" "audacity" "img" "email" "projects" "secrets" ".emacs.d" ".elfeed" ".electrum" ".mozilla" ".bitmonero" ".config" { directory = ".gnupg"; mode = "0700"; } { directory = ".ssh"; mode = "0700"; } { directory = ".local/share/keyrings"; mode = "0700"; } ".local/share/direnv" ]; files = [ ".emacs" ]; }; }; } #+end_src ** Main Configuration This is the backbone of the all the NixOS configurations, with all these options being shared because they enhance security. #+begin_src nix :tangle ../nix/modules/configuration.nix { config, pkgs, lib, ... }: { imports = [ ./matterbridge.nix ./mautrix.nix ./xserver.nix ./ssh.nix ./pipewire.nix ./tor.nix ./kubo.nix ./nvidia.nix ./cuda.nix ./nginx.nix ./git-daemon.nix ./ollama.nix ./i2pd.nix ./gitweb.nix ./conduit.nix ./bitcoin.nix ./murmur.nix ./ngircd.nix ./znc.nix ./docker.nix ./impermanence.nix ]; documentation = { enable = lib.mkDefault config.monorepo.profiles.documentation.enable; man.enable = lib.mkDefault config.monorepo.profiles.documentation.enable; dev.enable = lib.mkDefault config.monorepo.profiles.documentation.enable; }; environment = { etc = { securetty.text = '' # /etc/securetty: list of terminals on which root is allowed to login. # See securetty(5) and login(1). ''; }; }; systemd = { coredump.enable = false; network.config.networkConfig.IPv6PrivacyExtensions = "kernel"; tmpfiles.settings = { "restricthome"."/home/*".Z.mode = "~0700"; "restrictetcnixos"."/etc/nixos/*".Z = { mode = "0000"; user = "root"; group = "root"; }; }; }; boot = { extraModprobeConfig = '' options snd-usb-audio vid=0x1235 pid=0x8200 device_setup=1 ''; extraModulePackages = [ ]; initrd = { availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "sd_mod" "nvme" "sd_mod" "ehci_pci" "rtsx_pci_sdmmc" "usbhid" ]; kernelModules = [ ]; }; lanzaboote = { enable = config.monorepo.profiles.secureBoot.enable; pkiBundle = "/etc/secureboot"; }; loader = { systemd-boot.enable = lib.mkForce (! config.monorepo.profiles.grub.enable); efi.canTouchEfiVariables = lib.mkForce (! config.monorepo.profiles.grub.enable); }; kernelModules = [ "snd-seq" "snd-rawmidi" "xhci_hcd" "kvm_intel" ]; kernelParams = [ "usbcore.autosuspend=-1" "debugfs=off" "page_alloc.shuffle=1" "slab_nomerge" "page_poison=1" # madaidan "pti=on" "randomize_kstack_offset=on" "vsyscall=none" "module.sig_enforce=1" "lockdown=confidentiality" # cpu "spectre_v2=on" "spec_store_bypass_disable=on" "tsx=off" "l1tf=full,force" "kvm.nx_huge_pages=force" # hardened "extra_latent_entropy" # mineral "init_on_alloc=1" "random.trust_cpu=off" "random.trust_bootloader=off" "intel_iommu=on" "amd_iommu=force_isolation" "iommu=force" "iommu.strict=1" "init_on_free=1" "quiet" "loglevel=0" ]; blacklistedKernelModules = [ "netrom" "rose" "adfs" "affs" "bfs" "befs" "cramfs" "efs" "erofs" "exofs" "freevxfs" "f2fs" "hfs" "hpfs" "jfs" "minix" "nilfs2" "ntfs" "omfs" "qnx4" "qnx6" "sysv" "ufs" ]; kernel.sysctl = { "kernel.ftrace_enabled" = false; "net.core.bpf_jit_enable" = false; "kernel.kptr_restrict" = 2; # madaidan "kernel.smtcontrol" = "on"; "vm.swappiness" = 1; "vm.unprivileged_userfaultfd" = 0; "dev.tty.ldisc_autoload" = 0; "kernel.kexec_load_disabled" = 1; "kernel.sysrq" = 4; "kernel.perf_event_paranoid" = 3; # net "net.ipv4.icmp_echo_ignore_broadcasts" = true; "net.ipv4.conf.all.accept_redirects" = false; "net.ipv4.conf.all.secure_redirects" = false; "net.ipv4.conf.default.accept_redirects" = false; "net.ipv4.conf.default.secure_redirects" = false; "net.ipv6.conf.all.accept_redirects" = false; "net.ipv6.conf.default.accept_redirects" = false; }; }; networking = { useDHCP = lib.mkDefault true; networkmanager = { enable = true; }; firewall = { allowedTCPPorts = [ 22 11434 ]; allowedUDPPorts = [ ]; }; }; hardware = { enableAllFirmware = true; cpu.intel.updateMicrocode = true; graphics.enable = ! config.monorepo.profiles.ttyonly.enable; bluetooth = { enable = true; powerOnBoot = true; }; }; services = { pulseaudio.enable = ! config.monorepo.profiles.pipewire.enable; chrony = { enable = true; enableNTS = true; servers = [ "time.cloudflare.com" "ptbtime1.ptb.de" "ptbtime2.ptb.de" ]; }; jitterentropy-rngd.enable = true; resolved.dnssec = true; # usbguard.enable = true; usbguard.enable = false; dbus.apparmor = "enabled"; kanata.enable = true; # Misc. udev = { extraRules = ''''; packages = with pkgs; [ platformio-core platformio-core.udev openocd ]; }; printing.enable = true; udisks2.enable = true; }; programs = { nix-ld.enable = true; zsh.enable = true; light.enable = true; ssh.enableAskPassword = false; }; nixpkgs = { hostPlatform = lib.mkDefault "x86_64-linux"; config = { allowUnfree = true; cudaSupport = lib.mkDefault config.monorepo.profiles.cuda.enable; }; }; security = { acme = { acceptTerms = true; defaults.email = "ret2pop@gmail.com"; }; apparmor = { enable = true; killUnconfinedConfinables = true; }; pam.loginLimits = [ { domain = "*"; item = "nofile"; type = "-"; value = "32768"; } { domain = "*"; item = "memlock"; type = "-"; value = "32768"; } ]; rtkit.enable = true; lockKernelModules = true; protectKernelImage = true; allowSimultaneousMultithreading = true; forcePageTableIsolation = true; tpm2 = { enable = true; pkcs11.enable = true; tctiEnvironment.enable = true; }; auditd.enable = true; audit.enable = true; chromiumSuidSandbox.enable = (! config.monorepo.profiles.ttyonly.enable); sudo.enable = true; }; xdg.portal = { enable = (! config.monorepo.profiles.ttyonly.enable); wlr.enable = (! config.monorepo.profiles.ttyonly.enable); extraPortals = with pkgs; if (! config.monorepo.profiles.ttyonly.enable) then [ xdg-desktop-portal-gtk xdg-desktop-portal xdg-desktop-portal-hyprland ] else []; config.common.default = "*"; }; environment.etc."gitconfig".text = '' [init] defaultBranch = main ''; environment.extraInit = '' umask 0022 ''; environment.systemPackages = with pkgs; [ restic sbctl git vim curl nmap (writeShellScriptBin "new-repo" '' #!/bin/bash cd /srv/git git init --bare "$1" vim "$1/description" chown -R git:git "$1" '' ) ]; users.groups.nginx = lib.mkDefault {}; users.groups.git = lib.mkDefault {}; users.groups.ircd = lib.mkDefault {}; users.groups.ngircd = lib.mkDefault {}; users.users = { ngircd = { isSystemUser = lib.mkDefault true; group = "ngircd"; extraGroups = [ "acme" "nginx" ]; }; ircd = { isSystemUser = lib.mkDefault true; group = "ircd"; home = "/home/ircd"; }; nginx = { group = "nginx"; isSystemUser = lib.mkDefault true; extraGroups = [ "acme" ]; }; root.openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICts6+MQiMwpA+DfFQxjIN214Jn0pCw/2BDvOzPhR/H2 preston@continuity-dell" ]; git = { isSystemUser = true; home = "/srv/git"; shell = "${pkgs.git}/bin/git-shell"; group = "git"; openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICts6+MQiMwpA+DfFQxjIN214Jn0pCw/2BDvOzPhR/H2 preston@continuity-dell" ]; }; "${config.monorepo.vars.userName}" = { openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICts6+MQiMwpA+DfFQxjIN214Jn0pCw/2BDvOzPhR/H2 preston@continuity-dell" ]; initialPassword = "${config.monorepo.vars.userName}"; isNormalUser = true; description = config.monorepo.vars.fullName; extraGroups = [ "networkmanager" "wheel" "video" "docker" "jackaudio" "tss" "dialout" "docker" ]; shell = pkgs.zsh; packages = []; }; }; nixpkgs.config.permittedInsecurePackages = [ "olm-3.2.16" ]; nix = { settings = { experimental-features = "nix-command flakes"; trusted-users = [ "@wheel" ]; }; }; time.timeZone = config.monorepo.vars.timeZone; i18n.defaultLocale = "en_CA.UTF-8"; system.stateVersion = "24.11"; } #+end_src ** Disko This is the disko configuration for my continuity system. It features a boot and ext4 partition, with configurable disk. *** Btrfs #+begin_src nix :tangle ../nix/disko/btrfs-simple.nix { lib, config, ... }: let spec = { disko.devices = { disk = { main = { type = "disk"; device = config.monorepo.vars.device; 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"; passwordFile = "/tmp/secret.key"; content = { type = "btrfs"; extraArgs = [ "-f" ]; subvolumes = { "/root" = { mountpoint = "/"; mountOptions = [ "compress=zstd" "noatime" ]; }; "/home" = { mountpoint = "/home"; mountOptions = [ "compress=zstd" "noatime" ]; }; "/nix" = { mountpoint = "/nix"; mountOptions = [ "compress=zstd" "noatime" ]; }; "/persistent" = { mountpoint = "/persistent"; mountOptions = [ "compress=zstd" "noatime" ]; }; }; }; }; }; }; }; }; }; }; }; in { monorepo.vars.diskoSpec = spec; disko.devices = spec.disko.devices; } #+end_src *** Simple This configuration is used for simple partitioning schemes with EFI. #+begin_src nix :tangle ../nix/disko/drive-simple.nix { lib, config, ... }: let spec = { disko.devices = { disk = { my-disk = { device = config.monorepo.vars.device; type = "disk"; content = { type = "gpt"; partitions = { ESP = { type = "EF00"; size = "500M"; priority = 1; content = { type = "filesystem"; format = "vfat"; mountpoint = "/boot"; mountOptions = [ "umask=0077" ]; }; }; root = { size = "100%"; priority = 2; content = { type = "filesystem"; format = "ext4"; mountpoint = "/"; }; }; }; }; }; }; }; }; in { monorepo.vars.diskoSpec = spec; disko.devices = spec.disko.devices; } #+end_src *** BIOS For machines that use BIOS instead of EFI. #+begin_src nix :tangle ../nix/disko/drive-bios.nix { config, lib, ... }: let spec = { disko.devices = { disk = { main = { device = config.monorepo.vars.device; type = "disk"; content = { type = "gpt"; partitions = { boot = { size = "1M"; type = "EF02"; }; root = { label = "disk-main-root"; size = "100%"; content = { type = "filesystem"; format = "ext4"; mountpoint = "/"; }; }; }; }; }; }; }; }; in { monorepo.vars.diskoSpec = spec; disko.devices = spec.disko.devices; } #+end_src ** Home *** Default Home Profile As you can see, I have my installed home packages installed based on the profiles enabled. Also, I have many imports that we'll go through next. #+begin_src nix :tangle ../nix/modules/home/default.nix { lib, config, pkgs, sops-nix, ... }: { imports = [ sops-nix.homeManagerModules.sops ../vars.nix ./fcitx.nix ./secrets.nix ./emacs.nix ./firefox.nix ./git.nix ./hyprland.nix ./mpv.nix ./yt-dlp.nix ./wofi.nix ./kitty.nix ./waybar.nix ./zsh.nix ./mbsync.nix ./msmtp.nix ./gammastep.nix ./mpd.nix ./mako.nix ./user.nix ]; options = { monorepo.profiles = { enable = lib.mkEnableOption "Enables home manager desktop configuration"; # Programs graphics.enable = lib.mkEnableOption "Enables graphical programs for user"; lang-c.enable = lib.mkEnableOption "Enables C language support"; lang-sh.enable = lib.mkEnableOption "Enables sh language support"; lang-rust.enable = lib.mkEnableOption "Enables Rust language support"; lang-python.enable = lib.mkEnableOption "Enables python language support"; lang-sol.enable = lib.mkEnableOption "Enables solidity language support"; lang-openscad.enable = lib.mkEnableOption "Enables openscad language support"; lang-js.enable = lib.mkEnableOption "Enables javascript language support"; lang-nix.enable = lib.mkEnableOption "Enables nix language support"; lang-idris.enable = lib.mkEnableOption "Enables idris language support"; lang-agda.enable = lib.mkEnableOption "Enables agda language support"; lang-coq.enable = lib.mkEnableOption "Enables coq language support"; lang-lean.enable = lib.mkEnableOption "Enables lean language support"; lang-haskell.enable = lib.mkEnableOption "Enables haskell language support"; crypto.enable = lib.mkEnableOption "Enables various cryptocurrency wallets"; art.enable = lib.mkEnableOption "Enables various art programs"; music.enable = lib.mkEnableOption "Enables mpd"; workstation.enable = lib.mkEnableOption "Enables workstation packages (music production and others)"; cuda.enable = lib.mkEnableOption "Enables CUDA user package builds"; hyprland.enable = lib.mkEnableOption "Enables hyprland"; email = { email = lib.mkOption { type = lib.types.str; default = "ret2pop@gmail.com"; example = "john@example.com"; description = "Email address and imaps/smtps account"; }; imapsServer = lib.mkOption { type = lib.types.str; default = "imap.gmail.com"; example = "imap.example.com"; description = "imaps server address"; }; smtpsServer = lib.mkOption { type = lib.types.str; default = "smtp.gmail.com"; example = "smtp.example.com"; description = "smtp server address"; }; enable = lib.mkEnableOption "Enables email"; }; }; }; config = { home.packages = (if config.monorepo.profiles.email.enable then [ pkgs.mu ] else []) ++ (if config.monorepo.profiles.lang-c.enable then (with pkgs; [ autobuild clang gdb gnumake bear clang-tools autotools-language-server ]) else []) ++ (if config.monorepo.profiles.workstation.enable then (with pkgs; [ mumble ]) else []) ++ (if config.monorepo.profiles.lang-js.enable then (with pkgs; [ nodejs bun yarn typescript typescript-language-server vscode-langservers-extracted ]) else []) ++ (if config.monorepo.profiles.lang-rust.enable then (with pkgs; [ cargo rust-analyzer rustfmt ]) else []) ++ (if config.monorepo.profiles.lang-python.enable then (with pkgs; [ poetry python3 python312Packages.jedi ]) else []) ++ (if config.monorepo.profiles.lang-sol.enable then (with pkgs; [ solc ]) else []) ++ (if config.monorepo.profiles.lang-openscad.enable then (with pkgs; [ openscad openscad-lsp ]) else []) ++ (if config.monorepo.profiles.lang-sh.enable then (with pkgs; [ bash-language-server ]) else []) ++ (if config.monorepo.profiles.lang-haskell.enable then (with pkgs; [ haskell-language-server haskellPackages.hlint ghc ]) else []) ++ (if config.monorepo.profiles.lang-coq.enable then (with pkgs; [ coq ]) else []) ++ (if config.monorepo.profiles.lang-lean.enable then (with pkgs; [ lean4 ]) else []) ++ (if config.monorepo.profiles.lang-agda.enable then (with pkgs; [ agda ]) else []) ++ (if config.monorepo.profiles.lang-idris.enable then (with pkgs; [ idris idris2Packages.idris2Lsp ]) else []) ++ (if config.monorepo.profiles.lang-nix.enable then (with pkgs; [ nil nixd nixfmt-rfc-style nix-prefetch-scripts ]) else []) ++ (if config.monorepo.profiles.crypto.enable then (with pkgs; [ bitcoin electrum monero-cli monero-gui ]) else []) ++ (if config.monorepo.profiles.art.enable then (with pkgs; [ inkscape # krita ]) else []) ++ (if config.monorepo.profiles.music.enable then (with pkgs; [ mpc-cli sox ]) else []) ++ (if config.monorepo.profiles.workstation.enable then (with pkgs; [ alsa-utils alsa-scarlett-gui ardour audacity # blender foxdot fluidsynth qjackctl qsynth qpwgraph imagemagick supercollider inkscape kdePackages.kdenlive # kicad murmur ]) else []); monorepo.profiles = { enable = lib.mkDefault true; music.enable = lib.mkDefault config.monorepo.profiles.enable; hyprland.enable = lib.mkDefault config.monorepo.profiles.enable; email.enable = lib.mkDefault config.monorepo.profiles.enable; # Programming graphics.enable = lib.mkDefault config.monorepo.profiles.enable; lang-c.enable = lib.mkDefault config.monorepo.profiles.enable; lang-rust.enable = lib.mkDefault config.monorepo.profiles.enable; lang-python.enable = lib.mkDefault config.monorepo.profiles.enable; lang-sol.enable = lib.mkDefault config.monorepo.profiles.enable; lang-sh.enable = lib.mkDefault config.monorepo.profiles.enable; lang-openscad.enable = lib.mkDefault config.monorepo.profiles.enable; lang-js.enable = lib.mkDefault config.monorepo.profiles.enable; lang-nix.enable = lib.mkDefault config.monorepo.profiles.enable; lang-coq.enable = lib.mkDefault config.monorepo.profiles.enable; lang-lean.enable = lib.mkDefault config.monorepo.profiles.enable; lang-haskell.enable = lib.mkDefault config.monorepo.profiles.enable; lang-idris.enable = lib.mkDefault config.monorepo.profiles.enable; lang-agda.enable = lib.mkDefault config.monorepo.profiles.enable; crypto.enable = lib.mkDefault config.monorepo.profiles.enable; art.enable = lib.mkDefault config.monorepo.profiles.enable; workstation.enable = lib.mkDefault config.monorepo.profiles.enable; }; }; } #+end_src *** Firefox I conditionally enable metamask based on the cryptocurrency option. Everything else here should be straightforward. #+begin_src nix :tangle ../nix/modules/home/firefox.nix { lib, config, pkgs, ... }: { programs.firefox = { enable = lib.mkDefault config.monorepo.profiles.graphics.enable; package = pkgs.firefox-bin; policies = { EnableTrackingProtection = true; OfferToSaveLogins = false; }; profiles = { default = { id = 0; name = "default"; isDefault = true; extensions.packages = with pkgs.nur.repos.rycee.firefox-addons; [ ublock-origin tree-style-tab firefox-color vimium ] ++ (lib.optional config.monorepo.profiles.crypto.enable pkgs.nur.repos.rycee.firefox-addons.metamask); settings = { media = { memory_cache_max_size = 65536; cache_readahead_limit = 7200; cache_resume_threshold = 3600; peerconnection.ice = { proxy_only_if_behind_proxy = true; default_address_only = true; }; }; gfx = { content.skia-font-cache-size = 20; canvas.accelerated = { cache-items = 4096; cache-size = 512; }; }; network = { http = { max-connections = 1800; max-persistent-connections-per-server = 10; max-urgent-start-excessive-connections-per-host = 5; referer.XOriginTrimmingPolicy = 2; }; buffer.cache = { size = 262144; count = 128; }; dns = { max_high_priority_threads = 8; disablePrefetch = true; }; pacing.requests.enabled = false; dnsCacheExpiration = 3600; ssl_tokens_cache_capacity = 10240; prefetch-next = false; predictor.enabled = false; cookie.sameSite.noneRequiresSecure = true; IDN_show_punycode = true; auth.subresource-http-auth-allow = 1; captive-portal-service.enabled = false; connectivity-service.enabled = false; }; browser = { download = { always_ask_before_handling_new_types = true; manager.addToRecentDocs = false; open_pdf_attachments_inline = true; start_downloads_in_tmp_dir = true; }; urlbar = { suggest.quicksuggest.sponsored = false; suggest.quicksuggest.nonsponsored = false; suggest.calculator = true; update2.engineAliasRefresh = true; unitConversion.enabled = true; trending.featureGate = false; }; search = { separatePrivateDefault.ui.enabled = true; suggest.enabled = false; }; newtabpage.activity-stream = { feeds = { topsites = false; section.topstories = false; telemetry = false; }; asrouter.userprefs.cfr = { addons = false; features = false; }; telemetry = false; }; privatebrowsing = { vpnpromourl = ""; forceMediaMemoryCache = true; }; display = { focus_ring_on_anything = true; focus_ring_style = 0; focus_ring_width = 0; }; cache.jsbc_compression_level = 3; helperApps.deleteTempFileOnExit = true; uitour.enabled = false; sessionstore.interval = 60000; formfill.enable = false; xul.error_pages.expert_bad_cert = true; contentblocking.category = "strict"; ping-centre.telemetry = false; discovery.enabled = false; shell.checkDefaultBrowser = false; preferences.moreFromMozilla = false; tabs.tabmanager.enabled = false; aboutConfig.showWarning = false; aboutwelcome.enabled = false; bookmarks.openInTabClosesMenu = false; menu.showViewImageInfo = true; compactmode.show = true; safebrowsing.downloads.remote.enabled = false; tabs.crashReporting.sendReport = false; crashReports.unsubmittedCheck.autoSubmit2 = false; privateWindowSeparation.enabled = false; }; security = { mixed_content = { block_display_content = true; upgrade_display_content = true; }; insecure_connection_text = { enabled = true; pbmode.enabled = true; }; OCSP.enabled = 0; remote_settings.crlite_filters.enabled = true; pki.crlite_mode = 2; ssl.treat_unsafe_negotiation_as_broken = true; tls.enable_0rtt_data = false; }; toolkit = { telemetry = { unified = false; enabled = false; server = "data:,"; archive.enabled = false; newProfilePing.enabled = false; shutdownPingSender.enabled = false; updatePing.enabled = false; bhrPing.enabled = false; firstShutdownPing.enabled = false; coverage.opt-out = true; }; coverage = { opt-out = true; endpoint.base = ""; }; legacyUserProfileCustomizations.stylesheets = true; }; dom = { security = { https_first = true; https_first_schemeless = true; sanitizer.enabled = true; }; enable_web_task_scheduling = true; }; layout = { css = { grid-template-masonry-value.enabled = true; has-selector.enabled = true; prefers-color-scheme.content-override = 2; }; word_select.eat_space_to_next_word = false; }; urlclassifier = { trackingSkipURLs = "*.reddit.com, *.twitter.com, *.twimg.com, *.tiktok.com"; features.socialtracking.skipURLs = "*.instagram.com, *.twitter.com, *.twimg.com"; }; privacy = { globalprivacycontrol.enabled = true; history.custom = true; userContext.ui.enabled = true; trackingprotection = { enabled = true; pbmode.enabled = true; socialtracking.enabled = true; }; }; full-screen-api = { transition-duration = { enter = "0 0"; leave = "0 0"; }; warning = { delay = -1; timeout = 0; }; }; permissions.default = { desktop-notification = 2; geo = 2; }; signon = { formlessCapture.enabled = false; privateBrowsingCapture.enabled = false; }; datareporting = { policy.dataSubmissionEnabled = false; healthreport.uploadEnabled = false; }; extensions = { pocket.enabled = false; getAddons.showPane = false; htmlaboutaddons.recommendations.enabled = false; postDownloadThirdPartyPrompt = false; }; app = { shield.optoutstudies.enabled = false; normandy.enabled = false; normandy.api_url = ""; }; image.mem.decode_bytes_at_a_time = 32768; editor.truncate_user_pastes = false; pdfjs.enableScripting = false; geo.provider.network.url = "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%"; permissions.manager.defaultsUrl = ""; webchannel.allowObject.urlWhitelist = ""; breakpad.reportURL = ""; captivedetect.canonicalURL = ""; cookiebanners.service.mode = 1; findbar.highlightAll = true; content.notify.interval = 100000; }; }; }; }; } #+end_src *** Fcitx This is a virtual keyboard program for writing in multiple languages. I use this sometimes. #+begin_src nix :tangle ../nix/modules/home/fcitx.nix { config, pkgs, lib, ... }: { i18n.inputMethod = { type = "fcitx5"; enable = lib.mkDefault config.monorepo.profiles.graphics.enable; fcitx5.addons = with pkgs; [ fcitx5-gtk fcitx5-chinese-addons fcitx5-configtool fcitx5-mozc fcitx5-rime ]; }; } #+end_src Note that I configure fcitx with chinese and some japanese input enabled. *** Emacs I install all my emacs packages within Nix so that they build deterministically with native compilation, and because I can fetch their exact versions. Note that I have a stub configuration here that tells emacs to load my real configuration at ~~/monorepo/config/emacs.org~ as an org file which gets automatically tangled to an emacs-lisp file. #+begin_src nix :tangle ../nix/modules/home/emacs.nix { lib, config, pkgs, ... }: { programs.emacs = { enable = lib.mkDefault config.monorepo.profiles.graphics.enable; package = pkgs.emacs-pgtk; extraConfig = '' (setq debug-on-error t) (setq system-email "${config.monorepo.profiles.email.email}") (setq system-username "${config.monorepo.vars.internetName}") (setq system-fullname "${config.monorepo.vars.fullName}") (org-babel-load-file (expand-file-name "~/${config.monorepo.vars.repoName}/config/emacs.org"))''; extraPackages = epkgs: [ epkgs.agda2-mode epkgs.all-the-icons epkgs.auctex epkgs.catppuccin-theme epkgs.chatgpt-shell epkgs.company epkgs.company-solidity epkgs.counsel epkgs.dashboard epkgs.doom-themes epkgs.doom-modeline epkgs.elfeed epkgs.elfeed-org epkgs.elfeed-tube epkgs.elfeed-tube-mpv epkgs.ellama epkgs.elpher epkgs.ement epkgs.emmet-mode epkgs.emms epkgs.enwc epkgs.evil epkgs.evil-collection epkgs.evil-commentary epkgs.evil-org epkgs.f epkgs.flycheck epkgs.general epkgs.gptel epkgs.gruvbox-theme epkgs.haskell-mode epkgs.htmlize epkgs.idris-mode epkgs.irony-eldoc epkgs.ivy epkgs.ivy-pass epkgs.kiwix epkgs.latex-preview-pane epkgs.lsp-ivy epkgs.lsp-mode epkgs.lsp-haskell epkgs.lyrics-fetcher epkgs.mastodon epkgs.magit epkgs.magit-delta epkgs.mu4e epkgs.minuet epkgs.nix-mode epkgs.org-fragtog epkgs.org-journal epkgs.org-roam epkgs.org-roam-ui epkgs.org-superstar epkgs.page-break-lines epkgs.password-store epkgs.pdf-tools epkgs.pinentry epkgs.platformio-mode epkgs.projectile epkgs.rustic epkgs.scad-mode epkgs.simple-httpd epkgs.solidity-flycheck epkgs.solidity-mode epkgs.sudo-edit epkgs.treemacs epkgs.treemacs-evil epkgs.treemacs-magit epkgs.treemacs-projectile epkgs.treesit-auto epkgs.typescript-mode epkgs.unicode-fonts epkgs.use-package epkgs.vterm epkgs.wgrep epkgs.web-mode epkgs.websocket epkgs.which-key epkgs.writegood-mode epkgs.writeroom-mode epkgs.yaml-mode epkgs.yasnippet epkgs.yasnippet-snippets ]; }; } #+end_src *** Gammastep This is a program like redshift for making your screen emit more red and less blue light. Here I have the long and lat set for Vancouver, but you should replace it if you live outside the timezone. #+begin_src nix :tangle ../nix/modules/home/gammastep.nix { lib, config, ... }: { services.gammastep = { enable = lib.mkDefault config.monorepo.profiles.graphics.enable; provider = "manual"; latitude = 49.282730; longitude = -123.120735; temperature = { day = 5000; night = 3000; }; settings = { general = { adjustment-method = "wayland"; }; }; }; } #+end_src *** Git My git configuration uses information set in the ~vars.nix~ in order to set configuration options. Make sure those are set correctly. I've set it to sign by default. #+begin_src nix :tangle ../nix/modules/home/git.nix { lib, config, ... }: { programs.git = { enable = lib.mkDefault config.monorepo.profiles.graphics.enable; userName = config.monorepo.vars.fullName; userEmail = config.monorepo.profiles.email.email; signing = { key = config.monorepo.vars.gpgKey; signByDefault = true; }; extraConfig = { init.defaultBranch = "main"; }; aliases = { pl = "pull"; ps = "push"; co = "checkout"; c = "commit"; a = "add"; st = "status"; sw = "switch"; b = "branch"; }; }; } #+end_src *** Hyprland My compositor/window manager. This automatically starts on startup. Instructions on how to use this component will come soon. #+begin_src nix :tangle ../nix/modules/home/hyprland.nix { lib, config, wallpapers, pkgs, scripts, ... }: { wayland.windowManager.hyprland = { enable = lib.mkDefault config.monorepo.profiles.hyprland.enable; package = pkgs.hyprland; xwayland.enable = true; systemd.enable = true; settings = { "$mod" = "SUPER"; bezier = [ "overshot,0,1,0,0.95" ]; animation = [ "workspaces, 1, 10, overshot" ]; exec-once = [ "waybar" "swww-daemon --format xrgb" "swww img ${wallpapers}/imagination.png" "fcitx5-remote -r" "fcitx5 -d --replace" "fcitx5-remote -r" "emacs" "firefox" ]; env = [ "LIBVA_DRIVER_NAME,nvidia" "XDG_SESSION_TYPE,wayland" "GBM_BACKEND,nvidia-drm" "__GLX_VENDOR_LIBRARY_NAME,nvidia" "ELECTRON_OZONE_PLATFORM_HINT,auto" ]; blurls = [ "waybar" ]; monitor = [ "Unknown-1,disable" ]; windowrulev2 = [ "workspace 1, class:^(emacs)$" "workspace 2, class:^(firefox)$" "workspace 2, title:^(.*Tor Browser.*)$" "workspace 2, title:^(.*Chromium-browser.*)$" "workspace 2, class:^(chromium)$" "workspace 3, class:^(discord)$" "workspace 3, class:^(vesktop)$" "workspace 3, title:^(.*fluffychat.*)$" "workspace 3, class:^(.*element-desktop.*)$" "workspace 4, class:^(.*qpwgraph.*)$" "workspace 4, class:^(.*mpv.*)$" "workspace 5, title:^(.*Monero.*)$" "workspace 5, title:^(.*org\.bitcoin\..*)$" "workspace 5, title:^(.*Bitcoin Core - preston.*)$" "workspace 5, title:^(.*org\.getmonero\..*)$" "workspace 5, title:^(.*Monero - preston.*)$" "workspace 5, title:^(.*electrum.*)$" "pseudo,title:fcitx" ]; bind = [ "$mod, F, exec, firefox" "$mod, T, exec, tor-browser" "$mod, Return, exec, kitty" "$mod, E, exec, emacs" "$mod, B, exec, bitcoin-qt" "$mod, M, exec, monero-wallet-gui" "$mod, V, exec, vesktop" "$mod, C, exec, fluffychat" "$mod, D, exec, wofi --show run" "$mod, P, exec, bash ${scripts}/powermenu.sh" "$mod, Q, killactive" "$mod SHIFT, H, movewindow, l" "$mod SHIFT, L, movewindow, r" "$mod SHIFT, K, movewindow, u" "$mod SHIFT, J, movewindow, d" "$mod, H, movefocus, l" "$mod, L, movefocus, r" "$mod, K, movefocus, u" "$mod, J, movefocus, d" ", XF86AudioPlay, exec, mpc toggle" ", Print, exec, grim" ] ++ ( builtins.concatLists (builtins.genList ( x: let ws = let c = (x + 1) / 10; in builtins.toString (x + 1 - (c * 10)); in [ "$mod, ${ws}, workspace, ${toString (x + 1)}" "$mod SHIFT, ${ws}, movetoworkspace, ${toString (x + 1)}" ] ) 10) ); bindm = [ "$mod, mouse:272, movewindow" "$mod, mouse:273, resizewindow" "$mod ALT, mouse:272, resizewindow" ]; binde = [ ", XF86AudioRaiseVolume, exec, wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%+" ", XF86AudioLowerVolume, exec, wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%-" ", XF86AudioNext, exec, mpc next" ", XF86AudioPrev, exec, mpc prev" ", XF86MonBrightnessUp , exec, xbacklight -inc 10" ", XF86MonBrightnessDown, exec, xbacklight -dec 10" ]; decoration = { blur = { enabled = true; size = 5; passes = 2; }; rounding = 5; }; device = { name = "beken-usb-gaming-mouse-1"; sensitivity = -0.5; }; input = { kb_options = "caps:swapescape"; repeat_delay = 300; repeat_rate = 50; natural_scroll = true; touchpad = { natural_scroll = true; disable_while_typing = true; tap-to-click = true; }; }; cursor = { no_hardware_cursors = true; }; misc = { force_default_wallpaper = 0; disable_hyprland_logo = true; }; }; }; } #+end_src *** Kitty I've set my terminal, kitty, to use catppuccin colors. #+begin_src nix :tangle ../nix/modules/home/kitty.nix { lib, config, ... }: { programs.kitty = { enable = lib.mkDefault (config.monorepo.profiles.hyprland.enable && config.monorepo.profiles.graphics.enable); settings = { enable_audio_bell = false; font_family = "Iosevka Nerd Font"; font_size = 14; confirm_os_window_close = 0; background_opacity = "0.9"; # Catppuccin theme foreground = "#cdd6f4"; background = "#1e1e2e"; selection_foreground = "#1e1e2e"; selection_background = "#f5e0dc"; cursor = "#f5e0dc"; cursor_text_color = "#1e1e2e"; url_color = "#f5e0dc"; active_border_color = "#B4BEFE"; inactive_border_color = "#6C7086"; bell_border_color = "#F9E2AF"; wayland_titlebar_color = "#1E1E2E"; macos_titlebar_color = "#1E1E2E"; active_tab_foreground = "#11111B"; active_tab_background = "#CBA6F7"; inactive_tab_foreground = "#CDD6F4"; inactive_tab_background = "#181825"; tab_bar_background = "#11111B"; mark1_foreground = "#1E1E2E"; mark1_background = "#B4BEFE"; mark2_foreground = "#1E1E2E"; mark2_background = "#CBA6F7"; mark3_foreground = "#1E1E2E"; mark3_background = "#74C7EC"; color0 = "#45475A"; color8 = "#585B70"; color1 = "#F38BA8"; color9 = "#F38BA8"; color2 = "#A6E3A1"; color10 = "#A6E3A1"; color3 = "#F9E2AF"; color11 = "#F9E2AF"; color4 = "#89B4FA"; color12 = "#89B4FA"; color5 = "#F5C2E7"; color13 = "#F5C2E7"; color6 = "#94E2D5"; color14 = "#94E2D5"; color7 = "#BAC2DE"; color15 = "#A6ADC8"; }; }; } #+end_src *** Mako This is my notification system. My flake automatically fetches the notification sound, so you are all set from the get-go! #+begin_src nix :tangle ../nix/modules/home/mako.nix { lib, config, sounds, ... }: { services.mako = { enable = lib.mkDefault config.monorepo.profiles.graphics.enable; settings = { on-notify = "exec mpv ${sounds}/polite.ogg --no-config --no-video"; background-color = "#11111bf8"; text-color = "#cdd6f4"; border-color = "#89b4faff"; border-radius = 1; font = "Fira Code 10"; default-timeout = 3000; }; }; } #+end_src *** Mbsync Note that in order to use my email configuration, your imaps and smtps servers must be encrypted. This module uses the ~vars.nix~ as well as the home ~default.nix~ options. #+begin_src nix :tangle ../nix/modules/home/mbsync.nix { lib, config, ... }: { programs.mbsync = { enable = lib.mkDefault config.monorepo.profiles.email.enable; extraConfig = '' IMAPAccount ${config.monorepo.vars.internetName} Host ${config.monorepo.profiles.email.imapsServer} User ${config.monorepo.profiles.email.email} PassCmd "cat ${config.sops.secrets.mail.path}" Port 993 TLSType IMAPS AuthMechs * CertificateFile /etc/ssl/certs/ca-certificates.crt IMAPStore ${config.monorepo.vars.internetName}-remote Account ${config.monorepo.vars.internetName} MaildirStore ${config.monorepo.vars.internetName}-local Path ~/email/${config.monorepo.vars.internetName}/ Inbox ~/email/${config.monorepo.vars.internetName}/INBOX SubFolders Verbatim Channel ${config.monorepo.vars.internetName} Far :${config.monorepo.vars.internetName}-remote: Near :${config.monorepo.vars.internetName}-local: Patterns * Create Near Sync All Expunge None SyncState * ''; }; } #+end_src *** MSMTP This is the program I use to send email from emacs. It is really the same thing as above, just set the options to the ones you want in your system ~default.nix~. #+begin_src nix :tangle ../nix/modules/home/msmtp.nix { lib, config, ... }: { programs.msmtp = { enable = lib.mkDefault config.monorepo.profiles.email.enable; extraConfig = '' # Set default values for all following accounts. defaults auth on tls on tls_trust_file /etc/ssl/certs/ca-certificates.crt tls_certcheck off logfile ~/.msmtp.log # Gmail account ${config.monorepo.vars.userName} host ${config.monorepo.profiles.email.smtpsServer} port 587 from ${config.monorepo.profiles.email.email} user ${config.monorepo.profiles.email.email} passwordeval "cat ${config.sops.secrets.mail.path}" # Set a default account account default : ${config.monorepo.vars.userName} ''; }; } #+end_src *** Mpd This mpd configuration uses pipewire by default, and it should just work if you place music in the ~~/music~ directory and then run ~mpc add /~ afterwards. #+begin_src nix :tangle ../nix/modules/home/mpd.nix { lib, config, ... }: { services.mpd = { enable = lib.mkDefault config.monorepo.profiles.music.enable; dbFile = "/home/${config.monorepo.vars.userName}/.config/mpd/db"; dataDir = "/home/${config.monorepo.vars.userName}/.config/mpd/"; network.port = 6600; musicDirectory = "/home/${config.monorepo.vars.userName}/music"; playlistDirectory = "/home/${config.monorepo.vars.userName}/.config/mpd/playlists"; network.listenAddress = "0.0.0.0"; extraConfig = '' audio_output { type "pipewire" name "pipewire output" } audio_output { type "httpd" name "My HTTP Stream" encoder "opus" # optional port "8000" # quality "5.0" # do not define if bitrate is defined bitrate "128000" # do not define if quality is defined format "48000:16:1" always_on "yes" # prevent MPD from disconnecting all listeners when playback is stopped. tags "yes" # httpd supports sending tags to listening streams. } audio_output { type "shout" encoding "ogg" name "my cool stream" host "localhost" port "8000" mount "/example.ogg" user "source" password "" bitrate "64" format "44100:16:1" description "Nullring public radio" } ''; }; } #+end_src *** MPV I have some emacs + yt-dlp integrations with mpv with my rss feed, and therefore we need it here: #+begin_src nix :tangle ../nix/modules/home/mpv.nix { lib, config, ... }: { programs.mpv = { enable = lib.mkDefault config.monorepo.profiles.graphics.enable; config = { profile = "gpu-hq"; force-window = true; ytdl-format = "bestvideo+bestaudio"; cache-default = 4000000; }; }; } #+end_src *** Secrets This uses sops in order to declaratively create the secrets on my system by unencrypting the yaml file specified. Yes, this is safe to include in the repo. #+begin_src nix :tangle ../nix/modules/home/secrets.nix { config, ... }: { sops = { defaultSopsFile = ../../secrets/secrets.yaml; age = { keyFile = "/home/${config.monorepo.vars.userName}/.ssh/keys.txt"; }; secrets = { mail = { format = "yaml"; path = "${config.sops.defaultSymlinkPath}/mail"; }; cloudflare-dns = { format = "yaml"; path = "${config.sops.defaultSymlinkPath}/cloudflare-dns"; }; digikey = { format = "yaml"; path = "${config.sops.defaultSymlinkPath}/digikey"; }; dn42 = { format = "yaml"; path = "${config.sops.defaultSymlinkPath}/dn42"; }; znc = { format = "yaml"; path = "${config.sops.defaultSymlinkPath}/znc"; }; znc_password_salt = { format = "yaml"; path = "${config.sops.defaultSymlinkPath}/znc_password_salt"; }; znc_password_hash = { format = "yaml"; path = "${config.sops.defaultSymlinkPath}/znc_password_hash"; }; matrix_bridge = { format = "yaml"; path = "${config.sops.defaultSymlinkPath}/matrix_bridge"; }; }; defaultSymlinkPath = "/run/user/1000/secrets"; defaultSecretsMountPoint = "/run/user/1000/secrets.d"; }; } #+end_src *** Waybar This is the bar I use for my hyprland configuration. You will need to adjust the monitors field in the ~default.nix~ for it to really appear. #+begin_src nix :tangle ../nix/modules/home/waybar.nix { lib, config, ... }: { programs.waybar = { enable = lib.mkDefault config.monorepo.profiles.hyprland.enable; style = '' ,* { border: none; border-radius: 0px; font-family: Iosevka Nerd Font, FontAwesome, Noto Sans CJK; font-size: 14px; font-style: normal; min-height: 0; } window#waybar { background: rgba(30, 30, 46, 0.5); border-bottom: 1px solid #45475a; color: #cdd6f4; } #workspaces { background: #45475a; margin: 5px 5px 5px 5px; padding: 0px 5px 0px 5px; border-radius: 16px; border: solid 0px #f4d9e1; font-weight: normal; font-style: normal; } #workspaces button { padding: 0px 5px; border-radius: 16px; color: #a6adc8; } #workspaces button.active { color: #f4d9e1; background-color: transparent; border-radius: 16px; } #workspaces button:hover { background-color: #cdd6f4; color: black; border-radius: 16px; } #custom-date, #clock, #battery, #pulseaudio, #network, #custom-randwall, #custom-launcher { background: transparent; padding: 5px 5px 5px 5px; margin: 5px 5px 5px 5px; border-radius: 8px; border: solid 0px #f4d9e1; } #custom-date { color: #D3869B; } #custom-power { color: #24283b; background-color: #db4b4b; border-radius: 5px; margin-right: 10px; margin-top: 5px; margin-bottom: 5px; margin-left: 0px; padding: 5px 10px; } #tray { background: #45475a; margin: 5px 5px 5px 5px; border-radius: 16px; padding: 0px 5px; /*border-right: solid 1px #282738;*/ } #clock { color: #cdd6f4; background-color: #45475a; border-radius: 0px 0px 0px 24px; padding-left: 13px; padding-right: 15px; margin-right: 0px; margin-left: 10px; margin-top: 0px; margin-bottom: 0px; font-weight: bold; /*border-left: solid 1px #282738;*/ } #battery { color: #89b4fa; } #battery.charging { color: #a6e3a1; } #battery.warning:not(.charging) { background-color: #f7768e; color: #f38ba8; border-radius: 5px 5px 5px 5px; } #backlight { background-color: #24283b; color: #db4b4b; border-radius: 0px 0px 0px 0px; margin: 5px; margin-left: 0px; margin-right: 0px; padding: 0px 0px; } #network { color: #f4d9e1; border-radius: 8px; margin-right: 5px; } #pulseaudio { color: #f4d9e1; border-radius: 8px; margin-left: 0px; } #pulseaudio.muted { background: transparent; color: #928374; border-radius: 8px; margin-left: 0px; } #custom-randwall { color: #f4d9e1; border-radius: 8px; margin-right: 0px; } #custom-launcher { color: #e5809e; background-color: #45475a; border-radius: 0px 24px 0px 0px; margin: 0px 0px 0px 0px; padding: 0 20px 0 13px; /*border-right: solid 1px #282738;*/ font-size: 20px; } #custom-launcher button:hover { background-color: #FB4934; color: transparent; border-radius: 8px; margin-right: -5px; margin-left: 10px; } #custom-playerctl { background: #45475a; padding-left: 15px; padding-right: 14px; border-radius: 16px; /*border-left: solid 1px #282738;*/ /*border-right: solid 1px #282738;*/ margin-top: 5px; margin-bottom: 5px; margin-left: 0px; font-weight: normal; font-style: normal; font-size: 16px; } #custom-playerlabel { background: transparent; padding-left: 10px; padding-right: 15px; border-radius: 16px; /*border-left: solid 1px #282738;*/ /*border-right: solid 1px #282738;*/ margin-top: 5px; margin-bottom: 5px; font-weight: normal; font-style: normal; } #window { background: #45475a; padding-left: 15px; padding-right: 15px; border-radius: 16px; /*border-left: solid 1px #282738;*/ /*border-right: solid 1px #282738;*/ margin-top: 5px; margin-bottom: 5px; font-weight: normal; font-style: normal; } #custom-wf-recorder { padding: 0 20px; color: #e5809e; background-color: #1E1E2E; } #cpu { background-color: #45475a; /*color: #FABD2D;*/ border-radius: 16px; margin: 5px; margin-left: 5px; margin-right: 5px; padding: 0px 10px 0px 10px; font-weight: bold; } #memory { background-color: #45475a; /*color: #83A598;*/ border-radius: 16px; margin: 5px; margin-left: 5px; margin-right: 5px; padding: 0px 10px 0px 10px; font-weight: bold; } #disk { background-color: #45475a; /*color: #8EC07C;*/ border-radius: 16px; margin: 5px; margin-left: 5px; margin-right: 5px; padding: 0px 10px 0px 10px; font-weight: bold; } #custom-hyprpicker { background-color: #45475a; /*color: #8EC07C;*/ border-radius: 16px; margin: 5px; margin-left: 5px; margin-right: 5px; padding: 0px 11px 0px 9px; font-weight: bold; } ''; settings = { mainBar = { layer = "top"; position = "top"; height = 50; output = config.monorepo.vars.monitors; modules-left = [ "hyprland/workspaces" ]; modules-center = [ "hyprland/window" ]; modules-right = [ "battery" "clock" ]; battery = { format = "{icon} {capacity}%"; format-icons = ["" "" "" "" "" ]; }; clock = { format = "⏰ {:%a %d, %b %H:%M}"; }; }; }; }; } #+end_src *** Wofi This is a run launcher for wayland. I also use it for my powermenu. #+begin_src nix :tangle ../nix/modules/home/wofi.nix { lib, config, ... }: { programs.wofi = { enable = lib.mkDefault config.monorepo.profiles.graphics.enable; settings = { location = "bottom-right"; allow_markup = true; show = "drun"; width = 750; height = 400; always_parse_args = true; show_all = false; term = "kitty"; hide_scroll = true; print_command = true; insensitive = true; prompt = "Run what, Commander?"; columns = 2; }; style = '' @define-color rosewater #f5e0dc; @define-color rosewater-rgb rgb(245, 224, 220); @define-color flamingo #f2cdcd; @define-color flamingo-rgb rgb(242, 205, 205); @define-color pink #f5c2e7; @define-color pink-rgb rgb(245, 194, 231); @define-color mauve #cba6f7; @define-color mauve-rgb rgb(203, 166, 247); @define-color red #f38ba8; @define-color red-rgb rgb(243, 139, 168); @define-color maroon #eba0ac; @define-color maroon-rgb rgb(235, 160, 172); @define-color peach #fab387; @define-color peach-rgb rgb(250, 179, 135); @define-color yellow #f9e2af; @define-color yellow-rgb rgb(249, 226, 175); @define-color green #a6e3a1; @define-color green-rgb rgb(166, 227, 161); @define-color teal #94e2d5; @define-color teal-rgb rgb(148, 226, 213); @define-color sky #89dceb; @define-color sky-rgb rgb(137, 220, 235); @define-color sapphire #74c7ec; @define-color sapphire-rgb rgb(116, 199, 236); @define-color blue #89b4fa; @define-color blue-rgb rgb(137, 180, 250); @define-color lavender #b4befe; @define-color lavender-rgb rgb(180, 190, 254); @define-color text #cdd6f4; @define-color text-rgb rgb(205, 214, 244); @define-color subtext1 #bac2de; @define-color subtext1-rgb rgb(186, 194, 222); @define-color subtext0 #a6adc8; @define-color subtext0-rgb rgb(166, 173, 200); @define-color overlay2 #9399b2; @define-color overlay2-rgb rgb(147, 153, 178); @define-color overlay1 #7f849c; @define-color overlay1-rgb rgb(127, 132, 156); @define-color overlay0 #6c7086; @define-color overlay0-rgb rgb(108, 112, 134); @define-color surface2 #585b70; @define-color surface2-rgb rgb(88, 91, 112); @define-color surface1 #45475a; @define-color surface1-rgb rgb(69, 71, 90); @define-color surface0 #313244; @define-color surface0-rgb rgb(49, 50, 68); @define-color base #1e1e2e; @define-color base-rgb rgb(30, 30, 46); @define-color mantle #181825; @define-color mantle-rgb rgb(24, 24, 37); @define-color crust #11111b; @define-color crust-rgb rgb(17, 17, 27); * { font-family: 'Iosevka Nerd Font', monospace; font-size: 14px; } /* Window */ window { margin: 0px; padding: 10px; border: 0.16em solid @lavender; border-radius: 0.1em; background-color: @base; animation: slideIn 0.5s ease-in-out both; } /* Slide In */ @keyframes slideIn { 0% { opacity: 0; } 100% { opacity: 1; } } /* Inner Box */ #inner-box { margin: 5px; padding: 10px; border: none; background-color: @base; animation: fadeIn 0.5s ease-in-out both; } /* Fade In */ @keyframes fadeIn { 0% { opacity: 0; } 100% { opacity: 1; } } /* Outer Box */ #outer-box { margin: 5px; padding: 10px; border: none; background-color: @base; } /* Scroll */ #scroll { margin: 0px; padding: 10px; border: none; background-color: @base; } /* Input */ #input { margin: 5px 20px; padding: 10px; border: none; border-radius: 0.1em; color: @text; background-color: @base; animation: fadeIn 0.5s ease-in-out both; } #input image { border: none; color: @red; } #input * { outline: 4px solid @red!important; } /* Text */ #text { margin: 5px; border: none; color: @text; animation: fadeIn 0.5s ease-in-out both; } #entry { background-color: @base; } #entry arrow { border: none; color: @lavender; } /* Selected Entry */ #entry:selected { border: 0.11em solid @lavender; } #entry:selected #text { color: @mauve; } #entry:drop(active) { background-color: @lavender!important; } ''; }; } #+end_src *** yt-dlp A classic program that allows you to download from youtube. Also has integrations with mpv. #+begin_src nix :tangle ../nix/modules/home/yt-dlp.nix { lib, config, ... }: { programs.yt-dlp = { enable = lib.mkDefault config.monorepo.profiles.graphics.enable; settings = { embed-thumbnail = true; embed-subs = true; sub-langs = "all"; downloader = "aria2c"; downloader-args = "aria2c:'-c -x8 -s8 -k1M'"; }; }; } #+end_src *** Zsh My zsh config has some useful aliases that one should read through. Otherwise it is pretty standard. #+begin_src nix :tangle ../nix/modules/home/zsh.nix { lib, config, pkgs, systemHostName, ... }: { programs.zsh = { enable = true; initContent = '' umask 0022 export EXTRA_CCFLAGS="-I/usr/include" source ${pkgs.zsh-vi-mode}/share/zsh-vi-mode/zsh-vi-mode.plugin.zsh export QT_QPA_PLATFORM="wayland" export OLLAMA_MODEL="qwen3:14b" ''; localVariables = { EDITOR = "emacsclient --create-frame --alternate-editor=vim"; INPUT_METHOD = "fcitx"; QT_IM_MODULE = "fcitx"; GTK_IM_MODULE = "fcitx"; XMODIFIERS = "@im=fcitx"; XIM_SERVERS = "fcitx"; WXSUPPRESS_SIZER_FLAGS_CHECK = "1"; }; shellAliases = { get-channel-id = "yt-dlp --print \"%(channel_id)s\" --playlist-end 1 \"$1\""; se = "sops edit"; f = "vim $(fzf)"; e = "cd $(find . -type d -print | fzf)"; c = "clear"; g = "git"; v = "vim"; py = "python3"; rb = "sudo nixos-rebuild switch --flake $HOME/monorepo/nix#${systemHostName}"; nfu = "cd ~/monorepo/nix && git add . && git commit -m \"new flake lock\" && nix flake update"; usync = "rsync -azvP --chmod=\"Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r\" ~/website_html/ root@${config.monorepo.vars.remoteHost}:/var/www/${config.monorepo.vars.internetName}-website/"; usite = "cd ~/src/publish-org-roam-ui && bash local.sh && rm -rf ~/website_html/graph_view; cp -r ~/src/publish-org-roam-ui/out ~/website_html/graph_view && rsync -azvP --chmod=\"Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r\" ~/website_html/ root@${config.monorepo.vars.remoteHost}:/var/www/${config.monorepo.vars.internetName}-website/"; sai = "eval \"$(ssh-agent -s)\" && ssh-add ~/.ssh/id_ed25519 && ssh-add -l"; i3 = "exec ${pkgs.i3-gaps}/bin/i3"; }; loginExtra = '' if [[ "$(tty)" = "/dev/tty1" ]]; then exec Hyprland fi ''; }; } #+end_src *** Pantalaimon This is used with ement as a proxy in order to connect to a remote matrix server while having encryption. #+begin_src nix :tangle ../nix/modules/home/pantalaimon.nix { lib, config, ... }: { services.pantalaimon = { enable = lib.mkDefault config.monorepo.profiles.graphics.enable; settings = { Default = { LogLevel = "Debug"; SSL = true; }; local-matrix = { Homeserver = "https://matrix.${config.monorepo.vars.orgHost}"; ListenAddress = "127.0.0.1"; ListenPort = "8008"; }; }; }; } #+end_src *** User This configuration is the backbone configuration for the default user. It specifies some generally useful packages and something every home should have, as well as some dependencies for these configurations. #+begin_src nix :tangle ../nix/modules/home/user.nix { lib, config, pkgs, ... }: { home = { activation.startup-files = lib.hm.dag.entryAfter [ "installPackages" ] '' if [ ! -d "/home/${config.monorepo.vars.userName}/email/${config.monorepo.vars.internetName}/" ]; then mkdir -p /home/${config.monorepo.vars.userName}/email/${config.monorepo.vars.internetName}/ fi if [ ! -d "/home/${config.monorepo.vars.userName}/music" ]; then mkdir -p /home/${config.monorepo.vars.userName}/music fi if [ ! -d /home/${config.monorepo.vars.userName}/org ]; then mkdir -p /home/${config.monorepo.vars.userName}/org fi if [ ! -d /home/${config.monorepo.vars.userName}/src ]; then mkdir -p /home/${config.monorepo.vars.userName}/src fi touch /home/${config.monorepo.vars.userName}/org/agenda.org touch /home/${config.monorepo.vars.userName}/org/notes.org ''; enableNixpkgsReleaseCheck = false; username = config.monorepo.vars.userName; homeDirectory = "/home/${config.monorepo.vars.userName}"; stateVersion = "24.11"; packages = with pkgs; (if config.monorepo.profiles.graphics.enable then [ # wikipedia # kiwix kiwix-tools mupdf zathura fzf # passwords age sops # formatting ghostscript texliveFull pandoc # Emacs Deps graphviz jq # Apps # octaveFull vesktop grim swww vim telegram-desktop qwen-code fluffychat # Sound/media pavucontrol alsa-utils imagemagick ffmpeg helvum # Net curl rsync git iamb # Tor torsocks tor-browser # fonts nerd-fonts.iosevka noto-fonts noto-fonts-cjk-sans noto-fonts-emoji fira-code font-awesome_6 victor-mono (aspellWithDicts (dicts: with dicts; [ en en-computers en-science ])) # Misc. pinentry x11_ssh_askpass xdg-utils acpilight pfetch libnotify htop (pkgs.writeShellScriptBin "help" '' #!/usr/bin/env sh # Portable, colored, nicely aligned alias list # Generate uncolored alias pairs aliases=$(cat <<'EOF' ${let aliases = config.programs.zsh.shellAliases; in lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: "${name} -> ${value}" ) aliases)} EOF ) # Align and color using awk echo "$aliases" | awk ' BEGIN { GREEN="\033[0;32m"; YELLOW="\033[0;33m"; RESET="\033[0m"; maxlen=0; } { # Split line on " -> " split($0, parts, / -> /); name[NR]=parts[1]; cmd[NR]=parts[2]; if(length(parts[1])>maxlen) maxlen=length(parts[1]); } END { for(i=1;i<=NR;i++) { # printf with fixed width for alias name printf "%s%-*s%s -> %s%s%s\n", GREEN, maxlen, name[i], RESET, YELLOW, cmd[i], RESET; } }' '') (writeShellScriptBin "remote-build" '' #!/bin/bash nixos-rebuild --sudo --ask-sudo-password --target-host "$1" switch --flake $HOME/monorepo/nix#spontaneity '' ) (writeShellScriptBin "install-vps" '' #!/bin/bash nix run github:nix-community/nixos-anywhere -- --generate-hardware-config nixos-generate-config $HOME/monorepo/nix/systems/spontaneity/hardware-configuration.nix --flake $HOME/monorepo/nix#spontaneity --target-host "$1" '') ] else [ pfetch # net curl torsocks rsync ]); }; services = { gpg-agent = { pinentry.package = pkgs.pinentry-emacs; enable = true; extraConfig = '' allow-emacs-pinentry allow-loopback-pinentry ''; }; }; programs.bash.enable = true; gtk = { enable = lib.mkDefault config.monorepo.profiles.graphics.enable; theme = null; iconTheme = null; }; fonts.fontconfig.enable = true; } #+end_src * Systems ** Home This module dynamically imports the correct corresponding home.nix at the path. #+begin_src nix :tangle ../nix/systems/home.nix { config, sops-nix, ... }: { home-manager = { sharedModules = [ sops-nix.homeManagerModules.sops ]; useGlobalPkgs = true; useUserPackages = true; users."${config.monorepo.vars.userName}" = import (./. + "/${config.networking.hostName}/home.nix"); }; } #+end_src ** Common These are the common includes for each of my systems. This ensures that we don't have to duplicate includes every time we want to add a new system. Also more common configuration can go here. #+begin_src nix :tangle ../nix/systems/common.nix { config, lib, ... }: { imports = [ ./home.nix ../modules/default.nix ]; # Put configuration (e.g. monorepo variable configuration) common to all configs here } #+end_src ** Home Manager Common #+begin_src nix :tangle ../nix/systems/home-common.nix { lib, config, ... }: { imports = [ ../modules/home/default.nix ]; # Put configuration (e.g. monorepo variable configuration) common to all configs here } #+end_src ** Continuity This is pretty understandable, if you understand all the above. #+begin_src nix :tangle ../nix/systems/continuity/default.nix { ... }: { imports = [ ../../disko/btrfs-simple.nix ../common.nix ]; config = { monorepo = { profiles.impermanence.enable = true; vars = { device = "/dev/sda"; fileSystem = "btrfs"; }; }; }; } #+end_src *** Home Each system has a corresponding home configuration in order to set monorepo home options. #+begin_src nix :tangle ../nix/systems/continuity/home.nix { lib, config, pkgs, ... }: { imports = [ ../home-common.nix ]; config.monorepo.profiles.workstation.enable = false; } #+end_src ** Affinity This is my configuration for my workstation. It runs ollama, as well as several other useful services. #+begin_src nix :tangle ../nix/systems/affinity/default.nix { config, lib, home-manager, ... }: { imports = [ ../common.nix ../../disko/drive-simple.nix ]; config = { monorepo = { vars.device = "/dev/nvme0n1"; profiles = { server.enable = false; cuda.enable = true; workstation.enable = true; }; }; }; } #+end_src *** Home I want cuda in home manager too. #+begin_src nix :tangle ../nix/systems/affinity/home.nix { lib, config, pkgs, ... }: { imports = [ ../home-common.nix ]; config.monorepo = { profiles.cuda.enable = true; }; } #+end_src ** Spontaneity Spontaneity is my VPS instance. #+begin_src nix :tangle ../nix/systems/spontaneity/default.nix { config, lib, ... }: let ipv4addr = "66.42.84.130"; ipv6addr = "2001:19f0:5401:10d0:5400:5ff:fe4a:7794"; in { imports = [ ../common.nix ../../disko/drive-bios.nix # nixos-anywhere generates this file ./hardware-configuration.nix ]; config = { monorepo = { vars.device = "/dev/vda"; profiles = { server.enable = true; ttyonly.enable = true; grub.enable = true; }; }; boot.loader.grub.device = "nodev"; networking = { interfaces.ens3.ipv6.addresses = [ { address = ipv6addr; prefixLength = 64; } ]; firewall.allowedTCPPorts = [ 80 143 443 465 587 993 6697 6667 8448 ]; domains = { enable = true; baseDomains = { "${config.monorepo.vars.remoteHost}" = { a.data = ipv4addr; aaaa.data = ipv6addr; }; "${config.monorepo.vars.orgHost}" = { a.data = ipv4addr; aaaa.data = ipv6addr; }; }; subDomains = { "${config.monorepo.vars.remoteHost}" = {}; "matrix.${config.monorepo.vars.remoteHost}" = {}; "www.${config.monorepo.vars.remoteHost}" = {}; "mail.${config.monorepo.vars.remoteHost}" = { mx.data = "10 mail.${config.monorepo.vars.remoteHost}."; }; "${config.monorepo.vars.orgHost}" = {}; "git.${config.monorepo.vars.orgHost}" = {}; "matrix.${config.monorepo.vars.orgHost}" = {}; "talk.${config.monorepo.vars.orgHost}" = {}; "mail.${config.monorepo.vars.orgHost}" = {}; "${config.monorepo.vars.internetName}.${config.monorepo.vars.orgHost}" = {}; }; }; }; }; } #+end_src *** Home #+begin_src nix :tangle ../nix/systems/spontaneity/home.nix { lib, config, pkgs, ... }: { imports = [ ../home-common.nix ]; config.monorepo.profiles.enable = false; } #+end_src ** Installer My installer installs my systems almost completely without interaction. You can also make them install the exact version of the system that you want it to by pinning the commits to make it always work in the exact same deterministic way. *** Commit Hash Pinning Modify this to pin the installer image hash to make the installer image always work deterministically. #+begin_src nix :tangle ../nix/systems/installer/commits.nix { diskoCommitHash = "c8a0e78d86b12ea67be6ed0f7cae7f9bfabae75a"; monorepoCommitHash = "e2fbfac7ad7c0b4d438179b31d2ed53d884313a0"; monorepoUrl = "https://github.com/ret2pop/monorepo"; } #+end_src *** ISO Default Profile This contains the installation script I use to install my systems. #+begin_src nix :tangle ../nix/systems/installer/default.nix { pkgs, config, lib, modulesPath, ... }: let commits = import ./commits.nix; in { imports = [ (modulesPath + "/installer/cd-dvd/installation-cd-minimal.nix") ]; networking = { networkmanager = { enable = true; }; firewall = { allowedTCPPorts = [ 22 ]; allowedUDPPorts = [ ]; }; wireless.enable = false; }; services.openssh = { enable = true; ports = [ 22 ]; settings = { PasswordAuthentication = false; AllowUsers = null; UseDns = true; PermitRootLogin = lib.mkForce "prohibit-password"; }; }; users.extraUsers.root.password = "nixos"; users.extraUsers.nixos.password = "nixos"; users.users = { root.openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICts6+MQiMwpA+DfFQxjIN214Jn0pCw/2BDvOzPhR/H2 preston@continuity-dell" ]; nixos = { packages = with pkgs; [ git curl gum (writeShellScriptBin "nix_installer" '' #!/usr/bin/env bash set -euo pipefail if [ "$(id -u)" -eq 0 ]; then echo "ERROR! $(basename "$0") should be run as a regular user" exit 1 fi gum style --border normal --margin "1" --padding "1 2" "Notice: if using full disk encryption, write to /tmp/secret.key first with your password." sleep 3 cd "$HOME" ping -q -c1 google.com &>/dev/null && echo "online! Proceeding with the installation..." || nmtui if [ ! -d "$HOME/monorepo/" ]; then git clone ${commits.monorepoUrl} cd "$HOME/monorepo" git checkout "${commits.monorepoCommitHash}" cd "$HOME" fi gum style --border normal --margin "1" --padding "1 2" "Choose a system to install or select `new` in order to create a new system." SYSTEM="$(gum choose $(find "$HOME/monorepo/nix/systems" -mindepth 1 -maxdepth 1 -type d -printf "%f\n" | grep -v -E 'installer'; printf "New"))" if [[ "$SYSTEM" == "New" ]]; then gum style --border normal --margin "1" --padding "1 2" "Choose a system name" SYSTEM="$(gum input --placeholder "system name")" gum style --border normal --margin "1" --padding "1 2" "Select a drive file or create a new drive file." DRIVE="$(gum choose $(find "$HOME/monorepo/nix/disko" -mindepth 1 -maxdepth 1 -type f -printf "%f\n"; printf "New"))" if [[ "$DRIVE" == "New" ]]; then gum style --border normal --margin "1" --padding "1 2" "Choose a name to call your drive file." DRIVE="$(gum input --placeholder "drive file name (ex: partition_scheme.nix)")" fi fi if [ ! -d "$HOME/monorepo/nix/systems/$SYSTEM" ]; then mkdir -p "$HOME/monorepo/nix/systems/$SYSTEM" cp "$HOME/monorepo/nix/systems/continuity/home.nix" "$HOME/monorepo/nix/systems/$SYSTEM/home.nix" cat > "$HOME/monorepo/nix/systems/$SYSTEM/default.nix" </dev/null vim "$HOME/monorepo/nix/systems/$SYSTEM/default.nix" gum style --border normal --margin "1" --padding "1 2" "Edit the home default.nix with options." gum input --placeholder "Press Enter to continue" >/dev/null vim "$HOME/monorepo/nix/systems/$SYSTEM/home.nix" sed -i "/hostnames = \[/,/];/ s/];/ \"$1\"\n ];/" "$HOME/monorepo/nix/flake.nix" if [ ! -f "$HOME/monorepo/nix/disko/$DRIVE" ]; then cp "$HOME/monorepo/nix/disko/drive-simple.nix" "$HOME/monorepo/nix/disko/$DRIVE" gum style --border normal --margin "1" --padding "1 2" "Edit the drive file with your preferred partitioning scheme." gum input --placeholder "Press Enter to continue" >/dev/null vim "$HOME/monorepo/nix/disko/$DRIVE" fi cd "$HOME/monorepo" && git add . && cd "$HOME" fi nix --extra-experimental-features 'nix-command flakes' eval "$HOME/monorepo/nix#evalDisko.$SYSTEM" > "$HOME/drive.nix" gum style --border normal --margin "1" --padding "1 2" "Formatting the drive is destructive!" if gum confirm "Are you sure you want to continue?"; then echo "Proceeding..." else echo "Aborting." exit 1 fi sudo nix --experimental-features "nix-command flakes" run "github:nix-community/disko/${commits.diskoCommitHash}" -- --mode destroy,format,mount "$HOME/drive.nix" cd /mnt sudo nixos-install --flake "$HOME/monorepo/nix#$SYSTEM" target_user="$(ls /mnt/home | head -n1)" if [ -z "$target_user" ]; then echo "No user directories found in /mnt/home" exit 1 fi sudo cp -r "$HOME/monorepo" "/mnt/home/$target_user/" echo "rebooting..."; sleep 3; reboot '') ]; }; }; systemd = { services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ]; targets = { sleep.enable = false; suspend.enable = false; hibernate.enable = false; hybrid-sleep.enable = false; }; }; } #+end_src