diff --git a/.gitignore b/.gitignore index de901db..87a3018 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -# gitignore -.pre-commit-config.* \ No newline at end of file +result +*.qcow2 diff --git a/.sops.yaml b/.sops.yaml index 835dd06..e709730 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -1,7 +1,7 @@ keys: - - &rafiq age12l33pas8eptwjc7ewux3d8snyzfzwz0tn9qg5kw8le79fswmjgjqdjgyy6 + - &admin age12l33pas8eptwjc7ewux3d8snyzfzwz0tn9qg5kw8le79fswmjgjqdjgyy6 creation_rules: - - path_regex: \.(yaml)$ + - path_regex: \.(yaml|json|env|ini)$ key_groups: - age: - - *rafiq + - *admin diff --git a/README.md b/README.md new file mode 100644 index 0000000..b1d73f1 --- /dev/null +++ b/README.md @@ -0,0 +1,83 @@ +# Planning + +## To-do + +- [ ] Copy over ~/.ssh/id_ed25519 and zellij status bar plugin confirmation +- [ ] Migrate immich to apollo, point to helios +- [x] Migrate LibreChat to apollo, maintain db +- [ ] Figure out wakapi +- [x] Add forgejo +- [ ] Add simple blog + +## Versions + +- 1.0.0 + - Setup desktop as hypervisor with nixos and win11 + - Spare drive as steam library + - GPU passthrough to either system + - Always running, VMs spun down except when in use + - Apollo as hypervisor + - VMs for docker host, home-assistant, bare metal or containerised services + - Automated backups for home and state directories + - Ability to build VMs of all systems and implement integration tests + - Staging VMs for ad-hoc testing + - All servers set up with following services: + - Git server + - Chat app + - Network shares + - Federation with ActivityPub + - Wakapi + - Add a way to define services per host and refer to them by hostname + - helios as file and db server, apollo as services and reverse proxy +- 0.3.0 + - Integration tests for all services + - Migrate services from helios + +# Modules + +The nixosModules and homeModules exposed by this flake are slightly out of the norm. + +Option declarations for user specific configuration are kept to: + +- homeModules for CLI +- nixosModules for desktop + +System configurations, to this end, should include the window manager, lockscreen, terminal etc. for that system. + +These desktop programs will be **configured** in home-manager for each user, but those configurations consult the osConfig variable passed in by home-manager. + +# System Setup + +The following files are **required** for system activation: + +- /persist/home/${mainUser}/.ssh/id_ed25519 + +This private key will be used by sops-nix to decrypt the secrets in [this encrypted file](secrets/secrets.yaml). The secrets inside the yaml file should also be set, or otherwise removed alongside their declarations , found [here](modules/nixos/system/secrets.nix) and references. + +```bash +# On the target machine +# Boot into the NixOS installer + +sudo passwd + +# On the host machine +deploy --user "rafiq" --ip "10.10.0.102" --hostname "apollo" +``` + +### From a Local NixOS Installer + +The installation may run out of space when installing from an install ISO. In that case, use Disko to format the drives first, then create a `/mnt/tmp` directory and set it as TMPDIR for nixos-install. + +```bash +sudo su +nix --extra-experimental-features "nix-command flakes" run github:nix-community/disko/master -- --mode destroy,format,mount --flake github:rrvsh/pantheon# +# Copy SSH key to /persist/home/rafiq/.ssh +mkdir /mnt/tmp +TMPDIR=/mnt/tmp nixos-install --flake github:rrvsh/pantheon# --no-root-password +reboot +``` + +# Impermanence + +System and user state is stored under /persist. Anything not declared under +`{environment,home}.persistence` is deleted on system boot. diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index ff57ce6..0000000 --- a/docs/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Pantheon -This flake serves as a monorepo for my systems (using IaC), dotfiles, and scripts. -It's hosted at https://git.rrv.sh/rrvsh/pantheon, and mirrored to https://github.com/rrvsh/pantheon. - -## Structure -The system configurations are defined in [`flake.manifest`](nix/manifest.nix). -`flake.manifest.owner` provides the attributes for the administrator user, including username and pubkey. -`flake.manifest.hosts` provides the specifications for the system configurations that should be exposed by the flake as nixosConfigurations. -`flake.modules.nixos.*` provide NixOS options and configurations. -The attribute `flake.modules.nixos.default` provides options that will be applied to every system of that class. -You can use it as seen [here](nix/modules/flake/home-manager.nix): - -```nix -flake.modules.nixos.default.imports = [ inputs.home-manager.nixosModules.default ]; -``` - -The other attributes under `flake.modules.nixos` should be opt-in, i.e. provide options that will be set in the profiles. -`flake.profiles.nixos` provides profiles which use the options defined in `flake.modules.nixos` to define different roles for each system, such as graphical, laptop, headless, etc. -Options should not be defined here. -`flake.contracts.nixos.*` will provide contracts, such as reverse proxies or databases, which will configure options on the provider and receiver host. - -## Acknowledgements -Thanks to the following for inspiring this configuration. I highly recommend you look through their writings and configurations. -- [ornicar](https://github.com/ornicar/dotfiles) which is where I first heard of NixOS -- [No Boilerplate](https://www.youtube.com/watch?v=CwfKlX3rA6E&pp=0gcJCfwAo7VqN5tD) for making me finally try the OS -- [ryan4yin](https://nixos-and-flakes.thiscute.world/) for being an amazing introduction to NixOS, home-manager, and flakes -- [NotAShelf](https://github.com/NotAShelf/) for their blog and for the wonderful [NVF](https://github.com/notashelf/nvf) -- [mightyiam](https://github.com/mightyiam/infra) for their infrastructure repo using flake-parts -- [drupol](https://not-a-number.io/2025/refactoring-my-infrastructure-as-code-configurations/) for this blog post which convinced me to rebase my infra to use flake-parts diff --git a/docs/cheatsheet.md b/docs/cheatsheet.md deleted file mode 100644 index 4f76757..0000000 --- a/docs/cheatsheet.md +++ /dev/null @@ -1,2 +0,0 @@ -# cheatsheet -`__curPos.file` will give the full evaluated path of the nix file it is called in. See [this issue](https://github.com/NixOS/nix/issues/5897#issuecomment-1012165198) for more information. \ No newline at end of file diff --git a/flake.lock b/flake.lock index fb9b627..83e6f9b 100644 --- a/flake.lock +++ b/flake.lock @@ -67,88 +67,31 @@ "type": "github" } }, - "dedupe_flake-compat": { + "crane": { "locked": { - "lastModified": 1747046372, - "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "lastModified": 1750266157, + "narHash": "sha256-tL42YoNg9y30u7zAqtoGDNdTyXTi8EALDeCB13FtbQA=", + "owner": "ipetkov", + "repo": "crane", + "rev": "e37c943371b73ed87faf33f7583860f81f1d5a48", "type": "github" }, "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "dedupe_flake-utils": { - "inputs": { - "systems": [ - "systems" - ] - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "dedupe_gitignore": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "dedupe_mnw": { - "locked": { - "lastModified": 1748710831, - "narHash": "sha256-eZu2yH3Y2eA9DD3naKWy/sTxYS5rPK2hO7vj8tvUCSU=", - "owner": "gerg-l", - "repo": "mnw", - "rev": "cff958a4e050f8d917a6ff3a5624bc4681c6187d", - "type": "github" - }, - "original": { - "owner": "gerg-l", - "repo": "mnw", + "owner": "ipetkov", + "repo": "crane", "type": "github" } }, "disko": { "inputs": { - "nixpkgs": [ - "nixpkgs" - ] + "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1751854533, - "narHash": "sha256-U/OQFplExOR1jazZY4KkaQkJqOl59xlh21HP9mI79Vc=", + "lastModified": 1750903843, + "narHash": "sha256-Ng9+f0H5/dW+mq/XOKvB9uwvGbsuiiO6HrPdAcVglCs=", "owner": "nix-community", "repo": "disko", - "rev": "16b74a1e304197248a1bc663280f2548dbfcae3c", + "rev": "83c4da299c1d7d300f8c6fd3a72ac46cb0d59aae", "type": "github" }, "original": { @@ -157,21 +100,6 @@ "type": "github" } }, - "files": { - "locked": { - "lastModified": 1750263550, - "narHash": "sha256-EW/QJ8i/13GgiynBb6zOMxhLU1uEkRqmzbIDEP23yVA=", - "owner": "mightyiam", - "repo": "files", - "rev": "5f4ef1fd1f9012354a9748be093e277675d10f07", - "type": "github" - }, - "original": { - "owner": "mightyiam", - "repo": "files", - "type": "github" - } - }, "firefox-gnome-theme": { "flake": false, "locked": { @@ -188,11 +116,40 @@ "type": "github" } }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "locked": { + "lastModified": 1747046372, + "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { - "nixpkgs-lib": [ - "nixpkgs" - ] + "nixpkgs-lib": "nixpkgs-lib" }, "locked": { "lastModified": 1751413152, @@ -208,6 +165,157 @@ "type": "github" } }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "nur", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733312601, + "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_3": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_2" + }, + "locked": { + "lastModified": 1749398372, + "narHash": "sha256-tYBdgS56eXYaWVW3fsnPQ/nFlgWi/Z2Ymhyu21zVM98=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9305fe4e5c2a6fcf5ba6a3ff155720fbe4076569", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_4": { + "inputs": { + "nixpkgs-lib": [ + "stylix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1743550720, + "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "c621e8422220273271f52058f618c94e405bb0f5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils-plus": { + "inputs": { + "flake-utils": "flake-utils_2" + }, + "locked": { + "lastModified": 1715533576, + "narHash": "sha256-fT4ppWeCJ0uR300EH3i7kmgRZnAVxrH+XtK09jQWihk=", + "owner": "gytis-ivaskevicius", + "repo": "flake-utils-plus", + "rev": "3542fe9126dc492e53ddd252bb0260fe035f2c0f", + "type": "github" + }, + "original": { + "owner": "gytis-ivaskevicius", + "repo": "flake-utils-plus", + "rev": "3542fe9126dc492e53ddd252bb0260fe035f2c0f", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_7" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "fromYaml": { "flake": false, "locked": { @@ -227,21 +335,21 @@ "git-hooks": { "inputs": { "flake-compat": [ - "dedupe_flake-compat" - ], - "gitignore": [ - "dedupe_gitignore" + "stylix", + "flake-compat" ], + "gitignore": "gitignore", "nixpkgs": [ + "stylix", "nixpkgs" ] }, "locked": { - "lastModified": 1750779888, - "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=", + "lastModified": 1747372754, + "narHash": "sha256-2Y53NGIX2vxfie1rOW0Qb86vjRZ7ngizoo+bnXU9D9k=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d", + "rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46", "type": "github" }, "original": { @@ -250,6 +358,28 @@ "type": "github" } }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "stylix", + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "gnome-shell": { "flake": false, "locked": { @@ -268,17 +398,36 @@ } }, "home-manager": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1751462021, + "narHash": "sha256-RUKSK5JFZ15hsQK8qgthbzP0iTuBlAYfnkH8tjz6SPU=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "6c53df3b9c809e3b4b30d515e18bfa4c6f079254", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { "inputs": { "nixpkgs": [ + "stylix", "nixpkgs" ] }, "locked": { - "lastModified": 1751990210, - "narHash": "sha256-krWErNDl9ggMLSfK00Q2BcoSk3+IRTSON/DiDgUzzMw=", + "lastModified": 1748737919, + "narHash": "sha256-5kvBbLYdp+n7Ftanjcs6Nv+UO6sBhelp6MIGJ9nWmjQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "218da00bfa73f2a61682417efe74549416c16ba6", + "rev": "5675a9686851d9626560052a032c4e14e533c1fa", "type": "github" }, "original": { @@ -317,38 +466,52 @@ "type": "github" } }, - "make-shell": { - "inputs": { - "flake-compat": [ - "dedupe_flake-compat" - ] - }, + "mnw": { "locked": { - "lastModified": 1733933815, - "narHash": "sha256-9JjM7eT66W4NJAXpGUsdyAFXhBxFWR2Z9LZwUa7Hli0=", - "owner": "nicknovitski", - "repo": "make-shell", - "rev": "ffeceae9956df03571ea8e96ef77c2924f13a63c", + "lastModified": 1748710831, + "narHash": "sha256-eZu2yH3Y2eA9DD3naKWy/sTxYS5rPK2hO7vj8tvUCSU=", + "owner": "Gerg-L", + "repo": "mnw", + "rev": "cff958a4e050f8d917a6ff3a5624bc4681c6187d", "type": "github" }, "original": { - "owner": "nicknovitski", - "repo": "make-shell", + "owner": "Gerg-L", + "repo": "mnw", + "type": "github" + } + }, + "nil": { + "inputs": { + "nixpkgs": [ + "nvf", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1750047244, + "narHash": "sha256-vluLARrk4485npdyHOj8XKr0yk6H22pNf+KVRNL+i/Y=", + "owner": "oxalica", + "repo": "nil", + "rev": "870a4b1b5f12004832206703ac15aa85c42c247b", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "nil", "type": "github" } }, "nix-index-database": { "inputs": { - "nixpkgs": [ - "nixpkgs" - ] + "nixpkgs": "nixpkgs_3" }, "locked": { - "lastModified": 1751774635, - "narHash": "sha256-DuOznGdgMxeSlPpUu6Wkq0ZD5e2Cfv9XRZeZlHWMd1s=", + "lastModified": 1751170039, + "narHash": "sha256-3EKpUmyGmHYA/RuhZjINTZPU+OFWko0eDwazUOW64nw=", "owner": "nix-community", "repo": "nix-index-database", - "rev": "85686025ba6d18df31cc651a91d5adef63378978", + "rev": "9c932ae632d6b5150515e5749b198c175d8565db", "type": "github" }, "original": { @@ -359,11 +522,121 @@ }, "nixpkgs": { "locked": { - "lastModified": 1751792365, - "narHash": "sha256-J1kI6oAj25IG4EdVlg2hQz8NZTBNYvIS0l4wpr9KcUo=", + "lastModified": 1750836778, + "narHash": "sha256-sRLyRiC7TezRbbjGJwUFOgb2xMbSr3wQ0oJKfYlQ6s0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d7bb1922f0bb3d0c990f56f9cdb767fdb20a5f22", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1751159883, + "narHash": "sha256-urW/Ylk9FIfvXfliA1ywh75yszAbiTEVgpPeinFyVZo=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "14a40a1d7fb9afa4739275ac642ed7301a9ba1ab", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs-lib_2": { + "locked": { + "lastModified": 1748740939, + "narHash": "sha256-rQaysilft1aVMwF14xIdGS3sj1yHlI6oKQNBRTF40cc=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "656a64127e9d791a334452c6b6606d17539476e2", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs_10": { + "locked": { + "lastModified": 1748460289, + "narHash": "sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_11": { + "locked": { + "lastModified": 1750865895, + "narHash": "sha256-p2dWAQcLVzquy9LxYCZPwyUdugw78Qv3ChvnX755qHA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "61c0f513911459945e2cb8bf333dc849f1b976ff", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1751271578, + "narHash": "sha256-P/SQmKDu06x8yv7i0s8bvnnuJYkxVGBWLWHaU+tt4YY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3016b4b15d13f3089db8a41ef937b13a9e33a8df", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1751011381, + "narHash": "sha256-krGXKxvkBhnrSC/kGBmg5MyupUUT5R6IBCLEzx9jhMM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "30e2e2857ba47844aa71991daa6ed1fc678bcbb7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1751271578, + "narHash": "sha256-P/SQmKDu06x8yv7i0s8bvnnuJYkxVGBWLWHaU+tt4YY=", "owner": "nixos", "repo": "nixpkgs", - "rev": "1fd8bada0b6117e6c7eb54aad5813023eed37ccb", + "rev": "3016b4b15d13f3089db8a41ef937b13a9e33a8df", "type": "github" }, "original": { @@ -373,21 +646,124 @@ "type": "github" } }, + "nixpkgs_5": { + "locked": { + "lastModified": 1751271578, + "narHash": "sha256-P/SQmKDu06x8yv7i0s8bvnnuJYkxVGBWLWHaU+tt4YY=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "3016b4b15d13f3089db8a41ef937b13a9e33a8df", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_6": { + "locked": { + "lastModified": 1750215678, + "narHash": "sha256-Rc/ytpamXRf6z8UA2SGa4aaWxUXRbX2MAWIu2C8M+ok=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "5395fb3ab3f97b9b7abca147249fa2e8ed27b192", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_7": { + "locked": { + "lastModified": 1750506804, + "narHash": "sha256-VLFNc4egNjovYVxDGyBYTrvVCgDYgENp5bVi9fPTDYc=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "4206c4cb56751df534751b058295ea61357bbbaa", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_8": { + "locked": { + "lastModified": 1744868846, + "narHash": "sha256-5RJTdUHDmj12Qsv7XOhuospjAjATNiTMElplWnJE9Hs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ebe4301cbd8f81c4f8d3244b3632338bbeb6d49c", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_9": { + "locked": { + "lastModified": 1742889210, + "narHash": "sha256-hw63HnwnqU3ZQfsMclLhMvOezpM7RSB0dMAtD5/sOiw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "698214a32beb4f4c8e3942372c694f40848b360d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "nur": { + "inputs": { + "flake-parts": "flake-parts_2", + "nixpkgs": "nixpkgs_5", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1751458636, + "narHash": "sha256-hOl//m2j6DZPyoAe87qkZk4kD5dhfHw2odeZAFEBYmA=", + "owner": "nix-community", + "repo": "NUR", + "rev": "14864119daae84bbfdb639e1463b1b61580ce60c", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "NUR", + "type": "github" + } + }, + "nur_2": { "inputs": { "flake-parts": [ + "stylix", "flake-parts" ], "nixpkgs": [ + "stylix", "nixpkgs" - ] + ], + "treefmt-nix": "treefmt-nix_2" }, "locked": { - "lastModified": 1752005241, - "narHash": "sha256-+7DH6wh2BYnLRJzYXEbVlA1ZuAR4MxZI/paknbAuzk4=", + "lastModified": 1748730660, + "narHash": "sha256-5LKmRYKdPuhm8j5GFe3AfrJL8dd8o57BQ34AGjJl1R0=", "owner": "nix-community", "repo": "NUR", - "rev": "a2570fb4d0699fd34ebbbd52e2a763722601f6c6", + "rev": "2c0bc52fe14681e9ef60e3553888c4f086e46ecb", "type": "github" }, "original": { @@ -398,32 +774,24 @@ }, "nvf": { "inputs": { - "flake-parts": [ - "flake-parts" - ], - "flake-utils": [ - "dedupe_flake-utils" - ], - "mnw": [ - "dedupe_mnw" - ], - "nixpkgs": [ - "nixpkgs" - ], - "systems": [ - "systems" - ] + "flake-parts": "flake-parts_3", + "flake-utils": "flake-utils", + "mnw": "mnw", + "nil": "nil", + "nixpkgs": "nixpkgs_6", + "systems": "systems_2" }, "locked": { - "lastModified": 1752001027, - "narHash": "sha256-JgP8lW4QBr9v/U4ETaIOMvGCd/DAA1AjZ1lqjIwfWno=", - "owner": "notashelf", + "lastModified": 1751187535, + "narHash": "sha256-AMNouwcg9qSG/DI0JXoxZdjtcxfSErVaIsdQn4Q893k=", + "owner": "rrvsh", "repo": "nvf", - "rev": "c4d80273aaefeadaad96db97d077c647942b0e96", + "rev": "871440fb7e5dc9d4abf59a8577bbbf7bba63bff7", "type": "github" }, "original": { - "owner": "notashelf", + "owner": "rrvsh", + "ref": "uv-nvim", "repo": "nvf", "type": "github" } @@ -440,11 +808,11 @@ ] }, "locked": { - "lastModified": 1751898758, - "narHash": "sha256-8EmTPdfOymvvHhmHYWiyO3cwZ4gtLo5uBFm3CU5vySo=", + "lastModified": 1734836319, + "narHash": "sha256-h/Jiq852WJyyAL037sIxjPDScjeH8sUoZVZBWlciXaw=", "owner": "Janrupf", "repo": "python-flexseal", - "rev": "af318e1fd047abbefcc68d0292a4d902179c95fe", + "rev": "fdd313f7b9a5c9545c015acaf0729b01f708118a", "type": "github" }, "original": { @@ -455,36 +823,28 @@ }, "root": { "inputs": { - "dedupe_flake-compat": "dedupe_flake-compat", - "dedupe_flake-utils": "dedupe_flake-utils", - "dedupe_gitignore": "dedupe_gitignore", - "dedupe_mnw": "dedupe_mnw", "disko": "disko", - "files": "files", "flake-parts": "flake-parts", - "git-hooks": "git-hooks", "home-manager": "home-manager", "impermanence": "impermanence", "import-tree": "import-tree", - "make-shell": "make-shell", "nix-index-database": "nix-index-database", - "nixpkgs": "nixpkgs", + "nixpkgs": "nixpkgs_4", "nur": "nur", "nvf": "nvf", "rrv-sh": "rrv-sh", "rrvsh-nixpkgs": "rrvsh-nixpkgs", + "snowfall-lib": "snowfall-lib", "sops-nix": "sops-nix", "stable-diffusion-webui-nix": "stable-diffusion-webui-nix", "stylix": "stylix", - "systems": "systems", - "text": "text" + "systems": "systems_6", + "zjstatus": "zjstatus" } }, "rrv-sh": { "inputs": { - "nixpkgs": [ - "nixpkgs" - ] + "nixpkgs": "nixpkgs_7" }, "locked": { "lastModified": 1751721838, @@ -516,18 +876,59 @@ "type": "github" } }, - "sops-nix": { + "rust-overlay": { "inputs": { + "nixpkgs": [ + "zjstatus", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1750905536, + "narHash": "sha256-Mo7yXM5IvMGNvJPiNkFsVT2UERmnvjsKgnY6UyDdySQ=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "2fa7c0aabd15fa0ccc1dc7e675a4fcf0272ad9a1", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "snowfall-lib": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils-plus": "flake-utils-plus", "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1751606940, - "narHash": "sha256-KrDPXobG7DFKTOteqdSVeL1bMVitDcy7otpVZWDE6MA=", + "lastModified": 1736130495, + "narHash": "sha256-4i9nAJEZFv7vZMmrE0YG55I3Ggrtfo5/T07JEpEZ/RM=", + "owner": "snowfallorg", + "repo": "lib", + "rev": "02d941739f98a09e81f3d2d9b3ab08918958beac", + "type": "github" + }, + "original": { + "owner": "snowfallorg", + "repo": "lib", + "type": "github" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": "nixpkgs_8" + }, + "locked": { + "lastModified": 1750119275, + "narHash": "sha256-Rr7Pooz9zQbhdVxux16h7URa6mA80Pb/G07T4lHvh0M=", "owner": "Mic92", "repo": "sops-nix", - "rev": "3633fc4acf03f43b260244d94c71e9e14a2f6e0d", + "rev": "77c423a03b9b2b79709ea2cb63336312e78b72e2", "type": "github" }, "original": { @@ -538,24 +939,21 @@ }, "stable-diffusion-webui-nix": { "inputs": { - "flake-utils": [ - "dedupe_flake-utils" - ], - "nixpkgs": [ - "nixpkgs" - ], + "flake-utils": "flake-utils_3", + "nixpkgs": "nixpkgs_9", "python-flexseal": "python-flexseal" }, "locked": { - "lastModified": 1751899247, - "narHash": "sha256-bh6xwc24Rv0YE4grKXvj+kmXmydns+OrlWn4WLnJSY4=", - "owner": "janrupf", + "lastModified": 1751651278, + "narHash": "sha256-RFP58g7aWQE9LW+Av0ljtOuuvwThICBikAx+l+cYL+4=", + "owner": "rrvsh", "repo": "stable-diffusion-webui-nix", - "rev": "d5ba5dccd190b0ded17f9c4a23dc7665c6dc2eae", + "rev": "e7d156aef717cdeb1a98c7fe77cbd76c6e437c05", "type": "github" }, "original": { - "owner": "janrupf", + "owner": "rrvsh", + "ref": "fix/comfy-ui-data-directory", "repo": "stable-diffusion-webui-nix", "type": "github" } @@ -567,19 +965,14 @@ "base16-helix": "base16-helix", "base16-vim": "base16-vim", "firefox-gnome-theme": "firefox-gnome-theme", - "flake-parts": [ - "flake-parts" - ], + "flake-compat": "flake-compat_2", + "flake-parts": "flake-parts_4", + "git-hooks": "git-hooks", "gnome-shell": "gnome-shell", - "nixpkgs": [ - "nixpkgs" - ], - "nur": [ - "nur" - ], - "systems": [ - "systems" - ], + "home-manager": "home-manager_2", + "nixpkgs": "nixpkgs_10", + "nur": "nur_2", + "systems": "systems_5", "tinted-foot": "tinted-foot", "tinted-kitty": "tinted-kitty", "tinted-schemes": "tinted-schemes", @@ -587,11 +980,11 @@ "tinted-zed": "tinted-zed" }, "locked": { - "lastModified": 1751995939, - "narHash": "sha256-C5CSTv+b8XSbqJwqTP8SGkZEK3YCCJnmvRbg209ql5w=", + "lastModified": 1751405764, + "narHash": "sha256-romzrDMOWMPZioeChZnrugwaUSpROfkWClHhWHuRnRQ=", "owner": "nix-community", "repo": "stylix", - "rev": "8f3259dbc57c8ee871492fde80f77468826bbd63", + "rev": "5b257989a8337dddc22aa04a70d3665d0384abef", "type": "github" }, "original": { @@ -615,18 +1008,93 @@ "type": "github" } }, - "text": { + "systems_2": { "locked": { - "lastModified": 1751819711, - "narHash": "sha256-Emci++Hknzr2FEZRUbRDD7prI5JwwGsACO/GaU9Pmxg=", - "owner": "rrvsh", - "repo": "text.nix", - "rev": "00ba1e616ef3b761a52d5f7ac32892715cc4bcd1", + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { - "owner": "rrvsh", - "repo": "text.nix", + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_6": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_7": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", "type": "github" } }, @@ -710,6 +1178,70 @@ "repo": "base16-zed", "type": "github" } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nur", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733222881, + "narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "49717b5af6f80172275d47a418c9719a31a78b53", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "treefmt-nix_2": { + "inputs": { + "nixpkgs": [ + "stylix", + "nur", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733222881, + "narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "49717b5af6f80172275d47a418c9719a31a78b53", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "zjstatus": { + "inputs": { + "crane": "crane", + "flake-utils": "flake-utils_4", + "nixpkgs": "nixpkgs_11", + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1750957292, + "narHash": "sha256-2CYTG+jxP5e7GHAj1t5aMsgb0Rom4jdOb3rsdLKpVNA=", + "owner": "dj95", + "repo": "zjstatus", + "rev": "abd848f23eff00d21ec09278072111d97dfd7fe6", + "type": "github" + }, + "original": { + "owner": "dj95", + "repo": "zjstatus", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 86b2997..6cd5bd1 100644 --- a/flake.nix +++ b/flake.nix @@ -1,124 +1,43 @@ { + # TODO: use flake-parts and remove snowfall-lib outputs = inputs: - inputs.flake-parts.lib.mkFlake { inherit inputs; } ( - (inputs.import-tree ./nix) - // { - systems = import inputs.systems; - flake.paths.root = ./.; - } - ); + inputs.snowfall-lib.mkFlake { + inherit inputs; + src = ./.; + snowfall.namespace = "pantheon"; + }; inputs = { - ### SYSTEM ### - - # systems provides a list of supported nix systems. - systems.url = "github:nix-systems/default"; - # nixos-unstable provides a binary cache for all packages. + # We use nixos-unstable as everything is cached. nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; # My fork for random shit rrvsh-nixpkgs.url = "github:rrvsh/nixpkgs/librechat-module"; - # home-manager manages our user packages and dotfiles - home-manager = { - url = "github:nix-community/home-manager"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - # the nix user repository for mainly firefox extensions - nur = { - url = "github:nix-community/NUR"; - inputs.nixpkgs.follows = "nixpkgs"; - inputs.flake-parts.follows = "flake-parts"; - }; - # impermanence provides a nice abstraction over linking files from /persist - impermanence.url = "github:nix-community/impermanence"; - # flake-parts lets us define flake modules. - flake-parts = { - url = "github:hercules-ci/flake-parts"; - inputs.nixpkgs-lib.follows = "nixpkgs"; - }; - # disko provides declarative drive partitioning - disko = { - url = "github:nix-community/disko"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - # sops-nix lets us version control secrets like passwords and api keys - sops-nix = { - url = "github:Mic92/sops-nix"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - stylix = { - url = "github:nix-community/stylix"; - inputs = { - nixpkgs.follows = "nixpkgs"; - flake-parts.follows = "flake-parts"; - systems.follows = "systems"; - nur.follows = "nur"; - }; - }; - ### FLAKE PARTS MODULES ### - - # import-tree imports all nix files in a given directory. + # import-tree lets us use less imports = [] import-tree.url = "github:vic/import-tree"; - # files lets us write text files and automatically add checks for them - files.url = "github:mightyiam/files"; - # text.nix lets us easily define markdown text to pass to files - text.url = "github:rrvsh/text.nix"; - # make-shells. creates devShells and checks - make-shell = { - url = "github:nicknovitski/make-shell"; - inputs.flake-compat.follows = "dedupe_flake-compat"; - }; - # git-hooks ensures nix flake check is ran before commits - git-hooks = { - url = "github:cachix/git-hooks.nix"; - inputs = { - flake-compat.follows = "dedupe_flake-compat"; - nixpkgs.follows = "nixpkgs"; - gitignore.follows = "dedupe_gitignore"; - }; - }; - ### FLAKES ### - - # nix-index-database indexes the nixpkgs binaries for use with comma - nix-index-database = { - url = "github:nix-community/nix-index-database"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - # nvf provides modules to wrap neovim - nvf = { - url = "github:notashelf/nvf"; - inputs = { - nixpkgs.follows = "nixpkgs"; - flake-parts.follows = "flake-parts"; - systems.follows = "systems"; - flake-utils.follows = "dedupe_flake-utils"; - mnw.follows = "dedupe_mnw"; - }; - }; - # provides comfy ui and sdwebui services - stable-diffusion-webui-nix = { - url = "github:janrupf/stable-diffusion-webui-nix"; - inputs.nixpkgs.follows = "nixpkgs"; - inputs.flake-utils.follows = "dedupe_flake-utils"; - }; - # my website :) - rrv-sh = { - url = "github:rrvsh/rrv.sh"; + # The following are used for less boilerplate. + flake-parts.url = "github:hercules-ci/flake-parts"; + #TODO: remove snowfall + snowfall-lib = { + url = "github:snowfallorg/lib"; inputs.nixpkgs.follows = "nixpkgs"; }; - ### DEDUPE ### + # Various nix things + nur.url = "github:nix-community/NUR"; + sops-nix.url = "github:Mic92/sops-nix"; + disko.url = "github:nix-community/disko"; + home-manager.url = "github:nix-community/home-manager"; + impermanence.url = "github:nix-community/impermanence"; + nix-index-database.url = "github:nix-community/nix-index-database"; + stylix.url = "github:nix-community/stylix"; + systems.url = "github:nix-systems/default"; - dedupe_flake-compat.url = "github:edolstra/flake-compat"; - dedupe_flake-utils = { - url = "github:numtide/flake-utils"; - inputs.systems.follows = "systems"; - }; - dedupe_mnw.url = "github:gerg-l/mnw"; - dedupe_gitignore = { - url = "github:hercules-ci/gitignore.nix"; - inputs.nixpkgs.follows = "nixpkgs"; - }; + # Packages and services that we don't use nixpkgs for. + rrv-sh.url = "github:rrvsh/rrv.sh"; + nvf.url = "github:rrvsh/nvf/uv-nvim"; + stable-diffusion-webui-nix.url = "github:rrvsh/stable-diffusion-webui-nix/fix/comfy-ui-data-directory"; + zjstatus.url = "github:dj95/zjstatus"; }; } diff --git a/homes/x86_64-linux/rafiq/cli/default.nix b/homes/x86_64-linux/rafiq/cli/default.nix new file mode 100644 index 0000000..87182ea --- /dev/null +++ b/homes/x86_64-linux/rafiq/cli/default.nix @@ -0,0 +1,38 @@ +{ pkgs, inputs, ... }: +{ + imports = [ inputs.nix-index-database.hmModules.nix-index ]; + programs = { + tealdeer.enable = true; + tealdeer.enableAutoUpdates = true; + direnv = { + enable = true; + nix-direnv.enable = true; + }; + zoxide.enable = true; + nix-index.enable = true; + nix-index-database.comma.enable = true; + }; + persistDirs = [ ".local/share/zoxide" ]; + home = { + shellAliases = { + windows = "sudo systemctl reboot --boot-loader-entry=auto-windows"; + v = "$EDITOR"; + e = "edit"; + cd = "z"; # zoxide + ai = "aichat -r %shell% -e"; + }; + packages = with pkgs; [ + ripgrep + aichat + pantheon.rebuild + pantheon.deploy + pantheon.edit + pantheon.commit + ]; + }; + xdg.configFile."aichat/config.yaml".text = '' + model: gemini:gemini-2.0-flash + clients: + - type: gemini + ''; +} diff --git a/nix/homes/rafiq/_nvf/autocomplete.nix b/homes/x86_64-linux/rafiq/cli/editor/_nvf/autocomplete.nix similarity index 100% rename from nix/homes/rafiq/_nvf/autocomplete.nix rename to homes/x86_64-linux/rafiq/cli/editor/_nvf/autocomplete.nix diff --git a/nix/homes/rafiq/_nvf/binds.nix b/homes/x86_64-linux/rafiq/cli/editor/_nvf/binds.nix similarity index 100% rename from nix/homes/rafiq/_nvf/binds.nix rename to homes/x86_64-linux/rafiq/cli/editor/_nvf/binds.nix diff --git a/nix/homes/rafiq/_nvf/languages.nix b/homes/x86_64-linux/rafiq/cli/editor/_nvf/languages.nix similarity index 91% rename from nix/homes/rafiq/_nvf/languages.nix rename to homes/x86_64-linux/rafiq/cli/editor/_nvf/languages.nix index cc3dd8c..1eb16fb 100644 --- a/nix/homes/rafiq/_nvf/languages.nix +++ b/homes/x86_64-linux/rafiq/cli/editor/_nvf/languages.nix @@ -23,6 +23,8 @@ enable = true; format.type = "ruff"; lsp.server = "pyright"; + uv.enable = true; + uv.setupOpts.picker_integration = true; }; rust.enable = true; rust.crates.enable = true; diff --git a/nix/homes/rafiq/_nvf/lsp.nix b/homes/x86_64-linux/rafiq/cli/editor/_nvf/lsp.nix similarity index 100% rename from nix/homes/rafiq/_nvf/lsp.nix rename to homes/x86_64-linux/rafiq/cli/editor/_nvf/lsp.nix diff --git a/nix/homes/rafiq/_nvf/navigation.nix b/homes/x86_64-linux/rafiq/cli/editor/_nvf/navigation.nix similarity index 100% rename from nix/homes/rafiq/_nvf/navigation.nix rename to homes/x86_64-linux/rafiq/cli/editor/_nvf/navigation.nix diff --git a/nix/homes/rafiq/_nvf/snippets.nix b/homes/x86_64-linux/rafiq/cli/editor/_nvf/snippets.nix similarity index 100% rename from nix/homes/rafiq/_nvf/snippets.nix rename to homes/x86_64-linux/rafiq/cli/editor/_nvf/snippets.nix diff --git a/nix/homes/rafiq/_nvf/statusline.nix b/homes/x86_64-linux/rafiq/cli/editor/_nvf/statusline.nix similarity index 100% rename from nix/homes/rafiq/_nvf/statusline.nix rename to homes/x86_64-linux/rafiq/cli/editor/_nvf/statusline.nix diff --git a/nix/homes/rafiq/_nvf/ui.nix b/homes/x86_64-linux/rafiq/cli/editor/_nvf/ui.nix similarity index 100% rename from nix/homes/rafiq/_nvf/ui.nix rename to homes/x86_64-linux/rafiq/cli/editor/_nvf/ui.nix diff --git a/nix/homes/rafiq/_nvf/utility.nix b/homes/x86_64-linux/rafiq/cli/editor/_nvf/utility.nix similarity index 100% rename from nix/homes/rafiq/_nvf/utility.nix rename to homes/x86_64-linux/rafiq/cli/editor/_nvf/utility.nix diff --git a/nix/homes/rafiq/_nvf/visuals.nix b/homes/x86_64-linux/rafiq/cli/editor/_nvf/visuals.nix similarity index 100% rename from nix/homes/rafiq/_nvf/visuals.nix rename to homes/x86_64-linux/rafiq/cli/editor/_nvf/visuals.nix diff --git a/homes/x86_64-linux/rafiq/cli/editor/default.nix b/homes/x86_64-linux/rafiq/cli/editor/default.nix new file mode 100644 index 0000000..6364db8 --- /dev/null +++ b/homes/x86_64-linux/rafiq/cli/editor/default.nix @@ -0,0 +1,47 @@ +{ + pkgs, + lib, + inputs, + ... +}: +{ + imports = [ inputs.nvf.homeManagerModules.default ]; + home.sessionVariables.EDITOR = "nvim"; + programs.nvf.enable = true; + programs.nvf.settings.vim = { + syntaxHighlighting = true; + hideSearchHighlight = true; + searchCase = "ignore"; + undoFile.enable = true; + telescope.enable = true; + fzf-lua.enable = true; + git.enable = true; + autopairs.nvim-autopairs.enable = true; + autocomplete = import ./_nvf/autocomplete.nix { inherit lib; }; + binds = import ./_nvf/binds.nix; + languages = import ./_nvf/languages.nix; + lsp = import ./_nvf/lsp.nix; + navigation = import ./_nvf/navigation.nix; + notes.todo-comments.enable = true; + options = { + autoindent = true; + backspace = "indent,eol,start"; + cursorline = true; + expandtab = true; + shiftwidth = 2; + smartindent = true; + tabstop = 2; + }; + snippets = import ./_nvf/snippets.nix { inherit pkgs; }; + statusline = import ./_nvf/statusline.nix; + treesitter = { + autotagHtml = true; + fold = true; + indent.disable = [ "markdown" ]; + textobjects.enable = true; + }; + ui = import ./_nvf/ui.nix; + utility = import ./_nvf/utility.nix; + visuals = import ./_nvf/visuals.nix; + }; +} diff --git a/homes/x86_64-linux/rafiq/cli/fetch.nix b/homes/x86_64-linux/rafiq/cli/fetch.nix new file mode 100644 index 0000000..d45f3f0 --- /dev/null +++ b/homes/x86_64-linux/rafiq/cli/fetch.nix @@ -0,0 +1,23 @@ +{ pkgs, ... }: +{ + home = { + packages = [ pkgs.fastfetch ]; + sessionVariables.FETCH = "hyfetch"; + shellAliases.fetch = "hyfetch"; + }; + programs.hyfetch = { + enable = true; + settings = { + preset = "bisexual"; + mode = "rgb"; + light_dark = "dark"; + lightness = 0.5; + color_align = { + # Flag color alignment + mode = "horizontal"; + fore_back = null; + }; + backend = "fastfetch"; + }; + }; +} diff --git a/homes/x86_64-linux/rafiq/cli/file-browser.nix b/homes/x86_64-linux/rafiq/cli/file-browser.nix new file mode 100644 index 0000000..5a7d23b --- /dev/null +++ b/homes/x86_64-linux/rafiq/cli/file-browser.nix @@ -0,0 +1,8 @@ +{ + home.sessionVariables.FILE_BROWSER = "yazi"; + programs.yazi = { + enable = true; + shellWrapperName = "t"; + settings.mgr.sort_by = "natural"; + }; +} diff --git a/homes/x86_64-linux/rafiq/cli/finder.nix b/homes/x86_64-linux/rafiq/cli/finder.nix new file mode 100644 index 0000000..ceb3f8d --- /dev/null +++ b/homes/x86_64-linux/rafiq/cli/finder.nix @@ -0,0 +1,5 @@ +{ + programs.fzf.enable = true; + #TODO: fish + programs.fzf.enableZshIntegration = true; +} diff --git a/homes/x86_64-linux/rafiq/cli/multiplexer.nix b/homes/x86_64-linux/rafiq/cli/multiplexer.nix new file mode 100644 index 0000000..e972e50 --- /dev/null +++ b/homes/x86_64-linux/rafiq/cli/multiplexer.nix @@ -0,0 +1,61 @@ +{ + osConfig, + inputs, + pkgs, + ... +}: +let + zjstatus = inputs.zjstatus.packages.${pkgs.stdenv.hostPlatform.system}.default; +in +{ + home.sessionVariables.MULTIPLEXER = "zellij"; + # Persists sessions + persistDirs = [ "/.cache/zellij" ]; + programs.zellij = { + enable = true; + #TODO: fish + enableZshIntegration = true; + settings = { + pane_frames = false; + show_startup_tips = false; + show_release_notes = false; + }; + }; + xdg.configFile."zellij/layouts/default.kdl".text = # kdl + '' + layout { + default_tab_template { + pane size=1 borderless=true { + plugin location="file:${zjstatus}/bin/zjstatus.wasm" { + format_left "{mode} ${osConfig.hostname}" + format_center "{tabs}" + format_right "{datetime}" + format_space "" + format_hide_on_overlength "true" + format_precedence "lrc" + + border_enabled "false" + hide_frame_for_single_pane "false" + + mode_default_to_mode "normal" + mode_normal "#[bg=#89B4FA] {name} " + mode_locked "#[bg=#f55e18] {name} " + mode_session "#[bg=#00ff00] {name} " + + tab_normal "#[fg=#6C7086] {index} " + tab_active "#[fg=#9399B2,bold,italic] {index} " + tab_display_count "3" // limit to showing 3 tabs + tab_truncate_start_format "..." + tab_truncate_end_format "..." + + //TODO: disable if we are not on ssh + datetime "#[fg=#6C7086,bold] {format}" + datetime_format "%H:%M:%S" + datetime_timezone "Asia/Singapore" + } + } + children + } + } + ''; +} diff --git a/homes/x86_64-linux/rafiq/cli/shell.nix b/homes/x86_64-linux/rafiq/cli/shell.nix new file mode 100644 index 0000000..d7b238a --- /dev/null +++ b/homes/x86_64-linux/rafiq/cli/shell.nix @@ -0,0 +1,51 @@ +{ lib, pkgs, ... }: +let + inherit (builtins) toString; + inherit (lib) getExe mkOrder; + inherit (lib.strings) concatStrings; + screensaverTimeout = toString 100; + screensaverCommand = "${getExe pkgs.cbonsai} -S -w 0.1 -L 40 -M 2 -b 2"; +in +{ + home.shell.enableShellIntegration = true; + home.sessionVariables.SHELL = "fish"; + programs.fish.enable = true; + programs.starship = { + enable = true; + settings = { + add_newline = false; + format = concatStrings [ + # First Line + ## Left Prompt + "$hostname$directory" + "$fill" + ## Right Prompt + "$all" + # Second Line + ## Left Prompt + "$character" + ]; + git_branch.format = "[$symbol$branch(:$remote_branch)]($style) "; + shlvl.disabled = false; + username.disabled = true; + fill.symbol = " "; + }; + }; + # figure out for fish + programs.zsh.initContent = + mkOrder 1200 + # zsh + '' + precmd() { + TMOUT=${screensaverTimeout} + } + + TRAPALRM() { + TMOUT=1 + ${screensaverCommand} + # If we exit, assume the previous command was exited out of + TMOUT=${screensaverTimeout} + zle reset-prompt + } + ''; +} diff --git a/homes/x86_64-linux/rafiq/cli/utilities/git.nix b/homes/x86_64-linux/rafiq/cli/utilities/git.nix new file mode 100644 index 0000000..4794310 --- /dev/null +++ b/homes/x86_64-linux/rafiq/cli/utilities/git.nix @@ -0,0 +1,25 @@ +{ + home.sessionVariables.GIT_CONFIG_GLOBAL = "$HOME/.config/git/config"; + home.shellAliases = { + gs = "git status"; + gc = "git commit"; + gcam = "git commit -am"; + gu = "git push"; + gy = "git pull"; + gdh = "git diff HEAD"; + }; + programs.git = { + enable = true; + userName = "Mohammad Rafiq"; + userEmail = "rafiq@rrv.sh"; + signing.key = "~/.ssh/id_ed25519.pub"; + signing.signByDefault = true; + extraConfig = { + init.defaultBranch = "prime"; + push.autoSetupRemote = true; + pull.rebase = false; + core.editor = "$EDITOR"; + gpg.format = "ssh"; + }; + }; +} diff --git a/homes/x86_64-linux/rafiq/cli/utilities/zk.nix b/homes/x86_64-linux/rafiq/cli/utilities/zk.nix new file mode 100644 index 0000000..7ea3050 --- /dev/null +++ b/homes/x86_64-linux/rafiq/cli/utilities/zk.nix @@ -0,0 +1,19 @@ +{ pkgs, ... }: +{ + persistDirs = [ "notebook" ]; + programs.zk = { + enable = true; + settings.notebook.dir = "~/notebook"; + }; + home.packages = [ + (pkgs.writeShellScriptBin "note" # bash + '' + zk edit -i + pushd ~/notebook > /dev/null + git add . + commit -u + popd > /dev/null + '' + ) + ]; +} diff --git a/homes/x86_64-linux/rafiq/default.nix b/homes/x86_64-linux/rafiq/default.nix new file mode 100644 index 0000000..192d67f --- /dev/null +++ b/homes/x86_64-linux/rafiq/default.nix @@ -0,0 +1,15 @@ +{ + inputs, + osConfig, + lib, + ... +}: +let + inherit (lib) singleton optional; + inherit (inputs) import-tree; +in +{ + imports = + (optional osConfig.desktop.enable (import-tree ./desktop)) + ++ singleton (import-tree ./cli); +} diff --git a/homes/x86_64-linux/rafiq/desktop/browser.nix b/homes/x86_64-linux/rafiq/desktop/browser.nix new file mode 100644 index 0000000..4fd287d --- /dev/null +++ b/homes/x86_64-linux/rafiq/desktop/browser.nix @@ -0,0 +1,46 @@ +{ + lib, + inputs, + pkgs, + ... +}: +let + inherit (builtins) map listToAttrs; + inherit (lib.lists) findFirstIndex; + inherit (inputs.nur.legacyPackages.${pkgs.stdenv.hostPlatform.system}.repos.rycee) firefox-addons; + profiles = listToAttrs ( + map (name: { + inherit name; + # If there are duplicate profile names, findFirstIndex will cause issues. + value = profileCfg (findFirstIndex (x: x == name) null syncedProfiles); + }) syncedProfiles + ); + syncedProfiles = [ + "rafiq" + "test" + ]; + profileCfg = id: { + inherit id; + settings."extensions.autoDisableScopes" = 0; # Auto enable extensions + #TODO: add default seach unduck and add rest of extensions + extensions = { + force = true; + packages = with firefox-addons; [ + darkreader + gesturefy + sponsorblock + ublock-origin + ]; + }; + }; +in +{ + home.sessionVariables.BROWSER = "firefox"; + persistDirs = [ ".mozilla/firefox" ]; + programs.firefox = { + enable = true; + inherit profiles; + }; + stylix.targets.firefox.colorTheme.enable = true; + stylix.targets.firefox.profileNames = syncedProfiles; +} diff --git a/homes/x86_64-linux/rafiq/desktop/default.nix b/homes/x86_64-linux/rafiq/desktop/default.nix new file mode 100644 index 0000000..d769793 --- /dev/null +++ b/homes/x86_64-linux/rafiq/desktop/default.nix @@ -0,0 +1,19 @@ +{ pkgs, ... }: +{ + persistDirs = [ + "docs" + "repos" + "vids" + "tmp" + ".cache/Smart Code ltd/Stremio" + ".local/share/Smart Code ltd/Stremio" + ]; + programs = { + obs-studio.enable = true; + vesktop.enable = true; + thunderbird.enable = true; + thunderbird.profiles.rafiq.isDefault = true; + }; + home.packages = with pkgs; [ stremio ]; + stylix.image = ./wallpaper.png; +} diff --git a/homes/x86_64-linux/rafiq/desktop/launcher.nix b/homes/x86_64-linux/rafiq/desktop/launcher.nix new file mode 100644 index 0000000..5090898 --- /dev/null +++ b/homes/x86_64-linux/rafiq/desktop/launcher.nix @@ -0,0 +1,3 @@ +{ + home.sessionVariables.LAUNCHER = "fuzzel"; +} diff --git a/homes/x86_64-linux/rafiq/desktop/lockscreen.nix b/homes/x86_64-linux/rafiq/desktop/lockscreen.nix new file mode 100644 index 0000000..91f243b --- /dev/null +++ b/homes/x86_64-linux/rafiq/desktop/lockscreen.nix @@ -0,0 +1,29 @@ +let + styling = { + halign = "center"; + valign = "center"; + zindex = 1; + shadow_passes = 5; + shadow_size = 5; + }; +in +{ + home.sessionVariables.LOCKSCREEN = "hyprlock"; + programs.hyprlock.settings = { + general.hide_cursor = true; + general.ignore_empty_input = true; + background.blur_passes = 5; + background.blur_size = 5; + label = { + text = ''hi, $USER.''; + font_size = 32; + position = "0, 0"; + }// styling; + input-field = { + placeholder_text = ""; + fade_on_empty = true; + size = "200, 45"; + position = "0, -5%"; + } // styling; + }; +} diff --git a/homes/x86_64-linux/rafiq/desktop/media-player.nix b/homes/x86_64-linux/rafiq/desktop/media-player.nix new file mode 100644 index 0000000..482363e --- /dev/null +++ b/homes/x86_64-linux/rafiq/desktop/media-player.nix @@ -0,0 +1,200 @@ +{ + xdg.configFile."vlc/vlcrc".text = '' + [visual] # Visualizer filter + [glspectrum] # 3D OpenGL spectrum visualization + [wall] # Wall video filter + [panoramix] # Panoramix: wall with overlap video filter + [clone] # Clone video filter + [yuv] # YUV video output + [xdg_shell] # XDG shell surface + [xcb_xv] # XVideo output (XCB) + [xcb_x11] # X11 video output (XCB) + [xcb_window] # X11 video window (XCB) + [wl_shell] # Wayland shell surface + [vmem] # Video memory output + [vdummy] # Dummy video output + [gl] # OpenGL video output + [flaschen] # Flaschen-Taschen video output + [fb] # GNU/Linux framebuffer video output + [transform] # Video transformation filter + [sharpen] # Sharpen video filter + [sepia] # Sepia video filter + [scene] # Scene video filter + [rotate] # Rotate video filter + [puzzle] # Puzzle interactive game video filter + [postproc] # Video post processing filter + [posterize] # Posterize video filter + [motionblur] # Motion blur filter + [mirror] # Mirror video filter + [hqdn3d] # High Quality 3D Denoiser filter + [grain] # Grain video filter + [gradient] # Gradient video filter + [gradfun] # Gradfun video filter + [gaussianblur] # Gaussian blur video filter + [fps] # FPS conversion video filter + [extract] # Extract RGB component video filter + [erase] # Erase video filter + [deinterlace] # Deinterlacing video filter + [croppadd] # Video cropping filter + [colorthres] # Color threshold filter + [canvas] # Canvas video filter + [bluescreen] # Bluescreen video filter + [blendbench] # Blending benchmark filter + [ball] # Ball video filter + [antiflicker] # antiflicker video filter + [anaglyph] # Convert 3D picture to anaglyph image video filter + [alphamask] # Alpha mask video filter + [adjust] # Image properties filter + [swscale] # Video scaling filter + [vaapi_filters] # Video Accelerated API filters + [svg] # svg + [freetype] # Freetype2 font renderer + [stream_out_transcode] # Transcode stream output + [stats] # Writes statistic info about stream + [stream_out_standard] # Standard stream output + [smem] # Stream output to memory buffer + [setid] # Change the id of an elementary stream + [stream_out_rtp] # RTP stream output + [record] # Record stream output + [mosaic_bridge] # Mosaic bridge stream output + [es] # Elementary stream output + [display] # Display stream output + [delay] # Delay a stream + [stream_out_chromecast] # Chromecast stream output + [bridge] # Bridge stream output + [prefetch] # Stream prefetch filter + [subsdelay] # Subtitle delay + [rss] # RSS and Atom feed display + [remoteosd] # Remote-OSD over VNC + [mosaic] # Mosaic video sub source + [marq] # Marquee display + [logo] # Logo sub source + [dynamicoverlay] # Dynamic video overlay + [audiobargraph_v] # Audio Bar Graph Video sub source + [upnp] # Universal Plug'n'Play + [sap] # Network streams (SAP) + [podcast] # Podcasts + [mpegvideo] # MPEG-I/II video packetizer + [mux_ts] # TS muxer (libdvbpsi) + [ps] # PS muxer + [mux_ogg] # Ogg/OGM muxer + [mp4] # MP4/MOV muxer + [avi] # AVI muxer + [asf] # ASF muxer + [rtsp] # Legacy RTSP VoD server + [logger] # File logging + [gnutls] # GNU TLS transport layer security + [audioscrobbler] # Submission of played songs to last.fm + [folder] # Folder meta data + [lua] # Lua interpreter + [syslog] # System logger (syslog) + [file] # File logger + [console] # Console logger + [file] # Secrets are stored on a file without any encryption + [skins2] # Skinnable Interface + [qt] # Qt interface + qt-privacy-ask=0 + [ncurses] # Ncurses interface + [vc1] # VC1 video demuxer + [ts] # MPEG Transport Stream demuxer + [subtitle] # Text subtitle parser + [rawvid] # Raw video demuxer + [rawdv] # DV (Digital Video) demuxer + [rawaud] # Raw audio demuxer + [ps] # MPEG-PS demuxer + [playlist] # Playlist + [mp4] # MP4 stream demuxer + [mod] # MOD demuxer (libmodplug) + [mkv] # Matroska stream demuxer + [mjpeg] # M-JPEG camera demuxer + [image] # Image demuxer + [h26x] # H264 video demuxer + [es] # MPEG-I/II/4 / A52 / DTS / MLP audio + [diracsys] # Dirac video demuxer + [demuxdump] # File dumper + [avi] # AVI demuxer + [avformat] # Avformat demuxer + [adaptive] # Unified adaptive streaming for DASH/HLS + [oldrc] # Remote control interface + [netsync] # Network synchronization + [motion] # motion control interface + [gestures] # Mouse gestures control interface + [vorbis] # Vorbis audio decoder + [ttml] # TTML subtitles decoder + [theora] # Theora video decoder + [telx] # Teletext subtitles decoder + [svgdec] # SVG video decoder + [svcdsub] # Philips OGT (SVCD subtitle) decoder + [subsusf] # USF subtitles decoder + [subsdec] # Text subtitle decoder + [spudec] # DVD subtitles decoder + [speex] # Speex audio decoder + [schroedinger] # Dirac video decoder using libschroedinger + [libass] # Subtitle renderers using libass + [kate] # Kate overlay decoder + [jpeg] # JPEG image decoder + [fluidsynth] # FluidSynth MIDI synthesizer + [dvbsub] # DVB subtitles decoder + [ddummy] # Dummy decoder + [cc] # Closed Captions decoder + [avcodec] # FFmpeg audio/video decoder + [a52] # ATSC A/52 (AC-3) audio decoder + [amem] # Audio memory output + [alsa] # ALSA audio output + [afile] # File audio output + [stereo_widen] # Simple stereo widening effect + [speex_resampler] # Speex resampler + [spatializer] # Audio Spatializer + [spatialaudio] # Ambisonics renderer and binauralizer + [scaletempo] # Audio tempo scaler synched with rate + [scaletempo_pitch] # Pitch Shifter + [samplerate] # Secret Rabbit Code (libsamplerate) resampler + [remap] # Audio channel remapper + [param_eq] # Parametric Equalizer + [normvol] # Volume normalizer + [mono] # Stereo to mono downmixer + [headphone] # Headphone virtual spatialization effect + [gain] # Gain control filter + [equalizer] # Equalizer with 10 bands + [compressor] # Dynamic range compressor + [chorus_flanger] # Sound Delay + [audiobargraph_a] # Audio part of the BarGraph function + [udp] # UDP stream output + [access_output_srt] # SRT stream output + [access_output_rist] # RIST stream output + [access_output_livehttp] # HTTP Live streaming output + [http] # HTTP stream output + [file] # File stream output + [xcb_screen] # Screen capture (with X11/XCB) + [vdr] # VDR recordings + [v4l2] # Video4Linux input + [udp] # UDP input + [timecode] # Time code subpicture elementary stream generator + [smb] # SMB input + [shm] # Shared memory framebuffer + [sftp] # SFTP input + [satip] # SAT>IP Receiver Plugin + [rtp] # Real-Time Protocol (RTP) input + [rist] # RIST input + [live555] # RTP/RTSP/SDP demuxer (using Live555) + [linsys_hdsdi] # HD-SDI Input + [libbluray] # Blu-ray Disc support (libbluray) + [access] # HTTPS input + [http] # HTTP input + [ftp] # FTP input + [filesystem] # File input + [dvdread] # DVDRead Input (no menu support) + [dvdnav] # DVDnav Input + [dvb] # DVB input with v4l2 support + [dtv] # Digital Television and Radio + [cdda] # Audio CD input + [avio] # libavformat AVIO access + [access_srt] # SRT input + [access_mms] # Microsoft Media Server (MMS) input + [imem] # Memory input + [concat] # Concatenated inputs + [access_alsa] # ALSA audio capture + [core] # core program + metadata-network-access=1 + ''; +} diff --git a/homes/x86_64-linux/rafiq/desktop/notification-daemon.nix b/homes/x86_64-linux/rafiq/desktop/notification-daemon.nix new file mode 100644 index 0000000..8f80fa6 --- /dev/null +++ b/homes/x86_64-linux/rafiq/desktop/notification-daemon.nix @@ -0,0 +1,5 @@ +{ + home.sessionVariables.NOTIFICATION_DAEMON = "mako"; + services.mako.enable = true; + services.mako.settings.default-timeout = 10000; +} diff --git a/homes/x86_64-linux/rafiq/desktop/status-bar.nix b/homes/x86_64-linux/rafiq/desktop/status-bar.nix new file mode 100644 index 0000000..cd0d5ae --- /dev/null +++ b/homes/x86_64-linux/rafiq/desktop/status-bar.nix @@ -0,0 +1,53 @@ +{ pkgs, ... }: +{ + home.sessionVariables.STATUS_BAR = "waybar"; + stylix.targets.waybar.addCss = false; + programs.waybar = { + enable = true; + settings = [ + { + #TODO: review the rest of the modules to see what else can be added + layer = "top"; + modules-left = [ + "pulseaudio" + ]; + modules-right = [ + "battery" + "clock" + ]; + "pulseaudio" = { + format = "{icon} {volume}%"; + format-muted = ""; + format-icons.default = [ + "" + "" + ]; + on-click = "${pkgs.pulseaudio}/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle"; + }; + "clock" = { + interval = 1; + format = "{:%F %T}"; + }; + "battery" = { + interval = 1; + bat-compatibility = true; + }; + } + ]; + style = # css + '' + window#waybar { + background-color: rgba(0, 0, 0, 0); + } + + #pulseaudio, + #battery, + #clock { + padding-top: 5px; + padding-bottom: 5px; + padding-right: 5px; + color: #ffffff; + } + ''; + }; +} diff --git a/homes/x86_64-linux/rafiq/desktop/terminal.nix b/homes/x86_64-linux/rafiq/desktop/terminal.nix new file mode 100644 index 0000000..8d0b3a1 --- /dev/null +++ b/homes/x86_64-linux/rafiq/desktop/terminal.nix @@ -0,0 +1,9 @@ +{ + home.sessionVariables.TERMINAL = "ghostty"; + programs.ghostty = { + enable = true; + settings = { + confirm-close-surface = false; + }; + }; +} diff --git a/nix/homes/rafiq/desktop/wallpaper.png b/homes/x86_64-linux/rafiq/desktop/wallpaper.png similarity index 100% rename from nix/homes/rafiq/desktop/wallpaper.png rename to homes/x86_64-linux/rafiq/desktop/wallpaper.png diff --git a/nix/homes/rafiq/desktop/_hyprland/decoration.nix b/homes/x86_64-linux/rafiq/desktop/window-manager/_hyprland/decoration.nix similarity index 100% rename from nix/homes/rafiq/desktop/_hyprland/decoration.nix rename to homes/x86_64-linux/rafiq/desktop/window-manager/_hyprland/decoration.nix diff --git a/nix/homes/rafiq/desktop/_hyprland/keybinds.nix b/homes/x86_64-linux/rafiq/desktop/window-manager/_hyprland/keybinds.nix similarity index 100% rename from nix/homes/rafiq/desktop/_hyprland/keybinds.nix rename to homes/x86_64-linux/rafiq/desktop/window-manager/_hyprland/keybinds.nix diff --git a/homes/x86_64-linux/rafiq/desktop/window-manager/default.nix b/homes/x86_64-linux/rafiq/desktop/window-manager/default.nix new file mode 100644 index 0000000..56df97a --- /dev/null +++ b/homes/x86_64-linux/rafiq/desktop/window-manager/default.nix @@ -0,0 +1,21 @@ +{ lib, pkgs, ... }: +let + inherit (lib) mkMerge; +in +{ + wayland.windowManager.hyprland.settings = mkMerge [ + (import ./_hyprland/decoration.nix) + (import ./_hyprland/keybinds.nix { inherit pkgs; }) + { + ecosystem.no_update_news = true; + xwayland.force_zero_scaling = true; + monitor = [ ", preferred, auto, 1" ]; + exec-once = [ + "uwsm app -- $LOCKSCREEN" + "uwsm app -- $NOTIFICATION_DAEMON" + "uwsm app -- $STATUS_BAR" + ]; + } + ]; + # TODO: add gamescope here or in nixos desktop module +} diff --git a/hostSpec.nix b/hostSpec.nix new file mode 100644 index 0000000..e07bcda --- /dev/null +++ b/hostSpec.nix @@ -0,0 +1,78 @@ +{ + users.rafiq = { + primary = true; + email = "rafiq@rrv.sh"; + alternate-emails = [ + "mohammadrafiq@rrv.sh" + "mohammadrafiq567@gmail.com" + ]; + pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILdsZyY3gu8IGB8MzMnLdh+ClDxQQ2RYG9rkeetIKq8n"; + }; + + entrypoints = { + # For services that should only have one instance across the whole + # flake, define them here and they will get provisioned on those + # hosts, with whatever depends on them configured via that hostname. + nginx.host = "apollo"; + ssh.host = "apollo"; + }; + + # This will define all the hosts exposed by the flake and designate the + # modules and services, along with defining the hardware configuration + # for each host. + # of each attr set will resolve to the host's hostname. + hosts.nemesis = { + platform = "amd"; + gpu = "nvidia"; + ephemeralRoot = true; + boot-drive = "/dev/disk/by-id/nvme-CT2000P3SSD8_2325E6E77434"; + bootloader = "systemd-boot"; + # Enables dotfiles and desktop environment/services. + desktop.enable = true; + extraCfg = { }; + }; + hosts.apollo = { + platform = "intel"; + ephemeralRoot = true; + bootloader = "systemd-boot"; + boot-drive = "/dev/disk/by-id/nvme-eui.002538d221b47b01"; + # Public services will be exposed to the web server. + public-services = [ + { + name = "librechat"; + domain = "chat.bwfiq.com"; + } + { + name = "forgejo"; + domain = "git.rrv.sh"; + } + { + name = "rrv-sh"; + domain = "rrv.sh"; + } + { + name = "immich"; + domain = "photos.bwfiq.com"; + } + { + name = "aenyrathia-wiki"; + domain = "aenyrathia.wiki"; + } + ]; + # Internal services will be exposed with tailscale only. + internal-services = [ + "mongodb" + "mariadb" + "postgresql" + "redis" + ]; + extraCfg = { }; + }; + host.helios = { + platform = "intel"; + boot-drive = "nvme-eui.6479a784aad00284"; + ephemeralRoot = true; + bootloader = "systemd-boot"; + extraCfg = { }; + }; +} diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 0000000..4b42d00 --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,57 @@ +{ lib, ... }: +let + inherit (lib) mkOption singleton; + inherit (lib.types) + int + str + port + path + attrs + ; + inherit (lib.strings) splitString; + inherit (builtins) length concatStringsSep tail; +in +rec { + # Helpers + splitDomain = domain: splitString "." domain; + shortenList = + count: list: + let + len = length list; + in + if len <= count then list else (shortenList count (tail list)); + + # Modules + mkAttrOption = mkOption { + type = attrs; + default = { }; + }; + mkIntOption = + default: + mkOption { + type = int; + inherit default; + }; + mkStrOption = mkOption { + type = str; + default = ""; + }; + mkPortOption = + default: + mkOption { + type = port; + inherit default; + }; + mkPathOption = + default: + mkOption { + type = path; + inherit default; + }; + + # Domains + isRootDomain = domain: length (splitDomain domain) <= 2; + mkRootDomain = domain: concatStringsSep "." (shortenList 2 (splitDomain domain)); + mkWildcardDomain = rootDomain: concatStringsSep "." ((singleton "*") ++ (splitDomain rootDomain)); + mkHost = domain: if isRootDomain domain then domain else mkWildcardDomain (mkRootDomain domain); +} diff --git a/lib/modules/default.nix b/lib/modules/default.nix new file mode 100644 index 0000000..e8c5402 --- /dev/null +++ b/lib/modules/default.nix @@ -0,0 +1,66 @@ +{ lib, ... }: +let + inherit (builtins) toString; + inherit (lib) + mkMerge + mkEnableOption + singleton + mkIf + ; + inherit (lib.pantheon) + mkAttrOption + mkRootDomain + mkPortOption + mkStrOption + ; + networkingConfig = + { + config, + cfg, + name, + }: + mkIf (cfg.domain != "") { + assertions = singleton { + assertion = config.server.web-servers.nginx.enable; + message = "You must enable a web server if you want to set server.web-apps.${name}.domain."; + }; + server.networking.ddns.domains = singleton (mkRootDomain cfg.domain); + server.web-servers.nginx.proxies = singleton { + source = cfg.domain; + target = "http://${config.hostname}:${toString cfg.port}"; + }; + }; +in +{ + modules.mkWebApp = + { + config, + name, + defaultPort, + persistDirs ? [ ], + #TODO: specify required secrets + extraOptions ? { }, + extraConfig ? { }, + }: + let + cfg = config.server.web-apps.${name}; + in + { + options.server.web-apps.${name} = { + enable = mkEnableOption ""; + port = mkPortOption defaultPort; + domain = mkStrOption; + openFirewall = mkEnableOption ""; + extraCfg = mkAttrOption; + } // extraOptions; + + config = mkIf cfg.enable (mkMerge [ + { + inherit persistDirs; + networking.firewall = mkIf cfg.openFirewall { allowedTCPPorts = singleton cfg.port; }; + } + (networkingConfig { inherit config cfg name; }) + extraConfig + ]); + }; +} diff --git a/modules/home/default.nix b/modules/home/default.nix new file mode 100644 index 0000000..f31453d --- /dev/null +++ b/modules/home/default.nix @@ -0,0 +1,38 @@ +{ + config, + lib, + inputs, + ... +}: +let + inherit (lib) mkOption; + inherit (lib.types) listOf str; +in +{ + imports = [ inputs.impermanence.homeManagerModules.impermanence ]; + options.persistDirs = mkOption { + type = listOf str; + default = [ ]; + }; + config = { + # Helper options + home.persistence."/persist/home/${config.home.username}" = { + directories = config.persistDirs; + allowOther = true; + }; + + # Global options + persistDirs = [ + # For system activation + ".ssh" + ".config/sops/age" + ]; + programs.ssh.enable = true; + # To set colors properly when on ssh + programs.ssh.extraConfig = '' + Host * + SetEnv TERM=xterm-256color + ''; + home.stateVersion = "24.11"; + }; +} diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix new file mode 100644 index 0000000..3498a97 --- /dev/null +++ b/modules/nixos/default.nix @@ -0,0 +1,112 @@ +{ + inputs, + lib, + config, + ... +}: +let + inherit (lib) mkOption singleton; + inherit (lib.types) + listOf + str + coercedTo + submodule + shellPackage + ; + inherit (lib.pantheon) mkStrOption; + inherit (lib.snowfall.fs) get-file; + rootDir = submodule { + options = { + directory = mkOption { type = str; }; + user = mkOption { + type = str; + default = "root"; + }; + group = mkOption { + type = str; + default = "root"; + }; + mode = mkOption { + type = str; + default = "0755"; + }; + }; + }; +in +{ + imports = [ + inputs.sops-nix.nixosModules.sops + inputs.stylix.nixosModules.stylix + ]; + options = { + hostname = mkStrOption; + mainUser = { + name = mkStrOption; + publicKey = mkStrOption; + email = mkStrOption; + shell = mkOption { + type = shellPackage; + }; + }; + persistDirs = mkOption { + type = listOf (coercedTo str (d: { directory = d; }) rootDir); + default = [ ]; + }; + }; + config = { + # Helper options + environment.persistence."/persist".directories = config.persistDirs; + + # Global options + persistDirs = [ + "/var/lib/systemd" + "/var/lib/nixos" + ]; + stylix.enable = true; + nixpkgs.config.allowUnfree = true; + nix.settings.experimental-features = [ + "nix-command" + "flakes" + "pipe-operators" + ]; + nix.settings.trusted-users = [ "@wheel" ]; + system.stateVersion = "25.05"; + time.timeZone = "Asia/Singapore"; + i18n.defaultLocale = "en_US.UTF-8"; + users = { + # Don't allow imperative configuration + mutableUsers = false; + users.root.openssh.authorizedKeys.keys = [ config.mainUser.publicKey ]; + groups.users = { + gid = 100; + members = [ "${config.mainUser.name}" ]; + }; + users."${config.mainUser.name}" = { + inherit (config.mainUser) shell; + uid = 1000; + isNormalUser = true; + hashedPasswordFile = config.sops.secrets."${config.mainUser.name}/hashedPassword".path; + extraGroups = [ "wheel" ]; + openssh.authorizedKeys.keys = [ config.mainUser.publicKey ]; + }; + }; + security.sudo.wheelNeedsPassword = false; + sops = { + defaultSopsFile = get-file "secrets/secrets.yaml"; + age.sshKeyPaths = [ "/persist/home/${config.mainUser.name}/.ssh/id_ed25519" ]; + secrets = { + "keys/openrouter" = { }; + "keys/gemini" = { }; + "keys/cloudflare" = { }; + "keys/telegram_bot" = { }; + "rafiq/hashedPassword".neededForUsers = true; + "rafiq/personalEmailPassword" = { }; + "rafiq/workEmailPassword" = { }; + }; + }; + environment.shellInit = # sh + '' + export GEMINI_API_KEY=$(sudo cat ${config.sops.secrets."keys/gemini".path}) + ''; + }; +} diff --git a/modules/nixos/desktop/audio/default.nix b/modules/nixos/desktop/audio/default.nix new file mode 100644 index 0000000..7619ad7 --- /dev/null +++ b/modules/nixos/desktop/audio/default.nix @@ -0,0 +1,6 @@ +{ + services.pipewire = { + enable = true; + pulse.enable = true; + }; +} diff --git a/modules/nixos/desktop/browser/tor-browser/default.nix b/modules/nixos/desktop/browser/tor-browser/default.nix new file mode 100644 index 0000000..1a26e83 --- /dev/null +++ b/modules/nixos/desktop/browser/tor-browser/default.nix @@ -0,0 +1,20 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib) mkEnableOption mkIf singleton; + cfg = config.desktop.browser.tor-browser; +in +{ + options.desktop.browser.tor-browser.enable = mkEnableOption ""; + + config = mkIf cfg.enable { + home-manager.sharedModules = singleton { + persistDirs = singleton ".tor project"; + home.packages = singleton pkgs.tor-browser; + }; + }; +} diff --git a/modules/nixos/desktop/default.nix b/modules/nixos/desktop/default.nix new file mode 100644 index 0000000..282075d --- /dev/null +++ b/modules/nixos/desktop/default.nix @@ -0,0 +1,37 @@ +{ + lib, + config, + pkgs, + ... +}: +let + inherit (lib) + mkEnableOption + mkIf + singleton + optional + ; + inherit (lib.pantheon) mkStrOption; + inherit (pkgs) font-awesome wl-clipboard-rs; + cfg = config.desktop; +in +{ + options.desktop = { + enable = mkEnableOption ""; + enableWaylandUtilities = mkEnableOption ""; + mainMonitor = { + id = mkStrOption; + scale = mkStrOption; + resolution = mkStrOption; + refresh-rate = mkStrOption; + }; + }; + + config = mkIf cfg.enable { + fonts.packages = singleton font-awesome; + services.getty.autologinUser = config.mainUser.name; + home-manager.sharedModules = optional cfg.enableWaylandUtilities { + home.packages = [ wl-clipboard-rs ]; + }; + }; +} diff --git a/modules/nixos/desktop/gaming/default.nix b/modules/nixos/desktop/gaming/default.nix new file mode 100644 index 0000000..a6e4443 --- /dev/null +++ b/modules/nixos/desktop/gaming/default.nix @@ -0,0 +1,37 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib) + mkEnableOption + mkIf + mkMerge + singleton + ; + cfg = config.desktop.gaming; +in +{ + options.desktop.gaming = { + steam.enable = mkEnableOption ""; + prism-launcher.enable = mkEnableOption ""; + }; + + config = mkMerge [ + (mkIf cfg.steam.enable { + programs.steam = { + enable = true; + gamescopeSession.enable = true; + }; + home-manager.sharedModules = singleton { persistDirs = singleton ".local/share/Steam"; }; + }) + (mkIf cfg.prism-launcher.enable { + home-manager.sharedModules = singleton { + home.packages = singleton pkgs.prismlauncher; + persistDirs = singleton ".local/share/PrismLauncher"; + }; + }) + ]; +} diff --git a/modules/nixos/desktop/launcher/default.nix b/modules/nixos/desktop/launcher/default.nix new file mode 100644 index 0000000..3a35133 --- /dev/null +++ b/modules/nixos/desktop/launcher/default.nix @@ -0,0 +1,16 @@ +{ lib, config, ... }: +let + inherit (lib) singleton mkEnableOption; + cfg = config.desktop.launcher; +in +{ + options.desktop.launcher = { + fuzzel.enable = mkEnableOption ""; + wofi.enable = mkEnableOption ""; + }; + + config.home-manager.sharedModules = singleton { + programs.fuzzel.enable = cfg.fuzzel.enable; + programs.wofi.enable = cfg.wofi.enable; + }; +} diff --git a/modules/nixos/desktop/lockscreen/default.nix b/modules/nixos/desktop/lockscreen/default.nix new file mode 100644 index 0000000..1074bbd --- /dev/null +++ b/modules/nixos/desktop/lockscreen/default.nix @@ -0,0 +1,22 @@ +{ config, lib, ... }: +let + inherit (lib) + mkEnableOption + mkIf + mkMerge + singleton + ; + cfg = config.desktop.lockscreen; +in +{ + options.desktop.lockscreen = { + hyprlock.enable = mkEnableOption ""; + }; + + config = mkMerge [ + (mkIf cfg.hyprlock.enable { + security.pam.services.hyprlock = { }; + home-manager.sharedModules = singleton { programs.hyprlock.enable = true; }; + }) + ]; +} diff --git a/modules/nixos/desktop/media-player/default.nix b/modules/nixos/desktop/media-player/default.nix new file mode 100644 index 0000000..2c71170 --- /dev/null +++ b/modules/nixos/desktop/media-player/default.nix @@ -0,0 +1,18 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib) mkEnableOption optional singleton; + inherit (pkgs) vlc; + cfg = config.desktop.media-player; +in +{ + options.desktop.media-player = { + vlc.enable = mkEnableOption ""; + }; + + config.home-manager.sharedModules = optional cfg.vlc.enable { home.packages = singleton vlc; }; +} diff --git a/modules/nixos/desktop/services/default.nix b/modules/nixos/desktop/services/default.nix new file mode 100644 index 0000000..e3e39db --- /dev/null +++ b/modules/nixos/desktop/services/default.nix @@ -0,0 +1,30 @@ +{ config, lib, ... }: +let + inherit (lib) + mkMerge + singleton + mkEnableOption + mkIf + ; + cfg = config.desktop.services; +in +{ + options.desktop.services = { + spotifyd.enable = mkEnableOption ""; + }; + + config = mkMerge [ + (mkIf cfg.spotifyd.enable { + networking.firewall.allowedTCPPorts = [ 5353 ]; + networking.firewall.allowedUDPPorts = [ 5353 ]; + home-manager.sharedModules = singleton { + services.spotifyd.enable = true; + services.spotifyd.settings.global = { + device_name = "${config.hostname}"; + device_type = "computer"; + zeroconf_port = 5353; + }; + }; + }) + ]; +} diff --git a/modules/nixos/desktop/services/sunshine/default.nix b/modules/nixos/desktop/services/sunshine/default.nix new file mode 100644 index 0000000..9331030 --- /dev/null +++ b/modules/nixos/desktop/services/sunshine/default.nix @@ -0,0 +1,24 @@ +{ config, lib, ... }: +let + inherit (lib) singleton mkIf mkEnableOption; + cfg = config.desktop.services.sunshine; +in +{ + options.desktop.services.sunshine = { + enable = mkEnableOption ""; + }; + config = mkIf cfg.enable { + services.sunshine = { + enable = true; + capSysAdmin = true; + openFirewall = true; + settings = { + sunshine_name = config.hostname; + origin_pin_allowed = "wan"; + origin_web_ui_allowed = "wan"; + }; + applications = { }; + }; + home-manager.sharedModules = singleton { persistDirs = singleton ".config/sunshine"; }; + }; +} diff --git a/modules/nixos/desktop/window-manager/hyprland/default.nix b/modules/nixos/desktop/window-manager/hyprland/default.nix new file mode 100644 index 0000000..5d38de7 --- /dev/null +++ b/modules/nixos/desktop/window-manager/hyprland/default.nix @@ -0,0 +1,55 @@ +{ config, lib, ... }: +let + inherit (lib) mkEnableOption mkIf singleton; + inherit (config.desktop) mainMonitor; + cfg = config.desktop.window-manager.hyprland; +in +{ + options.desktop.window-manager.hyprland.enable = mkEnableOption ""; + + config = mkIf cfg.enable { + # Enable custom module for wayland utilities (clipboard etc.) + desktop.enableWaylandUtilities = true; + # Start Hyprland at boot only if not connecting through SSH + environment.loginShellInit = # sh + '' + if [[ -z "$SSH_CLIENT" && -z "$SSH_CONNECTION" ]]; then + if uwsm check may-start; then + exec uwsm start hyprland-uwsm.desktop + fi + fi + ''; + environment.variables = { + # Get Electron apps to use Wayland + ELECTRON_OZONE_PLATFORM_HINT = "auto"; + NIXOS_OZONE_WL = "1"; + }; + programs.hyprland = { + enable = true; + # Use UWSM to have each process controlled by systemd init + withUWSM = true; + }; + home-manager.sharedModules = singleton { + wayland.windowManager.hyprland = { + enable = true; + # This is needed for UWSM + systemd.enable = false; + # Null the packages since we use them system wide + package = null; + portalPackage = null; + settings.monitor = [ "${mainMonitor.id}, ${mainMonitor.resolution}@${mainMonitor.refresh-rate}, auto, ${mainMonitor.scale}" ]; + }; + xdg.configFile."uwsm/env".text = # sh + '' + # Force apps to scale right with Wayland + export GDK_SCALE=${mainMonitor.scale} + export STEAM_FORCE_DESKTOPUI_SCALING=${mainMonitor.scale} + ''; + xdg.configFile."uwsm/env-hyprland".text = # sh + '' + export GDK_SCALE=${mainMonitor.scale} + export STEAM_FORCE_DESKTOPUI_SCALING=${mainMonitor.scale} + ''; + }; + }; +} diff --git a/modules/nixos/machine/bootloader/default.nix b/modules/nixos/machine/bootloader/default.nix new file mode 100644 index 0000000..b5cedea --- /dev/null +++ b/modules/nixos/machine/bootloader/default.nix @@ -0,0 +1,30 @@ +{ + config, + lib, + ... +}: +let + inherit (lib.pantheon) mkIntOption mkStrOption; + cfg = config.machine.bootloader; +in +{ + options.machine.bootloader = { + type = mkStrOption; + configurationLimit = mkIntOption 5; + }; + config.boot = { + initrd.availableKernelModules = [ + "nvme" + "xhci_pci" + "ahci" + "usbhid" + "usb_storage" + "sd_mod" + ]; + loader.efi.canTouchEfiVariables = true; + loader.systemd-boot = { + enable = cfg.type == "systemd-boot"; + inherit (cfg) configurationLimit; + }; + }; +} diff --git a/modules/nixos/machine/default.nix b/modules/nixos/machine/default.nix new file mode 100644 index 0000000..b1aeb5a --- /dev/null +++ b/modules/nixos/machine/default.nix @@ -0,0 +1,19 @@ +{ lib, modulesPath, ... }: +let + inherit (lib) singleton; +in +{ + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + config = { + services.fwupd.enable = true; + persistDirs = singleton "/var/lib/bluetooth"; + hardware.bluetooth = { + enable = true; + settings.General.Experimental = true; + }; + hardware.xone.enable = true; + }; +} diff --git a/modules/nixos/machine/drives/btrfs/default.nix b/modules/nixos/machine/drives/btrfs/default.nix new file mode 100644 index 0000000..89923ff --- /dev/null +++ b/modules/nixos/machine/drives/btrfs/default.nix @@ -0,0 +1,116 @@ +{ + config, + lib, + inputs, + ... +}: +let + inherit (lib) mkIf mkEnableOption; + inherit (lib.pantheon) mkStrOption; + cfg = config.machine.drives.btrfs; + ephemeralRootCfg = { + boot.initrd.postDeviceCommands = 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 + ''; + programs.fuse.userAllowOther = true; + fileSystems."/persist".neededForBoot = true; + #FIXME: below should be in module or something + environment.persistence."/persist" = { + hideMounts = true; + files = [ + "/etc/ssh/ssh_host_ed25519_key" + "/etc/ssh/ssh_host_ed25519_key.pub" + "/etc/ssh/ssh_host_rsa_key" + "/etc/ssh/ssh_host_rsa_key.pub" + "/etc/machine-id" + ]; + }; + }; +in +{ + imports = [ + inputs.disko.nixosModules.disko + inputs.impermanence.nixosModules.impermanence + ]; + options.machine.drives.btrfs = { + enable = mkEnableOption ""; + drive = mkStrOption; + ephemeralRoot = mkEnableOption ""; + }; + config = mkIf cfg.enable ( + { + boot.initrd.kernelModules = [ "dm-snapshot" ]; + disko.devices.disk.main = { + device = cfg.drive; + type = "disk"; + content.type = "gpt"; + content.partitions = { + boot.name = "boot"; + boot.size = "1M"; + boot.type = "EF02"; + esp.name = "ESP"; + esp.size = "500M"; + esp.type = "EF00"; + esp.content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + }; + swap.size = "4G"; + swap.content = { + type = "swap"; + resumeDevice = true; + }; + root.name = "root"; + root.size = "100%"; + root.content = { + type = "lvm_pv"; + vg = "root_vg"; + }; + }; + }; + + disko.devices.lvm_vg.root_vg = { + type = "lvm_vg"; + lvs.root.size = "100%FREE"; + lvs.root.content.type = "btrfs"; + lvs.root.content.extraArgs = [ "-f" ]; + lvs.root.content.subvolumes = { + "/root".mountpoint = "/"; + "/persist".mountpoint = "/persist"; + "/persist".mountOptions = [ + "subvol=persist" + "noatime" + ]; + "/nix".mountpoint = "/nix"; + "/nix".mountOptions = [ + "subvol=nix" + "noatime" + ]; + }; + }; + } + // ephemeralRootCfg + ); +} diff --git a/modules/nixos/machine/gpu/default.nix b/modules/nixos/machine/gpu/default.nix new file mode 100644 index 0000000..1e54a51 --- /dev/null +++ b/modules/nixos/machine/gpu/default.nix @@ -0,0 +1,41 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib) + mkMerge + mkIf + mkEnableOption + singleton + ; + cfg = config.machine.gpu; +in +{ + options.machine.gpu = { + nvidia.enable = mkEnableOption ""; + }; + config = mkMerge [ + (mkIf cfg.nvidia.enable { + hardware = { + graphics.enable = true; + graphics.extraPackages = singleton pkgs.nvidia-vaapi-driver; + nvidia.open = true; + nvidia.package = config.boot.kernelPackages.nvidiaPackages.latest; + }; + services.xserver.videoDrivers = [ "nvidia" ]; + nixpkgs.config.allowUnfree = true; + environment.variables = { + LIBVA_DRIVER_NAME = "nvidia"; + __GLX_VENDOR_LIBRARY_NAME = "nvidia"; + NVD_BACKEND = "direct"; + }; + nix.settings.substituters = [ "https://cuda-maintainers.cachix.org" ]; + nix.settings.trusted-public-keys = [ + "cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E=" + ]; + }) + ]; +} diff --git a/modules/nixos/machine/platform/default.nix b/modules/nixos/machine/platform/default.nix new file mode 100644 index 0000000..a698c2b --- /dev/null +++ b/modules/nixos/machine/platform/default.nix @@ -0,0 +1,21 @@ +{ config, lib, ... }: +let + inherit (lib) singleton mkOption; + inherit (lib.types) enum; + cfg = config.machine.platform; +in +{ + options.machine.platform = { + type = mkOption { + type = enum [ + "amd" + "intel" + ]; + }; + }; + + config = { + hardware.cpu.${cfg.type}.updateMicrocode = true; + boot.kernelModules = singleton "kvm-${cfg.type}"; + }; +} diff --git a/modules/nixos/machine/usb/default.nix b/modules/nixos/machine/usb/default.nix new file mode 100644 index 0000000..9177356 --- /dev/null +++ b/modules/nixos/machine/usb/default.nix @@ -0,0 +1,45 @@ +{ + config, + pkgs, + lib, + ... +}: +let + inherit (lib) + mkEnableOption + mkIf + mkMerge + singleton + ; + cfg = config.machine.usb; +in +{ + options.machine.usb = { + automount = mkEnableOption ""; + enableQmk = mkEnableOption ""; + }; + + config = mkMerge [ + (mkIf cfg.automount { + services.udisks2.enable = true; + home-manager.sharedModules = singleton { + services.udiskie = { + enable = true; + automount = true; + notify = true; + }; + }; + }) + (mkIf cfg.enableQmk { + hardware.keyboard.qmk.enable = true; + services.udev = { + packages = with pkgs; [ + vial + qmk + qmk-udev-rules + qmk_hid + ]; + }; + }) + ]; +} diff --git a/modules/nixos/machine/virtualisation/distrobox/default.nix b/modules/nixos/machine/virtualisation/distrobox/default.nix new file mode 100644 index 0000000..b570fdb --- /dev/null +++ b/modules/nixos/machine/virtualisation/distrobox/default.nix @@ -0,0 +1,22 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib) mkIf mkEnableOption singleton; + cfg = config.machine.virtualisation.distrobox; +in +{ + options.machine.virtualisation.distrobox = { + enable = mkEnableOption ""; + }; + config = mkIf cfg.enable { + machine.virtualisation.podman.enable = true; + home-manager.sharedModules = singleton { + home.packages = singleton pkgs.distrobox; + # persistDirs = [ ".local/share/containers" ]; + }; + }; +} diff --git a/modules/nixos/machine/virtualisation/podman/default.nix b/modules/nixos/machine/virtualisation/podman/default.nix new file mode 100644 index 0000000..e130e17 --- /dev/null +++ b/modules/nixos/machine/virtualisation/podman/default.nix @@ -0,0 +1,32 @@ +{ config, lib, ... }: +let + inherit (lib) mkEnableOption mkIf; + cfg = config.machine.virtualisation.podman; +in +{ + options.machine.virtualisation.podman = { + enable = mkEnableOption ""; + }; + config = mkIf cfg.enable { + virtualisation = { + containers.enable = true; + podman = { + enable = true; + dockerCompat = true; + defaultNetwork.settings.dns_enabled = true; + }; + }; + users.users."${config.mainUser.name}" = { + extraGroups = [ "podman" ]; + # https://wiki.nixos.org/wiki/Distrobox + # subGidRanges = singleton { + # count = 65536; + # startGid = 1000; + # }; + # subUidRanges = singleton { + # count = 65536; + # startUid = 1000; + # }; + }; + }; +} diff --git a/modules/nixos/networking/default.nix b/modules/nixos/networking/default.nix new file mode 100644 index 0000000..ae9509e --- /dev/null +++ b/modules/nixos/networking/default.nix @@ -0,0 +1,28 @@ +{ config, lib, ... }: +let + inherit (lib) mkDefault singleton; +in +{ + sops.secrets = { + "tailscale/client-id".sopsFile = ./tailscale.yaml; + "tailscale/client-secret".sopsFile = ./tailscale.yaml; + }; + networking = { + enableIPv6 = false; + useDHCP = mkDefault true; + hostName = config.hostname; + networkmanager.enable = true; + }; + + services.openssh = { + enable = true; + settings.PrintMotd = true; + }; + + services.tailscale = { + enable = true; + authKeyFile = config.sops.secrets."tailscale/client-secret".path; + authKeyParameters.preauthorized = true; + }; + persistDirs = singleton "/var/lib/tailscale"; +} diff --git a/modules/nixos/networking/tailscale.yaml b/modules/nixos/networking/tailscale.yaml new file mode 100644 index 0000000..87aa9d8 --- /dev/null +++ b/modules/nixos/networking/tailscale.yaml @@ -0,0 +1,18 @@ +tailscale: + client-id: ENC[AES256_GCM,data:kQ4H9b2h8DN+5eTvwIYHZ6s=,iv:/nC3LM0qDNj3wIm9XZd7UUn5SxmAOA1dofsDGElKjVU=,tag:AIj5F7KkORujLDe+ZOxJgw==,type:str] + client-secret: ENC[AES256_GCM,data:O0cKyuK+FfK2E1mzQpkgybPrqEs0fH1y3jCOG6usT++6x3sWuJNvT56OIHpVNu8GH/6BIBsnenC1J/sVNTYIzA==,iv:FugIzSjNpoe9Bwy+x/GHl0BpCtbogQXpY7s3ICevQc0=,tag:1kQIO4ekjKuvexQ923YE3g==,type:str] +sops: + age: + - recipient: age12l33pas8eptwjc7ewux3d8snyzfzwz0tn9qg5kw8le79fswmjgjqdjgyy6 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGbTNsZE5lN2JOT1Jsd2hz + OWpDWTFzTW05Nzl5K1AyMmgxcVV2eHlBRlF3Cnc3VW5IN014ck8zM3BIWnBMNFFt + UnE4aGhGNERUOTlwZEJyNWF1Q1o0RXcKLS0tIFlZSFFoaDlOMnBMSFVyT3FMbFZj + ckl5RVZiMnkzV0RFQXN1aHZKM2doMnMKD6BjRdqsHiKDth4aBiZ1lvlcO1OgY36O + cGkZjuH45L4a0Y0kvptq3iZ/iPnmX8hw8n/gdplzUkpBzdsNPebvSg== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-07-01T21:11:39Z" + mac: ENC[AES256_GCM,data:YWgrMqqJgrGe+40a9CSDpAAgwPOeGXRFb58c6X6PxDHve3u5vQfHh+wkC0TFxadMsYcJTczRYf8YWuAwf7kFoO7ofYs+PfEi4ydKhl8WY9nXTsq+BFT4rDl/BaCfQw6qWD5/TKTtxm2pdtBNrG7bNeZJ8cVSOO/wsjoqrrbh3fk=,iv:8BXOX5O5apYLhZOWihagQBVldmsVoV+uEcejcO3cC0I=,tag:vansSul5Ebwooay48uYNZQ==,type:str] + unencrypted_suffix: _unencrypted + version: 3.10.2 diff --git a/modules/nixos/server/databases/default.nix b/modules/nixos/server/databases/default.nix new file mode 100644 index 0000000..726b449 --- /dev/null +++ b/modules/nixos/server/databases/default.nix @@ -0,0 +1,84 @@ +{ + lib, + config, + pkgs, + ... +}: +let + inherit (lib) singleton; + cfg = config.server.databases; +in +{ + options.server.databases = { + mongodb = { + enable = lib.mkEnableOption "the MongoDB server"; + port = lib.pantheon.mkPortOption 27017; + }; + mysql = { + enable = lib.mkEnableOption "the MySQL server"; + port = lib.pantheon.mkPortOption 3306; + }; + postgresql = { + enable = lib.mkEnableOption "the postgresql server"; + port = lib.pantheon.mkPortOption 5432; + }; + }; + + config = lib.mkMerge [ + (lib.mkIf cfg.postgresql.enable { + networking.firewall.allowedTCPPorts = lib.singleton cfg.postgresql.port; + persistDirs = singleton { + directory = builtins.toString config.services.postgresql.dataDir; + user = "postgres"; + group = "postgres"; + }; + services.postgresql = { + enable = true; + enableTCPIP = true; + settings = { inherit (cfg.postgresql) port; }; + authentication = lib.mkOverride 10 '' + #type database DBuser auth-method + local all all trust + + # ipv4 + host all all 0.0.0.0/0 trust + ''; + ensureDatabases = singleton "alphastory"; + ensureUsers = singleton { + name = "alphastory"; + ensureDBOwnership = true; + }; + }; + }) + (lib.mkIf cfg.mongodb.enable { + networking.firewall.allowedTCPPorts = [ cfg.mongodb.port ]; + persistDirs = singleton { + directory = builtins.toString config.services.mongodb.dbpath; + user = "mongodb"; + group = "mongodb"; + }; + services.mongodb = { + enable = true; + bind_ip = "0.0.0.0"; + extraConfig = '' + net.port: ${builtins.toString cfg.mongodb.port} + ''; + }; + }) + (lib.mkIf cfg.mysql.enable { + networking.firewall.allowedTCPPorts = [ cfg.mysql.port ]; + persistDirs = singleton { + directory = builtins.toString config.services.mysql.dataDir; + user = "mysql"; + group = "mysql"; + }; + services.mysql = { + enable = true; + package = pkgs.mariadb; + settings.mysqld = { + inherit (cfg.mysql) port; + }; + }; + }) + ]; +} diff --git a/modules/nixos/server/default.nix b/modules/nixos/server/default.nix new file mode 100644 index 0000000..a9592c5 --- /dev/null +++ b/modules/nixos/server/default.nix @@ -0,0 +1,43 @@ +{ lib, config, ... }: +{ + options.server.mountHelios = lib.mkEnableOption ""; + + config = lib.mkIf config.server.mountHelios { + sops.secrets."rafiq/oldSMBCredentials" = { }; + sops.templates."smb-credentials".content = '' + username=rafiq + password=${config.sops.placeholder."rafiq/oldSMBCredentials"} + ''; + fileSystems = { + "/media/helios/data" = { + device = "//helios/data"; + fsType = "cifs"; + options = [ + "x-systemd.automount" + "x-systemd.requires=tailscaled.service" + "x-systemd.mount-timeout=0" + ]; + }; + "/media/helios/rafiqcloud" = { + device = "//helios/rafiqcloud"; + fsType = "cifs"; + options = [ + "x-systemd.automount" + "x-systemd.requires=tailscaled.service" + "x-systemd.mount-timeout=0" + "credentials=${config.sops.templates."smb-credentials".path}" + ]; + }; + "/media/helios/rafiqmedia" = { + device = "//helios/rafiqmedia"; + fsType = "cifs"; + options = [ + "x-systemd.automount" + "x-systemd.requires=tailscaled.service" + "x-systemd.mount-timeout=0" + "credentials=${config.sops.templates."smb-credentials".path}" + ]; + }; + }; + }; +} diff --git a/modules/nixos/server/networking/ddns/default.nix b/modules/nixos/server/networking/ddns/default.nix new file mode 100644 index 0000000..b50dc0b --- /dev/null +++ b/modules/nixos/server/networking/ddns/default.nix @@ -0,0 +1,62 @@ +{ config, lib, ... }: +let + inherit (lib) mkIf mkOption mkEnableOption; + inherit (lib.types) enum str listOf; + inherit (lib.lists) unique; + inherit (builtins) map; + cfg = config.server.networking.ddns; + mkDomain = domain_name: { + inherit domain_name; + sub_domains = [ + "@" + "*" + ]; + }; + # Sanitize the list of domains with unique so we can add to it with every service. + mkDomains = map mkDomain (unique cfg.domains); +in +{ + options.server.networking.ddns = { + enable = mkEnableOption ""; + type = mkOption { + type = enum [ "godns" ]; + default = "godns"; + }; + domains = mkOption { + type = listOf str; + default = [ ]; + }; + }; + + config = mkIf cfg.enable { + services.godns = { + enable = if (cfg.type == "godns") then true else false; + loadCredential = [ + "cf_token:${config.sops.secrets."keys/cloudflare".path}" + "telegram_bot_token:${config.sops.secrets."keys/telegram_bot".path}" + ]; + settings = { + provider = "Cloudflare"; + login_token_file = "$CREDENTIALS_DIRECTORY/cf_token"; + domains = mkDomains; + resolver = "1.1.1.1"; + ip_urls = [ + "https://wtfismyip.com/text" + "https://api.ipify.org" + "https://myip.biturl.top" + "https://api-ipv4.ip.sb/ip" + ]; + ip_type = "IPv4"; + interval = 300; + notify = { + telegram = { + enabled = true; + bot_api_key_file = "$CREDENTIALS_DIRECTORY/telegram_bot_token"; + chat_id = "384288005"; + message_template = "Domain *{{ .Domain }} has been updated to %0A{{ .CurrentIP }}"; + }; + }; + }; + }; + }; +} diff --git a/modules/nixos/server/web-apps/comfy-ui/default.nix b/modules/nixos/server/web-apps/comfy-ui/default.nix new file mode 100644 index 0000000..19731b9 --- /dev/null +++ b/modules/nixos/server/web-apps/comfy-ui/default.nix @@ -0,0 +1,34 @@ +{ + config, + lib, + inputs, + ... +}: +let + inherit (lib) singleton; + inherit (lib.pantheon.modules) mkWebApp; + upstreamCfg = config.services.comfyUi; +in +mkWebApp { + inherit config; + name = "comfy-ui"; + defaultPort = 8188; + persistDirs = singleton { + directory = upstreamCfg.dataDir; + inherit (upstreamCfg) user group; + mode = "777"; + }; + extraConfig = { + assertions = singleton { + assertion = config.machine.gpu.nvidia.enable; + message = "You must run the comfy-ui service only with an nvidia gpu."; + }; + services.comfyUi = { + enable = true; + listenHost = "0.0.0.0"; + }; + }; +} +// { + imports = [ inputs.stable-diffusion-webui-nix.nixosModules.default ]; +} diff --git a/modules/nixos/server/web-apps/forgejo/default.nix b/modules/nixos/server/web-apps/forgejo/default.nix new file mode 100644 index 0000000..97140f8 --- /dev/null +++ b/modules/nixos/server/web-apps/forgejo/default.nix @@ -0,0 +1,41 @@ +{ config, lib, ... }: +let + inherit (lib) singleton optional; + inherit (lib.pantheon) mkPortOption; + inherit (lib.pantheon.modules) mkWebApp; + cfg = config.server.web-apps.forgejo; + upstreamCfg = config.services.forgejo; +in +mkWebApp { + inherit config; + name = "forgejo"; + defaultPort = 3000; + persistDirs = singleton { + directory = upstreamCfg.stateDir; + inherit (upstreamCfg) user group; + }; + extraOptions = { + sshPort = mkPortOption 2222; + }; + extraConfig = { + networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.sshPort; + services.forgejo = { + enable = true; + settings = { + server = { + DOMAIN = cfg.domain; + ROOT_URL = "https://${cfg.domain}/"; + HTTP_PORT = cfg.port; + START_SSH_SERVER = true; + SSH_PORT = cfg.sshPort; + }; + repository = { + USE_COMPAT_SSH_URI = false; + ENABLE_PUSH_CREATE_USER = true; + ENABLE_PUSH_CREATE_ORG = true; + }; + "repository.signing".FORMAT = "ssh"; + }; + }; + }; +} diff --git a/modules/nixos/server/web-apps/glance/default.nix b/modules/nixos/server/web-apps/glance/default.nix new file mode 100644 index 0000000..6e054db --- /dev/null +++ b/modules/nixos/server/web-apps/glance/default.nix @@ -0,0 +1,17 @@ +{ lib, config, ... }: +let + inherit (lib.pantheon.modules) mkWebApp; + cfg = config.server.web-apps.glance; +in +mkWebApp { + inherit config; + name = "glance"; + defaultPort = 8080; + extraConfig = { + services.glance = { + enable = true; + settings.server.host = "0.0.0.0"; + settings.server.port = cfg.port; + }; + }; +} diff --git a/modules/nixos/server/web-apps/librechat/default.nix b/modules/nixos/server/web-apps/librechat/default.nix new file mode 100644 index 0000000..cf6d71d --- /dev/null +++ b/modules/nixos/server/web-apps/librechat/default.nix @@ -0,0 +1,80 @@ +{ + config, + lib, + inputs, + ... +}: +let + inherit (lib) singleton; + inherit (lib.pantheon) mkStrOption; + inherit (lib.pantheon.modules) mkWebApp; + cfg = config.server.web-apps.librechat; + upstreamCfg = config.services.librechat; +in +mkWebApp { + inherit config; + name = "librechat"; + defaultPort = 3080; + persistDirs = singleton { + directory = upstreamCfg.dataDir; + inherit (upstreamCfg) user group; + }; + extraOptions.mongodbURI = mkStrOption // { + default = "mongodb://${config.hostname}:27017/LibreChat"; + }; + extraConfig = { + sops.secrets = { + "librechat/creds_key" = { }; + "librechat/creds_iv" = { }; + "librechat/jwt_secret" = { }; + "librechat/jwt_refresh_secret" = { }; + }; + services.librechat = { + enable = true; + openFirewall = true; + inherit (cfg) port; + env = { + HOST = "0.0.0.0"; + ALLOW_REGISTRATION = "true"; + NO_INDEX = "true"; + MONGO_URI = cfg.mongodbURI; + DOMAIN_CLIENT = cfg.domain; + DOMAIN_SERVER = cfg.domain; + ENDPOINTS = "anthropic,agents,google"; + }; + credentials = { + CREDS_KEY = config.sops.secrets."librechat/creds_key".path; + CREDS_IV = config.sops.secrets."librechat/creds_iv".path; + JWT_SECRET = config.sops.secrets."librechat/jwt_secret".path; + JWT_REFRESH_SECRET = config.sops.secrets."librechat/jwt_refresh_secret".path; + OPENROUTER_KEY = config.sops.secrets."keys/openrouter".path; + GOOGLE_KEY = config.sops.secrets."keys/gemini".path; + }; + settings = { + version = "1.1.4"; + cache = true; + endpoints.custom = [ + { + name = "OpenRouter"; + apiKey = "\${OPENROUTER_KEY}"; + baseURL = "https://openrouter.ai/api/v1"; + models.default = [ "meta-llama/llama-3-70b-instruct" ]; + models.fetch = true; + titleConvo = true; + titleModel = "current_model"; + modelDisplayLabel = "OpenRouter"; + } + ]; + interface = { + privacyPolicy = { + externalUrl = "https://librechat.ai/privacy-policy"; + openNewTab = true; + }; + }; + }; + }; + }; +} +// { + imports = singleton "${inputs.rrvsh-nixpkgs}/nixos/modules/services/web-apps/librechat.nix"; +} diff --git a/modules/nixos/server/web-apps/rrv-sh/default.nix b/modules/nixos/server/web-apps/rrv-sh/default.nix new file mode 100644 index 0000000..25a54bd --- /dev/null +++ b/modules/nixos/server/web-apps/rrv-sh/default.nix @@ -0,0 +1,24 @@ +{ + config, + lib, + inputs, + ... +}: +let + inherit (lib.pantheon.modules) mkWebApp; + cfg = config.server.web-apps.rrv-sh; +in +mkWebApp { + inherit config; + name = "rrv-sh"; + defaultPort = 2309; + extraConfig = { + services.rrv-sh = { + enable = true; + inherit (cfg) port; + }; + }; +} +// { + imports = [ inputs.rrv-sh.nixosModules.default ]; +} diff --git a/modules/nixos/server/web-apps/sd-webui-forge/default.nix b/modules/nixos/server/web-apps/sd-webui-forge/default.nix new file mode 100644 index 0000000..c7f4b04 --- /dev/null +++ b/modules/nixos/server/web-apps/sd-webui-forge/default.nix @@ -0,0 +1,34 @@ +{ + config, + lib, + inputs, + ... +}: +let + inherit (lib) singleton; + inherit (lib.pantheon.modules) mkWebApp; + upstreamCfg = config.services.sd-webui-forge; +in +mkWebApp { + inherit config; + name = "sd-webui-forge"; + defaultPort = 7860; + persistDirs = singleton { + directory = upstreamCfg.dataDir; + inherit (upstreamCfg) user group; + }; + extraConfig = { + assertions = singleton { + assertion = config.machine.gpu.nvidia.enable; + message = "You must run the sd-webui-forge service only with an nvidia gpu."; + }; + services.sd-webui-forge = { + enable = true; + listen = true; + extraArgs = "--cuda-malloc"; + }; + }; +} +// { + imports = [ inputs.stable-diffusion-webui-nix.nixosModules.default ]; +} diff --git a/modules/nixos/server/web-servers/default.nix b/modules/nixos/server/web-servers/default.nix new file mode 100644 index 0000000..1aee593 --- /dev/null +++ b/modules/nixos/server/web-servers/default.nix @@ -0,0 +1,34 @@ +{ config, lib, ... }: +let + inherit (lib) + mkMerge + mkIf + mkEnableOption + singleton + ; + cfg = config.server.web-servers; +in +{ + options.server.web-servers = { + enableSSL = mkEnableOption ""; + }; + + config = mkMerge [ + (mkIf cfg.enableSSL { + security.acme = { + acceptTerms = true; + defaults = { + inherit (config.mainUser) email; + dnsProvider = "cloudflare"; + credentialFiles."CLOUDFLARE_DNS_API_TOKEN_FILE" = config.sops.secrets."keys/cloudflare".path; + }; + certs = { + "rrv.sh".extraDomainNames = singleton "*.rrv.sh"; + "bwfiq.com".extraDomainNames = singleton "*.bwfiq.com"; + "slayment.com".extraDomainNames = singleton "*.slayment.com"; + "aenyrathia.wiki".extraDomainNames = singleton "*.aenyrathia.wiki"; + }; + }; + }) + ]; +} diff --git a/modules/nixos/server/web-servers/nginx/default.nix b/modules/nixos/server/web-servers/nginx/default.nix new file mode 100644 index 0000000..d0d6cc8 --- /dev/null +++ b/modules/nixos/server/web-servers/nginx/default.nix @@ -0,0 +1,119 @@ +{ config, lib, ... }: +let + inherit (lib) + mkMerge + mkOption + mkEnableOption + mkIf + singleton + ; + inherit (lib.types) listOf submodule attrs; + inherit (lib.pantheon) mkStrOption mkPathOption mkRootDomain; + inherit (builtins) listToAttrs map; + cfg = config.server.web-servers.nginx; + sslCheck = good: bad: if config.server.web-servers.enableSSL then good else bad; + defaultSink = mkIf cfg.enableDefaultSink { + "_" = { + default = true; + rejectSSL = sslCheck true false; + locations."/" = { + return = "444"; + }; + }; + }; + pages = listToAttrs ( + map (page: { + name = page.domain; + value = { + addSSL = sslCheck true false; + useACMEHost = sslCheck (mkRootDomain page.domain) null; + acmeRoot = null; # needed for DNS validation + locations = { + "/" = { + inherit (page) root; + } // page.extraConfig; + } // page.locations; + }; + }) cfg.pages + ); + proxyPasses = listToAttrs ( + map (proxy: { + name = proxy.source; + value = { + addSSL = sslCheck true false; + useACMEHost = sslCheck (mkRootDomain proxy.source) null; + acmeRoot = null; # needed for DNS validation + locations = { + "/" = { + proxyPass = proxy.target; + } // proxy.extraConfig; + } // proxy.locations; + }; + }) cfg.proxies + ); +in +{ + options.server.web-servers.nginx = { + enable = mkEnableOption "the Nginx server"; + openFirewall = mkEnableOption "" // { + default = true; + }; + enableDefaultSink = mkEnableOption "" // { + default = true; + }; + pages = mkOption { + default = [ ]; + type = listOf (submodule { + options = { + domain = mkStrOption; + root = mkPathOption ""; + extraConfig = lib.mkOption { + type = attrs; + default = { }; + }; + locations = lib.mkOption { + type = attrs; + default = { }; + }; + }; + }); + }; + proxies = mkOption { + default = [ ]; + type = listOf (submodule { + options = { + source = mkStrOption; + target = mkStrOption; + extraConfig = lib.mkOption { + type = attrs; + default = { }; + }; + locations = lib.mkOption { + type = attrs; + default = { }; + }; + }; + }); + }; + }; + + config = mkIf cfg.enable { + networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ + 443 + 80 + ]; + users.users.nginx.extraGroups = singleton "acme"; + services.nginx = { + enable = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + recommendedOptimisation = true; + recommendedGzipSettings = true; + virtualHosts = mkMerge [ + defaultSink + proxyPasses + pages + ]; + }; + }; +} diff --git a/nix/configurations.nix b/nix/configurations.nix deleted file mode 100644 index 1d27ceb..0000000 --- a/nix/configurations.nix +++ /dev/null @@ -1,45 +0,0 @@ -{ - config, - lib, - inputs, - ... -}: -let - inherit (lib) nixosSystem; - inherit (lib.lists) optional; - inherit (lib.attrsets) mapAttrs; - inherit (cfg.lib.modules) forAllUsers'; - cfg = config.flake; - globalCfg = name: hostConfig: { - useGlobalPkgs = true; - useUserPackages = true; - extraSpecialArgs = { - inherit hostConfig; - hostName = name; - }; - sharedModules = [ cfg.modules.homeManager.default ]; - users = forAllUsers' (name: _: cfg.modules.homeManager.${name}); - }; - hosts = cfg.manifest.hosts or { }; - mkConfigurations = - class: hosts: - mapAttrs ( - name: value: - if class == "nixos" then - nixosSystem { - specialArgs.hostName = name; - modules = [ - cfg.modules.nixos.default - inputs.home-manager.nixosModules.home-manager - { home-manager = globalCfg name value; } - (value.extraCfg or { }) - ] ++ optional value.graphical cfg.modules.nixos.graphical; - } - else - { } - ) hosts; -in -{ - imports = [ inputs.home-manager.flakeModules.home-manager ]; - flake.nixosConfigurations = mkConfigurations "nixos" hosts.nixos; -} diff --git a/nix/files/cheatsheet.nix b/nix/files/cheatsheet.nix deleted file mode 100644 index e307bbc..0000000 --- a/nix/files/cheatsheet.nix +++ /dev/null @@ -1,18 +0,0 @@ -{ lib, config, ... }: -let - inherit (builtins) concatStringsSep; - inherit (lib.lists) singleton; -in -{ - text.cheatsheet = concatStringsSep "\n" [ - "`__curPos.file` will give the full evaluated path of the nix file it is called in. See [this issue](https://github.com/NixOS/nix/issues/5897#issuecomment-1012165198) for more information." - ]; - perSystem = - { pkgs, ... }: - { - files.files = singleton { - path_ = "docs/cheatsheet.md"; - drv = pkgs.writeText "cheatsheet.md" config.text.cheatsheet; - }; - }; -} diff --git a/nix/files/gitignore.nix b/nix/files/gitignore.nix deleted file mode 100644 index a35e3ee..0000000 --- a/nix/files/gitignore.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ config, ... }: -{ - perSystem = - { pkgs, ... }: - { - files.files = [ - { - path_ = ".gitignore"; - drv = pkgs.writeText ".gitignore" config.text.gitignore; - } - ]; - }; -} diff --git a/nix/files/readme.nix b/nix/files/readme.nix deleted file mode 100644 index a8eccbf..0000000 --- a/nix/files/readme.nix +++ /dev/null @@ -1,54 +0,0 @@ -{ config, ... }: -{ - text.readme = { - heading = "Pantheon"; - description = # markdown - '' - This flake serves as a monorepo for my systems (using IaC), dotfiles, and scripts. - It's hosted at https://git.rrv.sh/rrvsh/pantheon, and mirrored to https://github.com/rrvsh/pantheon. - ''; - order = [ - "Structure" - "Acknowledgements" - ]; - parts."Acknowledgements" = # markdown - '' - Thanks to the following for inspiring this configuration. I highly recommend you look through their writings and configurations. - - [ornicar](https://github.com/ornicar/dotfiles) which is where I first heard of NixOS - - [No Boilerplate](https://www.youtube.com/watch?v=CwfKlX3rA6E&pp=0gcJCfwAo7VqN5tD) for making me finally try the OS - - [ryan4yin](https://nixos-and-flakes.thiscute.world/) for being an amazing introduction to NixOS, home-manager, and flakes - - [NotAShelf](https://github.com/NotAShelf/) for their blog and for the wonderful [NVF](https://github.com/notashelf/nvf) - - [mightyiam](https://github.com/mightyiam/infra) for their infrastructure repo using flake-parts - - [drupol](https://not-a-number.io/2025/refactoring-my-infrastructure-as-code-configurations/) for this blog post which convinced me to rebase my infra to use flake-parts - ''; - parts."Structure" = # markdown - '' - The system configurations are defined in [`flake.manifest`](nix/manifest.nix). - `flake.manifest.owner` provides the attributes for the administrator user, including username and pubkey. - `flake.manifest.hosts` provides the specifications for the system configurations that should be exposed by the flake as nixosConfigurations. - `flake.modules.nixos.*` provide NixOS options and configurations. - The attribute `flake.modules.nixos.default` provides options that will be applied to every system of that class. - You can use it as seen [here](nix/modules/flake/home-manager.nix): - - ```nix - flake.modules.nixos.default.imports = [ inputs.home-manager.nixosModules.default ]; - ``` - - The other attributes under `flake.modules.nixos` should be opt-in, i.e. provide options that will be set in the profiles. - `flake.profiles.nixos` provides profiles which use the options defined in `flake.modules.nixos` to define different roles for each system, such as graphical, laptop, headless, etc. - Options should not be defined here. - `flake.contracts.nixos.*` will provide contracts, such as reverse proxies or databases, which will configure options on the provider and receiver host. - ''; - }; - - perSystem = - { pkgs, ... }: - { - files.files = [ - { - path_ = "docs/README.md"; - drv = pkgs.writeText "README.md" config.text.readme; - } - ]; - }; -} diff --git a/nix/flake-parts/debug.nix b/nix/flake-parts/debug.nix deleted file mode 100644 index 38e2cb3..0000000 --- a/nix/flake-parts/debug.nix +++ /dev/null @@ -1,3 +0,0 @@ -{ - debug = true; -} diff --git a/nix/flake-parts/files.nix b/nix/flake-parts/files.nix deleted file mode 100644 index e210c52..0000000 --- a/nix/flake-parts/files.nix +++ /dev/null @@ -1,28 +0,0 @@ -{ - inputs, - withSystem, - lib, - config, - ... -}: -let - inherit (builtins) map head; - inherit (lib.lists) concatStringsSep; - mkListEntry = x: "- [" + x.path_ + "](" + x.path_ + ")"; - listOfGeneratedFiles = withSystem (head config.systems) (psArgs: psArgs.config.files.files); -in -{ - imports = [ inputs.files.flakeModules.default ]; - perSystem = psArgs: { - make-shells.default.packages = [ psArgs.config.files.writer.drv ]; - }; - text.readme.parts."Generated Files" = concatStringsSep "\n" ( - [ - "This flake uses the [files flake-parts module](https://flake.parts/options/files.html) to generate documentation." - - "The list of generated files are:" - - ] - ++ (map mkListEntry listOfGeneratedFiles) - ); -} diff --git a/nix/flake-parts/git-hooks.nix b/nix/flake-parts/git-hooks.nix deleted file mode 100644 index d17bcce..0000000 --- a/nix/flake-parts/git-hooks.nix +++ /dev/null @@ -1,24 +0,0 @@ -{ inputs, ... }: -{ - imports = [ inputs.git-hooks.flakeModule ]; - text.gitignore = ".pre-commit-config.*"; - perSystem = psArgs: { - pre-commit.settings.hooks = { - # Nix Linters - deadnix.enable = true; - statix.enable = true; - nil.enable = true; - nixfmt-rfc-style.enable = true; - # Flake Health Checks - flake-checker.enable = true; - # Misc - mixed-line-endings.enable = true; - trim-trailing-whitespace.enable = true; - #TODO: figure out vale - #TODO: make nix develop work - #TODO: add nix flake check - #TODO: add write-files - }; - make-shells.default.shellHook = psArgs.config.pre-commit.installationScript; - }; -} diff --git a/nix/flake-parts/make-shell.nix b/nix/flake-parts/make-shell.nix deleted file mode 100644 index 66ca600..0000000 --- a/nix/flake-parts/make-shell.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ inputs, ... }: -{ - #TODO: add to readme - imports = [ inputs.make-shell.flakeModules.default ]; -} diff --git a/nix/flake-parts/modules.nix b/nix/flake-parts/modules.nix deleted file mode 100644 index 1c75663..0000000 --- a/nix/flake-parts/modules.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ inputs, ... }: -{ - imports = [ inputs.flake-parts.flakeModules.modules ]; -} diff --git a/nix/flake-parts/text.nix b/nix/flake-parts/text.nix deleted file mode 100644 index 81b2f51..0000000 --- a/nix/flake-parts/text.nix +++ /dev/null @@ -1,4 +0,0 @@ -{ inputs, ... }: -{ - imports = [ inputs.text.flakeModules.default ]; -} diff --git a/nix/homes/rafiq/_scripts/note.nix b/nix/homes/rafiq/_scripts/note.nix deleted file mode 100644 index 0470fc2..0000000 --- a/nix/homes/rafiq/_scripts/note.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ pkgs, ... }: -pkgs.writeShellScriptBin "note" # bash - '' - zk edit -i - pushd ~/notebook > /dev/null - git add . - commit -u - popd > /dev/null - '' diff --git a/nix/homes/rafiq/default.nix b/nix/homes/rafiq/default.nix deleted file mode 100644 index ed01690..0000000 --- a/nix/homes/rafiq/default.nix +++ /dev/null @@ -1,145 +0,0 @@ -{ lib, inputs, ... }: -let - inherit (lib.strings) concatStrings; -in -{ - flake.modules.homeManager.rafiq = - { pkgs, ... }: - { - imports = [ - inputs.nvf.homeManagerModules.default - inputs.nix-index-database.hmModules.nix-index - ]; - persistDirs = [ - ".local/share/zoxide" - "notebook" - ]; - xdg.configFile."aichat/config.yaml".text = '' - model: gemini:gemini-2.0-flash - clients: - - type: gemini - ''; - home = { - sessionVariables = { - EDITOR = "nvim"; - FETCH = "hyfetch"; - FILE_BROWSER = "yazi"; - SHELL = "fish"; - }; - shellAliases = { - fetch = "hyfetch"; - windows = "sudo systemctl reboot --boot-loader-entry=auto-windows"; - v = "$EDITOR"; - e = "edit"; - cd = "z"; # zoxide - ai = "aichat -r %shell% -e"; - }; - packages = with pkgs; [ - fastfetch - ripgrep - aichat - (import ./_scripts/edit.nix { inherit pkgs; }) - (import ./_scripts/commit.nix { inherit pkgs; }) - (import ./_scripts/note.nix { inherit pkgs; }) - (import ./_scripts/rebuild.nix { inherit pkgs; }) - ]; - }; - programs = { - nvf.enable = true; - nvf.settings.vim = { - syntaxHighlighting = true; - hideSearchHighlight = true; - searchCase = "ignore"; - undoFile.enable = true; - telescope.enable = true; - fzf-lua.enable = true; - git.enable = true; - autopairs.nvim-autopairs.enable = true; - autocomplete = import ./_nvf/autocomplete.nix { inherit lib; }; - binds = import ./_nvf/binds.nix; - languages = import ./_nvf/languages.nix; - lsp = import ./_nvf/lsp.nix; - navigation = import ./_nvf/navigation.nix; - notes.todo-comments.enable = true; - options = { - autoindent = true; - backspace = "indent,eol,start"; - cursorline = true; - expandtab = true; - shiftwidth = 2; - smartindent = true; - tabstop = 2; - }; - snippets = import ./_nvf/snippets.nix { inherit pkgs; }; - statusline = import ./_nvf/statusline.nix; - treesitter = { - autotagHtml = true; - fold = true; - indent.disable = [ "markdown" ]; - textobjects.enable = true; - }; - ui = import ./_nvf/ui.nix; - utility = import ./_nvf/utility.nix; - visuals = import ./_nvf/visuals.nix; - }; - zk = { - enable = true; - settings.notebook.dir = "~/notebook"; - }; - hyfetch = { - enable = true; - settings = { - preset = "bisexual"; - mode = "rgb"; - light_dark = "dark"; - lightness = 0.5; - color_align = { - # Flag color alignment - mode = "horizontal"; - fore_back = null; - }; - backend = "fastfetch"; - }; - }; - - tealdeer.enable = true; - tealdeer.enableAutoUpdates = true; - direnv = { - enable = true; - nix-direnv.enable = true; - }; - zoxide.enable = true; - nix-index.enable = true; - nix-index-database.comma.enable = true; - fzf.enable = true; - fzf.enableZshIntegration = true; - yazi = { - enable = true; - shellWrapperName = "t"; - settings.mgr.sort_by = "natural"; - }; - fish.enable = true; - starship = { - enable = true; - settings = { - add_newline = false; - format = concatStrings [ - # First Line - ## Left Prompt - "$hostname$directory" - "$fill" - ## Right Prompt - "$all" - # Second Line - ## Left Prompt - "$character" - ]; - git_branch.format = "[$symbol$branch(:$remote_branch)]($style) "; - shlvl.disabled = false; - username.disabled = true; - fill.symbol = " "; - }; - }; - }; - }; -} diff --git a/nix/homes/rafiq/desktop/default.nix b/nix/homes/rafiq/desktop/default.nix deleted file mode 100644 index 9eb1fc4..0000000 --- a/nix/homes/rafiq/desktop/default.nix +++ /dev/null @@ -1,288 +0,0 @@ -{ - lib, - inputs, - config, - ... -}: -let - cfg = config.flake; -in -{ - allowedUnfreePackages = [ - "stremio-shell" - "stremio-server" - "steam" - "steam-unwrapped" - ]; - flake.modules.nixos.graphical = - { config, pkgs, ... }: - { - fonts.packages = [ pkgs.font-awesome ]; - services.getty.autologinUser = cfg.admin.username; - # Start Hyprland at boot only if not connecting through SSH - environment.loginShellInit = # sh - '' - if [[ -z "$SSH_CLIENT" && -z "$SSH_CONNECTION" ]]; then - if uwsm check may-start; then - exec uwsm start hyprland-uwsm.desktop - fi - fi - ''; - environment.variables = { - # Get Electron apps to use Wayland - ELECTRON_OZONE_PLATFORM_HINT = "auto"; - NIXOS_OZONE_WL = "1"; - }; - programs = { - hyprland = { - enable = true; - # Use UWSM to have each process controlled by systemd init - withUWSM = true; - }; - steam = { - enable = true; - gamescopeSession.enable = true; - }; - }; - security.pam.services.hyprlock = { }; - services.sunshine = { - enable = true; - capSysAdmin = true; - openFirewall = true; - settings = { - sunshine_name = config.networking.hostName; - origin_pin_allowed = "wan"; - origin_web_ui_allowed = "wan"; - }; - applications = { }; - }; - # spotifyd - networking.firewall.allowedTCPPorts = [ 5353 ]; - networking.firewall.allowedUDPPorts = [ 5353 ]; - }; - flake.modules.homeManager.rafiq = - { - pkgs, - config, - hostName, - hostConfig, - ... - }: - let - inherit (lib.modules) mkMerge mkIf; - inherit (builtins) map listToAttrs; - inherit (lib.lists) findFirstIndex; - inherit (inputs.nur.legacyPackages.${pkgs.stdenv.hostPlatform.system}.repos.rycee) firefox-addons; - profiles = listToAttrs ( - map (name: { - inherit name; - # If there are duplicate profile names, findFirstIndex will cause issues. - value = profileCfg (findFirstIndex (x: x == name) null syncedProfiles); - }) syncedProfiles - ); - syncedProfiles = [ - "rafiq" - "test" - ]; - profileCfg = id: { - inherit id; - settings."extensions.autoDisableScopes" = 0; # Auto enable extensions - extensions = { - force = true; - packages = with firefox-addons; [ - darkreader - gesturefy - sponsorblock - ublock-origin - ]; - }; - }; - in - mkIf config.graphical { - stylix = { - image = ./wallpaper.png; - targets = { - firefox.colorTheme.enable = true; - firefox.profileNames = syncedProfiles; - waybar.addCss = false; - }; - }; - persistDirs = [ - "docs" - "repos" - "vids" - "tmp" - ".cache/Smart Code ltd/Stremio" - ".local/share/Smart Code ltd/Stremio" - ".mozilla/firefox" - ".tor project" - ".local/share/Steam" - ".local/share/PrismLauncher" - ".config/sunshine" - ]; - home = { - packages = with pkgs; [ - prismlauncher - stremio - tor-browser - vlc - wl-clipboard-rs - ]; - sessionVariables = { - BROWSER = "firefox"; - LAUNCHER = "fuzzel"; - LOCKSCREEN = "hyprlock"; - NOTIFICATION_DAEMON = "mako"; - TERMINAL = "ghostty"; - STATUS_BAR = "waybar"; - }; - }; - programs = { - fuzzel.enable = true; - obs-studio.enable = true; - vesktop.enable = true; - thunderbird.enable = true; - thunderbird.profiles.rafiq.isDefault = true; - firefox = { - enable = true; - inherit profiles; - }; - hyprlock = { - enable = true; - settings = { - general.hide_cursor = true; - general.ignore_empty_input = true; - background.blur_passes = 5; - background.blur_size = 5; - label = { - text = ''hi, $USER.''; - font_size = 32; - position = "0, 0"; - halign = "center"; - valign = "center"; - zindex = 1; - shadow_passes = 5; - shadow_size = 5; - }; - input-field = { - placeholder_text = ""; - fade_on_empty = true; - size = "200, 45"; - position = "0, -5%"; - halign = "center"; - valign = "center"; - zindex = 1; - shadow_passes = 5; - shadow_size = 5; - }; - }; - }; - ghostty = { - enable = true; - settings = { - confirm-close-surface = false; - }; - }; - waybar = { - enable = true; - settings = [ - { - layer = "top"; - modules-left = [ - "pulseaudio" - ]; - modules-right = [ - "battery" - "clock" - ]; - "pulseaudio" = { - format = "{icon} {volume}%"; - format-muted = ""; - format-icons.default = [ - "" - "" - ]; - on-click = "${pkgs.pulseaudio}/bin/pactl set-sink-mute @DEFAULT_SINK@ toggle"; - }; - "clock" = { - interval = 1; - format = "{:%F %T}"; - }; - "battery" = { - interval = 1; - bat-compatibility = true; - }; - } - ]; - style = # css - '' - window#waybar { - background-color: rgba(0, 0, 0, 0); - } - - #pulseaudio, - #battery, - #clock { - padding-top: 5px; - padding-bottom: 5px; - padding-right: 5px; - color: #ffffff; - } - ''; - }; - - }; - services = { - spotifyd.enable = true; - spotifyd.settings.global = { - device_name = "${hostName}"; - device_type = "computer"; - zeroconf_port = 5353; - }; - - mako.enable = true; - mako.settings.default-timeout = 10000; - - }; - wayland.windowManager.hyprland = { - enable = true; - # This is needed for UWSM - systemd.enable = false; - # Null the packages since we use them system wide - package = null; - portalPackage = null; - settings = mkMerge [ - (import ./_hyprland/decoration.nix) - (import ./_hyprland/keybinds.nix { inherit pkgs; }) - { - ecosystem.no_update_news = true; - xwayland.force_zero_scaling = true; - monitor = - let - mainMonitor = hostConfig.machine.monitors.main; - in - [ - "${mainMonitor.id}, ${mainMonitor.resolution}@${mainMonitor.refresh-rate}, auto, ${mainMonitor.scale}" - ", preferred, auto, 1" - ]; - exec-once = [ - "uwsm app -- $LOCKSCREEN" - "uwsm app -- $NOTIFICATION_DAEMON" - "uwsm app -- $STATUS_BAR" - ]; - } - ]; - }; - # xdg.configFile."uwsm/env".text = # sh - # '' - # # Force apps to scale right with Wayland - # export GDK_SCALE=${mainMonitor.scale} - # export STEAM_FORCE_DESKTOPUI_SCALING=${mainMonitor.scale} - # ''; - # xdg.configFile."uwsm/env-hyprland".text = # sh - # '' - # export GDK_SCALE=${mainMonitor.scale} - # export STEAM_FORCE_DESKTOPUI_SCALING=${mainMonitor.scale} - # ''; - }; -} diff --git a/nix/homes/rafiq/git.nix b/nix/homes/rafiq/git.nix deleted file mode 100644 index fd6d21d..0000000 --- a/nix/homes/rafiq/git.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ - flake.modules.homeManager.rafiq = { - home.shellAliases = { - gs = "git status"; - gc = "git commit"; - gcam = "git commit -am"; - gu = "git push"; - gy = "git pull"; - gdh = "git diff HEAD"; - }; - programs.git = { - enable = true; - signing.signByDefault = true; - extraConfig = { - init.defaultBranch = "prime"; - push.autoSetupRemote = true; - pull.rebase = false; - core.editor = "$EDITOR"; - gpg.format = "ssh"; - }; - }; - }; -} diff --git a/nix/lib/attrsets.nix b/nix/lib/attrsets.nix deleted file mode 100644 index 1361c2a..0000000 --- a/nix/lib/attrsets.nix +++ /dev/null @@ -1,54 +0,0 @@ -{ lib, ... }: -let - inherit (builtins) attrNames head; - inherit (lib.trivial) pipe; - inherit (lib.attrsets) filterAttrs; -in -{ - flake.lib.attrsets = { - /** - `firstAttrNameMatching pred set` filters an attribute set `set` based on a predicate `pred` - and returns the *first* attribute name that satisfies the predicate. - - # Example - - ```nix - let - mySet = { - a = { value = 1; }; - b = { value = 2; }; - c = { value = 3; }; - }; - - isGreaterThanOne = name: value: value.value > 1; - - result = firstAttrNameMatching isGreaterThanOne mySet; - - in - result - # Output: "b" - ``` - - # Type - - ``` - firstAttrNameMatching :: (String -> Any -> Bool) -> AttrSet -> String - ``` - - # Arguments - - pred - : A function that takes an attribute name and its value and returns a boolean. - - set - : The attribute set to filter. - */ - firstAttrNameMatching = - pred: set: - pipe set [ - (filterAttrs pred) - attrNames - head - ]; - }; -} diff --git a/nix/lib/lists.nix b/nix/lib/lists.nix deleted file mode 100644 index 370362f..0000000 --- a/nix/lib/lists.nix +++ /dev/null @@ -1,13 +0,0 @@ -let - inherit (builtins) length tail; -in -{ - flake.lib.lists = rec { - shortenList = - count: list: - let - len = length list; - in - if len <= count then list else (shortenList count (tail list)); - }; -} diff --git a/nix/lib/modules.nix b/nix/lib/modules.nix deleted file mode 100644 index 0d5b50b..0000000 --- a/nix/lib/modules.nix +++ /dev/null @@ -1,101 +0,0 @@ -{ lib, config, ... }: -let - cfg = config.flake; - inherit (builtins) foldl' attrNames; - inherit (lib.attrsets) mapAttrs; -in -{ - flake.lib.modules = { - /** - Fold over the users list and create an attribute set. - - # Inputs - - `f` - - : A function that takes the name of a user and returns an attribute set. - - # Type - - ``` - userListToAttrs :: (String -> AttrSet) -> AttrSet - ``` - - # Examples - :::{.example} - ## `userListToAttrs` usage example - - ```nix - flake.manifest.users.rafiq = { ... }; - flake.modules.homeManager.users = userListToAttrs (name: { - ${name}.home.username = name; - }); - => flake.modules.homeManager.default.users.rafiq.home.username = "rafiq"; - ``` - - ::: - */ - userListToAttrs = f: foldl' (acc: elem: acc // (f elem)) { } (attrNames cfg.manifest.users); - /** - Return an attribute set for use with a option that needs to be used for all users. - - # Inputs - - `attrset` - - : An attribute set to apply to all the users. - - # Type - - ``` - forAllUsers :: AttrSet -> AttrSet - ``` - - # Examples - :::{.example} - ## `forAllUsers` usage example - - ```nix - flake.manifest.users.rafiq = { ... }; - flake.modules.nixos.default.users = forAllUsers { - isNormalUser = true; - }; - => flake.modules.nixos.default.users.rafiq.isNormalUser = true; - ``` - - ::: - */ - forAllUsers = attrset: mapAttrs (_: _: attrset) cfg.manifest.users; - - /** - Like forAllUsers, but passes in the name and value from the manifest. - - # Inputs - - `f` - - : A function that takes an attribute name and its value, and returns the new value for the attribute. - - # Type - - ``` - forAllUsers' :: (String -> Any -> Any) -> AttrSet - ``` - - # Examples - :::{.example} - ## `forAllUsers'` usage example - - ```nix - flake.manifest.users.rafiq = { ... }; - flake.modules.homeManager.users = forAllUsers' (name: value: { - home.username = name; - }); - => flake.modules.homeManager.default.users.rafiq.home.username = "rafiq"; - ``` - - ::: - */ - forAllUsers' = f: mapAttrs f cfg.manifest.users; - }; -} diff --git a/nix/lib/options.nix b/nix/lib/options.nix deleted file mode 100644 index 4d0c329..0000000 --- a/nix/lib/options.nix +++ /dev/null @@ -1,45 +0,0 @@ -{ lib, ... }: -let - inherit (lib.options) mkOption; - inherit (lib.types) - str - path - int - port - attrs - ; -in -{ - flake.lib.options = { - mkStrOption = - default: - mkOption { - inherit default; - type = str; - }; - mkAttrOption = - default: - mkOption { - inherit default; - type = attrs; - }; - mkIntOption = - default: - mkOption { - inherit default; - type = int; - }; - mkPortOption = - default: - mkOption { - type = port; - inherit default; - }; - mkPathOption = - default: - mkOption { - type = path; - inherit default; - }; - }; -} diff --git a/nix/lib/services.nix b/nix/lib/services.nix deleted file mode 100644 index 7ec6025..0000000 --- a/nix/lib/services.nix +++ /dev/null @@ -1,69 +0,0 @@ -{ config, lib, ... }: -let - inherit (builtins) length concatStringsSep; - inherit (lib.options) mkEnableOption; - inherit (lib.strings) splitString; - inherit (lib.lists) singleton; - inherit (lib.modules) mkMerge mkIf; - inherit (cfg.lib.options) mkStrOption mkPortOption mkAttrOption; - inherit (cfg.lib.lists) shortenList; - cfg = config.flake; -in -{ - flake.lib.services = rec { - splitDomain = domain: splitString "." domain; - isRootDomain = domain: length (splitDomain domain) <= 2; - mkRootDomain = domain: concatStringsSep "." (shortenList 2 (splitDomain domain)); - mkWildcardDomain = rootDomain: concatStringsSep "." ((singleton "*") ++ (splitDomain rootDomain)); - mkHost = domain: if isRootDomain domain then domain else mkWildcardDomain (mkRootDomain domain); - mkWebApp = - { - config, - name, - defaultPort, - persistDirs ? [ ], - extraOptions ? { }, - extraConfig ? { }, - }: - let - cfg = config.server.web-apps.${name}; - networkingConfig = - { - config, - cfg, - name, - }: - mkIf (cfg.domain != "") { - assertions = singleton { - assertion = config.server.web-servers.nginx.enable; - message = "You must enable a web server if you want to set server.web-apps.${name}.domain."; - }; - server.ddns.domains = singleton (mkRootDomain cfg.domain); - server.web-servers.nginx.proxies = singleton { - source = cfg.domain; - target = "http://${config.networking.hostName}:${toString cfg.port}"; - }; - }; - - in - { - options.server.web-apps.${name} = { - enable = mkEnableOption ""; - port = mkPortOption defaultPort; - domain = mkStrOption ""; - openFirewall = mkEnableOption ""; - extraCfg = mkAttrOption { }; - } // extraOptions; - - config = mkIf cfg.enable (mkMerge [ - { - inherit persistDirs; - networking.firewall = mkIf cfg.openFirewall { allowedTCPPorts = singleton cfg.port; }; - } - (networkingConfig { inherit config cfg name; }) - extraConfig - ]); - }; - - }; -} diff --git a/nix/manifest.nix b/nix/manifest.nix deleted file mode 100644 index 0643eb8..0000000 --- a/nix/manifest.nix +++ /dev/null @@ -1,92 +0,0 @@ -{ - flake.manifest = { - users.rafiq = { - primary = true; - name = "Mohammad Rafiq"; - email = "rafiq@rrv.sh"; - shell = "fish"; - pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILdsZyY3gu8IGB8MzMnLdh+ClDxQQ2RYG9rkeetIKq8n rafiq"; - }; - hosts.nixos = { - nemesis = { - graphical = true; - machine = { - platform = "amd"; - gpu = "nvidia"; - root.drive = "/dev/disk/by-id/nvme-CT2000P3SSD8_2325E6E77434"; - monitors.main = { - id = "desc:OOO AN-270W04K"; - resolution = "3840x2160"; - refresh-rate = "60"; - scale = "2"; - }; - }; - extraCfg = { - services.fwupd.enable = true; # FIXME: remove - machine = { - bluetooth.enable = true; - usb.automount = true; - virtualisation = { - podman.enable = true; - podman.distrobox.enable = true; - }; - }; - server.web-apps = { - comfy-ui.enable = true; - sd-webui-forge.enable = true; - }; - }; - }; - apollo = { - graphical = false; - machine = { - platform = "intel"; - root.drive = "/dev/disk/by-id/nvme-eui.002538d221b47b01"; - }; - extraCfg.server = { - ddns = { - enable = true; - domains = [ - "aenyrathia.wiki" - "slayment.com" - ]; - }; - web-servers = { - enableSSL = true; - nginx = { - enable = true; - proxies = [ - { - source = "aenyrathia.wiki"; - target = "http://helios:5896"; - } - { - source = "il.bwfiq.com"; - target = "http://helios:2283"; - } - ]; - }; - }; - databases = { - mongodb.enable = true; - mysql.enable = true; - postgresql.enable = true; - }; - web-apps = { - librechat = { - enable = true; - domain = "chat.bwfiq.com"; - }; - forgejo = { - enable = true; - domain = "git.rrv.sh"; - openFirewall = true; - }; - rrv-sh.enable = true; - rrv-sh.domain = "rrv.sh"; - }; - }; - }; - }; - }; -} diff --git a/nix/meta.nix b/nix/meta.nix deleted file mode 100644 index 0d95bd7..0000000 --- a/nix/meta.nix +++ /dev/null @@ -1,101 +0,0 @@ -{ - lib, - config, - inputs, - ... -}: -let - inherit (lib.options) mkOption mkEnableOption; - inherit (cfg.lib.options) mkStrOption; - inherit (lib.types) - path - lazyAttrsOf - raw - deferredModule - submodule - ; - inherit (inputs.flake-parts.lib) mkSubmoduleOptions; - inherit (cfg.lib.attrsets) firstAttrNameMatching; - cfg = config.flake; - monitorOpts = submodule { - options = { - id = mkStrOption ""; - resolution = mkStrOption ""; - refresh-rate = mkStrOption ""; - scale = mkStrOption ""; - }; - }; - userOpts = submodule { - options = { - username = mkStrOption ""; - primary = mkEnableOption ""; - name = mkStrOption ""; - email = mkStrOption ""; - shell = mkStrOption ""; - pubkey = mkStrOption ""; - }; - }; - hostOpts = submodule { - options = { - graphical = mkEnableOption ""; - machine = { - platform = mkStrOption ""; - gpu = mkStrOption ""; - root.drive = mkStrOption ""; - monitors = mkOption { - type = lazyAttrsOf monitorOpts; - default = { }; - }; - }; - extraCfg = mkOption { - type = deferredModule; - default = { }; - }; - }; - }; -in -{ - options.flake = mkSubmoduleOptions { - lib = mkOption { - type = lazyAttrsOf raw; - default = { }; - }; - paths = { - root = mkOption { type = path; }; - secrets = mkOption { - type = path; - readOnly = true; - }; - }; - manifest = mkOption { - type = submodule { - options = { - users = mkOption { - type = lazyAttrsOf userOpts; - default = { }; - }; - hosts = mkOption { - # hosts.nixos, hosts.darwin, etc. - type = lazyAttrsOf (lazyAttrsOf hostOpts); - default = { }; - }; - }; - }; - }; - # Helper Option - admin = mkOption { - type = userOpts; - default = { }; - }; - }; - config.flake = - let - username = firstAttrNameMatching (_: v: v.primary or false) cfg.manifest.users; - in - { - paths.secrets = cfg.paths.root + "/secrets"; - admin = cfg.manifest.users.${username} // { - inherit username; - }; - }; -} diff --git a/nix/modules/cli/git.nix b/nix/modules/cli/git.nix deleted file mode 100644 index c609a1a..0000000 --- a/nix/modules/cli/git.nix +++ /dev/null @@ -1,17 +0,0 @@ -{ config, ... }: -let - inherit (config.flake) manifest; -in -{ - flake.modules.homeManager.default = - { config, ... }: - { - home.sessionVariables.GIT_CONFIG_GLOBAL = "$HOME/.config/git/config"; - programs.git = { - enable = true; - userName = manifest.users.${config.home.username}.name; - userEmail = manifest.users.${config.home.username}.email; - signing.key = "~/.ssh/id_ed25519.pub"; - }; - }; -} diff --git a/nix/modules/cli/nix.nix b/nix/modules/cli/nix.nix deleted file mode 100644 index ad97ee5..0000000 --- a/nix/modules/cli/nix.nix +++ /dev/null @@ -1,6 +0,0 @@ -{ - flake.modules.nixos.default.nix.settings.experimental-features = [ - "nix-command" - "flakes" - ]; -} diff --git a/nix/modules/cli/shell.nix b/nix/modules/cli/shell.nix deleted file mode 100644 index c28f00b..0000000 --- a/nix/modules/cli/shell.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ config, lib, ... }: -let - cfg = config.flake; - inherit (cfg.lib.modules) forAllUsers'; - inherit (lib.attrsets) mapAttrs'; -in -{ - flake.modules.nixos.default = - { pkgs, ... }: - { - programs = mapAttrs' (name: value: { - name = value.shell; - value.enable = true; - }) cfg.manifest.users; - users.users = forAllUsers' (_: value: { shell = pkgs.${value.shell}; }); - }; - flake.modules.homeManager.default = - { config, ... }: - { - programs.${cfg.manifest.users.${config.home.username}.shell}.enable = true; - home.shell.enableShellIntegration = true; - }; -} diff --git a/nix/modules/graphical/default.nix b/nix/modules/graphical/default.nix deleted file mode 100644 index c714a2d..0000000 --- a/nix/modules/graphical/default.nix +++ /dev/null @@ -1,14 +0,0 @@ -{ lib, ... }: -let - inherit (lib.options) mkEnableOption; -in -{ - flake.modules.nixos.graphical = { - home-manager.sharedModules = [ { graphical = true; } ]; - services.pipewire = { - enable = true; - pulse.enable = true; - }; - }; - flake.modules.homeManager.default.options.graphical = mkEnableOption ""; -} diff --git a/nix/modules/graphical/stylix.nix b/nix/modules/graphical/stylix.nix deleted file mode 100644 index c4b3c65..0000000 --- a/nix/modules/graphical/stylix.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ inputs, ... }: -{ - # needs to be default because the options get - # evaluated even if graphical is set to false - flake.modules.nixos.default = - { pkgs, ... }: - { - imports = [ inputs.stylix.nixosModules.stylix ]; - stylix.enable = true; - stylix.base16Scheme = "${pkgs.base16-schemes}/share/themes/gruvbox-dark-hard.yaml"; - }; -} diff --git a/nix/modules/machine/bootloader.nix b/nix/modules/machine/bootloader.nix deleted file mode 100644 index 2fefe52..0000000 --- a/nix/modules/machine/bootloader.nix +++ /dev/null @@ -1,18 +0,0 @@ -{ - flake.modules.nixos.default.boot = { - initrd.availableKernelModules = [ - "nvme" - "xhci_pci" - "ahci" - "usbhid" - "usb_storage" - "sd_mod" - ]; - loader.efi.canTouchEfiVariables = true; - #TODO: disable for mbp? - loader.systemd-boot = { - enable = true; - configurationLimit = 5; - }; - }; -} diff --git a/nix/modules/machine/default.nix b/nix/modules/machine/default.nix deleted file mode 100644 index 8ad3f7a..0000000 --- a/nix/modules/machine/default.nix +++ /dev/null @@ -1,40 +0,0 @@ -{ lib, ... }: -let - inherit (lib.options) mkEnableOption; - inherit (lib.modules) mkIf mkMerge; -in -{ - flake.modules.nixos.default = - { config, modulesPath, ... }: - let - cfg = config.machine; - in - { - imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; - options.machine = { - bluetooth.enable = mkEnableOption ""; - usb.automount = mkEnableOption ""; - }; - config = mkMerge [ - (mkIf cfg.usb.automount { - services.udisks2.enable = true; - home-manager.sharedModules = [ - { - services.udiskie = { - enable = true; - automount = true; - notify = true; - }; - } - ]; - }) - (mkIf cfg.bluetooth.enable { - persistDirs = [ "/var/lib/bluetooth" ]; - hardware.bluetooth = { - enable = true; - settings.General.Experimental = true; - }; - }) - ]; - }; -} diff --git a/nix/modules/machine/gpu.nix b/nix/modules/machine/gpu.nix deleted file mode 100644 index 00c56cd..0000000 --- a/nix/modules/machine/gpu.nix +++ /dev/null @@ -1,41 +0,0 @@ -{ config, ... }: -let - cfg = config.flake; -in -{ - allowedUnfreePackages = [ - "nvidia-x11" - "nvidia-settings" - ]; - flake.modules.nixos.default = - { - config, - pkgs, - hostName, - ... - }: - let - gpu = cfg.manifest.hosts.nixos.${hostName}.machine.gpu or ""; - in - if gpu == "nvidia" then - { - hardware = { - graphics.enable = true; - graphics.extraPackages = [ pkgs.nvidia-vaapi-driver ]; - nvidia.open = true; - nvidia.package = config.boot.kernelPackages.nvidiaPackages.latest; - }; - services.xserver.videoDrivers = [ "nvidia" ]; - environment.variables = { - LIBVA_DRIVER_NAME = "nvidia"; - __GLX_VENDOR_LIBRARY_NAME = "nvidia"; - NVD_BACKEND = "direct"; - }; - nix.settings.substituters = [ "https://cuda-maintainers.cachix.org" ]; - nix.settings.trusted-public-keys = [ - "cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E=" - ]; - } - else - { }; -} diff --git a/nix/modules/machine/platform.nix b/nix/modules/machine/platform.nix deleted file mode 100644 index ae8ab61..0000000 --- a/nix/modules/machine/platform.nix +++ /dev/null @@ -1,14 +0,0 @@ -{ config, ... }: -{ - flake.modules.nixos.default = - { hostName, ... }: - let - inherit (config.flake.manifest.hosts.nixos.${hostName}.machine) platform; - arch = if platform == "amd" || platform == "intel" then "x86_64" else "aarch64"; - in - { - hardware.cpu.${platform}.updateMicrocode = true; - boot.kernelModules = [ "kvm-${platform}" ]; - nixpkgs.hostPlatform = "${arch}-linux"; - }; -} diff --git a/nix/modules/machine/root.nix b/nix/modules/machine/root.nix deleted file mode 100644 index 98c1120..0000000 --- a/nix/modules/machine/root.nix +++ /dev/null @@ -1,100 +0,0 @@ -{ - config, - lib, - inputs, - ... -}: -let - inherit (lib.modules) mkMerge mkIf mkAfter; -in -{ - flake.modules.nixos.default = - { hostName, ... }: - let - inherit (config.flake.manifest.hosts.nixos.${hostName}.machine) root; - in - { - imports = [ inputs.disko.nixosModules.disko ]; - config = mkMerge [ - { - # BTRFS - may add more later on - boot.initrd.kernelModules = [ "dm-snapshot" ]; - disko.devices.disk.main = { - device = root.drive; - content.type = "gpt"; - content.partitions = { - boot = { - name = "boot"; - size = "1M"; - type = "EF02"; - }; - esp = { - name = "ESP"; - size = "500M"; - type = "EF00"; - content = { - type = "filesystem"; - format = "vfat"; - mountpoint = "/boot"; - }; - }; - swap = { - size = "4G"; - content = { - type = "swap"; - resumeDevice = true; - }; - }; - root = { - name = "root"; - size = "100%"; - content = { - type = "lvm_pv"; - vg = "root_vg"; - }; - }; - }; - }; - - disko.devices.lvm_vg.root_vg = { - type = "lvm_vg"; - lvs.root = { - size = "100%FREE"; - content = { - type = "btrfs"; - extraArgs = [ "-f" ]; - subvolumes = { - "/root".mountpoint = "/"; - "/persist" = { - mountpoint = "/persist"; - mountOptions = [ - "subvol=persist" - "noatime" - ]; - }; - "/nix" = { - mountpoint = "/nix"; - mountOptions = [ - "subvol=nix" - "noatime" - ]; - }; - }; - }; - }; - }; - } - # Ephemeral by default - assumes btrfs - (mkIf (config.flake.manifest.hosts.nixos.${hostName}.machine.root.ephemeral or true) { - boot.initrd.postDeviceCommands = mkAfter '' - mkdir /btrfs_tmp - mount /dev/root_vg/root /btrfs_tmp - - if [[ -e /btrfs_tmp/root ]]; then - btrfs subvolume delete "/btrfs_tmp/root" - fi - ''; - }) - ]; - }; -} diff --git a/nix/modules/machine/virtualisation.nix b/nix/modules/machine/virtualisation.nix deleted file mode 100644 index 81b586e..0000000 --- a/nix/modules/machine/virtualisation.nix +++ /dev/null @@ -1,36 +0,0 @@ -{ lib, config, ... }: -let - inherit (lib.modules) mkIf; - inherit (lib.options) mkEnableOption; - inherit (lib.lists) optional; - inherit (config.flake.lib.modules) forAllUsers; -in -{ - flake.modules.nixos.default = - { pkgs, config, ... }: - let - cfg = config.machine.virtualisation; - in - { - options.machine.virtualisation = { - podman.enable = mkEnableOption ""; - podman.distrobox.enable = mkEnableOption ""; - }; - config = mkIf cfg.podman.enable { - virtualisation.containers.enable = true; - virtualisation.podman = { - enable = true; - dockerCompat = true; - defaultNetwork.settings.dns_enabled = true; - }; - users.users = forAllUsers { - extraGroups = [ "podman" ]; - autoSubUidGidRange = cfg.podman.distrobox.enable; - }; - home-manager.sharedModules = optional cfg.podman.distrobox.enable { - home.packages = [ pkgs.distrobox ]; - persistDirs = [ ".local/share/containers" ]; - }; - }; - }; -} diff --git a/nix/modules/networking/default.nix b/nix/modules/networking/default.nix deleted file mode 100644 index 435e501..0000000 --- a/nix/modules/networking/default.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ lib, ... }: -let - inherit (lib.modules) mkDefault; -in -{ - flake.modules.nixos.default = - { hostName, ... }: - { - networking = { - inherit hostName; - enableIPv6 = false; - useDHCP = mkDefault true; - networkmanager.enable = true; - }; - }; -} diff --git a/nix/modules/networking/ssh.nix b/nix/modules/networking/ssh.nix deleted file mode 100644 index d721746..0000000 --- a/nix/modules/networking/ssh.nix +++ /dev/null @@ -1,29 +0,0 @@ -{ config, lib, ... }: -let - cfg = config.flake; - inherit (lib.modules) mkMerge; - inherit (cfg.lib.modules) forAllUsers'; -in -{ - flake.modules.nixos.default = mkMerge [ - { - services.openssh.enable = true; - users.users = forAllUsers' (_: value: { openssh.authorizedKeys.keys = [ value.pubkey ]; }); - persistFiles = [ - "/etc/ssh/ssh_host_ed25519_key" - "/etc/ssh/ssh_host_ed25519_key.pub" - "/etc/ssh/ssh_host_rsa_key" - "/etc/ssh/ssh_host_rsa_key.pub" - ]; - } - { users.users.root.openssh.authorizedKeys.keys = [ cfg.admin.pubkey ]; } - ]; - flake.modules.homeManager.default = { - persistDirs = [ ".ssh" ]; - programs.ssh.enable = true; - programs.ssh.extraConfig = '' - Host * - SetEnv TERM=xterm-256color - ''; - }; -} diff --git a/nix/modules/networking/tailscale.nix b/nix/modules/networking/tailscale.nix deleted file mode 100644 index ddf1b9a..0000000 --- a/nix/modules/networking/tailscale.nix +++ /dev/null @@ -1,17 +0,0 @@ -{ config, ... }: -let - inherit (config.flake.paths) secrets; -in -{ - flake.modules.nixos.default = - { config, ... }: - { - services.tailscale = { - enable = true; - authKeyFile = config.sops.secrets."tailscale/client-secret".path; - authKeyParameters.preauthorized = true; - }; - persistDirs = [ "/var/lib/tailscale" ]; - sops.secrets."tailscale/client-secret".sopsFile = secrets + "/tailscale.yaml"; - }; -} diff --git a/nix/modules/server/databases.nix b/nix/modules/server/databases.nix deleted file mode 100644 index 2827b9d..0000000 --- a/nix/modules/server/databases.nix +++ /dev/null @@ -1,90 +0,0 @@ -{ lib, config, ... }: -let - inherit (builtins) toString; - inherit (lib.modules) mkIf mkMerge mkOverride; - inherit (lib.lists) singleton; - inherit (lib.options) mkEnableOption; - inherit (config.flake.lib.options) mkPortOption; -in -{ - allowedUnfreePackages = [ "mongodb" ]; - flake.modules.nixos.default = - { config, pkgs, ... }: - let - cfg = config.server.databases; - in - { - options.server.databases = { - mongodb = { - enable = mkEnableOption "the MongoDB server"; - port = mkPortOption 27017; - }; - mysql = { - enable = mkEnableOption "the MySQL server"; - port = mkPortOption 3306; - }; - postgresql = { - enable = mkEnableOption "the postgresql server"; - port = mkPortOption 5432; - }; - }; - - config = mkMerge [ - (mkIf cfg.postgresql.enable { - networking.firewall.allowedTCPPorts = singleton cfg.postgresql.port; - persistDirs = singleton { - directory = toString config.services.postgresql.dataDir; - user = "postgres"; - group = "postgres"; - }; - services.postgresql = { - enable = true; - enableTCPIP = true; - settings = { inherit (cfg.postgresql) port; }; - authentication = mkOverride 10 '' - #type database DBuser auth-method - local all all trust - - # ipv4 - host all all 0.0.0.0/0 trust - ''; - ensureDatabases = singleton "alphastory"; - ensureUsers = singleton { - name = "alphastory"; - ensureDBOwnership = true; - }; - }; - }) - (mkIf cfg.mongodb.enable { - networking.firewall.allowedTCPPorts = [ cfg.mongodb.port ]; - persistDirs = singleton { - directory = toString config.services.mongodb.dbpath; - user = "mongodb"; - group = "mongodb"; - }; - services.mongodb = { - enable = true; - bind_ip = "0.0.0.0"; - extraConfig = '' - net.port: ${toString cfg.mongodb.port} - ''; - }; - }) - (mkIf cfg.mysql.enable { - networking.firewall.allowedTCPPorts = [ cfg.mysql.port ]; - persistDirs = singleton { - directory = toString config.services.mysql.dataDir; - user = "mysql"; - group = "mysql"; - }; - services.mysql = { - enable = true; - package = pkgs.mariadb; - settings.mysqld = { - inherit (cfg.mysql) port; - }; - }; - }) - ]; - }; -} diff --git a/nix/modules/server/ddns.nix b/nix/modules/server/ddns.nix deleted file mode 100644 index 40a03ea..0000000 --- a/nix/modules/server/ddns.nix +++ /dev/null @@ -1,59 +0,0 @@ -{ lib, config, ... }: -let - inherit (lib.modules) mkIf; - inherit (lib.options) mkOption mkEnableOption; - inherit (lib.types) enum str listOf; - inherit (lib.lists) unique; - inherit (builtins) map; - inherit (config.flake.paths) secrets; -in -{ - flake.modules.nixos.default = - { config, ... }: - let - cfg = config.server.ddns; - mkDomain = domain_name: { - inherit domain_name; - sub_domains = [ - "@" - "*" - ]; - }; - in - { - options.server.ddns = { - enable = mkEnableOption ""; - type = mkOption { - type = enum [ "godns" ]; - default = "godns"; - }; - domains = mkOption { - type = listOf str; - default = [ ]; - }; - }; - - config = mkIf cfg.enable { - sops.secrets."keys/cloudflare".sopsFile = secrets + "/keys.yaml"; - services.godns = { - enable = if (cfg.type == "godns") then true else false; - loadCredential = [ "cf_token:${config.sops.secrets."keys/cloudflare".path}" ]; - settings = { - provider = "Cloudflare"; - login_token_file = "$CREDENTIALS_DIRECTORY/cf_token"; - # Sanitize the list of domains with unique so we can add to it with every service. - domains = map mkDomain (unique cfg.domains); - resolver = "1.1.1.1"; - ip_urls = [ - "https://wtfismyip.com/text" - "https://api.ipify.org" - "https://myip.biturl.top" - "https://api-ipv4.ip.sb/ip" - ]; - ip_type = "IPv4"; - interval = 300; - }; - }; - }; - }; -} diff --git a/nix/modules/server/web-apps/comfy-ui.nix b/nix/modules/server/web-apps/comfy-ui.nix deleted file mode 100644 index 738e2e5..0000000 --- a/nix/modules/server/web-apps/comfy-ui.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ - lib, - config, - inputs, - ... -}: -let - inherit (lib.lists) singleton; - inherit (config.flake.lib.services) mkWebApp; -in -{ - flake.modules.nixos.default = - { config, ... }: - let - upstreamCfg = config.services.comfyUi; - in - mkWebApp { - inherit config; - name = "comfy-ui"; - defaultPort = 8188; - persistDirs = singleton { - directory = upstreamCfg.dataDir; - inherit (upstreamCfg) user group; - mode = "777"; - }; - extraConfig.services.comfyUi = { - enable = true; - listenHost = "0.0.0.0"; - }; - } - // { - imports = [ inputs.stable-diffusion-webui-nix.nixosModules.default ]; - }; -} diff --git a/nix/modules/server/web-apps/forgejo.nix b/nix/modules/server/web-apps/forgejo.nix deleted file mode 100644 index 5beb028..0000000 --- a/nix/modules/server/web-apps/forgejo.nix +++ /dev/null @@ -1,47 +0,0 @@ -{ lib, config, ... }: -let - inherit (lib.lists) singleton optional; - inherit (config.flake.lib.options) mkPortOption; - inherit (config.flake.lib.services) mkWebApp; -in -{ - flake.modules.nixos.default = - { config, ... }: - let - cfg = config.server.web-apps.forgejo; - upstreamCfg = config.services.forgejo; - in - mkWebApp { - inherit config; - name = "forgejo"; - defaultPort = 3000; - persistDirs = singleton { - directory = upstreamCfg.stateDir; - inherit (upstreamCfg) user group; - }; - extraOptions = { - sshPort = mkPortOption 2222; - }; - extraConfig = { - networking.firewall.allowedTCPPorts = optional cfg.openFirewall cfg.sshPort; - services.forgejo = { - enable = true; - settings = { - server = { - DOMAIN = cfg.domain; - ROOT_URL = "https://${cfg.domain}/"; - HTTP_PORT = cfg.port; - START_SSH_SERVER = true; - SSH_PORT = cfg.sshPort; - }; - repository = { - USE_COMPAT_SSH_URI = false; - ENABLE_PUSH_CREATE_USER = true; - ENABLE_PUSH_CREATE_ORG = true; - }; - "repository.signing".FORMAT = "ssh"; - }; - }; - }; - }; -} diff --git a/nix/modules/server/web-apps/librechat.nix b/nix/modules/server/web-apps/librechat.nix deleted file mode 100644 index 63d2efa..0000000 --- a/nix/modules/server/web-apps/librechat.nix +++ /dev/null @@ -1,87 +0,0 @@ -{ - lib, - inputs, - config, - ... -}: -let - inherit (lib.lists) singleton; - inherit (config.flake.lib.options) mkStrOption; - inherit (config.flake.lib.services) mkWebApp; - inherit (config.flake.paths) secrets; -in -{ - flake.modules.nixos.default = - { config, ... }: - let - cfg = config.server.web-apps.librechat; - upstreamCfg = config.services.librechat; - in - mkWebApp { - inherit config; - name = "librechat"; - defaultPort = 3080; - persistDirs = singleton { - directory = upstreamCfg.dataDir; - inherit (upstreamCfg) user group; - }; - extraOptions.mongodbURI = mkStrOption "mongodb://${config.networking.hostName}:27017/LibreChat"; - extraConfig = { - sops.secrets = { - "librechat/creds_key".sopsFile = secrets + "/librechat.yaml"; - "librechat/creds_iv".sopsFile = secrets + "/librechat.yaml"; - "librechat/jwt_secret".sopsFile = secrets + "/librechat.yaml"; - "librechat/jwt_refresh_secret".sopsFile = secrets + "/librechat.yaml"; - "keys/gemini".sopsFile = secrets + "/keys.yaml"; - "keys/openrouter".sopsFile = secrets + "/keys.yaml"; - }; - services.librechat = { - enable = true; - openFirewall = true; - inherit (cfg) port; - env = { - HOST = "0.0.0.0"; - ALLOW_REGISTRATION = "true"; - NO_INDEX = "true"; - MONGO_URI = cfg.mongodbURI; - DOMAIN_CLIENT = cfg.domain; - DOMAIN_SERVER = cfg.domain; - ENDPOINTS = "anthropic,agents,google"; - }; - credentials = { - CREDS_KEY = config.sops.secrets."librechat/creds_key".path; - CREDS_IV = config.sops.secrets."librechat/creds_iv".path; - JWT_SECRET = config.sops.secrets."librechat/jwt_secret".path; - JWT_REFRESH_SECRET = config.sops.secrets."librechat/jwt_refresh_secret".path; - OPENROUTER_KEY = config.sops.secrets."keys/openrouter".path; - GOOGLE_KEY = config.sops.secrets."keys/gemini".path; - }; - settings = { - version = "1.1.4"; - cache = true; - endpoints.custom = [ - { - name = "OpenRouter"; - apiKey = "\${OPENROUTER_KEY}"; - baseURL = "https://openrouter.ai/api/v1"; - models.default = [ "meta-llama/llama-3-70b-instruct" ]; - models.fetch = true; - titleConvo = true; - titleModel = "current_model"; - modelDisplayLabel = "OpenRouter"; - } - ]; - interface = { - privacyPolicy = { - externalUrl = "https://librechat.ai/privacy-policy"; - openNewTab = true; - }; - }; - }; - }; - }; - } - // { - imports = singleton "${inputs.rrvsh-nixpkgs}/nixos/modules/services/web-apps/librechat.nix"; - }; -} diff --git a/nix/modules/server/web-apps/rrv-sh.nix b/nix/modules/server/web-apps/rrv-sh.nix deleted file mode 100644 index d4c801d..0000000 --- a/nix/modules/server/web-apps/rrv-sh.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ config, inputs, ... }: -let - inherit (config.flake.lib.services) mkWebApp; -in -{ - flake.modules.nixos.default = - { config, ... }: - let - cfg = config.server.web-apps.rrv-sh; - in - mkWebApp { - inherit config; - name = "rrv-sh"; - defaultPort = 2309; - extraConfig.services.rrv-sh = { - enable = true; - inherit (cfg) port; - }; - } - // { - imports = [ inputs.rrv-sh.nixosModules.default ]; - }; -} diff --git a/nix/modules/server/web-apps/sd-webui-forge.nix b/nix/modules/server/web-apps/sd-webui-forge.nix deleted file mode 100644 index cf88d86..0000000 --- a/nix/modules/server/web-apps/sd-webui-forge.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ - lib, - inputs, - config, - ... -}: -let - inherit (lib.lists) singleton; - inherit (config.flake.lib.services) mkWebApp; -in -{ - flake.modules.nixos.default = - { config, ... }: - let - upstreamCfg = config.services.sd-webui-forge; - in - mkWebApp { - inherit config; - name = "sd-webui-forge"; - defaultPort = 7860; - persistDirs = singleton { - directory = upstreamCfg.dataDir; - inherit (upstreamCfg) user group; - }; - extraConfig.services.sd-webui-forge = { - enable = true; - listen = true; - extraArgs = "--cuda-malloc"; - }; - } - // { - imports = [ inputs.stable-diffusion-webui-nix.nixosModules.default ]; - }; -} diff --git a/nix/modules/server/web-servers.nix b/nix/modules/server/web-servers.nix deleted file mode 100644 index 1967268..0000000 --- a/nix/modules/server/web-servers.nix +++ /dev/null @@ -1,142 +0,0 @@ -{ lib, config, ... }: -let - inherit (builtins) listToAttrs map; - inherit (config.flake.lib.options) mkStrOption mkPathOption; - inherit (config.flake.lib.services) mkRootDomain; - inherit (config.flake.paths) secrets; - inherit (config.flake.admin) email; - inherit (lib.types) listOf submodule attrs; - inherit (lib.options) mkOption mkEnableOption; - inherit (lib.modules) mkMerge mkIf; - inherit (lib.lists) singleton; -in -{ - flake.modules.nixos.default = - { config, ... }: - let - cfg = config.server.web-servers; - sslCheck = good: bad: if cfg.enableSSL then good else bad; - in - { - options.server.web-servers = { - enableSSL = mkEnableOption ""; - nginx = { - enable = mkEnableOption "the Nginx server"; - openFirewall = mkEnableOption "" // { - default = true; - }; - enableDefaultSink = mkEnableOption "" // { - default = true; - }; - pages = mkOption { - default = [ ]; - type = listOf (submodule { - options = { - domain = mkStrOption ""; - root = mkPathOption ""; - extraConfig = mkOption { - type = attrs; - default = { }; - }; - locations = mkOption { - type = attrs; - default = { }; - }; - }; - }); - }; - proxies = mkOption { - default = [ ]; - type = listOf (submodule { - options = { - source = mkStrOption ""; - target = mkStrOption ""; - extraConfig = mkOption { - type = attrs; - default = { }; - }; - locations = mkOption { - type = attrs; - default = { }; - }; - }; - }); - }; - }; - }; - config = mkMerge [ - (mkIf cfg.enableSSL { - sops.secrets."keys/cloudflare".sopsFile = secrets + "/keys.yaml"; - security.acme = { - acceptTerms = true; - defaults = { - inherit email; - dnsProvider = "cloudflare"; - credentialFiles."CLOUDFLARE_DNS_API_TOKEN_FILE" = config.sops.secrets."keys/cloudflare".path; - }; - certs = { - "rrv.sh".extraDomainNames = singleton "*.rrv.sh"; - "bwfiq.com".extraDomainNames = singleton "*.bwfiq.com"; - "slayment.com".extraDomainNames = singleton "*.slayment.com"; - "aenyrathia.wiki".extraDomainNames = singleton "*.aenyrathia.wiki"; - }; - }; - }) - (mkIf cfg.nginx.enable { - networking.firewall.allowedTCPPorts = mkIf cfg.nginx.openFirewall [ - 443 - 80 - ]; - users.users.nginx.extraGroups = singleton "acme"; - services.nginx = { - enable = true; - recommendedProxySettings = true; - recommendedTlsSettings = true; - recommendedOptimisation = true; - recommendedGzipSettings = true; - virtualHosts = mkMerge [ - (mkIf cfg.nginx.enableDefaultSink { - "_" = { - default = true; - rejectSSL = sslCheck true false; - locations."/" = { - return = "444"; - }; - }; - }) - (listToAttrs ( - map (page: { - name = page.domain; - value = { - addSSL = sslCheck true false; - useACMEHost = sslCheck (mkRootDomain page.domain) null; - acmeRoot = null; # needed for DNS validation - locations = { - "/" = { - inherit (page) root; - } // page.extraConfig; - } // page.locations; - }; - }) cfg.nginx.pages - )) - (listToAttrs ( - map (proxy: { - name = proxy.source; - value = { - addSSL = sslCheck true false; - useACMEHost = sslCheck (mkRootDomain proxy.source) null; - acmeRoot = null; # needed for DNS validation - locations = { - "/" = { - proxyPass = proxy.target; - } // proxy.extraConfig; - } // proxy.locations; - }; - }) cfg.nginx.proxies - )) - ]; - }; - }) - ]; - }; -} diff --git a/nix/modules/system/persist.nix b/nix/modules/system/persist.nix deleted file mode 100644 index 4e298c0..0000000 --- a/nix/modules/system/persist.nix +++ /dev/null @@ -1,63 +0,0 @@ -{ - lib, - inputs, - config, - ... -}: -let - inherit (lib.options) mkOption; - inherit (config.flake.lib.options) mkStrOption; - inherit (lib.types) - listOf - str - coercedTo - submodule - ; - permOpts = { - user = mkStrOption "root"; - group = mkStrOption "root"; - mode = mkStrOption "0755"; - }; - mkOpts = - type: opts: - mkOption { - default = [ ]; - type = listOf ( - coercedTo str (d: { ${type} = d; }) (submodule { - options = { - ${type} = mkStrOption ""; - } // opts; - }) - ); - }; -in -{ - flake.modules.nixos.default = - { config, ... }: - { - imports = [ inputs.impermanence.nixosModules.impermanence ]; - options.persistDirs = mkOpts "directory" permOpts; - options.persistFiles = mkOpts "file" { parentDirectory = permOpts; }; - config = { - programs.fuse.userAllowOther = true; - fileSystems."/persist".neededForBoot = true; - environment.persistence."/persist" = { - hideMounts = true; - directories = config.persistDirs; - files = config.persistFiles; - }; - }; - }; - flake.modules.homeManager.default = - { config, ... }: - { - imports = [ inputs.impermanence.homeManagerModules.impermanence ]; - options.persistDirs = mkOpts "directory" { }; - options.persistFiles = mkOpts "file" { }; - config.home.persistence."/persist${config.home.homeDirectory}" = { - allowOther = true; - directories = config.persistDirs; - files = config.persistFiles; - }; - }; -} diff --git a/nix/modules/system/secrets.nix b/nix/modules/system/secrets.nix deleted file mode 100644 index ff90532..0000000 --- a/nix/modules/system/secrets.nix +++ /dev/null @@ -1,50 +0,0 @@ -{ - config, - inputs, - lib, - ... -}: -let - cfg = config.flake; - inherit (builtins) readFile; - inherit (lib.meta) getExe; - inherit (lib.strings) trim; - inherit (cfg.admin) username pubkey; -in -{ - flake.modules.nixos.default = - { config, ... }: - { - imports = [ inputs.sops-nix.nixosModules.sops ]; - config.sops.age.sshKeyPaths = [ - "/persist${config.users.defaultUserHome}/${username}/.ssh/id_ed25519" - ]; - }; - flake.modules.homeManager.default.persistDirs = [ ".config/sops/age" ]; - perSystem = - { pkgs, ... }: - { - files.files = [ - { - path_ = ".sops.yaml"; - drv = - pkgs.writeText ".sops.yaml" # yaml - '' - keys: - - &${username} ${trim ( - readFile "${ - pkgs.runCommand "" { } '' - mkdir $out; echo ${pubkey} | ${getExe pkgs.ssh-to-age} > $out/agepubkey - '' - }/agepubkey" - )} - creation_rules: - - path_regex: \.(yaml)$ - key_groups: - - age: - - *${username} - ''; - } - ]; - }; -} diff --git a/nix/modules/system/sudo.nix b/nix/modules/system/sudo.nix deleted file mode 100644 index 1c9b560..0000000 --- a/nix/modules/system/sudo.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ config, ... }: -let - cfg = config.flake; -in -{ - flake.modules.nixos.default = { - security.sudo.wheelNeedsPassword = false; - nix.settings.trusted-users = [ "@wheel" ]; - users.users.${cfg.admin.username}.extraGroups = [ "wheel" ]; - }; -} diff --git a/nix/modules/system/system.nix b/nix/modules/system/system.nix deleted file mode 100644 index 15342b1..0000000 --- a/nix/modules/system/system.nix +++ /dev/null @@ -1,14 +0,0 @@ -{ - flake.modules.nixos.default = { - persistFiles = [ "/etc/machine-id" ]; - persistDirs = [ "/var/lib/systemd" ]; - time.timeZone = "Asia/Singapore"; - i18n.defaultLocale = "en_US.UTF-8"; - system.stateVersion = "25.11"; - }; - flake.modules.homeManager.default = - { osConfig, ... }: - { - home.stateVersion = osConfig.system.stateVersion; - }; -} diff --git a/nix/modules/system/users.nix b/nix/modules/system/users.nix deleted file mode 100644 index 5815089..0000000 --- a/nix/modules/system/users.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ config, ... }: -let - cfg = config.flake; - inherit (cfg.lib.modules) userListToAttrs forAllUsers'; -in -{ - flake.modules.nixos.default = - { config, ... }: - { - persistDirs = [ "/var/lib/nixos" ]; - users = { - mutableUsers = false; - groups.users.gid = 100; - users = forAllUsers' ( - name: _: { - isNormalUser = true; - hashedPasswordFile = config.sops.secrets."${name}/hashedPassword".path; - } - ); - }; - sops.secrets = userListToAttrs (name: { - "${name}/hashedPassword" = { - neededForUsers = true; - sopsFile = cfg.paths.secrets + "/users.yaml"; - }; - }); - home-manager.users = forAllUsers' ( - name: _: { - home.username = name; - home.homeDirectory = config.users.users.${name}.home; - } - ); - }; -} diff --git a/nix/modules/unfree-packages.nix b/nix/modules/unfree-packages.nix deleted file mode 100644 index b74984e..0000000 --- a/nix/modules/unfree-packages.nix +++ /dev/null @@ -1,17 +0,0 @@ -{ lib, config, ... }: -let - inherit (builtins) elem; - inherit (lib.options) mkOption; - inherit (lib.strings) getName; - inherit (lib.types) listOf str; - predicate = pkg: elem (getName pkg) config.allowedUnfreePackages; -in -{ - options.allowedUnfreePackages = mkOption { - type = listOf str; - default = [ ]; - }; - config.flake.modules.nixos.default = { - nixpkgs.config.allowUnfreePredicate = predicate; - }; -} diff --git a/nix/homes/rafiq/_scripts/commit.nix b/packages/commit/default.nix similarity index 100% rename from nix/homes/rafiq/_scripts/commit.nix rename to packages/commit/default.nix diff --git a/packages/deploy/default.nix b/packages/deploy/default.nix new file mode 100644 index 0000000..f9280e8 --- /dev/null +++ b/packages/deploy/default.nix @@ -0,0 +1,123 @@ +{ pkgs, ... }: +pkgs.writeShellScriptBin "deploy" # sh + '' + while [[ $# -gt 0 ]]; do + case "$1" in + --user) + USER="$2" + shift 2 + ;; + --ip) + IP="$2" + shift 2 + ;; + --hostname) + HOSTNAME="$2" + shift 2 + ;; + *) + echo "Error: Unknown parameter: $1" + exit 1 + ;; + esac + done + + # Check if required arguments are provided + if [[ -z "$USER" || -z "$IP" || -z "$HOSTNAME" ]]; then + echo "Usage: $0 --user --ip --hostname [--wait-timeout ]" + exit 1 + fi + + # --- Helper Functions --- + + wait_for_ping() { + local ip="$1" + + echo "Waiting for ping to $ip..." + while true; do + if ping -c 1 -W 1 "$ip"; then + echo "Ping successful." + return 0 + fi + sleep 2 + done + } + + wait_for_ssh() { + local ip="$1" + + echo "Waiting for SSH to $ip..." + while true; do + ssh-keygen -R "$ip" || true # Suppress error if key doesn't exist + if ssh -o StrictHostKeyChecking=no root@"$ip" exit; then + echo "SSH connection successful." + return 0 + fi + sleep 2 + done + } + + retry_rebuild() { + local ip="$1" + + echo "Attempting rebuild..." + while true; do + if nixos-rebuild switch --flake . --target-host root@"$ip"; then + echo "Rebuild successful." + return 0 + fi + sleep 2 + done + } + + test_connection() { + local ip="$1" + # Wait for the server to come back up after the reboot. Ping first. + if ! wait_for_ping $ip; then + echo "Error: Server did not respond to ping after reboot." + exit 1 + fi + + # Wait for SSH access after reboot + if ! wait_for_ssh $ip; then + echo "Error: SSH access not available after reboot." + exit 1 + fi + } + + # --- Deployment Steps --- + + test_connection "$IP" + + # Copy SSH key to remote server + ssh-copy-id -o StrictHostKeyChecking=no root@"$IP" || { echo "Error: Failed to copy SSH key."; exit 1; } + + # Deploy NixOS configuration using nixos-anywhere + nix run github:nix-community/nixos-anywhere -- \ + -i ~/.ssh/id_ed25519 --ssh-option StrictHostKeyChecking=no \ + --flake .#"$HOSTNAME" --target-host root@"$IP" || { echo "Error: nixos-anywhere failed."; exit 1; } + + test_connection "$IP" + + # Create SSH directory on the remote server (if not already present) + ssh root@"$IP" -o StrictHostKeyChecking=no mkdir -p "/persist/home/$USER/.ssh" || { echo "Error: Failed to create SSH directory."; exit 1; } + + # Set owner of the user's home directory + ssh root@"$IP" -o StrictHostKeyChecking=no chown -R "$USER:users" "/persist/home/$USER" || { echo "Error: Failed to set ownership."; exit 1; } + + # Copy SSH keys to the remote server + scp -r ~/.ssh root@"$IP":/persist/home/"$USER" || { echo "Error: Failed to copy SSH keys."; exit 1; } + + #TODO: remove device from tailscale + + # Build and switch the configuration + retry_rebuild "$IP" + + # Reboot the system + ssh root@"$IP" -o StrictHostKeyChecking=no systemctl reboot || { echo "Error: Failed to reboot."; exit 1; } + + test_connection "$IP" + test_connection "$HOSTNAME" + + echo "Deployment complete. System should be ready." + '' diff --git a/nix/homes/rafiq/_scripts/edit.nix b/packages/edit/default.nix similarity index 100% rename from nix/homes/rafiq/_scripts/edit.nix rename to packages/edit/default.nix diff --git a/nix/homes/rafiq/_scripts/rebuild.nix b/packages/rebuild/default.nix similarity index 95% rename from nix/homes/rafiq/_scripts/rebuild.nix rename to packages/rebuild/default.nix index 223a4db..cb303ac 100644 --- a/nix/homes/rafiq/_scripts/rebuild.nix +++ b/packages/rebuild/default.nix @@ -1,6 +1,6 @@ -{ pkgs }: +{ pkgs, lib, ... }: let - inherit (pkgs.lib) getExe; + inherit (lib) getExe; in pkgs.writeShellScriptBin "rebuild" # sh '' @@ -71,7 +71,7 @@ pkgs.writeShellScriptBin "rebuild" # sh local NEW_GENERATION=$(ssh "$1" readlink /nix/var/nix/profiles/system | cut -d- -f2) info "$1 - New generation is $NEW_GENERATION. Current is $CURRENT_GENERATION." if [ ! $NEW_GENERATION -gt $CURRENT_GENERATION ]; then - warn "New config was not added to bootloader." + warn "New config was not added to bootloader." fi fi } @@ -102,10 +102,10 @@ pkgs.writeShellScriptBin "rebuild" # sh hostnames=$(nix flake show --all-systems --json | , jq -r '.nixosConfigurations | keys | .[]') for host in ''${hostnames[@]}; do info "Checking if $host is reachable..." - if ping -c 1 -W 1 "$host" > /dev/null 2>&1 ; then + if ping -c 1 -W 1 "$host" > /dev/null 2>&1 ; then info "$host is reachable." reachable_hosts+=("$host") - else + else warn "$host is unreachable." fi done diff --git a/secrets/keys.yaml b/secrets/keys.yaml deleted file mode 100644 index 93a7ff8..0000000 --- a/secrets/keys.yaml +++ /dev/null @@ -1,19 +0,0 @@ -keys: - cloudflare: ENC[AES256_GCM,data:p2IISOuU/ShoifW5OFY/6Bi6PI0iIiQoBfnV512f2z84U9QS/KEhzA==,iv:5AkwtNAK8mD2DbvXCtTeNeIrpF/GIsSyOYxy8G4Jsqo=,tag:u2xJcRBR5WTMWdzupx4tbQ==,type:str] - gemini: ENC[AES256_GCM,data:GwXVBsQdLesgP6PUZJRrLO5u6jd6XYFv9vjNTsojOwaWlxkDeRos,iv:w6Uz6j/MfpgQdIRYqJCneWqTsA+JEsB/T3cySVY2k3c=,tag:JY+LDar1UzC6qLKLichKnQ==,type:str] - openrouter: ENC[AES256_GCM,data:kRr/f/qlso/SGyZa7J2zeQqbWDZnBoBsUvCEFbWuXpS8ah0qKDANfmX5NsJy3ehjXYOljbHl9WOxQcyriMTE8cyZodp9QySMEQ==,iv:NkWa/Q0AncaDQFo+SZEd3qKDddCxsLPgTi3bYb3SbhQ=,tag:HPTr27cxIV5mx432UMTfXQ==,type:str] -sops: - age: - - recipient: age12l33pas8eptwjc7ewux3d8snyzfzwz0tn9qg5kw8le79fswmjgjqdjgyy6 - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBmcTdPWURrK2w1QUZubVZo - VUMrcFFQU0UxdDU3OG9PdEUxcGs2bzZNcmg0Cm03cUlPZkRMK0ZXOTllV3BtZWFp - QXBPRWtOd0xjZC9BdGdmWnVoVGpHR1UKLS0tIEpaVXlSNkhpMVZnTFZWTFVEWTgv - T3VyZXZnaGZaMVBnVko2Tlc2S3FpdDQKRiHCOtkHKugfquQfYkk4o9SMtZlo1CqZ - 3i9+9Z516KS1+ERTklBUzZDBRZISY0c2nluO+tn71wnKAMIxetKryQ== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-07-08T20:53:06Z" - mac: ENC[AES256_GCM,data:hcY1uSNp1E6LrQDpEgK8MABDijc0NQg89iEH1duq8rXFlOFG8BWrEDTasoUX3mH8RPBu5DF9YJHv216w1v2RdVz5w32e4GlcpuA8NUjNxBx38cx/GCp9bx0wEapVVf4Er+a8OmCmbp0MUhKvV3Xy5xs/ZlNJ7KppRXX9hZvzW84=,iv:7SirDOpe3ds23+XKQXe7CKnzb4yhQQWhvcARFnL0qRU=,tag:75tXPKJHfrMKYiM+XUI98Q==,type:str] - unencrypted_suffix: _unencrypted - version: 3.10.2 diff --git a/secrets/librechat.yaml b/secrets/librechat.yaml deleted file mode 100644 index d6668cd..0000000 --- a/secrets/librechat.yaml +++ /dev/null @@ -1,20 +0,0 @@ -librechat: - creds_key: ENC[AES256_GCM,data:sELKgqif9ec6VV0Q9OVk8IbUAI5noPtUB1b1WrPvxjDzJODd9YoJHWiH+N0vwORje5LiuzqZ/0Kn/UMdPfy3qw==,iv:SFFW+P0vxy4s6TkaAyCNLLXLIBrdi8oMkm7Q/Vec/yk=,tag:ZNC0vMdyh+S204Qr0itvnw==,type:str] - creds_iv: ENC[AES256_GCM,data:h8RHcW7zt8CnKrYDGxlN/H9Wim4KpLaiFl2E2AK+YJY=,iv:xRctbyBFprN6Y1Lvk08EpzZNXa0owYCph+wqcOAR/Gw=,tag:ZdA0ibjyH1Y6DAd23mfJRQ==,type:str] - jwt_secret: ENC[AES256_GCM,data:mXMi0EenuU1EIZWUyLE3wkVTouJk2QPXIKV38sfwbKfjdc28GgdsaWtunaSpD4uYBrWCv1rXq5qj18ohlAKs/g==,iv:ZWZWgYzVQh+kRN4+EEBFdWc4aWGq5IDtlEVde9mzS7I=,tag:BmWQN9yI92RHJMy/pt8rRg==,type:str] - jwt_refresh_secret: ENC[AES256_GCM,data:iw+/E0wb2Ih1iQOaCCXBN5tj98Z2CdpaJMYOiuoTanjW7bvJXGfVObXKTBTtRs1P4TzCc4qK7mes5Sa6oajBpg==,iv:3mr3PYAjJ3bncATgfSwEyrIM2YioSfSu38NUfDmk6zs=,tag:RIYJ1YBaQVpwAmlo3CKg2Q==,type:str] -sops: - age: - - recipient: age12l33pas8eptwjc7ewux3d8snyzfzwz0tn9qg5kw8le79fswmjgjqdjgyy6 - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArcko2MmowTkpKaDJTdjZE - NVdzbklXZngxaHhrbkhGTXlCNDkzNml4dnlZCjRWOFZCSWRKenZzN0dhYXplVzh0 - OVdaUnRkS2dIYklFS2dwUXVxaElxNkkKLS0tICtxZDV0a2hIaUM2NFBwOGwxcklz - YWJyU0VKRXFxT29TSjR1KzE0ZHJGQncKrX5Sujd617WgFDYA5r63K4ZwoJpP9m8M - xexbGVHAeSyWNjOG7x5A9gYC1/dG3NY2l5xoITn0NKi68ZEfGD/J3w== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-07-08T19:37:50Z" - mac: ENC[AES256_GCM,data:LBkUPMR8D8+IVUugWzK4a51d0lkGJqnG5D9EkHC4aGXcuSpxpxkbUDXWsqK3u1FxxfCnR87ZhD+UGd3OV6Wvsl9/v968eC/3jxuZALnOgUGcTyUayo8qLq1J6HEFUDoUoH2tk/SF0Cn2r34fkcUd1NtRdQX+C0Zsc8Tk0zIRA8U=,iv:aUvg409sogxRBgYzNECW5eH7GsSAsYY9AHWmL0UD6PA=,tag:0pMoXeuF6DLCyIdDVsPmGA==,type:str] - unencrypted_suffix: _unencrypted - version: 3.10.2 diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml new file mode 100644 index 0000000..4fb2114 --- /dev/null +++ b/secrets/secrets.yaml @@ -0,0 +1,30 @@ +rafiq: + hashedPassword: ENC[AES256_GCM,data:SzzSPg5Ze4H+fVl6ZvAULO9FDfRehusmP6uldT4Ok2/9ZeOp9r4LgjKajoiw2A1DWD1zQ1GQwMCHKpeZjCC4rBUNWW5DMcBUJA==,iv:KktKuqr0JNhjeJIlIgkoAv6mP2dQlfQrXiIOASLPkbw=,tag:g9LarkT6EjDrH+dXSjMwPg==,type:str] + personalEmailPassword: ENC[AES256_GCM,data:TGJtDO++QcWqU1AbLe4=,iv:RjLRmq7fdbVRbv0M8ZQHyCK5l95JW3TRjN5w9Ci92zs=,tag:JibrH863smajCXESwhAR4g==,type:str] + workEmailPassword: ENC[AES256_GCM,data:++Gm9dIhmqEQz3+Ej9c=,iv:dAvyyLZvsHcjudU4gdU0iyWYDjjhe49UC2swHh++ldc=,tag:6o1DyJk5WOFO/Hfr0uMKSw==,type:str] + oldSMBCredentials: ENC[AES256_GCM,data:aY41trUJcvGa584H0A==,iv:3h9AZ33HXWT4D/vGMyy/o+TXyGg75Ixcj3+h2EskvIQ=,tag:dDo55h1ljOYLZBHn9bK7ew==,type:str] +keys: + openrouter: ENC[AES256_GCM,data:Uddc0leKVD2xxpvDpsTJV3qZ4oe89Uz6dJMuzF/TeI5iIrG+DNIAYPcnIQiA6LDScO9mag8XNiYpYH7lyMnUg1cvThChiVhO+A==,iv:RHSrL/L74dSvLKAvGwyMME53RzKr2+RDnI8xBpDJVng=,tag:d81mr26SeStmAa8UgEF/LA==,type:str] + gemini: ENC[AES256_GCM,data:t4XTzJLMbHBG7LNaWMwO0YyYHREYOp4Zn95Kwshunnpwq9ezVv+0,iv:ZHq1ytak7Qy5a/zHghwEIWRinDWAkk2Vxw4iu/Q/UPk=,tag:Wyk0FqLTOWelznWHg/anxg==,type:str] + cloudflare: ENC[AES256_GCM,data:nrtHnQR0Oon9BrSN0AeAjl8H8B7quuwSu/Qjabe9HFpWgcZq9n1JCA==,iv:ovyHqy5iKXDYXe4H7eRA51+kODhP+vAWoc98cS/6zG0=,tag:JyktO6EMRZ00CRhTb03+fg==,type:str] + telegram_bot: ENC[AES256_GCM,data:qGJx1Bph94oU2USjZL4h2NqV5ueCiYIvEbx84Xg687F5//MItLAS58MZdUPSuQ==,iv:WmldN5Je4miamLXCK6Cv17TTGmaBq/lde2czsEgNBi4=,tag:aU27eDE5PbYAniKEXk+MRA==,type:str] +librechat: + creds_key: ENC[AES256_GCM,data:/fzPgZiDnyWZalJUBFpFQ2/anxvbX3XLp18n+x1xfzOMisq52ISB5VJOzi9xaNRNruQEoh/lva9gDbIgNyzduA==,iv:xGgufMc/tPOLCKEb2MnEkxmf0FPpENGW1FcCm15CW6k=,tag:9aR+DndXkCg1sboxTFuygQ==,type:str] + creds_iv: ENC[AES256_GCM,data:fbBD9RsuEHwDETwiYtAS9kBxgTy6zubrxHWpcuoEsR0=,iv:uZcwIfDPPn4XUf8IZkI29VH9CiKvEOlWuUaWgSjl1Kc=,tag:qbgiQU7bWSFjoGEwoptCpg==,type:str] + jwt_secret: ENC[AES256_GCM,data:ZhDNIXrCaRWWfrlPxpBfnmeUluW0z72KGpQv9mGyf1kCCnfx3V2lPMm6QS6biajC+4oPVfgwqcXc4Lvs8OqU9g==,iv:1Ecj8fh+M5kw8cmVD96U6QgE7fNy9cbQV9v2Q305puc=,tag:U1ZglGWdTH1TGfcIIORMHQ==,type:str] + jwt_refresh_secret: ENC[AES256_GCM,data:/4X6h51oRRaOg7UZ/zUcS1L8QyFnhsTYrz8D6R3ZP/tFAEMO/IfYJHHQQ8UtgKjAEwIVYcpIco8lUDhm06folw==,iv:02/LgoiMZ6MzBSd+JAi+iuF3dzqsVyqX6gQfWPY8sIc=,tag:5VrCh7ZKNJD3ynjcyQpVyg==,type:str] +sops: + age: + - recipient: age12l33pas8eptwjc7ewux3d8snyzfzwz0tn9qg5kw8le79fswmjgjqdjgyy6 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBrUDN6TFlTVHdlWCsrWkFn + R1g5UjVLVk1NQzJRRE9NbDZlRVVJUjVvbmlnCk93NFhSRS9vbDUzNVd6Q3RuTEtZ + cFZvY0JML2tDSUZIbkcyVWVWWVFMY0UKLS0tIDlCbmxhUThUaHRGNkgySEp2QTB1 + WXFKbjNMWDF0LzNyekJJMGFva2diemcKQTc8ODuK6IWqRhulHiCF92aU+3p23riY + M94Nzh+VT6QTFOgb3J7bBJMLhRH/fkQb6L6ia2n9QrVXFyYYMJ0oBw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-07-01T21:34:46Z" + mac: ENC[AES256_GCM,data:NvJ6lCb80dsVMH4T4f4ZPO0b4JI44LfMvdanVaWtXDpi6FHJsF4OY8dftIyTBjacaLzdrVoT+JFfP3BrAnuEaZrCrfE1E+IRF4x/9NG4c4Cw++Jxgs7z7d01iYEjWJoVVPCLVnV32LGIq6nQltx2GFEVAsvV5zukJ/aJjvcIpQA=,iv:FWGaIdok23jgxMUs3d5ddK2iyJoOBliwv/yJDxmKLE0=,tag:FfLYymjZEJtW4cfFNhlNFg==,type:str] + unencrypted_suffix: _unencrypted + version: 3.10.2 diff --git a/secrets/tailscale.yaml b/secrets/tailscale.yaml deleted file mode 100644 index 0913120..0000000 --- a/secrets/tailscale.yaml +++ /dev/null @@ -1,17 +0,0 @@ -tailscale: - client-secret: ENC[AES256_GCM,data:qAJUDTHxnzhgUtpe/DaH8Vv72jy/DWU/1UKzp2Pg/GtayClZXGFz00bCNKmZJCE7NYHERgr2Ssnhpz90eRCjKg==,iv:aWp2lvIFpUH6OMTkD8V1HNMyxUPxiVA+Il4NvlVKjOA=,tag:OzkdsOKerKiSHzHSkScIQA==,type:str] -sops: - age: - - recipient: age12l33pas8eptwjc7ewux3d8snyzfzwz0tn9qg5kw8le79fswmjgjqdjgyy6 - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5ZytHNnlKcWFPVVNpTkxX - cFgxRjFDdWJkMzB2NUk1N2VLSWx3cVpvY20wCkdHbjZ4ZUlHTWp1QUFJVGxaV2cx - K0NlaFdnYlEvektieDJJVkY2cEtmL1UKLS0tIDFHQlM4OEIzaGVvUThCbUJZNTU3 - ZGNJd3NvSCsrdDNFb0VuMDJOU09DVEEKrDnezqYWRuEyS6/WRWq0jMfv4DQ3TS1L - Zic6TBIA3qNEjUlqXKRfq//H3vDRz4dzZCqbbh+5+FXDGBIVLL2DaA== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-07-07T11:12:16Z" - mac: ENC[AES256_GCM,data:rOuEqjHByaGaYredcMFGds+pB1rIgh0qu245Vt2gVGjjqOJtfEYcuvziVKgvV5yvBVhizcjeFIzCFdQ2KpflvwOLjiOZ594UaZChPGtO5hDc1VY/Gz86t8x6DYuHjWu4S1XOrBWgv2ebD0iBgbjuRNgBEhkWfVS2/7hn1PtqGD0=,iv:ZQ0b7pHG3NM2mwQdSVoGr4WsluIrp+/YUQi6KoMneC0=,tag:5E5bNxdRPQpTRVrQ+qoxfQ==,type:str] - unencrypted_suffix: _unencrypted - version: 3.10.2 diff --git a/secrets/users.yaml b/secrets/users.yaml deleted file mode 100644 index 76fe7e0..0000000 --- a/secrets/users.yaml +++ /dev/null @@ -1,18 +0,0 @@ -rafiq: - password: ENC[AES256_GCM,data:8KAfatz+YSaNozd5VGo=,iv:LNRxt47iBKSWzMZuBHSxv/qDZ2h6JiTIPps7OK/o7uU=,tag:oiSfLyRVswb/wxSTE69QMA==,type:str] - hashedPassword: ENC[AES256_GCM,data:NogYQ3kR1TseC79HIXARrXhIncCnvxzf9zMF2QrUyTmojTffPXRGtMdjNpfMEFj5dkKfZujBL/QTIpPFFTm1py7Dreg5/9VSKQ==,iv:IwfZsrsJbLYG1ELte6aBHUtff6hIQu9rHT5tSvILIGQ=,tag:oav3paDcUY+cl4FJlZa90A==,type:str] -sops: - age: - - recipient: age12l33pas8eptwjc7ewux3d8snyzfzwz0tn9qg5kw8le79fswmjgjqdjgyy6 - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVd09tYkhKUkVjNTBRdld6 - a1RkUnZqdnRqMlFTSGgwUFVCZlRhL0tLTnpVCjNXVjZldzNUOE9DQ0ZGejhWakY2 - TmRIZnpobE0ydDhNSDdJQUp2U3pSTzgKLS0tIDkxU3Fxa2lMUkhZY0g1Wm02T2ZE - UkQwOWZtVXVPSGJiRk1qRHVHYkN2cDgKLiYiA0q5se/oHfGRqvHLn3gRRDfmefEZ - z2U2N1Tjt0QgCfYOOXVfPV9F36a7PpabFva5ElSazawHgvI+Bot6og== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-07-07T08:56:26Z" - mac: ENC[AES256_GCM,data:2uGjIMxRgk7uWToQC4MrHpHFAt4bI7sEhaHvPU6Ae3bvRVH/TdJxZtikSPe95LEwReOuBmPajbcM580/d3Jt6VbA7nZzj1JduVscrRkSAFCzZp9Ti/mbOGITPJa6xWSGwVF1wSN3BnHXYIHDcKeSGtUdP7L7nBZr1KXPkok4NCo=,iv:+ELIes7lzb8M6CvOemAcyoq7Rx7L6NkNmHwntJN/RSc=,tag:ubyxO6VllH9cQK3VbvxiGg==,type:str] - unencrypted_suffix: _unencrypted - version: 3.10.2 diff --git a/systems/x86_64-linux/apollo/default.nix b/systems/x86_64-linux/apollo/default.nix new file mode 100644 index 0000000..6e9ba08 --- /dev/null +++ b/systems/x86_64-linux/apollo/default.nix @@ -0,0 +1,62 @@ +{ + lib, + pkgs, + inputs, + ... +}: +{ + imports = lib.singleton ../common.nix; + hostname = "apollo"; + + machine = { + platform.type = "intel"; + bootloader.type = "systemd-boot"; + drives.btrfs = { + enable = true; + drive = "/dev/disk/by-id/nvme-eui.002538d221b47b01"; + ephemeralRoot = true; + }; + }; + + server = { + networking.ddns = { + enable = true; + domains = [ + "aenyrathia.wiki" + "slayment.com" + ]; + }; + databases = { + mongodb.enable = true; + mysql.enable = true; + postgresql.enable = true; + }; + web-apps = { + librechat.enable = true; + librechat.domain = "chat.bwfiq.com"; + forgejo.enable = true; + forgejo.domain = "git.rrv.sh"; + forgejo.openFirewall = true; + glance.enable = true; + glance.domain = "glance.bwfiq.com"; + rrv-sh.enable = true; + rrv-sh.domain = "rrv.sh"; + }; + web-servers = { + enableSSL = true; + nginx = { + enable = true; + proxies = [ + { + source = "aenyrathia.wiki"; + target = "http://helios:5896"; + } + { + source = "il.bwfiq.com"; + target = "http://helios:2283"; + } + ]; + }; + }; + }; +} diff --git a/systems/x86_64-linux/common.nix b/systems/x86_64-linux/common.nix new file mode 100644 index 0000000..0954fff --- /dev/null +++ b/systems/x86_64-linux/common.nix @@ -0,0 +1,13 @@ +{ pkgs, ... }: +{ + mainUser = { + name = "rafiq"; + publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILdsZyY3gu8IGB8MzMnLdh+ClDxQQ2RYG9rkeetIKq8n"; + email = "rafiq@rrv.sh"; + shell = pkgs.fish; + }; + server.mountHelios = true; + stylix.base16Scheme = "${pkgs.base16-schemes}/share/themes/atelier-cave.yaml"; + programs.fish.enable = true; + programs.nix-ld.enable = true; +} diff --git a/systems/x86_64-linux/desktop.nix b/systems/x86_64-linux/desktop.nix new file mode 100644 index 0000000..4e15184 --- /dev/null +++ b/systems/x86_64-linux/desktop.nix @@ -0,0 +1,14 @@ +{ + desktop = { + enable = true; + lockscreen.hyprlock.enable = true; + launcher.fuzzel.enable = true; + media-player.vlc.enable = true; + window-manager.hyprland.enable = true; + }; + + machine.usb = { + automount = true; + enableQmk = true; + }; +} diff --git a/systems/x86_64-linux/mellinoe/default.nix b/systems/x86_64-linux/mellinoe/default.nix new file mode 100644 index 0000000..6bcc25f --- /dev/null +++ b/systems/x86_64-linux/mellinoe/default.nix @@ -0,0 +1,24 @@ +{ + imports = [ + ../common.nix + ../desktop.nix + ]; + hostname = "mellinoe"; + + machine = { + platform.type = "intel"; + bootloader.type = "systemd-boot"; + drives.btrfs = { + enable = true; + drive = "/dev/disk/by-id/nvme-KBG40ZPZ128G_TOSHIBA_MEMORY_Z0U103PCNCDL"; + ephemeralRoot = true; + }; + }; + + desktop.mainMonitor = { + id = "BOE 0x088B"; + scale = "2"; + resolution = "1920x1280"; + refresh-rate = "60"; + }; +} diff --git a/systems/x86_64-linux/nemesis/default.nix b/systems/x86_64-linux/nemesis/default.nix new file mode 100644 index 0000000..de55267 --- /dev/null +++ b/systems/x86_64-linux/nemesis/default.nix @@ -0,0 +1,40 @@ +{ + imports = [ + ../common.nix + ../desktop.nix + ]; + hostname = "nemesis"; + + machine = { + platform.type = "amd"; + gpu.nvidia.enable = true; + bootloader.type = "systemd-boot"; + drives.btrfs = { + enable = true; + drive = "/dev/disk/by-id/nvme-CT2000P3SSD8_2325E6E77434"; + ephemeralRoot = true; + }; + virtualisation.distrobox.enable = true; + }; + + desktop = { + browser.tor-browser.enable = true; + gaming = { + prism-launcher.enable = true; + steam.enable = true; + }; + services = { + sunshine.enable = true; + spotifyd.enable = true; + }; + mainMonitor = { + id = "desc:OOO AN-270W04K"; + scale = "2"; + resolution = "3840x2160"; + refresh-rate = "60"; + }; + }; + + server.web-apps.sd-webui-forge.enable = true; + server.web-apps.comfy-ui.enable = true; +}