├── .editorconfig ├── .envrc ├── .git-crypt ├── .gitattributes └── keys │ └── default │ └── 0 │ └── 978C4D08058BA26EB97CB51820782DBCACFAACDA.gpg ├── .gitattributes ├── .github ├── lint │ ├── .yamllint.yaml │ └── gitleaks.toml ├── renovate.json5 └── renovate │ └── groups.json5 ├── .gitignore ├── .pre-commit-config.yaml ├── .sops.yaml ├── LICENSE ├── README.md ├── TODO.md ├── Taskfile.yml ├── config ├── attic.nix ├── common-server.nix ├── default.nix ├── guests.nix ├── home-ops.nix ├── home-wifi.nix ├── ramblurr.nix ├── root.nix ├── secrets.nix ├── secrets_old.nix ├── site.nix ├── workstation-impermanence.nix └── zrepl.nix ├── configs ├── casey-pub.asc ├── home-ops │ ├── matrix-synapse.sops.yaml │ ├── recyclarr-plato.yml │ ├── recyclarr.yml │ └── shared.sops.yml └── ssh │ └── .gitignore ├── flake.lock ├── flake.nix ├── guests ├── invoiceninja │ ├── default.nix │ └── secrets.sops.yaml └── linkding │ ├── default.nix │ └── secrets.sops.yaml ├── hosts ├── addams │ ├── default.nix │ ├── disk-config.nix │ ├── hardware.nix │ ├── installer.nix │ ├── modules │ │ ├── chrony.nix │ │ ├── crowdsec.nix │ │ ├── dnsdist.nix │ │ ├── firewall │ │ │ ├── config │ │ │ │ ├── sets_addresses.nft │ │ │ │ └── sets_ports.nft │ │ │ ├── data.nix │ │ │ ├── default.nix │ │ │ ├── helpers.nix │ │ │ └── options.nix │ │ ├── kea │ │ │ ├── ddns.nix │ │ │ ├── default.nix │ │ │ ├── dhcp.nix │ │ │ └── helpers.nix │ │ ├── maddy.nix │ │ ├── mullvad-gateway.nix │ │ ├── ntopng.nix │ │ ├── podman.nix │ │ ├── powerdns.nix │ │ └── udpbroadcastrelay.nix │ ├── networking.nix │ ├── secrets.sops.yaml │ └── secrets │ │ └── local.nix ├── debord │ ├── default.nix │ ├── disk-config.nix │ ├── hardware.nix │ ├── secrets.sops.yaml │ └── secrets │ │ └── local.nix ├── dewey │ ├── default.nix │ ├── disk-config.nix │ ├── guests.nix │ ├── hardware.nix │ ├── secrets.sops.yaml │ └── secrets │ │ └── local.nix ├── mali │ ├── README.md │ ├── acme.nix │ ├── atticd.nix │ ├── avahi.nix │ ├── beets.nix │ ├── borgbackup-server.nix │ ├── default.nix │ ├── disks.sh │ ├── hardware-configuration.nix │ ├── install.sh │ ├── minio.nix │ ├── monitoring.nix │ ├── networking.nix │ ├── nfs.nix │ ├── nginx.nix │ ├── rclone.nix │ ├── samba.nix │ ├── secrets.sops.yaml │ ├── secrets │ │ ├── host.pub │ │ └── local.nix │ ├── startover.sh │ ├── syncthing.nix │ ├── ups.nix │ ├── upsd.sops.users │ ├── upsmon.sops.conf │ └── zrepl.nix ├── quine │ ├── .gitignore │ ├── README.md │ ├── bare-install.sh │ ├── default.nix │ ├── disks.sh │ ├── gaming.nix │ ├── hardware-configuration.nix │ ├── install.sh │ ├── ipfs.nix │ ├── libvirt.nix │ ├── microvm-test-impl.nix │ ├── microvm-test.nix │ ├── networking.nix │ ├── pipewire │ │ └── 90-roon-loopback.conf │ ├── roon-bridge.nix │ ├── secrets.sops.yaml │ ├── secrets │ │ └── local.nix │ ├── startover.sh │ ├── syncthing.nix │ ├── tabby.nix │ ├── wireplumber.nix │ └── wireplumber │ │ ├── 91-user-scripts.lua │ │ └── auto-connect-ports.lua └── witt │ ├── default.nix │ ├── disk-config.nix │ ├── gruvbox-rainbow.toml │ ├── hardware.nix │ ├── home.nix │ ├── secrets.sops.yaml │ ├── secrets │ └── host.pub │ └── syncthing.nix ├── lib ├── attrs.nix ├── default.nix ├── my.nix ├── network.nix ├── nix-clj.nix ├── nix-std.nix └── uint.nix ├── modules-unstable ├── default.nix ├── hardware │ ├── nvidia.nix │ └── nvidia │ │ ├── default.nix │ │ └── vaapi.nix └── services │ └── microsocks.nix ├── modules ├── SKELETON.nix.txt ├── boot │ └── zfs.nix ├── default.nix ├── desktop │ ├── browser │ │ ├── chromium.nix │ │ └── firefox.nix │ ├── dynamic-wallpaper.nix │ ├── fonts.nix │ ├── hyprland3 │ │ ├── anyrun.nix │ │ ├── dconf.nix │ │ ├── default.nix │ │ ├── dunst.nix │ │ ├── hyprland-config.nix │ │ ├── hyprpaper.nix │ │ ├── mako.nix │ │ ├── template.nix │ │ └── theme.nix │ ├── kde.nix │ ├── programs │ │ ├── 1password.nix │ │ ├── aseprite.nix │ │ ├── cad.nix │ │ ├── calibre.nix │ │ ├── chrysalis.nix │ │ ├── discord.nix │ │ ├── element.nix │ │ ├── fritzing.nix │ │ ├── junction.nix │ │ ├── kdeconnect.nix │ │ ├── kicad.nix │ │ ├── kitty │ │ │ ├── configs │ │ │ │ ├── kitty-monitor.session │ │ │ │ └── kitty.session │ │ │ └── default.nix │ │ ├── logseq.nix │ │ ├── musescore.nix │ │ ├── nextcloud.nix │ │ ├── nheko.nix │ │ ├── obs.nix │ │ ├── owncloud.nix │ │ ├── signal.nix │ │ ├── slack.nix │ │ ├── thunderbird.nix │ │ ├── wezterm │ │ │ └── default.nix │ │ └── yubico.nix │ ├── random-apps.nix │ ├── services │ │ ├── ha-shutdown.nix │ │ ├── hacompanion.nix │ │ ├── shutdown.py │ │ └── swhkd.nix │ ├── wayland.nix │ └── xdg.nix ├── dev │ ├── clojure │ │ ├── configs │ │ │ ├── clj-kondo │ │ │ │ └── config.edn │ │ │ └── deps.edn │ │ └── default.nix │ ├── fennel.nix │ ├── jetbrains │ │ ├── configs │ │ │ ├── ideavim │ │ │ │ ├── _all.vim │ │ │ │ ├── custom.vim │ │ │ │ ├── major.vim │ │ │ │ ├── projects.vim │ │ │ │ └── settings.vim │ │ │ └── ideavimrc │ │ └── default.nix │ ├── k8s │ │ └── default.nix │ ├── node │ │ ├── configs │ │ │ └── npm │ │ │ │ └── npmrc │ │ └── default.nix │ ├── python.nix │ ├── radicle.nix │ └── random.nix ├── distributed-config.nix ├── editors │ ├── emacs │ │ ├── configs │ │ │ ├── doom.sh │ │ │ └── icons │ │ │ │ └── doom.png │ │ └── default.nix │ ├── vim.nix │ └── vscode │ │ └── default.nix ├── firewall │ └── default.nix ├── globals.nix ├── hardware │ ├── misc.nix │ ├── pipewire.nix │ └── ryzen.nix ├── impermanence │ └── default.nix ├── meta.nix ├── microvm-guest │ ├── common.nix │ ├── default.nix │ ├── home-manager.nix │ ├── options.nix │ └── quadlet.nix ├── microvm-host │ └── default.nix ├── networking │ ├── systemd-netns-private.nix │ └── systemd-netns.nix ├── nix.nix ├── secrets.nix ├── security │ └── default.nix ├── server │ ├── smtp-external-relay.nix │ └── virtd │ │ └── default.nix ├── services │ ├── actual-budget.nix │ ├── archivebox.nix │ ├── attic-watch-store.nix │ ├── atuin-sync.nix │ ├── audiobookshelf.nix │ ├── authentik-module.nix │ ├── authentik.nix │ ├── borgmatic.nix │ ├── calibre-web.nix │ ├── calibre.nix │ ├── davis.nix │ ├── docker.nix │ ├── echo-server.nix │ ├── flatpak.nix │ ├── forgejo.nix │ ├── git-archive.nix │ ├── github-runner.nix │ ├── haproxy.nix │ ├── home-dl.nix │ ├── influxdb.nix │ ├── ingress-options.nix │ ├── ingress.nix │ ├── mariadb.nix │ ├── matrix-discord.nix │ ├── matrix-irc.nix │ ├── matrix-synapse-postgres.nix │ ├── matrix-synapse.nix │ ├── ocis.nix │ ├── onepassword-connect.nix │ ├── paperless.nix │ ├── plex.nix │ ├── podman.nix │ ├── postgresql.nix │ ├── printing.nix │ ├── radicle.nix │ ├── roon-server.nix │ ├── soju.nix │ ├── sshd.nix │ ├── tautulli.nix │ ├── udpbroadcastrelay.nix │ └── zfs-backup-check.nix ├── shell │ ├── aria2.nix │ ├── attic.nix │ ├── atuin.nix │ ├── direnv.nix │ ├── ffsend.nix │ ├── git.nix │ ├── gpg-agent.nix │ ├── htop │ │ ├── configs │ │ │ └── btop │ │ │ │ ├── gruvbox_dark.theme │ │ │ │ └── gruvbox_dark_v2.theme │ │ └── default.nix │ ├── mpv.nix │ ├── random.nix │ ├── ssh │ │ └── default.nix │ ├── tmux.nix │ ├── zoxide.nix │ └── zsh │ │ ├── configs │ │ ├── autocompletion.zsh │ │ ├── environment.zsh │ │ ├── gpg-ssh.zsh │ │ ├── init.zsh │ │ ├── keybindings.zsh │ │ ├── p10k-config │ │ │ └── p10k.zsh │ │ ├── privacy.zsh │ │ └── prompt.zsh │ │ └── default.nix ├── site-net │ ├── default.nix │ └── network.nix ├── site │ ├── default.nix │ ├── host-options.nix │ ├── interface-options.nix │ ├── link-options.nix │ └── net-options.nix ├── sops.nix ├── users │ └── default.nix ├── vpn │ ├── mullvad.nix │ └── tailscale.nix └── zfs-attrs.nix ├── nix ├── hosts.nix ├── iso-test.nix ├── nixos.nix └── pkgs.nix ├── overlays ├── .git-keep ├── cuda.nix ├── default.nix ├── last-known-good.nix ├── logseq.nix ├── qemu.nix ├── roon-server.nix └── rpi4.nix ├── pkgs ├── actual-server.nix ├── beets-dynamicrange.nix ├── beets-filetote.nix ├── cloudflare-utils.nix ├── default.nix ├── deploy.nix ├── invoiceninja │ ├── invoiceninja-redis.patch │ ├── invoiceninja.patch │ ├── package-from-src.nix │ └── package.nix ├── klassy.nix ├── kwin6-bismuth-decoration.nix ├── netns-proxy.nix ├── overseerr.nix ├── qobuz-dl.nix ├── swhkd │ ├── Cargo.lock │ └── default.nix └── udpbroadcastrelay.nix ├── scripts ├── deploy-anywhere.sh ├── enumerate-ports.py ├── gen-host.py ├── json2nix.py ├── migrate-sops-to-age ├── pass.py ├── pgbackrest-restore.sh └── restic-restore.sh ├── secrets ├── age-disaster-recovery.pub ├── age-keychain.pub ├── age-mini-quine.pub ├── global.nix ├── home-ops.nix ├── ocis-work-csp.yaml └── site.nix └── shell.nix /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [Makefile] 13 | indent_style = tab 14 | indent_size = 4 15 | 16 | [Makefile.j2] 17 | indent_style = tab 18 | indent_size = 4 19 | 20 | [*.{bash,sh}] 21 | indent_style = space 22 | indent_size = 4 23 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | use nix 2 | -------------------------------------------------------------------------------- /.git-crypt/.gitattributes: -------------------------------------------------------------------------------- 1 | # Do not edit this file. To specify the files to encrypt, create your own 2 | # .gitattributes file in the directory where your files are. 3 | * !filter !diff 4 | *.gpg binary 5 | -------------------------------------------------------------------------------- /.git-crypt/keys/default/0/978C4D08058BA26EB97CB51820782DBCACFAACDA.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/.git-crypt/keys/default/0/978C4D08058BA26EB97CB51820782DBCACFAACDA.gpg -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | **/*.secrets/** filter=git-crypt diff=git-crypt 2 | **/secrets/** filter=git-crypt diff=git-crypt 3 | # Just in case, never filter git files 4 | .gitattributes !filter !diff 5 | .gitignore !filter !diff 6 | **/*.sops.yaml !filter !diff 7 | **/*.sops.yml !filter !diff 8 | -------------------------------------------------------------------------------- /.github/lint/.yamllint.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ignore: | 3 | .direnv/ 4 | .private/ 5 | .vscode/ 6 | 7 | extends: default 8 | 9 | rules: 10 | truthy: 11 | allowed-values: ["true", "false", "on"] 12 | 13 | comments: 14 | min-spaces-from-content: 1 15 | 16 | line-length: disable 17 | 18 | braces: 19 | min-spaces-inside: 0 20 | max-spaces-inside: 1 21 | 22 | brackets: 23 | min-spaces-inside: 0 24 | max-spaces-inside: 0 25 | 26 | indentation: enable 27 | -------------------------------------------------------------------------------- /.github/lint/gitleaks.toml: -------------------------------------------------------------------------------- 1 | title = "gitleaks config" 2 | 3 | [extend] 4 | useDefault = true 5 | 6 | [[ rules ]] 7 | id = "generic-api-key" 8 | [ rules.allowlist ] 9 | paths = [ 'secrets/.*\.nix', 'secrets/.*\.secrets' ] 10 | regexTarget = "line" 11 | regexes= [ 12 | "signing.key =.*", 13 | "signingKey =.*" 14 | ] 15 | 16 | [allowlist] 17 | description = "ignore sops encrypted secrets" 18 | paths = [ 19 | '.*\.sops\.yaml', 20 | ] 21 | regexTarget = "line" 22 | regexes= [ 23 | '''ExAmPl3PA55W0rD''', 24 | '''.*ENC\[AES256_GCM,data:.*''', 25 | ] 26 | -------------------------------------------------------------------------------- /.github/renovate.json5: -------------------------------------------------------------------------------- 1 | { 2 | $schema: "https://docs.renovatebot.com/renovate-schema.json", 3 | extends: [ 4 | "config:recommended", 5 | "github>cidverse/renovate-config:default", 6 | "regexManagers:dockerfileVersions", 7 | "regexManagers:tfvarsVersions", 8 | "github>ramblurr/nixcfg//.github/renovate/groups.json5", 9 | ], 10 | enabled: true, 11 | timezone: "Europe/Berlin", 12 | semanticCommits: "enabled", 13 | dependencyDashboard: true, 14 | assignees: [], 15 | reviewers: ["Ramblurr"], 16 | vulnerabilityAlerts: { 17 | assignees: ["Ramblurr"], 18 | }, 19 | ignorePaths: ["**/archive/**"], 20 | rebaseWhen: "behind-base-branch", 21 | dependencyDashboardTitle: "Renovate Dashboard", 22 | // do not notify on closed unmerged PRs 23 | suppressNotifications: ["prIgnoreNotification"], 24 | // only rebase PRs when there's a conflict 25 | rebaseWhen: "conflicted", 26 | regexManagers: [ 27 | { 28 | description: ["Generic Docker image Regex manager"], 29 | fileMatch: [".*\\.nix$", ".*\\.ya?ml$"], 30 | matchStrings: [ 31 | '# renovate: docker-image( versioning=(?.*=?))?\n .*[:|=] "?(?.*?):(?[^"\n]*=?)"?', 32 | ], 33 | datasourceTemplate: "docker", 34 | versioningTemplate: "{{#if versioning}}{{{versioning}}}{{else}}semver{{/if}}", 35 | }, 36 | ], 37 | nix: { 38 | enabled: true, 39 | }, 40 | lockFileMaintenance: { 41 | enabled: true, 42 | extends: ["schedule:weekly"], 43 | }, 44 | packageRules: [ 45 | { 46 | matchDatasources: ["docker"], 47 | enabled: true, 48 | matchUpdateTypes: ["major", "minor", "patch"], 49 | }, 50 | { 51 | matchDatasources: ["docker"], 52 | semanticCommitScope: "images", 53 | separateMinorPatch: true, 54 | }, 55 | 56 | // add labels according to package and update types 57 | { 58 | matchDatasources: ["docker"], 59 | matchUpdateTypes: ["major"], 60 | commitMessagePrefix: "feat(images)!: ", 61 | labels: ["renovate/image", "dep/major"], 62 | }, 63 | { 64 | matchDatasources: ["docker"], 65 | matchUpdateTypes: ["minor"], 66 | semanticCommitType: "feat", 67 | labels: ["renovate/image", "dep/minor"], 68 | }, 69 | { 70 | matchDatasources: ["docker"], 71 | matchUpdateTypes: ["patch"], 72 | semanticCommitType: "fix", 73 | labels: ["renovate/image", "dep/patch"], 74 | }, 75 | ], 76 | } 77 | -------------------------------------------------------------------------------- /.github/renovate/groups.json5: -------------------------------------------------------------------------------- 1 | { 2 | $schema: "https://docs.renovatebot.com/renovate-schema.json", 3 | packageRules: [ 4 | { 5 | matchDatasources: ["maven", "deps-edn"], 6 | groupName: "clojure deps.edn", 7 | group: { 8 | commitMessageTopic: "{{{groupName}}} group", 9 | }, 10 | }, 11 | { 12 | description: "Immich Group", 13 | groupName: "Immich", 14 | matchPackagePatterns: ["immich"], 15 | matchDatasources: ["docker"], 16 | group: { 17 | commitMessageTopic: "{{{groupName}}} group", 18 | }, 19 | separateMinorPatch: true, 20 | }, 21 | ], 22 | } 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | result 2 | modules-new 3 | modules-old 4 | archive 5 | 6 | .clj-kondo 7 | .lsp 8 | modules/editors/emacs/configs/doom.d/flycheck_* 9 | .direnv 10 | dumps 11 | tmp 12 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fail_fast: false 3 | 4 | repos: 5 | - repo: local 6 | hooks: 7 | - id: nixfmt 8 | name: nixfmt 9 | entry: nixfmt 10 | language: system 11 | files: \.nix$ 12 | pass_filenames: true 13 | args: 14 | - --width=100 15 | 16 | - repo: https://github.com/adrienverge/yamllint 17 | rev: v1.32.0 18 | hooks: 19 | - args: 20 | - --config-file 21 | - .github/lint/.yamllint.yaml 22 | id: yamllint 23 | - repo: https://github.com/pre-commit/pre-commit-hooks 24 | rev: v4.4.0 25 | hooks: 26 | - id: trailing-whitespace 27 | #- id: end-of-file-fixer 28 | - id: fix-byte-order-marker 29 | - id: mixed-line-ending 30 | - id: check-added-large-files 31 | args: [--maxkb=2048] 32 | - id: check-merge-conflict 33 | - id: check-executables-have-shebangs 34 | - repo: https://github.com/Lucas-C/pre-commit-hooks 35 | rev: v1.5.4 36 | hooks: 37 | - id: remove-crlf 38 | - id: remove-tabs 39 | exclude: (Makefile) 40 | 41 | - repo: https://github.com/zricethezav/gitleaks 42 | rev: v8.23.3 43 | hooks: 44 | - id: gitleaks 45 | args: 46 | - --config 47 | - .github/lint/gitleaks.toml 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2021 Henrik Lissner. 4 | Copyright (c) 2022 David Li. 5 | Copyright (c) 2022-2023 Casey Link. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining 8 | a copy of this software and associated documentation files (the 9 | "Software"), to deal in the Software without restriction, including 10 | without limitation the rights to use, copy, modify, merge, publish, 11 | distribute, sublicense, and/or sell copies of the Software, and to 12 | permit persons to whom the Software is furnished to do so, subject to 13 | the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nixcfg 2 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 3 | 4 | --- 5 | 6 | ## Hosts 7 | 8 | | Hostname | Purpose | Channel | Source | | 9 | |----------|-----------------------------------------------|-----------------------------|----------------------------------|---| 10 | | debord | [Home Prod Server][home-ops] & Home Assistant | ![NixOS Unstable][unstable] | [hosts/debord/](./hosts/debord/) | | 11 | | dewey | [Home Prod Server][home-ops] | ![NixOS Unstable][unstable] | [hosts/dewey/](./hosts/dewey/) | | 12 | | mali | [Storage NAS][NAS] | ![NixOS Stable][stable] | [hosts/mali/](./hosts/mali/) | | 13 | | quine | [Primary workstation][workstation] | ![NixOS Unstable][unstable] | [hosts/quine/](./hosts/quine/) | | 14 | | witt | Travel laptop (Framework 13) | ![NixOS Unstable][unstable] | [hosts/witt/](./hosts/witt/) | | 15 | | addams | Router | ![NixOS Unstable][unstable] | [hosts/addams/](./hosts/addams/) | | 16 | 17 | 18 | Example build commands: 19 | 20 | ```sh 21 | task build host=quine 22 | task test host=quine 23 | task switch host=quine 24 | task image host=ovos-kitchen 25 | ``` 26 | 27 | --- 28 | 29 | # License and Inspiration 30 | 31 | 32 | I got help from some cool configs like: 33 | 34 | * [hlissner/dotfiles](https://github.com/hlissner/dotfiles) 35 | * [colemickens/nixcfg](https://github.com/colemickens/nixcfg) 36 | * [huantianad/nixos-config](https://github.com/huantianad/nixos-config) 37 | * [oddlama/nix-config](https://github.com/oddlama/nix-config) 38 | 39 | 40 | [Licensed under MIT](./LICENSE), have at it! 41 | 42 | 43 | [ovos]: https://github.com/OpenVoiceOS/ 44 | [unstable]: https://img.shields.io/badge/NixOS-unstable-blue.svg?style=flat-square&logo=NixOS&logoColor=white 45 | [stable]: https://img.shields.io/badge/NixOS-stable-green.svg?style=flat-square&logo=NixOS&logoColor=white 46 | [NAS]: https://notes.binaryelysium.com/HomeOps/NAS/ 47 | [workstation]: https://notes.binaryelysium.com/HomeOps/PrimaryWorkstation/ 48 | [home-ops]: https://notes.binaryelysium.com/HomeOps/ 49 | [home-ops-git]: https://github.com/ramblurr/home-ops 50 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | 4 | ## Upgrade options 5 | 6 | Once everything is on 24.05: 7 | 8 | - [ ] `services.avahi.nssmdns` to `services.avahi.nssmdns4` 9 | -------------------------------------------------------------------------------- /config/attic.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | config, 4 | lib, 5 | ... 6 | }: 7 | let 8 | cfg = config.home.attic; 9 | in 10 | { 11 | options.home.attic = { 12 | enable = lib.mkEnableOption "Enable local attic substituters"; 13 | }; 14 | config = lib.mkIf cfg.enable { 15 | nix = { 16 | settings = { 17 | extra-substituters = [ 18 | config.repo.secrets.global.localAtticSubstituter 19 | ]; 20 | extra-trusted-public-keys = [ 21 | config.repo.secrets.global.localAtticPublicKey 22 | ]; 23 | }; 24 | extraOptions = '' 25 | # Ensure we can still build when missing-server is not accessible 26 | fallback = true 27 | ''; 28 | }; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /config/default.nix: -------------------------------------------------------------------------------- 1 | { inputs, ... }: 2 | { 3 | imports = [ 4 | ./secrets.nix 5 | ./attic.nix 6 | ./site.nix 7 | ./ramblurr.nix 8 | ./root.nix 9 | ]; 10 | } 11 | -------------------------------------------------------------------------------- /config/guests.nix: -------------------------------------------------------------------------------- 1 | { inputs, config, ... }: 2 | { 3 | imports = [ 4 | inputs.home-manager.nixosModules.home-manager 5 | inputs.microvm.nixosModules.microvm 6 | inputs.impermanence.nixosModules.impermanence 7 | inputs.sops-nix.nixosModules.sops 8 | ./common-server.nix 9 | ./site.nix 10 | ./secrets.nix 11 | ../modules/services/sshd.nix 12 | ../modules/microvm-guest 13 | ../modules/meta.nix 14 | ../modules/secrets.nix 15 | ../modules/sops.nix 16 | ../modules/impermanence/default.nix 17 | ]; 18 | 19 | home-manager = { 20 | useGlobalPkgs = true; 21 | useUserPackages = true; 22 | sharedModules = [ 23 | { 24 | home.stateVersion = config.system.stateVersion; 25 | } 26 | inputs.quadlet-nix.homeManagerModules.quadlet 27 | ]; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /config/home-wifi.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | config, 4 | lib, 5 | ... 6 | }: 7 | let 8 | inherit (config.repo.secrets.global) wifi; 9 | cfg = config.home; 10 | in 11 | { 12 | options.home.wifi = { 13 | iot = { 14 | enable = lib.mkEnableOption "WiFi for IoT"; 15 | interface = lib.mkOption { 16 | type = lib.types.str; 17 | default = "wlan0"; 18 | description = "The WiFi interface to use"; 19 | }; 20 | }; 21 | primary = { 22 | enable = lib.mkEnableOption "WiFi"; 23 | interface = lib.mkOption { 24 | type = lib.types.str; 25 | default = "wlan0"; 26 | description = "The WiFi interface to use"; 27 | }; 28 | }; 29 | }; 30 | config = lib.mkIf (cfg.wifi.iot.enable || cfg.wifi.primary.enable) { 31 | networking = 32 | if cfg.wifi.iot.enable then 33 | { 34 | interfaces."${cfg.wifi.iot.interface}".useDHCP = true; 35 | wireless = { 36 | interfaces = [ "${cfg.wifi.iot.interface}" ]; 37 | enable = true; 38 | networks = { 39 | "${wifi.iot.ssid}".psk = "${wifi.iot.password}"; 40 | }; 41 | }; 42 | } 43 | else if cfg.wifi.primary.enable then 44 | { 45 | wireless = { 46 | interfaces = [ "${cfg.wifi.primary.interface}" ]; 47 | enable = true; 48 | networks = { 49 | "${wifi.primary.ssid}".psk = "${wifi.primary.password}"; 50 | }; 51 | }; 52 | } 53 | else 54 | { }; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /config/ramblurr.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | { 8 | modules.users.primaryUser = { 9 | username = "ramblurr"; 10 | name = "Casey Link"; 11 | homeDirectory = "/home/ramblurr"; 12 | signingKey = "978C4D08058BA26EB97CB51820782DBCACFAACDA"; 13 | email = "unnamedrambler@gmail.com"; 14 | passwordSecretKey = "ramblurr-password"; 15 | authorizedKeys = config.repo.secrets.global.pubKeys; 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /config/root.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | { 8 | sops.secrets.root-password = { 9 | neededForUsers = true; 10 | }; 11 | users.users.root = { 12 | initialHashedPassword = lib.mkForce null; 13 | hashedPasswordFile = config.sops.secrets.root-password.path; 14 | openssh.authorizedKeys.keys = config.repo.secrets.global.pubKeys; 15 | shell = pkgs.zsh; 16 | }; 17 | 18 | programs.zsh.enable = true; 19 | 20 | # This cannot currently be derived automatically due to a design flaw in nixpkgs. 21 | environment.persistence."/persist".users.root.home = "/root"; 22 | } 23 | -------------------------------------------------------------------------------- /config/secrets.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | inputs, 4 | lib, 5 | ... 6 | }: 7 | 8 | let 9 | local = config.node.secretsDir + "/local.nix"; 10 | in 11 | { 12 | # Define local repo secrets 13 | repo.secretFiles = { 14 | global = ../secrets/global.nix; 15 | site = ../secrets/site.nix; 16 | } // lib.optionalAttrs (lib.pathExists local) { inherit local; }; 17 | } 18 | -------------------------------------------------------------------------------- /config/secrets_old.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | inputs, 4 | lib, 5 | ... 6 | }: 7 | 8 | let 9 | local = config.node.secretsDir + "/local.nix"; 10 | in 11 | { 12 | # Define local repo secrets 13 | repo.secretFiles_old = { 14 | global = ../secrets/global.nix; 15 | } // lib.optionalAttrs (lib.pathExists local) { inherit local; }; 16 | } 17 | -------------------------------------------------------------------------------- /config/zrepl.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | let 9 | home-ops = config.repo.secrets.home-ops; 10 | nodeSettings = config.repo.secrets.global.nodes.${config.networking.hostName}; 11 | cidrToIp = ip: builtins.head (builtins.split "/" ip); 12 | in 13 | { 14 | options.home-ops.zrepl = { 15 | enable = lib.mkEnableOption "Enable zrepl"; 16 | }; 17 | config = lib.mkIf config.home-ops.zrepl.enable { 18 | # zrepl - ZFS snapshotting and replication 19 | # Every node has a source job and snapshots are pulled by the NAS 20 | networking.firewall.allowedTCPPorts = [ 21 | home-ops.ports.zrepl-metrics 22 | home-ops.ports.zrepl-source 23 | ]; 24 | services.zrepl = { 25 | enable = true; 26 | settings = { 27 | global = { 28 | logging = [ 29 | { 30 | type = "syslog"; 31 | level = "info"; 32 | format = "human"; 33 | } 34 | ]; 35 | monitoring = [ 36 | { 37 | type = "prometheus"; 38 | listen = ":${toString home-ops.ports.zrepl-metrics}"; 39 | listen_freebind = true; 40 | } 41 | ]; 42 | }; 43 | 44 | jobs = [ 45 | { 46 | name = "${config.networking.hostName}_source"; 47 | type = "source"; 48 | serve = { 49 | type = "tcp"; 50 | listen = "${cidrToIp nodeSettings.dataCIDR}:${toString home-ops.ports.zrepl-source}"; 51 | listen_freebind = true; 52 | clients = { 53 | "${lib.my.cidrToIp config.repo.secrets.global.nodes.mali.dataCIDR}" = "mali"; 54 | }; 55 | }; 56 | filesystems = { 57 | "rpool<" = false; 58 | "rpool/encrypted/safe/svc<" = true; 59 | "rpool/encrypted/safe/persist<" = true; 60 | "rpool/encrypted/safe/vms<" = true; 61 | "rpool/encrypted/safe/extra/atuin<" = true; 62 | "tank<" = false; 63 | }; 64 | # "send.compressed" = true; 65 | snapshotting = { 66 | type = "periodic"; 67 | prefix = "zrepl_"; 68 | interval = "6h"; 69 | }; 70 | } 71 | ]; 72 | }; 73 | }; 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /configs/ssh/.gitignore: -------------------------------------------------------------------------------- 1 | hosts.nix 2 | -------------------------------------------------------------------------------- /hosts/addams/hardware.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | modulesPath, 6 | ... 7 | }: 8 | { 9 | 10 | imports = [ 11 | (modulesPath + "/profiles/all-hardware.nix") 12 | ./disk-config.nix 13 | ]; 14 | 15 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 16 | hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 17 | 18 | services.getty.autologinUser = "ramblurr"; 19 | boot = { 20 | loader.systemd-boot.enable = true; 21 | loader.efi.canTouchEfiVariables = true; 22 | zfs.devNodes = lib.mkForce "/dev/disk/by-partuuid"; 23 | kernelModules = [ "kvm-intel" ]; 24 | extraModulePackages = [ ]; 25 | 26 | initrd = { 27 | availableKernelModules = [ 28 | "xhci_pci" 29 | "thunderbolt" 30 | "ahci" 31 | "usbhid" 32 | "usb_storage" 33 | "sd_mod" 34 | "sr_mod" 35 | ]; 36 | kernelModules = [ ]; 37 | 38 | postDeviceCommands = lib.mkAfter '' 39 | zfs rollback -r rpool/encrypted/local/root@blank && \ 40 | echo "rollback complete" 41 | ''; 42 | }; 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /hosts/addams/modules/chrony.nix: -------------------------------------------------------------------------------- 1 | { ... }: 2 | { 3 | environment.persistence."/persist".directories = [ "/var/lib/chrony" ]; 4 | services.chrony = { 5 | enable = true; 6 | servers = [ "id.pool.ntp.org" ]; 7 | serverOption = "iburst"; 8 | extraConfig = '' 9 | allow 127.0.0.0/8 10 | allow 10.0.0.0/8 11 | allow 172.16.0.0/12 12 | allow 192.168.0.0/16 13 | ''; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /hosts/addams/modules/firewall/options.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | let 3 | cfg = config.modules.router; 4 | in 5 | { 6 | options = { 7 | modules.router = { 8 | enable = lib.mkEnableOption ""; 9 | nat.forwardPorts = lib.mkOption { 10 | type = 11 | with lib.types; 12 | listOf (submodule { 13 | options = { 14 | sourcePort = lib.mkOption { 15 | type = lib.types.either lib.types.int (lib.types.strMatching "[[:digit:]]+:[[:digit:]]+"); 16 | example = 8080; 17 | description = lib.mdDoc ''Source port of the external interface; to specify a port range, use a string with a colon (e.g. "60000:61000")''; 18 | }; 19 | 20 | destination = lib.mkOption { 21 | type = lib.types.str; 22 | example = "10.0.0.1:80"; 23 | description = lib.mdDoc "Forward connection to destination ip:port (or [ipv6]:port); to specify a port range, use ip:start-end"; 24 | }; 25 | 26 | proto = lib.mkOption { 27 | type = lib.types.str; 28 | default = "tcp"; 29 | example = "udp"; 30 | description = lib.mdDoc "Protocol of forwarded connection"; 31 | }; 32 | 33 | loopbackIPs = lib.mkOption { 34 | type = lib.types.listOf lib.types.str; 35 | default = [ ]; 36 | example = literalExpression ''[ "55.1.2.3" ]''; 37 | description = lib.mdDoc "Public IPs for NAT reflection; for connections to `loopbackip:sourcePort' from the host itself and from other hosts behind NAT"; 38 | }; 39 | }; 40 | }); 41 | default = [ ]; 42 | example = [ 43 | { 44 | sourcePort = 8080; 45 | destination = "10.0.0.1:80"; 46 | proto = "tcp"; 47 | } 48 | { 49 | sourcePort = 8080; 50 | destination = "[fc00::2]:80"; 51 | proto = "tcp"; 52 | } 53 | ]; 54 | description = lib.mdDoc '' 55 | List of forwarded ports from the external interface to 56 | internal destinations by using DNAT. Destination can be 57 | IPv6 if IPv6 NAT is enabled. 58 | ''; 59 | }; 60 | }; 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /hosts/addams/modules/kea/ddns.nix: -------------------------------------------------------------------------------- 1 | { lib, config, ... }: 2 | let 3 | dhcpLib = import ./helpers.nix { inherit lib; }; 4 | keaddnsUser = "kea"; 5 | 6 | pdnsServer = [ 7 | { 8 | ip-address = "127.0.0.1"; 9 | port = 8853; 10 | } 11 | ]; 12 | 13 | vlans = [ 14 | "local" 15 | "guest" 16 | "prim" 17 | "mgmt" 18 | "data" 19 | #"iot" 20 | #"not" 21 | ]; 22 | in 23 | { 24 | # add user, needed to access the secret 25 | users = { 26 | users.${keaddnsUser} = { 27 | isSystemUser = true; 28 | group = keaddnsUser; 29 | }; 30 | groups.${keaddnsUser} = { }; 31 | }; 32 | 33 | sops.secrets."kea/tsig-key" = { 34 | owner = keaddnsUser; 35 | group = keaddnsUser; 36 | }; 37 | 38 | services.kea = { 39 | dhcp4.settings = { 40 | dhcp-ddns.enable-updates = true; 41 | ddns-replace-client-name = "when-not-present"; 42 | ddns-update-on-renew = true; # always update when a lease is renewed, in case I lost the DNS server database 43 | ddns-override-client-update = true; # always generate ddns update request ignoring the client's wishes not to 44 | ddns-override-no-update = true; # same as above but for different client's wishes 45 | }; 46 | dhcp-ddns = { 47 | enable = true; 48 | settings = { 49 | tsig-keys = [ 50 | { 51 | name = "kea"; 52 | algorithm = "hmac-sha512"; 53 | secret-file = "${config.sops.secrets."kea/tsig-key".path}"; 54 | } 55 | ]; 56 | forward-ddns = { 57 | ddns-domains = [ 58 | { 59 | name = "${config.repo.secrets.global.domain.home}."; 60 | key-name = "kea"; 61 | dns-servers = pdnsServer; 62 | } 63 | ]; 64 | }; 65 | reverse-ddns = { 66 | ddns-domains = map (zone: { 67 | key-name = "kea"; 68 | name = zone; 69 | dns-servers = pdnsServer; 70 | }) config.repo.secrets.local.reverseZones; 71 | }; 72 | }; 73 | }; 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /hosts/addams/modules/kea/default.nix: -------------------------------------------------------------------------------- 1 | { ... }: 2 | { 3 | imports = [ 4 | ./ddns.nix 5 | ./dhcp.nix 6 | ]; 7 | } 8 | -------------------------------------------------------------------------------- /hosts/addams/modules/kea/helpers.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | ... 4 | }: 5 | let 6 | # Takes a CIDR like "10.9.4.1/22" and returns a list of reverse zones 7 | toReverseZones = 8 | cidr: 9 | let 10 | # Split CIDR into address and prefix 11 | parts = builtins.split "/" cidr; 12 | addr = builtins.elemAt parts 0; 13 | prefix = builtins.fromJSON (builtins.elemAt parts 2); 14 | 15 | # Split address into octets 16 | octets = builtins.split "\\." addr; 17 | firstOctet = builtins.elemAt octets 0; 18 | secondOctet = builtins.elemAt octets 2; 19 | thirdOctet = builtins.fromJSON (builtins.elemAt octets 4); 20 | 21 | # Calculate number of /24 networks (2^(24-prefix) if prefix < 24, else 1) 22 | numNetworks = 23 | if prefix >= 24 then 24 | 1 25 | else if prefix == 23 then 26 | 2 27 | else if prefix == 22 then 28 | 4 29 | else if prefix == 21 then 30 | 8 31 | else if prefix == 20 then 32 | 16 33 | else 34 | 1; # fallback for larger networks 35 | 36 | # Generate list of third octets 37 | thirdOctets = builtins.genList (x: thirdOctet + x) numNetworks; 38 | in 39 | map (third: "${toString third}.${secondOctet}.${firstOctet}.in-addr.arpa.") thirdOctets; 40 | 41 | mkReverseDdns = 42 | keyName: dnsServers: vlans: 43 | let 44 | vlanToReverseDomains = 45 | vlan: 46 | map (zone: { 47 | dns-servers = dnsServers; 48 | key-name = keyName; 49 | name = zone; 50 | }) (toReverseZones vlan.cidr); 51 | 52 | # Combine all VLANs' reverse domains into a single list 53 | allReverseDomains = builtins.concatLists ( 54 | builtins.attrValues (builtins.mapAttrs (name: vlan: vlanToReverseDomains vlan) vlans) 55 | ); 56 | in 57 | allReverseDomains; 58 | 59 | joinList = lib.concatStringsSep ", "; 60 | in 61 | { 62 | inherit 63 | joinList 64 | toReverseZones 65 | mkReverseDdns 66 | ; 67 | } 68 | -------------------------------------------------------------------------------- /hosts/addams/modules/ntopng.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | pkg, 4 | lib, 5 | ... 6 | }: 7 | { 8 | 9 | sops.secrets."maxmind/licenseKey" = { }; 10 | services.geoipupdate = { 11 | enable = true; 12 | settings = { 13 | AccountID = config.repo.secrets.local.maxmind.accountId; 14 | EditionIDs = [ 15 | "GeoLite2-ASN" 16 | "GeoLite2-City" 17 | "GeoLite2-Country" 18 | ]; 19 | LicenseKey = config.sops.secrets."maxmind/licenseKey".path; 20 | }; 21 | }; 22 | environment.persistence."/persist".directories = [ "/var/lib/ntopng" ]; 23 | services.ntopng = { 24 | enable = true; 25 | interfaces = [ 26 | "wan0" 27 | "lan0" 28 | "iot" 29 | "inot" 30 | "mgmt" 31 | "vpn" 32 | "prim" 33 | "guest" 34 | "svc" 35 | "data" 36 | ]; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /hosts/addams/modules/podman.nix: -------------------------------------------------------------------------------- 1 | { ... }: 2 | { 3 | virtualisation = { 4 | containers.enable = true; 5 | oci-containers.backend = "podman"; 6 | podman = { 7 | enable = true; 8 | defaultNetwork.settings = { 9 | network_interface = "ctr0"; 10 | # setting this to true ironically breaks the dns because dns server is not running in the gateway ip 11 | # even setting `dns_name_servers` here doesn't work with this set to true 12 | dns_enabled = false; 13 | subnets = [ 14 | # change these 15 | { 16 | subnet = "10.12.0.0/24"; 17 | gateway = "10.12.0.1"; 18 | lease_range = { 19 | start_ip = "10.12.0.50"; 20 | end_ip = "10.12.0.200"; 21 | }; 22 | } 23 | ]; 24 | }; 25 | }; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /hosts/addams/modules/udpbroadcastrelay.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | ... 4 | }: 5 | { 6 | services.udpbroadcastrelay = { 7 | enable = false; 8 | instances = { 9 | roon = { 10 | port = 9003; 11 | id = 1; 12 | interfaces = [ 13 | "me-prim" 14 | "lan0" 15 | "me-iot" 16 | ]; 17 | }; 18 | mdns = { 19 | port = 5353; 20 | id = 2; 21 | interfaces = [ 22 | "me-prim" 23 | "lan0" 24 | "me-iot" 25 | "me-not" 26 | ]; 27 | multicast = "224.0.0.251"; 28 | }; 29 | syncthing = { 30 | port = 21027; 31 | id = 3; 32 | interfaces = [ 33 | "me-prim" 34 | "lan0" 35 | ]; 36 | }; 37 | }; 38 | 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /hosts/addams/secrets/local.nix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/hosts/addams/secrets/local.nix -------------------------------------------------------------------------------- /hosts/debord/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | pkgs, 4 | lib, 5 | inputs, 6 | ... 7 | }: 8 | let 9 | defaultSopsFile = ./secrets.sops.yaml; 10 | in 11 | { 12 | imports = [ 13 | ./hardware.nix 14 | ./disk-config.nix 15 | ../../config 16 | ../../config/home-ops.nix 17 | ../../modules/site-net 18 | ]; 19 | system.stateVersion = "24.05"; 20 | environment.etc."machine-id".text = config.repo.secrets.local.machineId; 21 | repo.secretFiles.home-ops = ../../secrets/home-ops.nix; 22 | sops.defaultSopsFile = ./secrets.sops.yaml; 23 | 24 | networking.firewall.logRefusedConnections = lib.mkForce true; 25 | modules.vpn.tailscale.enable = true; 26 | modules.vpn.tailscale.useRoutingFeatures = "both"; 27 | security.rtkit.enable = true; 28 | 29 | networking.firewall.allowedUDPPorts = [ 30 | 4214 31 | ]; 32 | networking.firewall.allowedTCPPorts = [ 33 | 4214 34 | ]; 35 | environment.systemPackages = with pkgs; [ 36 | alsa-utils 37 | pipewire 38 | wireplumber 39 | pulsemixer 40 | jless 41 | (pkgs.vlc.override { 42 | chromecastSupport = false; 43 | jackSupport = false; 44 | onlyLibVLC = false; 45 | skins2Support = false; 46 | waylandSupport = false; 47 | withQt5 = false; 48 | }) 49 | ]; 50 | services.pipewire = { 51 | enable = true; 52 | alsa.enable = true; 53 | pulse.enable = true; 54 | jack.enable = false; 55 | wireplumber.enable = true; 56 | audio.enable = true; 57 | }; 58 | home-ops = { 59 | enable = true; 60 | containers.enable = false; 61 | hypervisor.enable = true; 62 | }; 63 | myhm = 64 | { pkgs, ... }@hm: 65 | { 66 | #home.persistence."/persist${ramblurr.homeDirectory}" = { 67 | # directories = [ { directory = "work"; } ]; 68 | #}; 69 | }; 70 | 71 | # Merge in the site secrets 72 | site = config.repo.secrets.site.site; 73 | systemd.network = { 74 | links = { 75 | "10-lan0" = { 76 | matchConfig.MACAddress = config.repo.secrets.site.site.hosts.debord.interfaces.lan0.hwaddr; 77 | linkConfig.Name = "lan0"; 78 | }; 79 | #"10-lan1" = { 80 | # matchConfig.MACAddress = config.repo.secrets.site.site.hosts.debord.interfaces.lan1.hwaddr; 81 | # linkConfig.Name = "lan1"; 82 | #}; 83 | }; 84 | }; 85 | modules.server.virtd-host.net.brprim4.iface = "prim"; 86 | } 87 | -------------------------------------------------------------------------------- /hosts/debord/hardware.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | modulesPath, 6 | ... 7 | }: 8 | { 9 | imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; 10 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 11 | hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 12 | 13 | boot = { 14 | zfs.devNodes = lib.mkForce "/dev/disk/by-partuuid"; 15 | loader = { 16 | efi = { 17 | canTouchEfiVariables = true; 18 | }; 19 | systemd-boot = { 20 | enable = true; 21 | configurationLimit = 20; 22 | }; 23 | }; 24 | kernelModules = [ "kvm-intel" ]; 25 | extraModulePackages = [ ]; 26 | 27 | initrd = { 28 | availableKernelModules = [ 29 | "xhci_pci" 30 | "thunderbolt" 31 | "ahci" 32 | "usbhid" 33 | "usb_storage" 34 | "sd_mod" 35 | "sr_mod" 36 | ]; 37 | kernelModules = [ ]; 38 | 39 | postDeviceCommands = lib.mkAfter '' 40 | zfs rollback -r rpool/encrypted/local/root@blank && \ 41 | echo "rollback complete" 42 | ''; 43 | }; 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /hosts/debord/secrets/local.nix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/hosts/debord/secrets/local.nix -------------------------------------------------------------------------------- /hosts/dewey/guests.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | pkgs, 4 | lib, 5 | inputs, 6 | ... 7 | }: 8 | let 9 | inherit (config.repo.secrets) global; 10 | inherit (config.repo.secrets) home-ops; 11 | 12 | guests = [ 13 | "linkding" 14 | "invoiceninja" 15 | ]; 16 | 17 | genGuestSecret = hostname: { 18 | "microvm-${hostname}-sops-key" = { 19 | sopsFile = ../../guests/${hostname}/secrets.sops.yaml; 20 | key = "ssh_host_ed25519_key"; 21 | owner = "microvm"; 22 | mode = "400"; 23 | }; 24 | }; 25 | svcIp = hostname: lib.elemAt config.site.net.svc.hosts4.${hostname} 0; 26 | mkGuest = 27 | { 28 | hostname, 29 | domain, 30 | forwardAuth ? false, 31 | external ? false, 32 | acmeHost ? global.domain.home, 33 | pgEnable ? false, 34 | pgUsername ? hostname, 35 | pgDatabase ? hostname, 36 | ip ? svcIp hostname, 37 | dataset ? hostname, 38 | datasetMountpoint ? "/var/lib/${hostname}", 39 | }: 40 | { 41 | modules.services.ingress.virtualHosts."${domain}" = { 42 | acmeHost = acmeHost; 43 | upstream = "http://${ip}:8080"; 44 | forwardAuth = forwardAuth; 45 | }; 46 | modules.services.ingress.domains = lib.mkIf external { 47 | "${acmeHost}" = { 48 | externalDomains = [ domain ]; 49 | }; 50 | }; 51 | modules.services.postgresql.extraAuthentication = lib.mkIf pgEnable [ 52 | "host ${pgUsername} ${pgDatabase} ${ip}/32 scram-sha-256" 53 | ]; 54 | 55 | modules.zfs.datasets.properties = lib.mkIf (dataset != null && dataset != "") { 56 | "rpool/encrypted/safe/svc/${dataset}" = { 57 | "mountpoint" = datasetMountpoint; 58 | "com.sun:auto-snapshot" = "false"; 59 | }; 60 | }; 61 | }; 62 | in 63 | lib.mkMerge [ 64 | { 65 | sops.secrets = lib.mori.reduceAttrs genGuestSecret guests; 66 | } 67 | (mkGuest { 68 | hostname = "linkding"; 69 | domain = "bookmarks.${global.domain.home}"; 70 | forwardAuth = true; 71 | pgEnable = true; 72 | }) 73 | (mkGuest { 74 | hostname = "invoiceninja"; 75 | domain = "clients.${global.domain.work}"; 76 | external = true; 77 | acmeHost = global.domain.work; 78 | dataset = "invoiceninja2"; 79 | datasetMountpoint = "/var/lib/invoiceninja2"; 80 | }) 81 | ] 82 | -------------------------------------------------------------------------------- /hosts/dewey/hardware.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | modulesPath, 6 | ... 7 | }: 8 | { 9 | imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; 10 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 11 | hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 12 | 13 | boot = { 14 | zfs.devNodes = lib.mkForce "/dev/disk/by-partuuid"; 15 | loader = { 16 | efi = { 17 | canTouchEfiVariables = true; 18 | }; 19 | systemd-boot = { 20 | enable = true; 21 | configurationLimit = 20; 22 | }; 23 | }; 24 | kernelModules = [ "kvm-intel" ]; 25 | extraModulePackages = [ ]; 26 | initrd = { 27 | availableKernelModules = [ 28 | "xhci_pci" 29 | "ahci" 30 | "nvme" 31 | "usbhid" 32 | "usb_storage" 33 | "sd_mod" 34 | "sr_mod" 35 | "sdhci_pci" 36 | ]; 37 | kernelModules = [ ]; 38 | postDeviceCommands = lib.mkAfter '' 39 | zfs rollback -r rpool/encrypted/local/root@blank && \ 40 | zfs rollback -r rpool/encrypted/vms@blank && \ 41 | echo "rollback complete" 42 | ''; 43 | }; 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /hosts/dewey/secrets/local.nix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/hosts/dewey/secrets/local.nix -------------------------------------------------------------------------------- /hosts/mali/README.md: -------------------------------------------------------------------------------- 1 | # Mali - a NAS 2 | 3 | ## Flake Install 4 | 5 | 1. Boot into installer 6 | 7 | 2. Follow: 8 | ``` sh 9 | # 1. 10 | # from workstation 11 | ssh-copy-id -f -i ~/.ssh/casey.pub nixos 12 | rsync -avr ~/nixcfg nixos: 13 | 14 | # WARNING: ensure target disks are correct 15 | lsblk -a -o NAME,SIZE,VENDOR,NAME,MODEL,PARTLABEL 16 | 17 | # 2. 18 | # from target 19 | cd /home/nixos/nixcfg/hosts/stable/x86_64-linux/mali 20 | sudo ./disks.sh 21 | 22 | # 3. Save hdd.key and boot.key 23 | scp nixos:/home/nixos/nixcfg/hosts/stable/x86_64-linux/mali/boot.key . 24 | scp nixos:/home/nixos/nixcfg/hosts/stable/x86_64-linux/mali/hdd.key . 25 | # Add them to your password manager 26 | 27 | # 3. 28 | # go into a root shell 29 | sudo -i 30 | nix-shell -p git htop 31 | 32 | # 4. Resolve TODO(qemu) in hardware-configuration.nix 33 | 34 | # 5. 35 | bash ./install.sh 36 | 37 | # 6. 38 | # when prompted 39 | # from workstation 40 | # sops -d --extract "['ssh_host_ed25519_key']" ./secrets.sops.yaml | ssh nixos 'cat - | sudo tee -a /mnt/persist/etc/ssh/ssh_host_ed25519_key' 41 | # then on target type YES 42 | ``` 43 | 44 | 3. Reboot 45 | 4. Login 46 | -------------------------------------------------------------------------------- /hosts/mali/acme.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | pkgs, 4 | config, 5 | ... 6 | }: 7 | let 8 | inherit (config.repo.secrets.global) domain email; 9 | in 10 | { 11 | security.acme = { 12 | acceptTerms = true; 13 | defaults = { 14 | email = email.acme; 15 | dnsProvider = "cloudflare"; 16 | credentialsFile = config.sops.templates.acme-credentials.path; 17 | extraLegoFlags = [ "--dns.resolvers=1.1.1.1:53" ]; 18 | }; 19 | }; 20 | sops.secrets."acmeSecrets/cloudflareDnsToken" = { 21 | sopsFile = ./secrets.sops.yaml; 22 | restartUnits = [ ]; 23 | }; 24 | 25 | sops.templates.acme-credentials.content = '' 26 | CF_DNS_API_TOKEN=${config.sops.placeholder."acmeSecrets/cloudflareDnsToken"} 27 | ''; 28 | security.acme.certs = { 29 | #"mali" = { 30 | # domain = "mali.int.${domain.home}"; 31 | # extraDomainNames = []; 32 | # group = "nginx"; 33 | # directory = "/persist/var/lib/acme/mali"; 34 | #}; 35 | "s3.data.${domain.home}" = { 36 | domain = "s3.data.${domain.home}"; 37 | extraDomainNames = [ 38 | "*.s3.data.${domain.home}" 39 | "minio.data.${domain.home}" 40 | "*.s3.mgmt.${domain.home}" 41 | "minio.mgmt.${domain.home}" 42 | "s3.mgmt.${domain.home}" 43 | ]; 44 | postRun = "systemctl reload nginx.service"; 45 | group = "nginx"; 46 | }; 47 | "attic.mgmt.${domain.home}" = { 48 | domain = "attic.mgmt.${domain.home}"; 49 | postRun = "systemctl reload nginx.service"; 50 | group = "nginx"; 51 | extraDomainNames = [ 52 | "attic.int.${domain.home}" 53 | ]; 54 | }; 55 | }; 56 | 57 | environment.persistence = { 58 | "/persist" = { 59 | directories = [ "/var/lib/acme" ]; 60 | }; 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /hosts/mali/avahi.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | { 8 | services.avahi = { 9 | enable = false; 10 | nssmdns4 = true; 11 | openFirewall = true; 12 | publish = { 13 | enable = true; 14 | addresses = true; 15 | domain = true; 16 | hinfo = true; 17 | userServices = true; 18 | workstation = true; 19 | }; 20 | allowInterfaces = [ "prim" ]; 21 | extraServiceFiles = { 22 | smb = '' 23 | 24 | 25 | 26 | %h 27 | 28 | _smb._tcp 29 | 445 30 | 31 | 32 | ''; 33 | }; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /hosts/mali/borgbackup-server.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | let 8 | backupUser = "borg"; 9 | backupDir = "/mnt/tank2/backups/borg_repos"; 10 | in 11 | { 12 | users.users."${backupUser}" = { }; 13 | systemd.tmpfiles.rules = [ "d ${backupDir} 0755 root root - -" ]; 14 | services.borgbackup.repos = { 15 | aquinas = { 16 | path = "/mnt/tank2/backups/borg_repos/aquinas"; 17 | authorizedKeys = [ 18 | "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFUmi4lHn11g1eo0KFax0R2gQEKmn3J+quvM5Nx0UipJ" 19 | "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM9LkzTZXu/qsSuj+rdy24BBySWOLSmjcfA142AZcXJ5bDIrjWPHBg5pm0iroaRqC5eArWCD6VFA4e8cQzTzJE4=" 20 | ]; 21 | }; 22 | work = { 23 | path = "/mnt/tank2/backups/borg_repos/work"; 24 | authorizedKeys = [ 25 | "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDu4mlO4RTeRKGY0Whb2r0u9iM2I6+Rr2hKlQhhlLv25" 26 | ]; 27 | }; 28 | proxmox = { 29 | path = "/mnt/tank2/backups/borg_repos/proxmox"; 30 | authorizedKeys = [ 31 | "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDVhO6fCS/WBKebnGaNLxUDg5jWyMTv7nXvirPONXY3a" 32 | ]; 33 | }; 34 | }; 35 | systemd.services = lib.mapAttrs' (repo: repoCfg: { 36 | name = "borgbackup-compact-${repo}"; 37 | value = { 38 | path = with pkgs; [ borgbackup ]; 39 | script = "borg compact --verbose ${repoCfg.path}"; 40 | serviceConfig = { 41 | CPUSchedulingPolicy = "idle"; 42 | IOSchedulingClass = "idle"; 43 | PrivateTmp = true; 44 | ProtectSystem = "strict"; 45 | ReadWritePaths = repoCfg.path; 46 | User = backupUser; 47 | }; 48 | startAt = "Mon 4:55"; 49 | }; 50 | }) config.services.borgbackup.repos; 51 | } 52 | -------------------------------------------------------------------------------- /hosts/mali/install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | export COLOR_RESET="\033[0m" 4 | export RED_BG="\033[41m" 5 | export BLUE_BG="\033[44m" 6 | 7 | HOST_DIR=hosts/stable/x86_64-linux/mali 8 | 9 | function err { 10 | echo -e "${RED_BG}$1${COLOR_RESET}" 11 | } 12 | 13 | function info { 14 | echo -e "${BLUE_BG}$1${COLOR_RESET}" 15 | } 16 | 17 | function check_key { 18 | if [[ -f "/mnt/persist/etc/ssh/ssh_host_ed25519_key" ]]; 19 | then 20 | echo 21 | info "Here we go..." 22 | chown -R root:root /mnt/persist/etc/ssh/ssh_host_ed25519_key 23 | chmod 0600 /mnt/persist/etc/ssh/ssh_host_ed25519_key 24 | else 25 | mkdir -p /mnt/persist/etc/ssh 26 | echo 27 | echo "Please create /mnt/persist/etc/ssh/ssh_host_ed25519_key" 28 | echo "It is used to decrypt secrets." 29 | echo 30 | read -p "Are you ready? (type 'yes' in capital letters to begin installation): " -r 31 | if ! [[ $REPLY == "YES" ]]; 32 | then 33 | err "Aborting" 34 | exit 1 35 | fi 36 | check_key 37 | fi 38 | } 39 | 40 | if [[ "$EUID" -gt 0 ]]; then 41 | err "Must run as root" 42 | exit 1 43 | fi 44 | 45 | if [[ ! -d /mnt/boot ]]; then 46 | err "No /mnt/boot directory found. Did you run disks.sh first?" 47 | exit 1 48 | fi 49 | 50 | check_key 51 | rm -f /mnt/etc/nixos/configuration.nix 52 | 53 | 54 | nixos-install --flake '.#mali' 55 | 56 | info "Done." 57 | echo 58 | info "You can now reboot into your new NixOS installation." 59 | -------------------------------------------------------------------------------- /hosts/mali/minio.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | { 8 | environment.systemPackages = with pkgs; [ minio-client ]; 9 | sops.secrets.minio-root-credentials = { 10 | owner = "minio"; 11 | }; 12 | services.minio = { 13 | enable = true; 14 | dataDir = [ "/mnt/tank2/services/minio" ]; 15 | package = pkgs.minio; 16 | rootCredentialsFile = config.sops.secrets.minio-root-credentials.path; 17 | listenAddress = "127.0.0.1:9000"; 18 | consoleAddress = "127.0.0.1:8999"; 19 | }; 20 | 21 | environment.persistence."/persist" = { 22 | directories = [ "/var/lib/minio/" ]; 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /hosts/mali/monitoring.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | { 8 | environment.systemPackages = with pkgs; [ 9 | ipmitool 10 | lm_sensors 11 | ]; 12 | networking.firewall.allowedTCPPorts = [ 13 | config.services.prometheus.exporters.node.port 14 | config.services.prometheus.exporters.zfs.port 15 | config.services.prometheus.exporters.smartctl.port 16 | config.services.prometheus.exporters.ipmi.port 17 | config.services.prometheus.exporters.nut.port 18 | ]; 19 | services.prometheus = { 20 | exporters = { 21 | node = { 22 | enable = true; 23 | enabledCollectors = [ "systemd" ]; 24 | disabledCollectors = [ "textfile" ]; 25 | port = 9001; 26 | }; 27 | zfs = { 28 | enable = true; 29 | port = 9002; 30 | }; 31 | smartctl = { 32 | enable = true; 33 | port = 9003; 34 | }; 35 | ipmi = { 36 | enable = true; 37 | port = 9004; 38 | }; 39 | nut = { 40 | enable = true; 41 | port = 9005; 42 | nutUser = "admin"; 43 | group = "nut"; 44 | passwordPath = config.sops.secrets.upsAdminPassword.path; 45 | }; 46 | }; 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /hosts/mali/nfs.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | { 8 | services.nfs.server = { 9 | enable = true; 10 | statdPort = 4000; 11 | lockdPort = 4001; 12 | mountdPort = 4002; 13 | exports = config.repo.secrets.local.nfsExports; 14 | }; 15 | networking.firewall.allowedTCPPorts = [ 16 | 111 17 | 2049 18 | 4000 19 | 4001 20 | 4002 21 | 20048 22 | ]; 23 | networking.firewall.allowedUDPPorts = [ 24 | 111 25 | 2049 26 | 4000 27 | 4001 28 | 4002 29 | 20048 30 | ]; 31 | } 32 | -------------------------------------------------------------------------------- /hosts/mali/secrets/host.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/hosts/mali/secrets/host.pub -------------------------------------------------------------------------------- /hosts/mali/secrets/local.nix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/hosts/mali/secrets/local.nix -------------------------------------------------------------------------------- /hosts/mali/startover.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | 4 | if [ -d "/home/ramblurr" ];then 5 | echo "WHAT ARE YOU DOING?" 6 | exit 1 7 | fi 8 | 9 | 10 | umount /mnt/boot 11 | swapoff /dev/mapper/cryptswap 12 | cryptsetup close /dev/mapper/cryptswap 13 | cryptsetup close /dev/mapper/cryptkey 14 | zpool destroy rpool 15 | -------------------------------------------------------------------------------- /hosts/quine/.gitignore: -------------------------------------------------------------------------------- 1 | archive 2 | -------------------------------------------------------------------------------- /hosts/quine/README.md: -------------------------------------------------------------------------------- 1 | # Quine 2 | 3 | ## Bare Install 4 | 5 | 1. Boot into installer 6 | 7 | 2. Follow: 8 | ``` sh 9 | # go into a root shell 10 | sudo su 11 | 12 | # create this folder if necessary 13 | mkdir -p /mnt/etc/ 14 | 15 | git clone https://github.com/ramblurr/nixcfg.git /mnt/etc/nixos --recurse-submodules 16 | 17 | cd /mnt/etc/nixos/unstable/x86_64-linux/quine 18 | 19 | # edit disks.sh and verify vars 20 | 21 | # partition disk 22 | ./disks.sh 23 | 24 | # Edit /persist/etc/ssh/ssh_host_ed25519_key and place the private key 25 | # it is used to decrypt the secrets with sops 26 | 27 | # install 28 | ./bare-install.sh 29 | 30 | ``` 31 | 3. Reboot 32 | 33 | ## Flake Install 34 | 35 | > WARNING: This isn't working yet as of 2023-04-24 because of 36 | > ```error: filesystem error: cannot rename: Invalid cross-device link [/mnt/nix/store/1caynpxvnlc0a6bcyr35z4gpjiy1qacq-manifest.json.drv.chroot/nix/store/5b37nyxpghm0h2fsx8nn23qh9mpp3f65-manifest.json] [/nix/store/5b37nyxpghm0h2fsx8nn23qh9mpp3f65-manifest.json]``` 37 | > So in the meantime use the "Bare Install" 38 | 39 | 40 | 1. Boot into installer 41 | 42 | 2. Follow: 43 | ``` sh 44 | # go into a root shell 45 | sudo su 46 | 47 | # create this folder if necessary 48 | mkdir -p /mnt/etc/ 49 | 50 | git clone https://github.com/ramblurr/nixcfg.git /mnt/etc/nixos --recurse-submodules 51 | 52 | cd /mnt/etc/nixos/unstable/x86_64-linux/quine 53 | 54 | # edit disks.sh and verify vars 55 | 56 | # partition disk 57 | ./disks.sh 58 | 59 | # Edit /persist/etc/ssh/ssh_host_ed25519_key and place the private key 60 | # it is used to decrypt the secrets with sops 61 | 62 | # install 63 | ./install.sh 64 | 65 | ``` 66 | 67 | You could get some hashes errors, just change the bad hashes in the config file 68 | to the given ones by the Nix Output. 69 | 3. Reboot 70 | 4. Login 71 | 5. `chown -R $USER /etc/nixos` 72 | -------------------------------------------------------------------------------- /hosts/quine/install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | export COLOR_RESET="\033[0m" 4 | export RED_BG="\033[41m" 5 | export BLUE_BG="\033[44m" 6 | 7 | function err { 8 | echo -e "${RED_BG}$1${COLOR_RESET}" 9 | } 10 | 11 | function info { 12 | echo -e "${BLUE_BG}$1${COLOR_RESET}" 13 | } 14 | 15 | function check_key { 16 | if [[ -f "/mnt/persist/etc/ssh/ssh_host_ed25519_key" ]]; 17 | then 18 | echo 19 | info "Here we go..." 20 | else 21 | mkdir -p /mnt/persist/etc/ssh 22 | echo 23 | echo "Please create /mnt/persist/etc/ssh/ssh_host_ed25519_key" 24 | echo "It is used to decrypt secrets." 25 | echo 26 | read -p "Are you ready? (type 'yes' in capital letters to begin installation): " -r 27 | if ! [[ $REPLY == "YES" ]]; 28 | then 29 | err "Aborting" 30 | exit 1 31 | fi 32 | check_key 33 | fi 34 | } 35 | 36 | if [[ "$EUID" -gt 0 ]]; then 37 | err "Must run as root" 38 | exit 1 39 | fi 40 | 41 | if [[ ! -d /mnt/boot ]]; then 42 | err "No /mnt/boot directory found. Did you run disks.sh first?" 43 | exit 1 44 | fi 45 | 46 | check_key 47 | 48 | chown -R root:root /mnt/persist/etc/ssh/ssh_host_ed25519_key 49 | chmod 0600 /mnt/persist/etc/ssh/ssh_host_ed25519_key 50 | 51 | info "Generating NixOS configuration (/mnt/etc/nixos/*.nix) ..." 52 | nixos-generate-config --root /mnt 53 | 54 | 55 | cd /home/nixos/nixcfg 56 | rm /mnt/etc/nixos/configuration.nix 57 | mv /mnt/etc/nixos/hardware-configuration.nix ./hosts/quine/ 58 | 59 | 60 | nixos-install --no-root-passwd \ 61 | --flake '.#quine' 62 | 63 | #--option substituters "https://aseipp-nix-cache.global.ssl.fastly.net" \ 64 | 65 | info "Done." 66 | echo 67 | info "You can now reboot into your new NixOS installation." 68 | -------------------------------------------------------------------------------- /hosts/quine/ipfs.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | { 8 | services.kubo = { 9 | enable = true; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /hosts/quine/microvm-test-impl.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | inputs, 6 | ... 7 | }: 8 | 9 | let 10 | 11 | inherit (config.networking) hostName; 12 | nets = config.site.net; 13 | hostConfig = config.site.hosts.${hostName}; 14 | hostBridges = builtins.attrNames ( 15 | lib.filterAttrs (_: { type, ... }: type == "bridge") hostConfig.interfaces 16 | ); 17 | in 18 | { 19 | imports = [ 20 | ../../modules/site 21 | ../../modules/site-net 22 | ]; 23 | 24 | home-ops.microvm-host = { 25 | enable = true; 26 | baseZfsDataset = "rpool/encrypted/safe/microvms"; 27 | }; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /hosts/quine/networking.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | { 8 | site = config.repo.secrets.site.site; 9 | #systemd.services.systemd-networkd.serviceConfig.Environment = ["SYSTEMD_LOG_LEVEL=debug"]; 10 | services.resolved.fallbackDns = [ 11 | "1.1.1.1#cloudflare-dns.com" 12 | "8.8.8.8#dns.google" 13 | "1.0.0.1#cloudflare-dns.com" 14 | "8.8.4.4#dns.google" 15 | ]; 16 | systemd.network = { 17 | config.networkConfig = { 18 | IPv4Forwarding = true; 19 | #IPv6Forwarding = false; 20 | }; 21 | links = { 22 | "10-lan0" = { 23 | matchConfig.MACAddress = config.repo.secrets.local.lan0.mac; 24 | linkConfig.Name = "lan0"; 25 | }; 26 | "10-lan1" = { 27 | matchConfig.MACAddress = config.repo.secrets.local.lan1.mac; 28 | linkConfig.Name = "lan1"; 29 | }; 30 | }; 31 | netdevs = { 32 | "30-brwork" = { 33 | netdevConfig = { 34 | Name = "brwork"; 35 | Kind = "bridge"; 36 | MTUBytes = "1500"; 37 | }; 38 | }; 39 | }; 40 | networks = 41 | # Disabled interfaces 42 | (lib.mori.merge ( 43 | map 44 | (iface: { 45 | "10-${iface}" = { 46 | matchConfig.Name = iface; 47 | networkConfig.ConfigureWithoutCarrier = true; 48 | linkConfig = { 49 | Unmanaged = "yes"; 50 | ActivationPolicy = "always-down"; 51 | }; 52 | }; 53 | }) 54 | [ 55 | "lan1" 56 | "wlp8s0" 57 | ] 58 | )) 59 | // { 60 | "30-prim".networkConfig.IPv6AcceptRA = lib.mkForce false; 61 | "30-brwork" = { 62 | matchConfig.Name = "brwork"; 63 | linkConfig.RequiredForOnline = "no"; 64 | addresses = [ 65 | config.repo.secrets.local.workBridgeAddress 66 | ]; 67 | networkConfig = { 68 | ConfigureWithoutCarrier = true; 69 | DHCPServer = "yes"; 70 | }; 71 | 72 | dhcpServerStaticLeases = [ 73 | { 74 | Address = config.repo.secrets.local.workIp; 75 | MACAddress = config.repo.secrets.local.workMac; 76 | } 77 | ]; 78 | 79 | dhcpServerConfig = { 80 | PoolOffset = 100; 81 | PoolSize = 50; 82 | EmitDNS = "no"; 83 | EmitRouter = "no"; 84 | }; 85 | }; 86 | }; 87 | }; 88 | } 89 | -------------------------------------------------------------------------------- /hosts/quine/pipewire/90-roon-loopback.conf: -------------------------------------------------------------------------------- 1 | context.objects = [ 2 | #{ 3 | #factory = adapter 4 | # args = { 5 | 6 | # factory.name = api.alsa.pcm.sink 7 | # node.name = "roon-loopback-audio-in" 8 | # node.description = "RoonLoopback Audio In" 9 | # media.class = "Audio/Sink" 10 | # api.alsa.path = "hw:RoonLoopback,0" 11 | # #api.alsa.period-size = 1024 12 | # #api.alsa.headroom = 0 13 | # #api.alsa.disable-mmap = false 14 | # #api.alsa.disable-batch = false 15 | # #audio.format = "S16LE" 16 | # #audio.rate = 44100 17 | # audio.channels = 2 18 | # audio.position = "FL,FR" 19 | # } 20 | #}, 21 | 22 | { factory = adapter 23 | args = { 24 | 25 | factory.name = api.alsa.pcm.source 26 | node.name = "roon-loopback-audio-out" 27 | node.description = "RoonLoopback Audio Out" 28 | media.class = "Audio/Source" 29 | api.alsa.path = "hw:RoonLoopback,0" 30 | api.alsa.period-size = 1024 31 | api.alsa.headroom = 1024 # This is required to prevent stuttering 32 | #api.alsa.disable-mmap = false 33 | #api.alsa.disable-batch = false 34 | #audio.format = "S16LE" 35 | #audio.rate = 44100 36 | audio.channels = 2 37 | audio.position = "FL,FR" 38 | } 39 | } 40 | #{ factory = link-factory 41 | # args = { 42 | # link.output.node = "roon-loopback-audio-out" 43 | # link.output.port = capture_FR 44 | # link.input.node = "alsa_output.usb-TOPPING_VX1-00.analog-stereo" 45 | # link.input.port = playback_FR 46 | # link.passive = true 47 | # } 48 | #} 49 | 50 | #{ factory = link-factory 51 | # args = { 52 | # link.output.node = "roon-loopback-audio-out" 53 | # link.output.port = capture_FL 54 | # link.input.node = "alsa_output.usb-TOPPING_VX1-00.analog-stereo" 55 | # link.input.port = playback_FL 56 | # link.passive = true 57 | # } 58 | #} 59 | 60 | ] 61 | -------------------------------------------------------------------------------- /hosts/quine/roon-bridge.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | { 8 | boot.extraModprobeConfig = '' 9 | options snd-aloop id=RoonLoopback 10 | ''; 11 | services.avahi.enable = true; 12 | services.roon-bridge = { 13 | enable = false; 14 | user = "ramblurr"; 15 | group = "ramblurr"; 16 | openFirewall = true; 17 | }; 18 | # These ports are required for roon-bridge to work 19 | networking.firewall = { 20 | allowedTCPPortRanges = [ 21 | { 22 | from = 9100; 23 | to = 9200; 24 | } 25 | { 26 | from = 32768; 27 | to = 60999; 28 | } 29 | ]; 30 | allowedUDPPorts = [ 9003 ]; 31 | allowedUDPPortRanges = [ 32 | { 33 | from = 32768; 34 | to = 60999; 35 | } 36 | ]; 37 | }; 38 | myhm = 39 | { ... }@hm: 40 | { 41 | #persistence = { 42 | # directories = [ 43 | # ]; 44 | #}; 45 | home.file.".local/share/applications/roon.desktop" = { 46 | text = '' 47 | [Desktop Entry] 48 | Name=Roon 49 | Exec=bottles-cli run -p Roon -b 'Roon' -- %u 50 | Type=Application 51 | Terminal=false 52 | Categories=Application; 53 | Icon=/srv/data/roon-client/Roon/icons/Roon.png 54 | Comment=Launch Roon using Bottles. 55 | StartupWMClass=Roon 56 | Actions=Configure; 57 | [Desktop Action Configure] 58 | Name=Configure in Bottles 59 | Exec=bottles -b 'Roon' 60 | ''; 61 | }; 62 | }; 63 | environment.persistence."/persist" = { 64 | directories = [ "/var/lib/roon-bridge" ]; 65 | }; 66 | } 67 | -------------------------------------------------------------------------------- /hosts/quine/secrets/local.nix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/hosts/quine/secrets/local.nix -------------------------------------------------------------------------------- /hosts/quine/startover.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | 4 | swapoff /dev/mapper/cryptswap 5 | cryptsetup close /dev/mapper/cryptswap 6 | cryptsetup close /dev/mapper/cryptkey 7 | zpool destroy rpool 8 | -------------------------------------------------------------------------------- /hosts/quine/tabby.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | inputs, 4 | lib, 5 | pkgs, 6 | mine, 7 | ... 8 | }: 9 | 10 | { 11 | 12 | disabledModules = [ 13 | "${inputs.nixpkgs-unstable}/nixos/modules/services/misc/tabby.nix" 14 | ]; 15 | imports = [ 16 | "${inputs.nixpkgs-mine}/nixos/modules/services/misc/tabby.nix" 17 | ]; 18 | config = { 19 | services.tabby = { 20 | enable = true; 21 | package = ( 22 | mine.tabby.override { 23 | cudaSupport = true; 24 | acceleration = "cuda"; 25 | } 26 | ); 27 | model = "TabbyML/DeepseekCoder-6.7B"; 28 | }; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /hosts/quine/wireplumber/91-user-scripts.lua: -------------------------------------------------------------------------------- 1 | load_script("/home/ramblurr/.config/wireplumber/scripts/auto-connect-ports.lua") 2 | -------------------------------------------------------------------------------- /hosts/witt/hardware.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | pkgs, 4 | lib, 5 | inputs, 6 | ... 7 | }: 8 | { 9 | imports = [ inputs.nixos-hardware.nixosModules.framework-13-7040-amd ]; 10 | # The firmware on the fingerprint sensor needs a downgrade to make it work on Linux. The process is documented here. 11 | # However on recent NixOS versions also fwupd can no longer update the firmware. Using the following snippet allows 12 | # to temporarly downgrade fwupd to an old-enough version: 13 | services.fwupd = { 14 | enable = true; 15 | # we need fwupd 1.9.7 to downgrade the fingerprint sensor firmware 16 | # package = 17 | # (import (builtins.fetchTarball { 18 | # url = "https://github.com/NixOS/nixpkgs/archive/bb2009ca185d97813e75736c2b8d1d8bb81bde05.tar.gz"; 19 | # sha256 = "sha256:003qcrsq5g5lggfrpq31gcvj82lb065xvr7bpfa8ddsw8x4dnysk"; 20 | # }) { inherit (pkgs) system; }).fwupd; 21 | }; 22 | 23 | boot = { 24 | zfs.devNodes = lib.mkForce "/dev/disk/by-partuuid"; 25 | loader = { 26 | efi = { 27 | canTouchEfiVariables = true; 28 | }; 29 | systemd-boot = { 30 | enable = true; 31 | configurationLimit = 20; 32 | }; 33 | }; 34 | extraModulePackages = [ ]; 35 | kernelModules = [ "kvm-amd" ]; 36 | initrd = { 37 | availableKernelModules = [ 38 | "nvme" 39 | "xhci_pci" 40 | "thunderbolt" 41 | "usb_storage" 42 | "sd_mod" 43 | ]; 44 | kernelModules = [ ]; 45 | postDeviceCommands = lib.mkAfter '' 46 | zfs rollback -r rpool/encrypted/local/root@blank && \ 47 | echo "rollback complete" 48 | ''; 49 | }; 50 | }; 51 | 52 | hardware = { 53 | #bluetooth = { enable = true; powerOnBoot = false; }; 54 | enableRedistributableFirmware = true; # enables microcode updates 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /hosts/witt/home.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | inputs, 6 | ... 7 | }: 8 | 9 | let 10 | mainSansFont = "Cabin"; 11 | in 12 | { 13 | #home-manager.sharedModules = [ inputs.plasma-manager.homeManagerModules.plasma-manager ]; 14 | myhm = 15 | { ... }@hm: 16 | { 17 | # Starship prompt color - something very different to distinguish it from my main workstation 18 | programs.starship.settings = pkgs.lib.importTOML ./gruvbox-rainbow.toml; 19 | 20 | # Make certain user services happy 21 | # https://github.com/nix-community/home-manager/issues/2064 22 | systemd.user.targets.tray = { 23 | Unit = { 24 | Description = "Home Manager System Tray"; 25 | Requires = [ "graphical-session-pre.target" ]; 26 | }; 27 | }; 28 | 29 | # Apps, apps, apps 30 | home.packages = with pkgs; [ 31 | appimage-run 32 | zeal 33 | musescore 34 | audacity 35 | pavucontrol 36 | brightnessctl 37 | meld 38 | gimp 39 | pdfarranger 40 | qpwgraph # pipewire wiring gui tool 41 | easyeffects # pipewire eq 42 | ]; 43 | 44 | }; # end home manager 45 | } 46 | -------------------------------------------------------------------------------- /hosts/witt/secrets/host.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/hosts/witt/secrets/host.pub -------------------------------------------------------------------------------- /lib/default.nix: -------------------------------------------------------------------------------- 1 | inputs: final: prev: 2 | prev.lib.composeManyExtensions ( 3 | # Order is important to allow using prev instead of final in more places to 4 | # speed up evaluation. 5 | map (x: import x inputs) [ 6 | ./nix-std.nix 7 | ./nix-clj.nix 8 | ./my.nix 9 | ./attrs.nix 10 | ./uint.nix 11 | ./network.nix 12 | ] 13 | ) final prev 14 | -------------------------------------------------------------------------------- /lib/my.nix: -------------------------------------------------------------------------------- 1 | _inputs: _final: prev: { 2 | lib = prev.lib // { 3 | my = { 4 | # just a clean little placeholder that will be filled in 5 | }; 6 | }; 7 | 8 | } 9 | -------------------------------------------------------------------------------- /lib/network.nix: -------------------------------------------------------------------------------- 1 | _inputs: _final: prev: { 2 | lib = prev.lib // { 3 | my = prev.lib.my // { 4 | /* 5 | cidrToIp :: string -> string 6 | 7 | Given an IP address in CIDR notation, returns the IP address without the CIDR suffix 8 | */ 9 | cidrToIp = ip: builtins.head (builtins.split "/" ip); 10 | 11 | generateHostId = 12 | hostName: 13 | prev.lib.concatStringsSep "" ( 14 | prev.lib.take 8 (prev.lib.stringToCharacters (builtins.hashString "sha256" hostName)) 15 | ); 16 | 17 | /* 18 | generateMacAddress :: string -> string 19 | 20 | Given a string, returns a MAC address. 21 | */ 22 | generateMacAddress = 23 | s: 24 | let 25 | hash = builtins.hashString "sha256" s; 26 | c = off: builtins.substring off 2 hash; 27 | in 28 | "${builtins.substring 0 1 hash}2:${c 2}:${c 4}:${c 6}:${c 8}:${c 10}"; 29 | 30 | /* 31 | eui64Suffix :: string -> string 32 | 33 | Given a MAC address, returns the EUI-64 suffix. The returned suffix can be appended to a prefix to create a valid ipv6 ip address. 34 | */ 35 | eui64Suffix = 36 | mac: 37 | let 38 | inherit (prev.lib.std) 39 | list 40 | regex 41 | string 42 | num 43 | ; 44 | inherit (prev.lib.my) uint; 45 | parts = list.map string.toLower (regex.splitOn ":" mac); 46 | part = list.unsafeIndex parts; 47 | part0 = 48 | part: 49 | let 50 | nibble1' = uint.fromHexDigit (string.unsafeIndex part 1); 51 | nibble1 = num.bits.bitXor 2 nibble1'; 52 | nibble0 = string.unsafeIndex part 0; 53 | in 54 | nibble0 + uint.toHexLower nibble1; 55 | in 56 | "${part0 (part 0)}${part 1}:${part 2}ff:fe${part 3}:${part 4}${part 5}"; 57 | }; 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /lib/nix-clj.nix: -------------------------------------------------------------------------------- 1 | # A collection of pure functions that should be familiar to any Clojure programmer. 2 | inputs: _final: prev: { 3 | lib = prev.lib // { 4 | mori = rec { 5 | /* 6 | vals :: Attr -> [Any] 7 | Returns the values of an attrset as a list 8 | */ 9 | vals = builtins.attrValues; 10 | 11 | /* 12 | keys :: Attr -> [String] 13 | Returns the names of an attrset as a list 14 | */ 15 | keys = builtins.attrNames; 16 | 17 | /* 18 | merge :: [ Attr ] -> Attrs 19 | Merge a list of attribute sets together. In case of duplicate attributes, values from later list elements take precedence over earlier ones. 20 | */ 21 | merge = prev.lib.mergeAttrsList; 22 | 23 | reduce = builtins.foldl'; 24 | reduceAttrs = fn: list: builtins.foldl' (result: item: result // (fn item)) { } list; 25 | 26 | some = builtins.any; 27 | 28 | containsKey = prev.lib.flip builtins.hasAttr; 29 | 30 | filter = 31 | pred: coll: 32 | (if builtins.isList coll then (builtins.filter pred coll) else (prev.lib.filterAttrs pred coll)); 33 | 34 | nth = coll: index: builtins.elemAt coll index; 35 | 36 | count = builtins.length; 37 | first = builtins.head; 38 | second = list: nth list 1; 39 | rest = builtins.tail; 40 | last = list: nth list (count list - 1); 41 | 42 | # Behaves more like clojure's map 43 | # if coll is a list, does a normal map 44 | # if coll is an attrset does a mapAttrsToList 45 | map = 46 | f: coll: 47 | (if builtins.isList coll then builtins.map f coll else prev.lib.attrsets.mapAttrsToList f coll); 48 | 49 | # Concatenate a list of lists. 50 | _concatLists = prev.lib.std.list.foldr (x: y: x ++ y) [ ]; 51 | 52 | # Map and concatenate the result. 53 | mapcat = f: list: _concatLists (map f list); 54 | 55 | thread = initial: fnList: builtins.foldl' (result: fn: fn result) initial fnList; 56 | 57 | dissoc = keys: attrs: builtins.removeAttrs attrs keys; 58 | 59 | }; 60 | }; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /lib/nix-std.nix: -------------------------------------------------------------------------------- 1 | inputs: _final: prev: { 2 | lib = prev.lib // { 3 | # A sane standard library of pure functions 4 | # ref: https://github.com/chessai/nix-std 5 | std = inputs.nix-std.lib; 6 | }; 7 | 8 | } 9 | -------------------------------------------------------------------------------- /modules-unstable/default.nix: -------------------------------------------------------------------------------- 1 | { ... }: 2 | 3 | { 4 | imports = [ 5 | #./hardware/nvidia.nix 6 | ./hardware/nvidia 7 | ./services/microsocks.nix 8 | ]; 9 | } 10 | -------------------------------------------------------------------------------- /modules-unstable/services/microsocks.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | let 10 | cfg = config.modules.services.microsocks; 11 | username = config.modules.users.primaryUser.username; 12 | withImpermanence = config.modules.impermanence.enable; 13 | useMullvad = config.modules.vpn.mullvad.enable; 14 | in 15 | { 16 | options.modules.services.microsocks = { 17 | enable = lib.mkEnableOption "microsocks"; 18 | }; 19 | config = lib.mkIf cfg.enable { 20 | environment.systemPackages = with pkgs; [ microsocks ]; 21 | services.microsocks = { 22 | enable = true; 23 | port = 1081; 24 | execWrapper = lib.optionalString useMullvad "${pkgs.mullvad-vpn}/bin/mullvad-exclude"; 25 | }; 26 | 27 | systemd.services.microsocks = lib.mkIf useMullvad { 28 | after = [ "mullvad-exclusion-init.service" ]; 29 | wants = [ "mullvad-exclusion-init.service" ]; 30 | requires = [ "mullvad-exclusion-init.service" ]; 31 | }; 32 | 33 | systemd.services.mullvad-exclusion-init = lib.mkIf useMullvad { 34 | enable = true; 35 | description = "sets up mullvad exclusion cgroup"; 36 | after = [ "mullvad-daemon.service" ]; 37 | wants = [ "mullvad-daemon.service" ]; 38 | restartIfChanged = true; 39 | serviceConfig = { 40 | User = "root"; 41 | ExecStart = "/bin/sh -c '${pkgs.coreutils}/bin/mkdir -p /sys/fs/cgroup/net_cls/mullvad-exclusions/ && ${pkgs.coreutils}/bin/touch /sys/fs/cgroup/net_cls/mullvad-exclusions/cgroup.procs && ${pkgs.coreutils}/bin/chmod 777 /sys/fs/cgroup/net_cls/mullvad-exclusions/cgroup.procs'"; 42 | NotifyAccess = "all"; 43 | Type = "oneshot"; 44 | RemainAfterExit = "yes"; 45 | }; 46 | path = [ pkgs.coreutils ]; 47 | }; 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /modules/SKELETON.nix.txt: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | cfg = config.modules.shell.ZZNAME; 11 | username = config.modules.users.primaryUser.username; 12 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 13 | withImpermanence = config.modules.impermanence.enable; 14 | in { 15 | options.modules.shell.ZZNAME = { 16 | enable = lib.mkEnableOption ""; 17 | }; 18 | config = mkIf cfg.enable { 19 | home-manager.users."${username}" = { 20 | home.packages = with pkgs; [ 21 | ]; 22 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { 23 | directories = [ 24 | ]; 25 | }; 26 | }; 27 | }; 28 | } 29 | 30 | 31 | { 32 | options, 33 | config, 34 | lib, 35 | pkgs, 36 | inputs, 37 | ... 38 | }: 39 | with lib; 40 | cfg = config.modules.services.ZZNAME; 41 | withImpermanence = config.modules.impermanence.enable; 42 | in { 43 | options.modules.services.ZZNAME = { 44 | enable = lib.mkEnableOption ""; 45 | }; 46 | config = mkIf cfg.enable { 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /modules/desktop/hyprland3/hyprpaper.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | inputs, 6 | ... 7 | }: 8 | 9 | let 10 | cfg = config.modules.desktop.hyprland3; 11 | username = config.modules.users.primaryUser.username; 12 | hyprland = config.programs.hyprland.package; 13 | in 14 | { 15 | 16 | config = lib.mkIf cfg.enable { 17 | myhm = 18 | { ... }@hm: 19 | { 20 | services.hyprpaper = { 21 | enable = true; 22 | settings = { 23 | preload = [ 24 | #"~/docs/img/walls/safe-landing.jpg" 25 | "~/docs/img/walls/hyprland/gruv-vertical.jpg" 26 | #"~/docs/img/walls/hyprland/abstract-4.png" 27 | #"~/docs/img/walls/safe-landing-vertical.jpg" 28 | "~/docs/img/walls/hyprland/gruvbox_astro_wide.jpg" 29 | ]; 30 | wallpaper = [ 31 | "HDMI-A-1,~/docs/img/walls/hyprland/gruv-vertical.jpg" 32 | "DP-2,contain:~/docs/img/walls/hyprland/gruvbox_astro_wide.jpg" 33 | ]; 34 | }; 35 | }; 36 | }; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /modules/desktop/hyprland3/mako.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.modules.desktop.hyprland3; 10 | username = config.modules.users.primaryUser.username; 11 | in 12 | { 13 | config = lib.mkIf cfg.enable { 14 | myhm = 15 | { pkgs, ... }@hm: 16 | { 17 | services.mako = { 18 | enable = true; 19 | anchor = "top-center"; 20 | markup = true; 21 | padding = "5"; 22 | #backgroundColor = "#689d6a"; 23 | #progressColor = "#ebdbb2"; 24 | #textColor = "#1d2021"; 25 | 26 | #borderColor = "#ebdbb2"; 27 | #borderSize = 5; 28 | #borderRadius = 2; 29 | 30 | # 31 | backgroundColor = "#282828"; 32 | textColor = "#ebdbb2"; 33 | progressColor = "#ebdbb2"; 34 | borderColor = "#928374"; 35 | borderSize = 3; 36 | borderRadius = 6; 37 | }; 38 | }; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /modules/desktop/hyprland3/template.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.modules.desktop.hyprland3; 10 | in 11 | 12 | { 13 | config = lib.mkIf cfg.enable { 14 | 15 | myhm = { ... }@hm: { }; 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /modules/desktop/hyprland3/theme.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.modules.desktop.hyprland3; 10 | nerdfonts = with pkgs; [ 11 | nerd-fonts.iosevka 12 | nerd-fonts.fira-code 13 | nerd-fonts.mononoki 14 | nerd-fonts.jetbrains-mono 15 | nerd-fonts.symbols-only 16 | ]; 17 | 18 | #font.mono = "Iosevka Comfy Fixed"; 19 | #font.mono = "Berkeley Mono Trial"; 20 | font.mono = "Iosevka"; 21 | font.term = "Iosevka Nerd Font Mono"; 22 | font.serif = "Noto Serif"; 23 | font.sans = "Noto Sans"; 24 | font.emoji = "Noto Color Emoji"; 25 | 26 | theme = { 27 | name = "adw-gtk3-dark"; 28 | package = pkgs.adw-gtk3; 29 | }; 30 | cursorTheme = { 31 | name = "Adwaita"; 32 | size = 24; 33 | package = pkgs.adwaita-icon-theme; 34 | }; 35 | iconTheme = { 36 | name = "Adwaita"; 37 | package = pkgs.adwaita-icon-theme; 38 | }; 39 | in 40 | 41 | { 42 | config = lib.mkIf cfg.enable { 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /modules/desktop/programs/1password.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.onepassword; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.onepassword = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | programs._1password = { 22 | enable = true; 23 | }; 24 | programs._1password-gui = { 25 | enable = true; 26 | polkitPolicyOwners = [ username ]; 27 | }; 28 | 29 | environment.persistence."/persist" = mkIf withImpermanence { 30 | users.${username} = { 31 | directories = [ ".config/1Password" ]; 32 | }; 33 | }; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /modules/desktop/programs/aseprite.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.aseprite; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.aseprite = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | myhm = { 22 | home.packages = with pkgs; [ pkgs.aseprite ]; 23 | persistence = mkIf withImpermanence { 24 | directories = [ 25 | ".config/libresprite" 26 | ".config/aseprite" 27 | ]; 28 | }; 29 | }; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /modules/desktop/programs/cad.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.cad; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.cad = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = lib.mkIf cfg.enable { 21 | 22 | environment.persistence."/persist" = lib.mkIf withImpermanence { 23 | 24 | users.${username} = { 25 | directories = [ 26 | ".config/FreeCAD" 27 | ".cache/FreeCAD" 28 | ".local/share/FreeCAD" 29 | ".config/OpenSCAD" 30 | ".local/share/OpenSCAD" 31 | ]; 32 | files = [ 33 | ".config/CQ-editorrc" 34 | ".config/OpenSCADrc" 35 | ]; 36 | 37 | }; 38 | }; 39 | home-manager.users."${username}" = 40 | { pkgs, config, ... }@hm: 41 | { 42 | home.packages = with pkgs; [ 43 | freecad 44 | # BLOCKED: https://github.com/NixOS/nixpkgs/issues/375763 45 | #(inputs.cadquery.packages.${pkgs.system}.cq-editor) 46 | openscad-unstable 47 | openscad-lsp 48 | ]; 49 | }; 50 | }; 51 | } 52 | -------------------------------------------------------------------------------- /modules/desktop/programs/calibre.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.calibre; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.calibre = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | home-manager.users."${username}" = 22 | { pkgs, config, ... }@hm: 23 | { 24 | home.packages = with pkgs; [ calibre ]; 25 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { 26 | directories = [ ".config/calibre" ]; 27 | }; 28 | }; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /modules/desktop/programs/chrysalis.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.chrysalis; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.chrysalis = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | services.udev.packages = [ pkgs.chrysalis ]; 22 | home-manager.users."${username}" = 23 | { pkgs, config, ... }@hm: 24 | { 25 | home.packages = [ pkgs.chrysalis ]; 26 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { 27 | directories = [ 28 | ".config/chrysalis" 29 | ".config/Chrysalis" 30 | ]; 31 | }; 32 | }; 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /modules/desktop/programs/discord.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.discord; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.discord = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | home-manager.users."${username}" = 22 | { pkgs, config, ... }@hm: 23 | { 24 | home.packages = with pkgs; [ 25 | discord 26 | betterdiscordctl 27 | ]; 28 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { 29 | directories = [ 30 | ".config/BetterDiscord" 31 | ".config/discord" 32 | ]; 33 | }; 34 | }; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /modules/desktop/programs/fritzing.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.fritzing; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.fritzing = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | home-manager.users."${username}" = 22 | { pkgs, config, ... }@hm: 23 | { 24 | home.packages = [ pkgs.fritzing ]; 25 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { 26 | directories = [ ".config/Fritzing" ]; 27 | }; 28 | }; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /modules/desktop/programs/junction.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.junction; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.junction = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | home-manager.users."${username}" = 22 | { pkgs, config, ... }@hm: 23 | { 24 | home.packages = [ pkgs.junction ]; 25 | }; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /modules/desktop/programs/kdeconnect.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.kdeconnect; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.kdeconnect = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | networking.firewall.allowedTCPPortRanges = [ 22 | { 23 | from = 1714; 24 | to = 1764; 25 | } 26 | ]; 27 | networking.firewall.allowedUDPPortRanges = [ 28 | { 29 | from = 1714; 30 | to = 1764; 31 | } 32 | ]; 33 | home-manager.users."${username}" = 34 | { pkgs, config, ... }@hm: 35 | { 36 | services.kdeconnect = { 37 | enable = true; 38 | indicator = true; 39 | }; 40 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { 41 | directories = [ ".config/kdeconnect" ]; 42 | }; 43 | }; 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /modules/desktop/programs/kicad.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.kicad; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.kicad = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | home-manager.users."${username}" = 22 | { pkgs, config, ... }@hm: 23 | { 24 | home.packages = with pkgs; [ kicad ]; 25 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { 26 | directories = [ 27 | ".config/kicad" 28 | ".config/kicad5" 29 | ]; 30 | }; 31 | }; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /modules/desktop/programs/kitty/configs/kitty-monitor.session: -------------------------------------------------------------------------------- 1 | launch btop 2 | -------------------------------------------------------------------------------- /modules/desktop/programs/kitty/configs/kitty.session: -------------------------------------------------------------------------------- 1 | launch zsh 2 | -------------------------------------------------------------------------------- /modules/desktop/programs/kitty/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.kitty; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | termFont = config.modules.desktop.fonts.terminal; 16 | in 17 | { 18 | options.modules.desktop.programs.kitty = { 19 | enable = lib.mkEnableOption ""; 20 | }; 21 | config = mkIf cfg.enable { 22 | home-manager.users."${username}" = 23 | { pkgs, config, ... }@hm: 24 | { 25 | home.file = { 26 | ".config/kitty/kitty.session" = { 27 | source = ./configs/kitty.session; 28 | }; 29 | ".config/kitty/kitty-monitor.session" = { 30 | source = ./configs/kitty-monitor.session; 31 | }; 32 | }; 33 | 34 | home.packages = [ pkgs.kitty ]; 35 | programs.kitty = { 36 | enable = true; 37 | themeFile = "gruvbox-dark"; 38 | font = { 39 | name = termFont.name; 40 | size = termFont.size; 41 | }; 42 | settings = { 43 | background_opacity = "0.90"; 44 | #font_size = "16"; 45 | #bold_font = "auto"; 46 | #italic_font = "auto"; 47 | #bold_italic_font = "auto"; 48 | #disable_ligatures = "never"; 49 | cursor_blink_interval = "1"; 50 | cursor_stop_blinking_after = "0.0"; 51 | select_by_word_characters = "@-./_~?&=%+#"; 52 | enable_audio_bell = "no"; 53 | }; 54 | }; 55 | }; 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /modules/desktop/programs/logseq.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.logseq; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.logseq = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | 22 | environment.persistence."/persist" = mkIf withImpermanence { 23 | users.${username} = { 24 | directories = [ 25 | ".config/Logseq" 26 | ".logseq" 27 | ]; 28 | }; 29 | }; 30 | 31 | home-manager.users."${username}" = 32 | { pkgs, config, ... }@hm: 33 | { 34 | # I am using flatpak logseq, because it is more stable than the nix pkg (as of 2024-09) 35 | # ref: https://github.com/NixOS/nixpkgs/issues/264885 36 | # https://github.com/logseq/logseq/issues/10851 37 | #home.packages = [ pkgs.logseq ]; 38 | #Exec=env -u NIXOS_OZONE_WL logseq %u 39 | #Icon=logseq 40 | home.file.".local/share/applications/logseq-wayland.desktop" = { 41 | text = '' 42 | [Desktop Entry] 43 | Name=Logseq (flatpak wayland) 44 | Exec=GDK_BACKEND=wayland flatpak run com.logseq.Logseq --enable-features=UseOzonePlatform --ozone-platform=wayland --enable-features=WaylandWindowDecorations %u 45 | Terminal=false 46 | Type=Application 47 | Icon=com.logseq.Logseq 48 | StartupWMClass=Logseq 49 | Comment=A privacy-first, open-source platform for knowledge management and collaboration. 50 | MimeType=x-scheme-handler/logseq 51 | Categories=Utility 52 | ''; 53 | }; 54 | }; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /modules/desktop/programs/musescore.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.musescore; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.musescore = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | 22 | environment.persistence."/persist" = mkIf withImpermanence { 23 | users.${username} = { 24 | directories = [ 25 | ".config/MuseScore" 26 | ".local/share/MuseScore" 27 | ".local/state/MuseScore" 28 | ".local/state/muse-sounds-manager" 29 | ".local/share/MuseSampler" 30 | ".muse-hub" 31 | ]; 32 | }; 33 | }; 34 | home-manager.users."${username}" = 35 | { pkgs, config, ... }@hm: 36 | { 37 | home.packages = [ 38 | pkgs.musescore 39 | pkgs.muse-sounds-manager 40 | ]; 41 | }; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /modules/desktop/programs/nextcloud.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.nextcloud; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.nextcloud = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | 22 | environment.persistence."/persist" = mkIf withImpermanence { 23 | users.${username} = { 24 | directories = [ 25 | ".config/Nextcloud" 26 | ".local/share/Nextcloud" 27 | ]; 28 | }; 29 | }; 30 | myhm = { 31 | services.nextcloud-client = { 32 | enable = true; 33 | startInBackground = true; 34 | }; 35 | }; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /modules/desktop/programs/nheko.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.nheko; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.nheko = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | environment.persistence."/persist" = mkIf withImpermanence { 22 | users.${username} = { 23 | directories = [ 24 | ".config/nheko" 25 | ".cache/nheko" 26 | ".local/share/nheko" 27 | ]; 28 | }; 29 | }; 30 | home-manager.users."${username}" = 31 | { pkgs, config, ... }@hm: 32 | { 33 | home.packages = with pkgs; [ nheko ]; 34 | }; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /modules/desktop/programs/obs.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.obs; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.obs = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | boot.extraModulePackages = [ config.boot.kernelPackages.v4l2loopback ]; 22 | 23 | environment.systemPackages = with pkgs; [ 24 | v4l-utils 25 | 26 | (pkgs.writeScriptBin "obs-v4l2loopback-setup.sh" '' 27 | set -x 28 | sudo modprobe \ 29 | v4l2loopback \ 30 | devices=1 \ 31 | video_nr=13 \ 32 | card_label="''${CAMERA_NAME:-"OBS Virtual Camera"}" \ 33 | exclusive_caps=1 34 | '') 35 | ]; 36 | 37 | home-manager.users."${username}" = 38 | { pkgs, config, ... }@hm: 39 | { 40 | programs.obs-studio = { 41 | enable = true; 42 | 43 | # TODO: is this even needed? isn't it built in? 44 | plugins = with pkgs; [ 45 | # obs-studio-plugins.wlrobs 46 | ]; 47 | }; 48 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { directories = [ ]; }; 49 | }; 50 | }; 51 | } 52 | -------------------------------------------------------------------------------- /modules/desktop/programs/owncloud.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.owncloud; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.owncloud = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | 22 | environment.persistence."/persist" = mkIf withImpermanence { 23 | users.${username} = { 24 | directories = [ ".config/ownCloud" ]; 25 | }; 26 | }; 27 | myhm = { 28 | home.packages = [ pkgs.owncloud-client ]; 29 | }; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /modules/desktop/programs/signal.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.signal; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.signal = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | 22 | environment.persistence."/persist" = mkIf withImpermanence { 23 | users.${username} = { 24 | directories = [ ".config/Signal" ]; 25 | }; 26 | }; 27 | home-manager.users."${username}" = 28 | { pkgs, config, ... }@hm: 29 | { 30 | home.packages = [ pkgs.signal-desktop ]; 31 | home.file.".local/share/applications/signal-desktop.desktop" = { 32 | text = '' 33 | [Desktop Entry] 34 | Name=Signal Desktop 35 | Exec=/nix/store/pkdmssw4rvnbd55i1x2ha4bx6liv1fdz-signal-desktop-7.14.0/bin/signal-desktop --ozone-platform-hint=auto --no-sandbox %U 36 | Terminal=false 37 | Type=Application 38 | Icon=signal-desktop 39 | StartupWMClass=signal 40 | Comment=Private messaging from your desktop 41 | MimeType=x-scheme-handler/sgnl;x-scheme-handler/signalcaptcha; 42 | Categories=Network;InstantMessaging;Chat; 43 | ''; 44 | }; 45 | }; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /modules/desktop/programs/slack.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.slack; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.slack = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | 22 | environment.persistence."/persist" = mkIf withImpermanence { 23 | users.${username} = { 24 | directories = [ ".config/Slack" ]; 25 | }; 26 | }; 27 | home-manager.users."${username}" = 28 | { pkgs, config, ... }@hm: 29 | { 30 | home.packages = [ pkgs.slack ]; 31 | }; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /modules/desktop/programs/wezterm/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.wezterm; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | termFont = config.modules.desktop.fonts.terminal; 16 | in 17 | { 18 | options.modules.desktop.programs.wezterm = { 19 | enable = lib.mkEnableOption ""; 20 | }; 21 | config = mkIf cfg.enable { 22 | home-manager.users."${username}" = 23 | { pkgs, config, ... }@hm: 24 | { 25 | home.packages = [ pkgs.wezterm ]; 26 | programs.wezterm = { 27 | enable = true; 28 | extraConfig = '' 29 | local wezterm = require 'wezterm' 30 | local config = wezterm.config_builder() 31 | config.mux_enable_ssh_agent = false 32 | 33 | --config.color_scheme = 'Gruvbox dark, hard (base16)' 34 | --config.color_scheme = 'GruvboxDarkHard' 35 | config.color_scheme = 'GruvboxDark' 36 | config.font = wezterm.font_with_fallback { 37 | "${termFont.name}", 38 | --"Berkeley Mono Trial", 39 | -- "Iosevka Nerd Font Mono", 40 | --"Iosevka Term", 41 | --"Iosevka Comfy Fixed", 42 | --"Symbols Nerd Font Mono", 43 | "Noto Color Emoji" 44 | } 45 | config.font_size = ${toString termFont.size}; 46 | config.freetype_load_flags = 'NO_HINTING' 47 | --config.freetype_load_target = 'Normal' 48 | config.freetype_load_target = 'Light' 49 | --config.freetype_load_target = 'HorizontalLcd' 50 | --config.freetype_load_target = 'VerticalLcd' 51 | --config.front_end = "OpenGL" 52 | config.front_end = "WebGpu" 53 | --config.line_height = 0.9 54 | config.hide_tab_bar_if_only_one_tab = true 55 | 56 | config.enable_scroll_bar = true 57 | config.window_padding = { 58 | left = 0, 59 | right = 5, 60 | top = 0, 61 | bottom = 0, 62 | } 63 | 64 | return config 65 | 66 | ''; 67 | }; 68 | }; 69 | }; 70 | } 71 | -------------------------------------------------------------------------------- /modules/desktop/programs/yubico.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.programs.yubico; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.desktop.programs.yubico = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | programs.yubikey-touch-detector.enable = true; 22 | myhm = { 23 | home.packages = with pkgs; [ 24 | yubikey-manager 25 | yubioath-flutter 26 | age-plugin-yubikey 27 | age 28 | rage 29 | ]; 30 | }; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /modules/desktop/random-apps.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.random-apps; 12 | in 13 | { 14 | options.modules.desktop.random-apps = { 15 | enable = lib.mkEnableOption ""; 16 | }; 17 | config = mkIf cfg.enable { 18 | myhm = 19 | { ... }@hm: 20 | { 21 | home.packages = lib.mkMerge [ 22 | #(lib.mkIf (pkgs.hostPlatform.system == "x86_64-linux") (with pkgs; [ 23 | # # x86_64-linux only 24 | # zenith # system monitor 25 | #])) 26 | (lib.mkIf (pkgs.hostPlatform.system == "aarch_64-linux") ( 27 | with pkgs; 28 | [ 29 | # aarch64-linux only 30 | ] 31 | )) 32 | (with pkgs; [ 33 | zeal 34 | libreoffice 35 | appimage-run 36 | audacity 37 | pavucontrol 38 | prusa-slicer 39 | #eagle 40 | #xcircuit 41 | brightnessctl 42 | virt-viewer 43 | evince 44 | kooha 45 | #onlyoffice-bin 46 | #libreoffice-qt 47 | #hunspell 48 | #hunspellDicts.en_US 49 | #hunspellDicts.de_AT 50 | #morgen # disabled because of electron-30.5.1 51 | ffmpeg-full 52 | libnotify # `notify-send` 53 | gparted 54 | inkscape 55 | #krita 56 | meld 57 | #gimp-with-plugins 58 | gimp 59 | pdfgrep 60 | nerdfix 61 | kid3 62 | pdfarranger 63 | #makemkv 64 | # BLOCKED: https://github.com/NixOS/nixpkgs/issues/380197 65 | fava 66 | beancount_2 67 | keepassxc 68 | dex 69 | qpwgraph # pipewire wiring gui tool 70 | easyeffects # pipewire eq 71 | ]) 72 | ]; 73 | 74 | persistence = { 75 | files = [ 76 | ".config/kritarc" 77 | ".config/kritadisplayrc" 78 | ]; 79 | }; 80 | }; 81 | }; 82 | } 83 | -------------------------------------------------------------------------------- /modules/desktop/services/ha-shutdown.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | with lib; 8 | let 9 | cfg = config.modules.desktop.services.ha-shutdown; 10 | shutdownScript = pkgs.writeScript "ha-shutdown.py" (builtins.readFile ./shutdown.py); 11 | username = config.modules.users.primaryUser.username; 12 | in 13 | { 14 | options.modules.desktop.services.ha-shutdown = { 15 | enable = mkEnableOption "ha-shutdown"; 16 | environmentFile = mkOption { 17 | description = "The full path to a file that contains the secret environment variables needed for the shutdown service"; 18 | type = with types; nullOr str; 19 | default = null; 20 | }; 21 | listenPort = mkOption { 22 | type = types.int; 23 | default = 5001; 24 | }; 25 | timeout = mkOption { 26 | type = types.int; 27 | default = 60000; 28 | description = "The number of milliseconds to wait for a response from Home Assistant before shutting down"; 29 | }; 30 | }; 31 | config = mkIf cfg.enable { 32 | networking.firewall.allowedTCPPorts = [ cfg.listenPort ]; 33 | sops.secrets.HA_SHUTDOWN_TOKEN = { 34 | owner = username; 35 | mode = "0400"; 36 | }; 37 | systemd.user.services.ha-shutdown = { 38 | description = "HA Shutdown Service"; 39 | wantedBy = [ "default.target" ]; 40 | after = [ 41 | "network.target" 42 | "network-online.target" 43 | "sops-nix.service" 44 | ]; 45 | path = with pkgs; [ 46 | python3 47 | dunst 48 | systemd 49 | ]; 50 | serviceConfig = { 51 | EnvironmentFile = config.sops.secrets.HA_SHUTDOWN_TOKEN.path; 52 | ExecStart = "${pkgs.python3}/bin/python -u ${shutdownScript} --timeout ${toString cfg.timeout} --port ${toString cfg.listenPort} "; 53 | Restart = "always"; 54 | RestartSec = "10s"; 55 | StandardError = "journal"; 56 | StandardOutput = "journal"; 57 | }; 58 | }; 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /modules/desktop/wayland.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.desktop.wayland; 12 | username = config.modules.users.primaryUser.username; 13 | in 14 | { 15 | options.modules.desktop.wayland = { 16 | enable = lib.mkEnableOption ""; 17 | }; 18 | config = mkIf cfg.enable { 19 | myhm = { 20 | home.sessionVariables = { 21 | QT_QPA_PLATFORM = "wayland"; 22 | XDG_SESSION_TYPE = "wayland"; 23 | NIXOS_OZONE_WL = "1"; 24 | MOZ_ENABLE_WAYLAND = "1"; 25 | _JAVA_AWT_WM_NONREPARENTING = "1"; 26 | }; 27 | home.packages = with pkgs; [ 28 | qt5.qtwayland 29 | qt6.qtwayland 30 | 31 | wl-clipboard # wl-{copy,paste} 32 | wtype # virtual keystroke insertion 33 | 34 | # imv # image viewer 35 | oculante # image viewer (rust) 36 | grim # area selection 37 | slurp # screen capture 38 | wf-recorder # screen record 39 | wev # event viewer 40 | ]; 41 | }; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /modules/dev/clojure/configs/clj-kondo/config.edn: -------------------------------------------------------------------------------- 1 | {:lint-as {com.fulcrologic.fulcro.components/defsc clojure.core/defn 2 | com.fulcrologic.fulcro.routing.dynamic-routing/defrouter clojure.core/defn 3 | mount.core/defstate clojure.core/def 4 | com.wsscode.pathom.connect/defresolver clojure.core/defn 5 | com.wsscode.pathom.connect/defmutation clojure.core/defn 6 | nubank.workspaces.core/defcard clojure.core/def 7 | com.fulcrologic.guardrails.core/>defn clojure.core/defn 8 | taoensso.encore/if-let clojure.core/if-let 9 | ctmx.core/defcomponent clojure.core/defn 10 | simpleui.core/defcomponent clojure.core/defn 11 | helix.core/defnc clojure.core/defn 12 | uix.core/defui clojure.core/defn 13 | day8.re-frame.tracing/fn-traced clojure.core/fn} 14 | 15 | :linters {:unresolved-var {:level :error} 16 | :unresolved-symbol {:exclude [(app.ui/tw) 17 | (ctmx.core/defcomponent [path id value self]) 18 | (ctmx.core/with-req [post? put? patch? delete?]) 19 | (simpleui.core/defcomponent [path id value self]) 20 | (simpleui.core/with-req [post? put? patch? delete?])]}}} 21 | -------------------------------------------------------------------------------- /modules/dev/fennel.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | inputs, 4 | options, 5 | lib, 6 | pkgs, 7 | my, 8 | ... 9 | }: 10 | with lib; 11 | let 12 | devCfg = config.modules.dev; 13 | cfg = devCfg.fennel; 14 | username = config.modules.users.primaryUser.username; 15 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 16 | withImpermanence = config.modules.impermanence.enable; 17 | nur = import inputs.nur { 18 | nurpkgs = pkgs; 19 | inherit pkgs; 20 | }; 21 | in 22 | { 23 | options.modules.dev.fennel = { 24 | enable = lib.mkEnableOption ""; 25 | }; 26 | 27 | config = mkIf cfg.enable { 28 | environment.systemPackages = with pkgs; [ 29 | lua 30 | luajit 31 | lua-language-server 32 | fennel 33 | fnlfmt 34 | nur.repos.bandithedoge.fennel-language-server 35 | love 36 | ]; 37 | home-manager.users."${username}" = { 38 | #home.packages = with pkgs; [ 39 | #]; 40 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { 41 | directories = [ ".config/fennel" ]; 42 | }; 43 | }; 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /modules/dev/jetbrains/configs/ideavim/_all.vim: -------------------------------------------------------------------------------- 1 | """ This file contains all my custom settings 2 | 3 | " base settings 4 | source ~/.config/ideavim/settings.vim 5 | 6 | " project management 7 | source ~/.config/ideavim/projects.vim 8 | 9 | " major modes 10 | source ~/.config/ideavim/major.vim 11 | -------------------------------------------------------------------------------- /modules/dev/jetbrains/configs/ideavim/custom.vim: -------------------------------------------------------------------------------- 1 | set visualbell 2 | set noerrorbells 3 | 4 | set clipboard+=unnamed 5 | 6 | nnoremap yy "+yy 7 | vnoremap y "+y 8 | 9 | nnoremap p "+p 10 | vnoremap p "+p 11 | nnoremap P "+P 12 | vnoremap P "+P 13 | -------------------------------------------------------------------------------- /modules/dev/jetbrains/configs/ideavim/projects.vim: -------------------------------------------------------------------------------- 1 | " Open terminal in project root 2 | nnoremap p! :action ActivateTerminalToolWindow 3 | vnoremap p! :action ActivateTerminalToolWindow 4 | 5 | " Toggle between implementation file and its test file 6 | nnoremap pa :action GotoTest 7 | vnoremap pa :action GotoTest 8 | 9 | " Switch among recently opened files 10 | nnoremap pb :action RecentFiles 11 | vnoremap pb :action RecentFiles 12 | nnoremap ph :action RecentFiles 13 | vnoremap ph :action RecentFiles 14 | nnoremap pr :action RecentFiles 15 | vnoremap pr :action RecentFiles 16 | 17 | " Make project 18 | nnoremap pc :action CompileDirty 19 | vnoremap pc :action CompileDirty 20 | 21 | " Focus on project window. 22 | " Sadly when you are inside the project window this key binding does not work 23 | " anymore. You can use if you want to close the window or if you 24 | " want to leave the window opened and focus on the code. 25 | nnoremap pD :action ActivateProjectToolWindow 26 | vnoremap pD :action ActivateProjectToolWindow 27 | nnoremap pt :action ActivateProjectToolWindow 28 | vnoremap pt :action ActivateProjectToolWindow 29 | 30 | " Find files 31 | nnoremap pf :action GotoFile 32 | vnoremap pf :action GotoFile 33 | 34 | " Invalidate cache 35 | nnoremap pI :action InvalidateCaches 36 | vnoremap pI :action InvalidateCaches 37 | 38 | " Recent projects 39 | nnoremap pp :action ManageRecentProjects 40 | vnoremap pp :action ManageRecentProjects 41 | 42 | " Replace in path 43 | nnoremap pR :action ReplaceInPath 44 | vnoremap pR :action ReplaceInPath 45 | 46 | " Rerun tests 47 | nnoremap pT :action RerunTests 48 | vnoremap pT :action RerunTests 49 | 50 | " Show local changes (git status) 51 | nnoremap pv :action Vcs.Show.Local.Changes 52 | vnoremap pv :action Vcs.Show.Local.Changes 53 | -------------------------------------------------------------------------------- /modules/dev/jetbrains/configs/ideavim/settings.vim: -------------------------------------------------------------------------------- 1 | """ Settings to behave as similar as possible to spacemacs defaults 2 | 3 | " as the leader key 4 | let mapleader = " " 5 | 6 | " Show current vim mode 7 | set showmode 8 | 9 | " Use the clipboard register '*' for all yank, delete, change and put operations 10 | " which would normally go to the unnamed register. 11 | set clipboard+=unnamed 12 | 13 | " Search as characters are entered 14 | set incsearch 15 | 16 | " Highlight search results 17 | set hlsearch 18 | 19 | " If a pattern contains an uppercase letter, searching is case sensitive, 20 | " otherwise, it is not. 21 | set ignorecase 22 | set smartcase 23 | 24 | " Emulate vim-surround. Commands: ys, cs, ds, S. 25 | set surround 26 | 27 | set history=1000 28 | 29 | set relativenumber 30 | set number 31 | -------------------------------------------------------------------------------- /modules/dev/jetbrains/configs/ideavimrc: -------------------------------------------------------------------------------- 1 | source ~/.config/ideavim/settings.vim 2 | source ~/.config/ideavim/major.vim 3 | -------------------------------------------------------------------------------- /modules/dev/jetbrains/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | options, 4 | inputs, 5 | lib, 6 | pkgs, 7 | my, 8 | ... 9 | }: 10 | with lib; 11 | let 12 | devCfg = config.modules.dev; 13 | cfg = devCfg.jetbrains; 14 | username = config.modules.users.primaryUser.username; 15 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 16 | withImpermanence = config.modules.impermanence.enable; 17 | in 18 | { 19 | options.modules.dev.jetbrains = { 20 | enable = lib.mkEnableOption ""; 21 | }; 22 | 23 | config = mkIf cfg.enable { 24 | environment.systemPackages = with pkgs; [ ]; 25 | 26 | environment.persistence."/persist" = mkIf withImpermanence { 27 | users.${username} = { 28 | directories = [ 29 | ".config/JetBrains" 30 | ".cache/JetBrains" 31 | ".local/share/JetBrains" 32 | ".java/.userPrefs/jetbrains" 33 | ]; 34 | }; 35 | }; 36 | myhm = { 37 | home.packages = with pkgs; [ 38 | # BLOCKED: https://github.com/NixOS/nixpkgs/issues/380196 39 | #jetbrains.idea-ultimate 40 | #jetbrains.datagrip 41 | #jetbrains.gateway 42 | #jetbrains.clion 43 | #dotnet-sdk_7 44 | #dotnet-sdk 45 | #msbuild 46 | #mono 47 | #mono4 48 | #(with dotnetCorePackages; 49 | # combinePackages [ 50 | # sdk_6_0 51 | # sdk_7_0 52 | # ]) 53 | ]; 54 | 55 | home.file.".ideavimrc" = { 56 | source = ./configs/ideavimrc; 57 | }; 58 | xdg.configFile."ideavim" = { 59 | source = ./configs/ideavim; 60 | recursive = true; 61 | }; 62 | }; 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /modules/dev/k8s/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | options, 4 | inputs, 5 | lib, 6 | pkgs, 7 | my, 8 | ... 9 | }: 10 | with lib; 11 | let 12 | devCfg = config.modules.dev; 13 | cfg = devCfg.k8s; 14 | username = config.modules.users.primaryUser.username; 15 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 16 | withImpermanence = config.modules.impermanence.enable; 17 | in 18 | { 19 | options.modules.dev.k8s = { 20 | enable = lib.mkEnableOption ""; 21 | }; 22 | 23 | config = mkIf cfg.enable { 24 | environment.systemPackages = with pkgs; [ ]; 25 | myhm = { 26 | home.packages = with pkgs; [ 27 | influxdb2-cli 28 | k9s 29 | kubernetes-helm 30 | kubectl 31 | kubeconform 32 | krew 33 | kustomize 34 | cilium-cli 35 | talosctl 36 | fluxcd 37 | cloudflared 38 | ]; 39 | 40 | persistence = mkIf withImpermanence { 41 | directories = [ 42 | ".config/k9s" 43 | ".config/kube" 44 | ".config/krew" 45 | ".influxdbv2" 46 | ]; 47 | }; 48 | }; 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /modules/dev/node/configs/npm/npmrc: -------------------------------------------------------------------------------- 1 | prefix=${XDG_DATA_HOME}/npm 2 | cache=${XDG_CACHE_HOME}/npm 3 | init-module=${XDG_CONFIG_HOME}/npm/config/npm-init.js 4 | -------------------------------------------------------------------------------- /modules/dev/node/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | options, 4 | lib, 5 | pkgs, 6 | my, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | devCfg = config.modules.dev; 12 | cfg = devCfg.node; 13 | username = config.modules.users.primaryUser.username; 14 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 15 | withImpermanence = config.modules.impermanence.enable; 16 | in 17 | { 18 | options.modules.dev.node = { 19 | enable = lib.mkEnableOption ""; 20 | }; 21 | 22 | config = mkIf cfg.enable { 23 | environment.systemPackages = with pkgs; [ ]; 24 | 25 | environment.persistence."/persist" = mkIf withImpermanence { 26 | users.${username} = { 27 | directories = [ 28 | ".config/npm" 29 | ".cache/npm-packages" 30 | ".config/yarn/" 31 | ".local/share/npm" 32 | ".local/share/volta" 33 | ]; 34 | }; 35 | }; 36 | home-manager.users."${username}" = { 37 | home.packages = with pkgs; [ 38 | nodejs_20 39 | yarn 40 | #volta 41 | ]; 42 | 43 | #xdg.configFile."npm" = { 44 | # source = ./configs/npm; 45 | # recursive = true; 46 | #}; 47 | }; 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /modules/dev/python.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | options, 4 | lib, 5 | pkgs, 6 | my, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | devCfg = config.modules.dev; 12 | cfg = devCfg.python; 13 | username = config.modules.users.primaryUser.username; 14 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 15 | withImpermanence = config.modules.impermanence.enable; 16 | in 17 | { 18 | options.modules.dev.python = { 19 | enable = lib.mkEnableOption ""; 20 | }; 21 | 22 | config = mkIf cfg.enable { 23 | environment.systemPackages = with pkgs; [ 24 | python3Packages.python-lsp-server 25 | python3Packages.netaddr 26 | (python3.withPackages ( 27 | ps: with ps; [ 28 | pip 29 | pytest 30 | virtualenv 31 | black 32 | isort 33 | setuptools 34 | wheel 35 | requests 36 | netaddr 37 | ] 38 | )) 39 | ]; 40 | home-manager.users."${username}" = { 41 | home.packages = with pkgs; [ pyright ]; 42 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { 43 | directories = [ ".cache/pypoetry/virtualenvs/" ]; 44 | }; 45 | }; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /modules/dev/radicle.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | options, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.dev.radicle; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | #radicle = inputs.radicle.packages.${pkgs.system}.default; 17 | { 18 | options.modules.dev.radicle = { 19 | enable = lib.mkEnableOption ""; 20 | }; 21 | 22 | config = mkIf cfg.enable { 23 | systemd.tmpfiles.rules = mkIf withImpermanence [ 24 | "d '/persist${homeDirectory}/.config/radicle' - ${username} ${username} - -" 25 | ]; 26 | myhm = 27 | { ... }@hm: 28 | { 29 | home.packages = [ radicle ]; 30 | 31 | home.sessionVariables = { 32 | RAD_HOME = "${hm.config.xdg.configHome}/radicle"; 33 | }; 34 | 35 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { 36 | directories = [ ".config/radicle" ]; 37 | }; 38 | 39 | systemd.user.services.radicle-node = { 40 | Unit = { 41 | Description = "radicle-cli node "; 42 | Documentation = "man:rad(1)"; 43 | }; 44 | Install = { 45 | WantedBy = [ "default.target" ]; 46 | }; 47 | Service = { 48 | Type = "simple"; 49 | Environment = [ 50 | "PATH=/run/wrappers/bin:/run/current-system/sw/bin:/etc/profiles/per-user/${username}/bin" 51 | "RAD_HOME=${hm.config.xdg.configHome}/radicle" 52 | "RUST_LOG=debug" 53 | "RUST_BACKTRACE=1" 54 | ]; 55 | Restart = "always"; 56 | RestartSec = "5"; 57 | ExecStart = "${radicle}/bin/rad node start --foreground"; 58 | }; 59 | }; 60 | }; 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /modules/editors/emacs/configs/doom.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | DOOM="$XDG_CONFIG_HOME/emacs" 4 | 5 | if [ ! -d "$DOOM" ]; then 6 | echo "Doom emacs is not installed at $DOOM" 7 | exit 1 8 | else 9 | kitty $DOOM/bin/doom sync 10 | fi 11 | -------------------------------------------------------------------------------- /modules/editors/emacs/configs/icons/doom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/modules/editors/emacs/configs/icons/doom.png -------------------------------------------------------------------------------- /modules/hardware/misc.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | with lib; 8 | let 9 | cfg = config.modules.hardware; 10 | in 11 | { 12 | options = { 13 | modules.hardware = { 14 | fwupd.enable = lib.mkOption { 15 | type = lib.types.bool; 16 | default = true; 17 | }; 18 | udisks2.enable = lib.mkOption { 19 | type = lib.types.bool; 20 | default = true; 21 | }; 22 | enableRedistributableFirmware = lib.mkOption { 23 | type = lib.types.bool; 24 | default = true; 25 | }; 26 | usbModeSwitch.enable = lib.mkEnableOption ""; 27 | }; 28 | }; 29 | config = { 30 | ## MISC HARDWARE RELATED ################################################ 31 | services.fwupd.enable = cfg.fwupd.enable; 32 | services.udisks2.enable = cfg.udisks2.enable; 33 | hardware.enableRedistributableFirmware = cfg.enableRedistributableFirmware; 34 | hardware.usb-modeswitch.enable = cfg.usbModeSwitch.enable; 35 | hardware.cpu.amd.updateMicrocode = pkgs.hostPlatform.system == "x86_64-linux"; 36 | hardware.cpu.intel.updateMicrocode = pkgs.hostPlatform.system == "x86_64-linux"; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /modules/hardware/ryzen.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | with lib; 8 | let 9 | cfg = config.modules.hardware.ryzen; 10 | in 11 | { 12 | options = { 13 | modules.hardware.ryzen = { 14 | enable = lib.mkEnableOption ""; 15 | undervolt = { 16 | enable = lib.mkEnableOption ""; 17 | value = mkOption { 18 | type = types.str; 19 | default = "-p 0 -v 30 -f A8"; # Pstate 0, 1.25 voltage, 4200 clock speed 20 | }; 21 | }; 22 | }; 23 | }; 24 | 25 | config = mkIf cfg.enable { 26 | boot.kernelModules = [ "msr" ]; # Needed for zenstates 27 | hardware.cpu.amd.updateMicrocode = true; 28 | # Ryzen cpu control 29 | systemd.services.zenstates = mkIf cfg.undervolt.enable { 30 | enable = true; 31 | description = "Ryzen Undervolt"; 32 | after = [ 33 | "syslog.target" 34 | "systemd-modules-load.service" 35 | ]; 36 | 37 | unitConfig = { 38 | ConditionPathExists = "${pkgs.zenstates}/bin/zenstates"; 39 | }; 40 | 41 | serviceConfig = { 42 | User = "root"; 43 | ExecStart = "${pkgs.zenstates}/bin/zenstates ${cfg.undervolt.value}"; 44 | }; 45 | 46 | wantedBy = [ "multi-user.target" ]; 47 | }; 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /modules/impermanence/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | ... 4 | }: 5 | { 6 | options.modules.impermanence = { 7 | enable = lib.mkEnableOption ""; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /modules/meta.nix: -------------------------------------------------------------------------------- 1 | { lib, config, ... }: 2 | let 3 | inherit (lib) mkOption types; 4 | in 5 | { 6 | options.node = { 7 | name = mkOption { 8 | description = "A unique name for this node (host) in the repository. Defines the default hostname, but this can be overwritten."; 9 | type = types.str; 10 | }; 11 | secretsDir = mkOption { 12 | description = "Path to the secrets directory for this node."; 13 | type = types.path; 14 | }; 15 | }; 16 | config = { 17 | networking.hostName = config.node.name; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /modules/microvm-guest/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | ... 3 | }: 4 | { 5 | imports = [ 6 | ./options.nix 7 | ./common.nix 8 | ./home-manager.nix 9 | ./quadlet.nix 10 | ]; 11 | } 12 | -------------------------------------------------------------------------------- /modules/microvm-guest/home-manager.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | inputs, 4 | config, 5 | pkgs, 6 | ... 7 | }: 8 | let 9 | cfg = config.modules.microvm-guest; 10 | username = cfg.homeManager.username; 11 | uid = cfg.homeManager.uid; 12 | home = config.users.users.${username}.home; 13 | in 14 | lib.mkIf cfg.homeManager.enable { 15 | microvm.writableStoreOverlay = "/nix/.rw-store"; 16 | nix.settings.allowed-users = [ username ]; 17 | users.users.${username} = { 18 | name = username; 19 | isNormalUser = true; 20 | uid = uid; 21 | group = username; 22 | linger = true; 23 | home = "/home/${username}"; 24 | createHome = true; 25 | autoSubUidGidRange = true; 26 | }; 27 | 28 | users.groups.${username} = { 29 | name = username; 30 | gid = cfg.homeManager.gid; 31 | }; 32 | 33 | systemd.services."home-manager-${username}" = { 34 | serviceConfig.TimeoutStartSec = lib.mkOverride 99 "15m"; 35 | after = [ "network-online.target" ]; 36 | wants = [ "network-online.target" ]; 37 | }; 38 | home-manager.users.${username} = 39 | { pkgs, config, ... }: 40 | { 41 | home.homeDirectory = home; 42 | home.sessionVariables = { 43 | EDITOR = "vim"; 44 | DBUS_SESSION_BUS_ADDRESS = "unix:path=/run/user/${toString uid}/bus"; 45 | XDG_RUNTIME_DIR = "/run/user/${toString uid}"; 46 | }; 47 | 48 | systemd.user.startServices = "sd-switch"; 49 | programs.bash = { 50 | enable = true; 51 | initExtra = '' 52 | [[ -f "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh" ]] && source "${config.home.profileDirectory}/etc/profile.d/hm-session-vars.sh" 53 | ''; 54 | }; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /modules/microvm-guest/quadlet.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | inputs, 4 | config, 5 | pkgs, 6 | ... 7 | }: 8 | let 9 | cfg = config.modules.microvm-guest; 10 | username = cfg.homeManager.username; 11 | in 12 | lib.mkIf cfg.quadlet.enable { 13 | virtualisation.podman = { 14 | enable = true; 15 | autoPrune.enable = true; 16 | autoPrune.dates = "weekly"; 17 | #defaultNetwork.settings.dns_enabled = true; 18 | }; 19 | 20 | # TODO: fix https://github.com/nikstur/userborn/issues/7 21 | environment.etc = 22 | let 23 | autosubs = lib.pipe config.users.users [ 24 | lib.attrValues 25 | (lib.filter (u: u.uid != null && u.isNormalUser)) 26 | (lib.concatMapStrings (u: "${toString u.uid}:${toString (100000 + u.uid * 65536)}:65536\n")) 27 | ]; 28 | in 29 | { 30 | "subuid".text = autosubs; 31 | "subuid".mode = "0444"; 32 | "subgid".text = autosubs; 33 | "subgid".mode = "0444"; 34 | }; 35 | home-manager.users.${username} = 36 | { pkgs, config, ... }: 37 | { 38 | virtualisation.quadlet.autoUpdate.enable = lib.mkDefault true; 39 | home.packages = [ 40 | pkgs.podman 41 | pkgs.nix 42 | pkgs.dive 43 | pkgs.podman-tui 44 | ]; 45 | #xdg.configFile."containers/containers.conf" = { 46 | # text = ''''; 47 | #}; 48 | xdg.configFile."containers/storage.conf" = { 49 | text = '' 50 | [storage] 51 | driver = "overlay" 52 | rootless_storage_path="/var/lib/podman/${username}/containers/storage" 53 | ''; 54 | }; 55 | 56 | xdg.configFile."systemd/user/podman-user-wait-network-online.service.d/override2.conf" = { 57 | text = '' 58 | [Service] 59 | ExecSearchPath=/run/current-system/sw/bin 60 | ''; 61 | }; 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /modules/nix.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs, 3 | config, 4 | lib, 5 | pkgs, 6 | actual-nixpkgs, 7 | ... 8 | }: 9 | with lib; 10 | { 11 | environment.variables.NIXPKGS_ALLOW_UNFREE = "1"; 12 | nix = { 13 | extraOptions = "experimental-features = nix-command flakes"; 14 | settings = { 15 | substituters = [ 16 | "https://cache.nixos.org" 17 | "https://hyprland.cachix.org" 18 | ]; 19 | trusted-public-keys = [ 20 | "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" 21 | "hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc=" 22 | ]; 23 | trusted-users = [ 24 | "root" 25 | "@wheel" 26 | ]; 27 | auto-optimise-store = true; 28 | }; 29 | 30 | gc = { 31 | automatic = true; 32 | dates = "daily"; 33 | options = "--delete-older-than 7d"; 34 | }; 35 | 36 | registry.nixpkgs.flake = actual-nixpkgs; 37 | 38 | nixPath = [ "nixpkgs=/etc/nixpkgs/channels/nixpkgs" ]; 39 | }; 40 | 41 | systemd.tmpfiles.rules = [ "L+ /etc/nixpkgs/channels/nixpkgs - - - - ${actual-nixpkgs}" ]; 42 | 43 | programs.command-not-found.enable = false; 44 | #home-manager.users.huantian.programs.nix-index.enable = true; 45 | 46 | system.configurationRevision = with inputs; mkIf (self ? rev) self.rev; 47 | 48 | # Just the bare necessities... 49 | environment.systemPackages = with pkgs; [ 50 | kitty.terminfo 51 | cached-nix-shell 52 | dig 53 | jq 54 | curlHTTP3 55 | vim 56 | wget 57 | unzip 58 | killall 59 | nvd 60 | lsof 61 | 62 | # These are used by the flake tooling 63 | git 64 | git-crypt 65 | sops 66 | gnupg 67 | ]; 68 | system = { 69 | # Enable printing changes on nix build etc with nvd 70 | activationScripts.report-changes = '' 71 | PATH=$PATH:${ 72 | lib.makeBinPath [ 73 | pkgs.nvd 74 | pkgs.nix 75 | ] 76 | } 77 | nvd diff $(ls -dv /nix/var/nix/profiles/system-*-link | tail -2) || true 78 | ''; 79 | }; 80 | 81 | documentation.nixos.enable = false; 82 | } 83 | -------------------------------------------------------------------------------- /modules/security/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.security.default; 12 | in 13 | { 14 | options = { 15 | modules.security.default = { 16 | enable = lib.mkOption { 17 | type = types.bool; 18 | default = true; 19 | }; 20 | }; 21 | }; 22 | 23 | config = mkIf cfg.enable { 24 | systemd.extraConfig = "DefaultLimitNOFILE=1048576"; 25 | security = { 26 | sudo.enable = true; 27 | sudo.wheelNeedsPassword = false; 28 | sudo.extraRules = 29 | let 30 | # systemPath is the path where the system being activated is uploaded by `deploy`. 31 | systemPath = "/nix/store/*-activatable-nixos-system-${config.networking.hostName}-*"; 32 | nopasswd = command: { 33 | inherit command; 34 | options = [ 35 | "NOPASSWD" 36 | "SETENV" 37 | ]; 38 | }; 39 | in 40 | [ 41 | { 42 | groups = [ "wheel" ]; 43 | runAs = "root"; 44 | commands = [ (nopasswd "/run/current-system/sw/bin/systemctl reboot") ]; 45 | } 46 | ]; 47 | please.enable = true; 48 | please.wheelNeedsPassword = false; 49 | #pam.loginLimits = [ 50 | # { 51 | # domain = "*"; 52 | # type = "soft"; 53 | # item = "nofile"; 54 | # value = "1048576"; 55 | # } 56 | #]; 57 | }; 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /modules/services/attic-watch-store.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | let 10 | cfg = config.modules.services.attic-watch-store; 11 | username = config.modules.users.primaryUser.username; 12 | in 13 | { 14 | options.modules.services.attic-watch-store = { 15 | enable = lib.mkEnableOption "attic-watch-store"; 16 | }; 17 | config = lib.mkIf cfg.enable { 18 | environment.systemPackages = [ pkgs.attic-client ]; 19 | systemd.services.attic-watch-store = { 20 | enable = true; 21 | wantedBy = [ "multi-user.target" ]; 22 | description = "attic-watch-store"; 23 | serviceConfig = { 24 | User = username; 25 | ExecStart = "${pkgs.attic-client}/bin/attic watch-store socozy"; 26 | Restart = "always"; 27 | RestartSec = 30; 28 | }; 29 | }; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /modules/services/atuin-sync.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | let 10 | cfg = config.modules.services.atuin-sync; 11 | home-ops = config.repo.secrets.home-ops; 12 | httpPort = toString cfg.ports.http; 13 | stateDirActual = "/var/lib/private/actual-budget"; 14 | stateDirEffective = "/var/lib/actual-budget"; 15 | cfgFile = pkgs.writeText "actual.json" ( 16 | builtins.toJSON { 17 | dataDir = stateDirEffective; 18 | hostname = "127.0.0.1"; 19 | port = cfg.ports.http; 20 | serverFiles = "${stateDirEffective}/server"; 21 | userFiles = "${stateDirEffective}/user"; 22 | loginMethod = "password"; 23 | trustedProxies = [ "127.0.0.1/24" ]; 24 | } 25 | ); 26 | in 27 | { 28 | options.modules.services.atuin-sync = { 29 | enable = lib.mkEnableOption "atuin-sync"; 30 | domain = lib.mkOption { 31 | type = lib.types.str; 32 | example = "atuin.example.com"; 33 | description = "The domain to use for the atuin-sync"; 34 | }; 35 | ports = { 36 | http = lib.mkOption { 37 | type = lib.types.port; 38 | description = "The HTTP port to use for the atuin-sync"; 39 | }; 40 | }; 41 | ingress = lib.mkOption { 42 | type = lib.types.submodule ( 43 | lib.recursiveUpdate (import ./ingress-options.nix { inherit config lib; }) { } 44 | ); 45 | }; 46 | }; 47 | 48 | config = lib.mkIf cfg.enable { 49 | services.atuin = { 50 | enable = true; 51 | openRegistration = false; 52 | port = cfg.ports.http; 53 | }; 54 | modules.services.ingress.domains = lib.mkIf cfg.ingress.external { 55 | "${cfg.ingress.domain}" = { 56 | externalDomains = [ cfg.domain ]; 57 | }; 58 | }; 59 | modules.services.ingress.virtualHosts.${cfg.domain} = { 60 | acmeHost = cfg.ingress.domain; 61 | upstream = "http://127.0.0.1:${toString cfg.ports.http}"; 62 | forwardAuth = false; 63 | }; 64 | }; 65 | } 66 | -------------------------------------------------------------------------------- /modules/services/audiobookshelf.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | utils, 6 | pkgs, 7 | inputs, 8 | globals, 9 | ... 10 | }: 11 | let 12 | cfg = config.modules.services.audiobookshelf; 13 | home-ops = config.repo.secrets.home-ops; 14 | localPath = "/mnt/mali/${cfg.nfsShare}"; 15 | serviceDeps = [ "${utils.escapeSystemdPath localPath}.mount" ]; 16 | in 17 | { 18 | options.modules.services.audiobookshelf = { 19 | enable = lib.mkEnableOption "audiobookshelf"; 20 | domain = lib.mkOption { 21 | type = lib.types.str; 22 | example = "audiobookshelf.example.com"; 23 | description = "The domain to use for the audiobookshelf"; 24 | }; 25 | ingress = lib.mkOption { 26 | type = lib.types.submodule ( 27 | lib.recursiveUpdate (import ./ingress-options.nix { inherit config lib; }) { } 28 | ); 29 | }; 30 | nfsShare = lib.mkOption { type = lib.types.str; }; 31 | user = lib.mkOption { type = lib.types.unspecified; }; 32 | group = lib.mkOption { type = lib.types.unspecified; }; 33 | }; 34 | config = lib.mkIf cfg.enable { 35 | users.users.${cfg.user.name} = { 36 | name = cfg.user.name; 37 | uid = lib.mkForce cfg.user.uid; 38 | isSystemUser = true; 39 | group = lib.mkForce cfg.group.name; 40 | extraGroups = [ "media" ]; 41 | }; 42 | 43 | users.groups.${cfg.group.name} = { 44 | name = cfg.group.name; 45 | gid = lib.mkForce cfg.group.gid; 46 | }; 47 | 48 | fileSystems."${localPath}" = { 49 | device = "${lib.my.cidrToIp config.repo.secrets.global.nodes.mali.dataCIDR}:/mnt/${cfg.nfsShare}"; 50 | fsType = "nfs"; 51 | }; 52 | 53 | modules.zfs.datasets.properties = { 54 | "tank/encrypted/svc/audiobookshelf"."mountpoint" = config.services.audiobookshelf.dataDir; 55 | "tank/encrypted/svc/audiobookshelf"."com.sun:auto-snapshot" = "false"; 56 | }; 57 | 58 | services.audiobookshelf = { 59 | enable = true; 60 | openFirewall = false; 61 | user = cfg.user.name; 62 | group = cfg.group.name; 63 | }; 64 | }; 65 | } 66 | -------------------------------------------------------------------------------- /modules/services/docker.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.services.docker; 12 | withImpermanence = config.modules.impermanence.enable; 13 | in 14 | { 15 | options.modules.services.docker = { 16 | enable = lib.mkEnableOption ""; 17 | enableOnBoot = lib.mkOption { 18 | type = lib.types.bool; 19 | default = true; 20 | }; 21 | }; 22 | config = mkIf cfg.enable { 23 | environment.persistence."/persist" = { 24 | directories = [ "/var/lib/docker" ]; 25 | }; 26 | virtualisation.docker = { 27 | enable = true; 28 | enableOnBoot = cfg.enableOnBoot; 29 | }; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /modules/services/echo-server.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | let 10 | cfg = config.modules.services.echo-server; 11 | 12 | httpPort = toString cfg.ports.http; 13 | in 14 | { 15 | options.modules.services.echo-server = { 16 | enable = lib.mkEnableOption "echo-server"; 17 | domain = lib.mkOption { 18 | type = lib.types.str; 19 | example = "echo-test.example.com"; 20 | description = "The domain to use for the echo-server"; 21 | }; 22 | ports = { 23 | http = lib.mkOption { 24 | type = lib.types.port; 25 | default = 9992; 26 | description = "The HTTP port to use for the echo-server"; 27 | }; 28 | }; 29 | 30 | ingress = lib.mkOption { 31 | type = lib.types.submodule ( 32 | lib.recursiveUpdate (import ./ingress-options.nix { inherit config lib; }) { } 33 | ); 34 | }; 35 | }; 36 | config = lib.mkIf cfg.enable { 37 | modules.services.ingress.domains = lib.mkIf cfg.ingress.external { 38 | "${cfg.ingress.domain}" = { 39 | externalDomains = [ cfg.domain ]; 40 | }; 41 | }; 42 | 43 | virtualisation.oci-containers.containers.echo-server = { 44 | # renovate: docker-image 45 | image = "docker.io/mendhak/http-https-echo:31"; 46 | autoStart = true; 47 | ports = [ "127.0.0.1:${httpPort}:8080" ]; 48 | }; 49 | 50 | modules.services.ingress.virtualHosts.${cfg.domain} = { 51 | acmeHost = cfg.ingress.domain; 52 | upstream = "http://127.0.0.1:${httpPort}"; 53 | extraConfig = '' 54 | client_max_body_size 0; 55 | ''; 56 | }; 57 | }; 58 | } 59 | -------------------------------------------------------------------------------- /modules/services/flatpak.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.services.flatpak; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.services.flatpak = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | services.flatpak.enable = true; 22 | environment.persistence."/persist" = mkIf withImpermanence { 23 | directories = [ "/var/lib/flatpak" ]; 24 | users.${username} = { 25 | directories = [ 26 | ".cache/flatpak" 27 | ".local/share/flatpak" 28 | ".var/app" 29 | ]; 30 | }; 31 | }; 32 | # Workaround for https://github.com/NixOS/nixpkgs/issues/119433#issuecomment-1694123978 33 | system.fsPackages = [ pkgs.bindfs ]; 34 | fileSystems = 35 | let 36 | mkRoSymBind = path: { 37 | device = path; 38 | fsType = "fuse.bindfs"; 39 | options = [ 40 | "ro" 41 | "resolve-symlinks" 42 | "x-gvfs-hide" 43 | ]; 44 | }; 45 | aggregatedIcons = pkgs.buildEnv { 46 | name = "system-icons"; 47 | paths = with pkgs; [ 48 | libsForQt5.breeze-qt5 # for plasma 49 | gnome-themes-extra 50 | ]; 51 | pathsToLink = [ "/share/icons" ]; 52 | }; 53 | aggregatedFonts = pkgs.buildEnv { 54 | name = "system-fonts"; 55 | paths = config.fonts.packages; 56 | pathsToLink = [ "/share/fonts" ]; 57 | }; 58 | in 59 | { 60 | "/usr/share/icons" = mkRoSymBind "${aggregatedIcons}/share/icons"; 61 | "/usr/local/share/fonts" = mkRoSymBind "${aggregatedFonts}/share/fonts"; 62 | }; 63 | systemd.user.services.flatpak-auto-update = { 64 | enable = true; 65 | serviceConfig = { 66 | Type = "oneshot"; 67 | ExecStart = "${pkgs.flatpak}/bin/flatpak --user update --noninteractive --assumeye"; 68 | }; 69 | }; 70 | 71 | systemd.user.timers.flatpak-auto-update = { 72 | enable = true; 73 | description = "Enable automatic flatpak updates"; 74 | timerConfig = { 75 | OnCalendar = "daily"; 76 | Persistent = "true"; 77 | }; 78 | }; 79 | }; 80 | } 81 | -------------------------------------------------------------------------------- /modules/services/github-runner.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.services.github-runner; 12 | withImpermanence = config.modules.impermanence.enable; 13 | in 14 | { 15 | options.modules.services.github-runner = { 16 | enable = lib.mkEnableOption ""; 17 | runnerName = lib.mkOption { 18 | type = lib.types.uniq lib.types.str; 19 | default = "my-runner"; 20 | }; 21 | url = lib.mkOption { 22 | type = lib.types.uniq lib.types.str; 23 | default = ""; 24 | }; 25 | extraLabels = mkOption { 26 | type = types.listOf types.str; 27 | default = [ ]; 28 | }; 29 | }; 30 | config = mkIf cfg.enable { 31 | sops.secrets."github-runner.token" = { }; 32 | services.github-runners."${cfg.runnerName}" = { 33 | enable = true; 34 | replace = true; 35 | name = cfg.runnerName; 36 | nodeRuntimes = [ "node20" ]; 37 | extraPackages = with pkgs; [ 38 | gh 39 | docker 40 | gawk 41 | nix 42 | ]; 43 | url = cfg.url; 44 | tokenFile = "/run/secrets/github-runner.token"; 45 | extraLabels = cfg.extraLabels; 46 | serviceOverrides = { 47 | Group = "docker"; 48 | }; 49 | }; 50 | #environment.persistence."/persist" = { 51 | # directories = [ 52 | # ]; 53 | #}; 54 | }; 55 | } 56 | -------------------------------------------------------------------------------- /modules/services/haproxy.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | with lib; 8 | let 9 | cfg = config.modules.server.haproxy; 10 | 11 | sniBackends = map (backend: '' 12 | backend ${backend.upstreamName} 13 | mode tcp 14 | server ${backend.upstreamName} ${backend.upstreamHost}:${toString backend.upstreamPort} 15 | '') cfg.sniBackends; 16 | 17 | sniBackendsStr = concatStringsSep "\n " sniBackends; 18 | 19 | sniDomainsPerBackend = map ( 20 | backend: 21 | map (domain: '' 22 | use_backend ${backend.upstreamName} if { req.ssl_sni -i ${domain} } 23 | '') backend.sniDomains 24 | ) cfg.sniBackends; 25 | sniDomainsPerBackendStr = concatMapStringsSep "\n " ( 26 | x: concatStringsSep "\n " x 27 | ) sniDomainsPerBackend; 28 | in 29 | { 30 | 31 | options.modules.server.haproxy = { 32 | enable = mkEnableOption "haproxy service"; 33 | defaultBackend = mkOption { type = types.str; }; 34 | sniBackends = mkOption { 35 | type = types.listOf ( 36 | types.submodule { 37 | options = { 38 | upstreamName = mkOption { type = types.str; }; 39 | upstreamHost = mkOption { type = types.str; }; 40 | upstreamPort = mkOption { type = types.int; }; 41 | sniDomains = mkOption { type = types.listOf types.str; }; 42 | }; 43 | } 44 | ); 45 | }; 46 | }; 47 | config = mkIf cfg.enable { 48 | services.haproxy = { 49 | enable = true; 50 | config = '' 51 | global 52 | maxconn 4096 53 | user haproxy 54 | group haproxy 55 | daemon 56 | log /dev/log local0 debug 57 | 58 | defaults 59 | log global 60 | mode tcp 61 | option tcplog 62 | option dontlognull 63 | timeout connect 10s 64 | timeout client 1m 65 | timeout server 1m 66 | 67 | frontend tls_sni_frontend 68 | bind *:443 69 | tcp-request inspect-delay 5s 70 | tcp-request content accept if { req.ssl_hello_type 1 } 71 | log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq SNI:%[ssl_fc_sni]" 72 | log global 73 | default_backend ${cfg.defaultBackend} 74 | 75 | ${sniDomainsPerBackendStr} 76 | ${sniBackendsStr} 77 | 78 | ''; 79 | }; 80 | }; 81 | } 82 | -------------------------------------------------------------------------------- /modules/services/ingress-options.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | 3 | { 4 | options = { 5 | external = lib.mkOption { 6 | type = lib.types.bool; 7 | default = false; 8 | description = "Whether to expose the service externally"; 9 | }; 10 | domain = lib.mkOption { 11 | type = lib.types.str; 12 | example = "example.com"; 13 | description = "The ingress domain to use"; 14 | }; 15 | forwardAuth = lib.mkOption { 16 | type = lib.types.bool; 17 | default = true; 18 | description = "Whether to use forward authentication"; 19 | }; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /modules/services/mariadb.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.modules.services.mariadb; 10 | mysqlUser = config.services.mysql.user; 11 | 12 | serviceDeps = [ 13 | "var-lib-mysql.mount" 14 | "zfs-datasets.service" 15 | ]; 16 | in 17 | { 18 | options.modules.services.mariadb = { 19 | enable = lib.mkEnableOption "mariadb"; 20 | package = lib.mkOption { 21 | type = lib.types.package; 22 | }; 23 | }; 24 | 25 | config = lib.mkIf cfg.enable { 26 | 27 | services.mysql = { 28 | enable = true; 29 | package = cfg.package; 30 | dataDir = "/var/lib/mysql/data"; 31 | settings = { 32 | mysqld = { 33 | skip-innodb_doublewrite = true; 34 | innodb_flush_method = "fsync"; 35 | innodb_doublewrite = 0; 36 | innodb_use_atomic_writes = 0; 37 | innodb_use_native_aio = 0; 38 | innodb_read_io_threads = 10; 39 | innodb_write_io_threads = 10; 40 | innodb_buffer_pool_size = "4G"; 41 | innodb_flush_log_at_trx_commit = 1; 42 | innodb_log_file_size = "1G"; 43 | innodb_flush_neighbors = 0; 44 | innodb_fast_shutdown = 2; 45 | }; 46 | }; 47 | }; 48 | 49 | systemd.services.mysql.requires = serviceDeps; 50 | systemd.services.mysql.wants = serviceDeps; 51 | 52 | # services.mysqlBackup = { 53 | # enable = true; 54 | # location = "/var/backup/mysql"; 55 | # calendar = "11:00:00"; 56 | # singleTransaction = true; 57 | # }; 58 | 59 | modules.zfs.datasets.properties = { 60 | "rpool/encrypted/safe/svc/mariadb"."mountpoint" = "/var/lib/mysql"; 61 | "rpool/encrypted/safe/svc/mariadb"."com.sun:auto-snapshot" = "false"; 62 | "rpool/encrypted/safe/svc/mariadb"."recordsize" = "16k"; 63 | "rpool/encrypted/safe/svc/mariadb"."primarycache" = "all"; 64 | "rpool/encrypted/safe/svc/mariadb"."logbias" = "throughput"; 65 | }; 66 | systemd.tmpfiles.rules = [ "z /var/lib/mysql 750 ${mysqlUser} ${mysqlUser}" ]; 67 | }; 68 | } 69 | -------------------------------------------------------------------------------- /modules/services/matrix-irc.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | let 8 | cfg = config.modules.services.matrix-synapse.bridges.irc; 9 | rootCfg = config.modules.services.matrix-synapse; 10 | dataDir = "${rootCfg.dataDir}/mautrix-irc"; 11 | in 12 | { 13 | options.modules.services.matrix-synapse.bridges.irc = { 14 | enable = lib.mkEnableOption "heisenbridge for personal irc matrix bridging"; 15 | }; 16 | config = lib.mkIf cfg.enable { 17 | services.heisenbridge = { 18 | enable = true; 19 | homeserver = "https://${config.modules.services.matrix-synapse.domain}"; 20 | }; 21 | 22 | systemd.services.heisenbridge = { 23 | before = [ "matrix-synapse.service" ]; 24 | wantedBy = [ "multi-user.target" ]; 25 | serviceConfig = { 26 | Restart = "on-failure"; 27 | }; 28 | unitConfig = { 29 | StartLimitBurst = 3; 30 | StartLimitIntervalSec = "30s"; 31 | }; 32 | }; 33 | # TODO: Make work in cases where this isn't on the same machine. 34 | services.matrix-synapse.settings.app_service_config_files = [ 35 | "/var/lib/heisenbridge/registration.yml" 36 | ]; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /modules/services/podman.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.services.podman; 12 | withImpermanence = config.modules.impermanence.enable; 13 | in 14 | { 15 | options.modules.services.podman = { 16 | enable = lib.mkEnableOption ""; 17 | }; 18 | config = mkIf cfg.enable { 19 | environment.persistence."/persist" = { 20 | directories = [ "/var/lib/containers" ]; 21 | }; 22 | virtualisation.podman = { 23 | enable = true; 24 | autoPrune.enable = true; 25 | autoPrune.dates = "weekly"; 26 | defaultNetwork.settings.dns_enabled = true; 27 | extraPackages = [ pkgs.zfs ]; 28 | }; 29 | 30 | systemd.services.podman-auto-update = { 31 | wants = [ "network-online.target" ]; 32 | after = [ "network-online.target" ]; 33 | serviceConfig = { 34 | Type = "oneshot"; 35 | ExecStart = "${pkgs.podman}/bin/podman auto-update"; 36 | ExecStartPost = "${pkgs.podman}/bin/podman image prune -f"; 37 | }; 38 | }; 39 | 40 | systemd.timers.podman-auto-update = { 41 | wantedBy = [ "timers.target" ]; 42 | timerConfig = { 43 | OnCalendar = "03:30"; 44 | Persistent = true; 45 | }; 46 | }; 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /modules/services/printing.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.services.printing; 12 | in 13 | { 14 | options.modules.services.printing = { 15 | enable = lib.mkEnableOption ""; 16 | drivers = mkOption { 17 | type = types.listOf types.package; 18 | default = [ ]; 19 | }; 20 | }; 21 | config = mkIf cfg.enable { 22 | services.printing.enable = true; 23 | services.printing.drivers = cfg.drivers; 24 | services.avahi.enable = mkDefault true; 25 | services.avahi.nssmdns4 = mkDefault true; 26 | # for a WiFi printer 27 | services.avahi.openFirewall = mkDefault true; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /modules/services/soju.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | let 10 | cfg = config.modules.services.soju; 11 | home-ops = config.repo.secrets.home-ops; 12 | ircPort = toString cfg.ports.irc; 13 | stateDirActual = "/var/lib/private/soju"; 14 | stateDirEffective = "/var/lib/soju"; 15 | in 16 | { 17 | options.modules.services.soju = { 18 | enable = lib.mkEnableOption "soju"; 19 | domain = lib.mkOption { 20 | type = lib.types.str; 21 | example = "soju.example.com"; 22 | description = "The domain to use for soju"; 23 | }; 24 | ports = { 25 | irc = lib.mkOption { 26 | type = lib.types.port; 27 | description = "The irc port to use for soju"; 28 | }; 29 | }; 30 | #ingress = lib.mkOption { 31 | # type = lib.types.submodule ( 32 | # lib.recursiveUpdate (import ./ingress-options.nix { inherit config lib; }) { } 33 | # ); 34 | #}; 35 | }; 36 | 37 | config = lib.mkIf cfg.enable { 38 | modules.zfs.datasets.properties = { 39 | "rpool/encrypted/safe/svc/soju"."mountpoint" = stateDirActual; 40 | }; 41 | #modules.services.ingress.domains = lib.mkIf cfg.ingress.external { 42 | # "${cfg.ingress.domain}" = { 43 | # externalDomains = [ cfg.domain ]; 44 | # }; 45 | #}; 46 | #modules.services.ingress.virtualHosts.${cfg.domain} = { 47 | # acmeHost = cfg.ingress.domain; 48 | # upstream = "http://127.0.0.1:${httpPort}"; 49 | # forwardAuth = false; 50 | #}; 51 | services.soju = { 52 | enable = true; 53 | hostName = cfg.domain; 54 | listen = [ "irc+insecure://:${ircPort}" ]; 55 | }; 56 | networking.firewall.allowedTCPPorts = [ ircPort ]; 57 | }; 58 | } 59 | -------------------------------------------------------------------------------- /modules/services/sshd.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.services.sshd; 12 | withImpermanence = config.modules.impermanence.enable; 13 | in 14 | { 15 | options.modules.services.sshd = { 16 | enable = lib.mkOption { 17 | type = lib.types.bool; 18 | default = true; 19 | }; 20 | }; 21 | config = mkIf cfg.enable { 22 | # Should exist already as it is used for sops bootstrapping 23 | # sops.secrets.ssh_host_ed25519_key = { 24 | # path = "/persist/etc/ssh/ssh_host_ed25519_key"; 25 | # }; 26 | 27 | sops.secrets.ssh_host_ed25519_key_pub = { 28 | path = "${lib.optionalString withImpermanence "/persist"}/etc/ssh/ssh_host_ed25519_key.pub"; 29 | }; 30 | networking.firewall.allowedTCPPorts = [ 22 ]; 31 | 32 | services.openssh = { 33 | enable = true; 34 | authorizedKeysFiles = lib.mkForce [ "/etc/ssh/authorized_keys.d/%u" ]; 35 | settings = { 36 | AcceptEnv = "SYSTEMD_PAGER"; 37 | LoginGraceTime = 30; 38 | PermitRootLogin = lib.mkOverride 900 "prohibit-password"; 39 | PasswordAuthentication = false; 40 | KbdInteractiveAuthentication = false; 41 | StreamLocalBindUnlink = true; 42 | }; 43 | hostKeys = [ 44 | { 45 | path = "${lib.optionalString withImpermanence "/persist"}/etc/ssh/ssh_host_ed25519_key"; 46 | type = "ed25519"; 47 | } 48 | ]; 49 | }; 50 | 51 | environment.persistence."/persist" = mkIf withImpermanence { 52 | files = [ "${config.users.users.root.home}/.ssh/known_hosts" ]; 53 | }; 54 | }; 55 | } 56 | -------------------------------------------------------------------------------- /modules/shell/aria2.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.shell.aria2; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.shell.aria2 = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | home-manager.users."${username}" = { 22 | programs.aria2 = { 23 | enable = true; 24 | settings = { 25 | listen-port = "6881-6999"; 26 | dht-listen-port = "6881-6999"; 27 | }; 28 | }; 29 | }; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /modules/shell/attic.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.shell.attic; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.shell.attic = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | environment.systemPackages = [ pkgs.attic-client ]; 22 | systemd.tmpfiles.rules = mkIf withImpermanence [ 23 | "d /persist${homeDirectory}/.config/attic 700 ${username} ${username}" 24 | "d /persist${homeDirectory}/.local/share/attic 700 ${username} ${username}" 25 | ]; 26 | home-manager.users."${username}" = 27 | { pkgs, config, ... }@hm: 28 | { 29 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { 30 | directories = [ 31 | ".config/attic" 32 | ".local/share/attic" 33 | ]; 34 | }; 35 | }; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /modules/shell/atuin.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.shell.atuin; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.shell.atuin = { 18 | enable = lib.mkEnableOption ""; 19 | sync.enable = lib.mkEnableOption ""; 20 | sync.address = lib.mkOption { 21 | type = lib.types.uniq lib.types.str; 22 | default = "https://atuin.socozy.casa"; 23 | }; 24 | }; 25 | config = lib.mkIf cfg.enable { 26 | 27 | myhm = 28 | { pkgs, config, ... }@hm: 29 | { 30 | programs.atuin = { 31 | enable = true; 32 | enableBashIntegration = true; 33 | daemon.enable = true; 34 | settings = 35 | { 36 | style = "compact"; 37 | update_check = false; 38 | } 39 | // lib.optionalAttrs cfg.sync.enable { 40 | sync_address = cfg.sync.address; 41 | auto_sync = false; 42 | }; 43 | }; 44 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { 45 | directories = [ ".config/atuin" ]; 46 | }; 47 | home.file = mkIf withImpermanence { 48 | ".local/share/atuin".source = config.lib.file.mkOutOfStoreSymlink "/persist/extra/atuin"; 49 | }; 50 | 51 | systemd.user.timers.atuin-sync = lib.mkIf cfg.sync.enable { 52 | Unit.Description = "Atuin auto sync"; 53 | Timer.OnUnitActiveSec = "1h"; 54 | Install.WantedBy = [ "timers.target" ]; 55 | }; 56 | 57 | systemd.user.services.atuin-sync = lib.mkIf cfg.sync.enable { 58 | Unit.Description = "Atuin auto sync"; 59 | 60 | Service = { 61 | Type = "oneshot"; 62 | ExecStart = "${pkgs.atuin}/bin/atuin sync"; 63 | IOSchedulingClass = "idle"; 64 | }; 65 | }; 66 | }; 67 | }; 68 | } 69 | -------------------------------------------------------------------------------- /modules/shell/direnv.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.shell.direnv; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.shell.direnv = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | programs.direnv = { 22 | enable = true; 23 | package = pkgs.direnv; 24 | }; 25 | # Nix options for derivations to persist garbage collection 26 | nix.extraOptions = '' 27 | keep-outputs = true 28 | keep-derivations = true 29 | ''; 30 | environment.pathsToLink = [ "/share/nix-direnv" ]; 31 | 32 | myhm = { 33 | persistence = mkIf withImpermanence { directories = [ ".local/share/direnv" ]; }; 34 | }; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /modules/shell/ffsend.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | ... 7 | }: 8 | let 9 | cfg = config.modules.shell.ffsend; 10 | username = config.modules.users.primaryUser.username; 11 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 12 | withImpermanence = config.modules.impermanence.enable; 13 | in 14 | { 15 | options.modules.shell.ffsend = { 16 | enable = lib.mkEnableOption ""; 17 | }; 18 | config = lib.mkIf cfg.enable { 19 | environment.persistence."/persist" = lib.mkIf withImpermanence { 20 | users.${username} = { 21 | directories = [ 22 | ".cache/ffsend" 23 | ]; 24 | }; 25 | }; 26 | systemd.tmpfiles.rules = lib.mkIf withImpermanence [ 27 | "d '/persist${homeDirectory}/.cache/ffsend' - ${username} ${username} - -" 28 | ]; 29 | home-manager.users."${username}" = { 30 | home.packages = [ pkgs.ffsend ]; 31 | }; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /modules/shell/gpg-agent.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.shell.gpg-agent; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.shell.gpg-agent = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | services.pcscd.enable = true; 22 | myhm = 23 | { ... }@hm: 24 | { 25 | services.gpg-agent = { 26 | enable = true; 27 | enableSshSupport = true; 28 | enableZshIntegration = true; 29 | defaultCacheTtl = 60; 30 | maxCacheTtl = 120; 31 | enableExtraSocket = true; 32 | enableBashIntegration = true; 33 | pinentryPackage = pkgs.pinentry-qt; 34 | sshKeys = [ "978C4D08058BA26EB97CB51820782DBCACFAACDA" ]; 35 | }; 36 | programs.gpg = { 37 | enable = true; 38 | homedir = "${hm.config.xdg.configHome}/.gnupg"; 39 | publicKeys = [ 40 | { 41 | source = ../../configs/casey-pub.asc; 42 | trust = "ultimate"; 43 | } 44 | ]; 45 | scdaemonSettings = { 46 | disable-ccid = true; 47 | card-timeout = "2"; 48 | pcsc-shared = true; 49 | debug-level = "basic"; 50 | log-file = "${hm.config.home.homeDirectory}/.cache/scdaemon.log"; 51 | }; 52 | }; 53 | 54 | persistence = mkIf withImpermanence { directories = [ "${hm.config.xdg.configHome}/.gnupg" ]; }; 55 | }; 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /modules/shell/htop/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.shell.htop; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.shell.htop = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | home-manager.users."${username}" = { 22 | xdg.configFile."btop/themes/gruvbox_dark_v2.theme".source = ./configs/btop/gruvbox_dark_v2.theme; 23 | programs.btop = { 24 | enable = true; 25 | settings = { 26 | color_theme = "gruvbox_dark_v2"; 27 | theme_background = true; 28 | rounded_corners = true; 29 | vim_keys = true; 30 | }; 31 | }; 32 | programs.htop = { 33 | enable = true; 34 | settings = { 35 | hide_kernel_threads = 1; 36 | hide_userland_threads = 1; 37 | }; 38 | }; 39 | }; 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /modules/shell/mpv.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.shell.mpv; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.shell.mpv = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | home-manager.users."${username}" = { 22 | programs.mpv = { 23 | enable = true; 24 | config = { 25 | #hwdec = "auto-safe"; 26 | #vo = "gpu"; 27 | #profile = "gpu-hq"; 28 | }; 29 | scripts = [ 30 | pkgs.mpvScripts.uosc 31 | # pkgs.mpvScripts.cutter 32 | pkgs.mpvScripts.memo 33 | pkgs.mpvScripts.sponsorblock 34 | pkgs.mpvScripts.quality-menu 35 | ]; 36 | }; 37 | }; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /modules/shell/ssh/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.shell.ssh; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.shell.ssh = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | 22 | environment.persistence."/persist" = mkIf withImpermanence { 23 | users.${username} = { 24 | directories = [ ".ssh" ]; 25 | }; 26 | }; 27 | home-manager.users."${username}" = { 28 | # note using home-manager programs.ssh because of 29 | # https://github.com/nix-community/home-manager/issues/322 30 | home.file.".ssh/control/.keep".text = ""; 31 | }; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /modules/shell/tmux.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.shell.tmux; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.shell.tmux = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | home-manager.users."${username}" = { 22 | programs.tmux = { 23 | enable = true; 24 | historyLimit = 100000; 25 | resizeAmount = 5; 26 | escapeTime = 0; 27 | baseIndex = 1; # Widows numbers begin with 1 28 | keyMode = "vi"; 29 | newSession = true; 30 | extraConfig = '' 31 | 32 | set -g default-terminal "tmux-256color" 33 | # use s for horizontal split 34 | bind s split-window -v 35 | # use v for vertical split 36 | bind v split-window -h 37 | unbind '"' 38 | unbind % 39 | 40 | # navigate pans like vim 41 | bind h select-pane -L 42 | bind j select-pane -D 43 | bind k select-pane -U 44 | bind l select-pane -R 45 | 46 | # switch panes using Alt-arrow without prefix 47 | bind -n M-Left select-pane -L 48 | bind -n M-Right select-pane -R 49 | bind -n M-Up select-pane -U 50 | bind -n M-Down select-pane -D 51 | 52 | # resize panes more easily 53 | bind < resize-pane -L 10 54 | bind > resize-pane -R 10 55 | bind - resize-pane -D 10 56 | bind + resize-pane -U 10 57 | 58 | # window separators 59 | set-option -wg window-status-separator "" 60 | 61 | # monitor window changes 62 | set-option -wg monitor-activity on 63 | set-option -wg monitor-bell on 64 | 65 | # set statusbar update interval 66 | set-option -g status-interval 1 67 | ''; 68 | }; 69 | }; 70 | }; 71 | } 72 | -------------------------------------------------------------------------------- /modules/shell/zoxide.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.shell.zoxide; 12 | username = config.modules.users.primaryUser.username; 13 | homeDirectory = config.modules.users.primaryUser.homeDirectory; 14 | withImpermanence = config.modules.impermanence.enable; 15 | in 16 | { 17 | options.modules.shell.zoxide = { 18 | enable = lib.mkEnableOption ""; 19 | }; 20 | config = mkIf cfg.enable { 21 | home-manager.users."${username}" = { 22 | programs.zoxide = { 23 | enable = true; 24 | }; 25 | home.persistence."/persist${homeDirectory}" = mkIf withImpermanence { 26 | directories = [ ".local/share/zoxide" ]; 27 | }; 28 | }; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /modules/shell/zsh/configs/autocompletion.zsh: -------------------------------------------------------------------------------- 1 | # ██ 2 | # ░██ 3 | # ██████ ██████░██ 4 | # ░░░░██ ██░░░░ ░██████ 5 | # ██ ░░█████ ░██░░░██ 6 | # ██ ░░░░░██░██ ░██ 7 | # ██████ ██████ ░██ ░██ 8 | # ░░░░░░ ░░░░░░ ░░ ░░ 9 | # 10 | # ▓▓▓▓▓▓▓▓▓▓ 11 | # ░▓ author ▓ casey 12 | # ░▓ code ▓ https://code.caseylink.com 13 | # ░▓ thanks ▓ https://github.com/xero 14 | # ░▓▓▓▓▓▓▓▓▓▓ 15 | # ░░░░░░░░░░ 16 | # 17 | #█▓▒░ autocompletion systems 18 | autoload -Uz compinit 19 | compinit 20 | if [[ -d "$ZDOTDIR/completion" ]]; then 21 | autoload -U $ZDOTDIR/completion/*(:t) 22 | fi 23 | 24 | # +---------+ 25 | # | Options | 26 | # +---------+ 27 | 28 | # setopt GLOB_COMPLETE # Show autocompletion menu with globs 29 | #setopt MENU_COMPLETE # Automatically highlight first element of completion menu 30 | setopt AUTO_LIST # Automatically list choices on ambiguous completion. 31 | setopt COMPLETE_IN_WORD # Complete from both ends of a word. 32 | 33 | # +---------+ 34 | # | zstyles | 35 | # +---------+ 36 | 37 | zstyle ':completion:*' auto-description 'specify: %d' 38 | zstyle ':completion:*' completer _expand _complete _correct _approximate 39 | zstyle ':completion:*' format 'Completing %d' 40 | zstyle ':completion:*' group-name '' 41 | zstyle ':completion:*' menu select=2 eval "$(dircolors -b)" 42 | zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS} 43 | zstyle ':completion:*' list-colors '' 44 | zstyle ':completion:*' list-prompt %SAt %p: hit TAB for more, or the character to insert%s 45 | zstyle ':completion:*' matcher-list '' 'm:{a-z}={A-Z}' 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=* l:|=*' 46 | zstyle ':completion:*' menu select=long 47 | zstyle ':completion:*' select-prompt %SScrolling active: current selection at %p%s 48 | zstyle ':completion:*' use-compctl false 49 | zstyle ':completion:*' verbose true 50 | zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31' 51 | zstyle ':completion:*:kill:*' command 'ps -u $USER -o pid,%cpu,tty,cputime,cmd' 52 | zstyle ':completion:*:*:kubectl:*' list-grouped false 53 | zstyle -e ':completion:*:(ssh|scp|sftp|rsh|rsync):hosts' hosts 'reply=(${=${${(f)"$(cat {/etc/ssh_,~/.ssh/known_}hosts(|2)(N) /dev/null)"}%%[# ]*}//,/ })' 54 | -------------------------------------------------------------------------------- /modules/shell/zsh/configs/gpg-ssh.zsh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | 3 | if [[ ! -f /usr/lib/systemd/user/gpg-agent.socket ]]; then 4 | # well we're on an older system without the systemd services 5 | 6 | # use a tty for gpg 7 | # solves error: "gpg: signing failed: Inappropriate ioctl for device" 8 | GPG_TTY=$(tty) 9 | export GPG_TTY 10 | 11 | # add alias for ssh to update the tty 12 | #alias ssh="gpg-connect-agent updatestartuptty /bye >/dev/null; ssh" 13 | gpgconf --launch gpg-agent 14 | export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) 15 | fi 16 | if [[ -z "$SSH_AUTH_SOCK" ]]; then 17 | export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) 18 | fi 19 | -------------------------------------------------------------------------------- /modules/shell/zsh/configs/init.zsh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | 3 | source $ZDOTDIR/autocompletion.zsh .zsh 4 | source $ZDOTDIR/environment.zsh 5 | source $ZDOTDIR/keybindings.zsh 6 | source $ZDOTDIR/privacy.zsh 7 | #source $ZDOTDIR/gpg-ssh.zsh 8 | 9 | if command -v starship &>/dev/null; then 10 | if [[ $TERM != "dumb" && (-z $INSIDE_EMACS || $INSIDE_EMACS == "vterm") ]]; then 11 | eval "$(starship init zsh)" 12 | fi 13 | else 14 | source $ZDOTDIR/prompt.zsh 15 | fi 16 | -------------------------------------------------------------------------------- /modules/shell/zsh/configs/keybindings.zsh: -------------------------------------------------------------------------------- 1 | # ██ 2 | # ░██ 3 | # ██████ ██████░██ 4 | # ░░░░██ ██░░░░ ░██████ 5 | # ██ ░░█████ ░██░░░██ 6 | # ██ ░░░░░██░██ ░██ 7 | # ██████ ██████ ░██ ░██ 8 | # ░░░░░░ ░░░░░░ ░░ ░░ 9 | # 10 | # ▓▓▓▓▓▓▓▓▓▓ 11 | # ░▓ author ▓ xero 12 | # ░▓ code ▓ http://code.xero.nu/dotfiles 13 | # ░▓ mirror ▓ http://git.io/.files 14 | # ░▓▓▓▓▓▓▓▓▓▓ 15 | # ░░░░░░░░░░ 16 | # 17 | #█▓▒░ keybindings 18 | typeset -A key 19 | 20 | key[Home]=${terminfo[khome]} 21 | key[End]=${terminfo[kend]} 22 | key[Insert]=${terminfo[kich1]} 23 | key[Delete]=${terminfo[kdch1]} 24 | key[Up]=${terminfo[kcuu1]} 25 | key[Down]=${terminfo[kcud1]} 26 | key[Left]=${terminfo[kcub1]} 27 | key[Right]=${terminfo[kcuf1]} 28 | key[PageUp]=${terminfo[kpp]} 29 | key[PageDown]=${terminfo[knp]} 30 | 31 | [[ -n "${key[Home]}" ]] && bindkey "${key[Home]}" beginning-of-line 32 | [[ -n "${key[End]}" ]] && bindkey "${key[End]}" end-of-line 33 | [[ -n "${key[Insert]}" ]] && bindkey "${key[Insert]}" overwrite-mode 34 | [[ -n "${key[Delete]}" ]] && bindkey "${key[Delete]}" delete-char 35 | [[ -n "${key[Up]}" ]] && bindkey "${key[Up]}" up-line-or-history 36 | [[ -n "${key[Down]}" ]] && bindkey "${key[Down]}" down-line-or-history 37 | [[ -n "${key[Left]}" ]] && bindkey "${key[Left]}" backward-char 38 | [[ -n "${key[Right]}" ]] && bindkey "${key[Right]}" forward-char 39 | [[ -n "${key[PageUp]}" ]] && bindkey "${key[PageUp]}" beginning-of-buffer-or-history 40 | [[ -n "${key[PageDown]}" ]] && bindkey "${key[PageDown]}" end-of-buffer-or-history 41 | bindkey "^[[1;5C" forward-word 42 | bindkey "^[[1;5D" backward-word 43 | 44 | #if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} )); then 45 | # function zle-line-init () { 46 | # printf '%s' "${terminfo[smkx]}" 47 | # } 48 | # function zle-line-finish () { 49 | # printf '%s' "${terminfo[rmkx]}" 50 | # } 51 | # zle -N zle-line-init 52 | # zle -N zle-line-finish 53 | #fi 54 | -------------------------------------------------------------------------------- /modules/shell/zsh/configs/privacy.zsh: -------------------------------------------------------------------------------- 1 | # ██ 2 | # ░██ 3 | # ██████ ██████░██ 4 | # ░░░░██ ██░░░░ ░██████ 5 | # ██ ░░█████ ░██░░░██ 6 | # ██ ░░░░░██░██ ░██ 7 | # ██████ ██████ ░██ ░██ 8 | # ░░░░░░ ░░░░░░ ░░ ░░ 9 | # 10 | # ▓▓▓▓▓▓▓▓▓▓ 11 | # ░▓ author ▓ casey 12 | # ░▓ code ▓ https://code.caseylink.com 13 | # ░▓ thanks ▓ https://github.com/xero 14 | # ░▓▓▓▓▓▓▓▓▓▓ 15 | # ░░░░░░░░░░ 16 | # 17 | #█▓▒░ 18 | export DOTNET_CLI_TELEMETRY_OPTOUT=1 19 | -------------------------------------------------------------------------------- /modules/site-net/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | hostName, 3 | config, 4 | lib, 5 | ... 6 | }: 7 | { 8 | imports = [ 9 | ./network.nix 10 | ]; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /modules/sops.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | { 8 | options = { 9 | modules.sops.secretsFile = lib.mkOption { 10 | type = lib.types.str; 11 | default = ""; 12 | description = "Path to the decrypted SOPS secrets file."; 13 | }; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /modules/vpn/tailscale.nix: -------------------------------------------------------------------------------- 1 | { 2 | options, 3 | config, 4 | lib, 5 | pkgs, 6 | inputs, 7 | ... 8 | }: 9 | with lib; 10 | let 11 | cfg = config.modules.vpn.tailscale; 12 | username = config.modules.users.primaryUser.username; 13 | withImpermanence = config.modules.impermanence.enable; 14 | in 15 | { 16 | options.modules.vpn.tailscale = { 17 | enable = lib.mkEnableOption ""; 18 | useRoutingFeatures = mkOption { 19 | type = types.enum [ 20 | "none" 21 | "client" 22 | "server" 23 | "both" 24 | ]; 25 | default = "none"; 26 | }; 27 | }; 28 | config = mkIf cfg.enable { 29 | services.tailscale.enable = lib.mkIf cfg.enable true; 30 | services.tailscale.useRoutingFeatures = cfg.useRoutingFeatures; 31 | # ref: https://github.com/tailscale/tailscale/issues/3310 32 | networking.firewall.checkReversePath = "loose"; 33 | 34 | boot.kernel.sysctl."net.ipv4.conf.all.forwarding" = lib.mkForce true; 35 | 36 | networking.firewall.trustedInterfaces = [ "tailscale0" ]; 37 | systemd.services.tailscaled.serviceConfig.ExecStart = mkIf config.modules.vpn.mullvad.enable [ 38 | "" 39 | "${pkgs.mullvad-vpn}/bin/mullvad-exclude ${pkgs.tailscale}/bin/tailscaled --state=/var/lib/tailscale/tailscaled.state --socket=/run/tailscale/tailscaled.sock --port=\${PORT} $FLAGS" 40 | ]; 41 | 42 | environment.persistence = mkIf config.modules.impermanence.enable { 43 | "/persist".directories = [ 44 | "/var/lib/tailscale" 45 | "/var/cache/tailscale" 46 | ]; 47 | }; 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /nix/iso-test.nix: -------------------------------------------------------------------------------- 1 | { inputs, ... }: 2 | { 3 | perSystem = 4 | { 5 | config, 6 | self', 7 | inputs', 8 | pkgs, 9 | system, 10 | ... 11 | }: 12 | { 13 | packages.iso-test = pkgs.writeShellApplication { 14 | name = "iso-test"; 15 | runtimeInputs = with pkgs; [ 16 | qemu-utils 17 | qemu_kvm 18 | ]; 19 | text = '' 20 | disk1=disk1.qcow2 21 | if [ ! -f $disk1 ]; then 22 | qemu-img create -f qcow2 $disk1 8G 23 | fi 24 | exec qemu-kvm \ 25 | -boot c \ 26 | -cpu host \ 27 | -smp cores=2 \ 28 | -M pc \ 29 | -m 2G \ 30 | -device virtio-balloon \ 31 | -device virtio-rng-pci \ 32 | -device nvme,serial=deadbeef,drive=nvm \ 33 | -device usb-ehci \ 34 | -device usb-storage,drive=usbdisk \ 35 | -device e1000,netdev=wan0,mac=8c:16:45:ce:0f:f4 \ 36 | -netdev user,id=wan0 \ 37 | -device virtio-net-pci,netdev=lan0,mac=e4:1d:2d:bf:df:51 \ 38 | -netdev user,id=lan0 \ 39 | -device virtio-net-pci,netdev=lan1,mac=e4:1d:2d:bf:df:50 \ 40 | -netdev user,id=lan1 \ 41 | -device virtio-net-pci,netdev=testnet0,mac=8c:1d:2d:bf:df:53 \ 42 | -netdev user,id=testnet0,hostfwd=tcp::2222-:22 \ 43 | -drive file=$disk1,format=qcow2,if=none,id=nvm,cache=unsafe,werror=report \ 44 | -drive if=pflash,format=raw,unit=0,readonly=on,file=${pkgs.OVMF.firmware} \ 45 | -drive id=usbdisk,if=none,readonly=on,file="$(echo ${inputs.self.nixosConfigurations.addams-installer.config.system.build.isoImage}/iso/*.iso)" \ 46 | -virtfs local,path=./shared,mount_tag=host0,security_model=none,id=host0 47 | ''; 48 | }; 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /nix/pkgs.nix: -------------------------------------------------------------------------------- 1 | { inputs, ... }: 2 | { 3 | imports = [ 4 | ( 5 | { lib, flake-parts-lib, ... }: 6 | flake-parts-lib.mkTransposedPerSystemModule { 7 | name = "pkgs"; 8 | file = ./pkgs.nix; 9 | option = lib.mkOption { type = lib.types.unspecified; }; 10 | } 11 | ) 12 | ]; 13 | 14 | perSystem = 15 | { pkgs, system, ... }: 16 | { 17 | _module.args.pkgs = import inputs.nixpkgs { 18 | inherit system; 19 | config.allowUnfree = true; 20 | overlays = (import ../pkgs/default.nix inputs) ++ [ inputs.nixos-extra-modules.overlays.default ]; 21 | }; 22 | 23 | inherit pkgs; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /overlays/.git-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/overlays/.git-keep -------------------------------------------------------------------------------- /overlays/cuda.nix: -------------------------------------------------------------------------------- 1 | final: prev: { 2 | #openai-whisper = prev.openai-whisper.override { torch = prev.pkgs.python3Packages.torch-bin; }; 3 | } 4 | -------------------------------------------------------------------------------- /overlays/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | { } 8 | -------------------------------------------------------------------------------- /overlays/logseq.nix: -------------------------------------------------------------------------------- 1 | # https://nixos.wiki/wiki/Logseq 2 | # https://github.com/logseq/logseq/issues/10851 3 | final: prev: { 4 | logseq = prev.logseq.overrideAttrs (oldAttrs: { 5 | postFixup = '' 6 | makeWrapper ${prev.electron_30}/bin/electron $out/bin/${oldAttrs.pname} \ 7 | --set "LOCAL_GIT_DIRECTORY" ${prev.git} \ 8 | --add-flags $out/share/${oldAttrs.pname}/resources/app \ 9 | --add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations}}" \ 10 | --prefix LD_LIBRARY_PATH : "${prev.lib.makeLibraryPath [ prev.stdenv.cc.cc.lib ]}" 11 | ''; 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /overlays/qemu.nix: -------------------------------------------------------------------------------- 1 | final: prev: { 2 | quickemu = prev.quickemu.overrideAttrs (oldAttrs: { 3 | postPatch = 4 | (oldAttrs.postPatch or "") 5 | + '' 6 | substituteInPlace quickemu \ 7 | --replace-fail 'args+=(-nic bridge,br=''${network},model=virtio-net-pci''${MAC})' \ 8 | 'args+=(-nic bridge,br=''${network},helper=/run/wrappers/bin/qemu-bridge-helper,model=virtio-net-pci''${MAC})' 9 | ''; 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /overlays/roon-server.nix: -------------------------------------------------------------------------------- 1 | final: prev: { 2 | roon-server = prev.roon-server.overrideAttrs ( 3 | old: 4 | let 5 | version = "2.50.1528"; 6 | urlVersion = builtins.replaceStrings [ "." ] [ "0" ] version; 7 | in 8 | { 9 | version = version; 10 | src = prev.fetchurl { 11 | url = "https://download.roonlabs.com/updates/production/RoonServer_linuxx64_${urlVersion}.tar.bz2"; 12 | hash = "sha256-8Dxxjj/5JSuXeTxTV2l37ZAmf6BDdhykPSinmgZeEVY="; 13 | }; 14 | } 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /pkgs/beets-dynamicrange.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | fetchFromGitHub, 4 | python3Packages, 5 | beets, 6 | dr14_tmeter, 7 | }: 8 | python3Packages.buildPythonApplication rec { 9 | pname = "beets-dynamicrange"; 10 | version = "unstable-2023-12-05"; 11 | 12 | src = fetchFromGitHub { 13 | owner = "auchter"; 14 | repo = pname; 15 | rev = "62fc157f85293d1d2dcc36b5afa33d5322cc8c5f"; 16 | sha256 = "sha256-ALNGrpZOKdUE3g4np8Ms+0s8uWi6YixF2IVHSgaQVj4="; 17 | }; 18 | 19 | nativeBuildInputs = [ beets ]; 20 | 21 | propagatedBuildInputs = [ dr14_tmeter ]; 22 | 23 | postPatch = '' 24 | substituteInPlace beetsplug/dynamicrange.py \ 25 | --replace dr14_tmeter ${dr14_tmeter}/bin/dr14_tmeter 26 | ''; 27 | 28 | doCheck = false; 29 | 30 | meta = with lib; { 31 | homepage = "https://github.com/auchter/beets-dynamicrange"; 32 | description = "Calculate and store dynamic range of music for beets"; 33 | license = licenses.mit; 34 | maintainers = with maintainers; [ auchter ]; 35 | platforms = platforms.linux; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /pkgs/beets-filetote.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | fetchFromGitHub, 5 | beets, 6 | poetry-core, 7 | python3Packages, 8 | }: 9 | python3Packages.buildPythonApplication rec { 10 | pname = "beets-filetote"; 11 | version = "0.4.9"; 12 | pyproject = true; 13 | 14 | src = fetchFromGitHub { 15 | owner = "gtronset"; 16 | repo = "beets-filetote"; 17 | rev = "v${version}"; 18 | hash = "sha256-pZ6c2XQMSiiPHyZMLSiSE+LXeCfi3HEWtsTK5DP9YZE="; 19 | }; 20 | 21 | build-system = [ 22 | python3Packages.poetry-core 23 | ]; 24 | 25 | postPatch = '' 26 | sed -i -e '/audible/d' tests/helper.py 27 | 28 | # beets v2.1.0 compat 29 | # 30 | sed -i -e 's/util\.py3_path/os.fsdecode/g' tests/_common.py 31 | ''; 32 | 33 | pytestFlagsArray = [ "-r fEs" ]; 34 | 35 | disabledTests = [ 36 | # XXX: Needs update for Beets v2.0.0 37 | # 38 | "test_move_on_modify_command" 39 | "test_prune_modify_query" 40 | ]; 41 | 42 | disabledTestPaths = [ 43 | "tests/test_audible_m4b_files.py" 44 | ]; 45 | nativeCheckInputs = with python3Packages; [ 46 | pytestCheckHook 47 | beets 48 | reflink 49 | toml 50 | typeguard 51 | ]; 52 | 53 | preBuild = '' 54 | export HOME=$(mktemp -d) 55 | ''; 56 | 57 | pythonImportsCheck = [ 58 | "beetsplug.filetote" 59 | "beetsplug.filetote_dataclasses" 60 | ]; 61 | 62 | meta = with lib; { 63 | description = "Beets plugin to move non-music files during the import process"; 64 | homepage = "https://github.com/gtronset/beets-filetote"; 65 | changelog = "https://github.com/gtronset/beets-filetote/blob/${src.rev}/CHANGELOG.md"; 66 | maintainers = with maintainers; [ dansbandit ]; 67 | license = licenses.mit; 68 | inherit (beets.meta) platforms; 69 | }; 70 | } 71 | -------------------------------------------------------------------------------- /pkgs/cloudflare-utils.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | stdenv, 5 | fetchFromGitHub, 6 | }: 7 | pkgs.buildGoModule rec { 8 | name = "cloudflare-utils"; 9 | version = "1.2.1"; 10 | src = pkgs.fetchFromGitHub { 11 | owner = "Cyb3r-Jak3"; 12 | repo = "cloudflare-utils"; 13 | rev = "v${version}"; 14 | sha256 = "sha256-41TQ+St6U4exLSl4dwc1E6K8P+oqQ4m5RSI7L2/dWwI="; 15 | }; 16 | vendorHash = "sha256-HE6x4KSe9b9ZzcYz7sP25aTeDGU4zXgkYm/1RwYYBt4="; 17 | meta = with lib; { 18 | description = "Helpful Cloudflare utility program"; 19 | homepage = "https://github.com/Cyb3r-Jak3/cloudflare-utils"; 20 | license = licenses.asl20; 21 | maintainers = with maintainers; [ ]; 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /pkgs/default.nix: -------------------------------------------------------------------------------- 1 | inputs: [ 2 | (_final: prev: { 3 | netns-proxy = prev.callPackage ./netns-proxy.nix { }; 4 | udpbroadcastrelay = prev.callPackage ./udpbroadcastrelay.nix { }; 5 | deploy = prev.callPackage ./deploy.nix { }; 6 | swhkd = prev.callPackage ./swhkd { }; 7 | overseerr = prev.callPackage ./overseerr.nix { }; 8 | cloudflare-utils = prev.callPackage ./cloudflare-utils.nix { }; 9 | actual-server = prev.callPackage ./actual-server.nix { }; 10 | qobuz-dl = prev.callPackage ./qobuz-dl.nix { }; 11 | kwin6-bismuth-decoration = prev.callPackage ./kwin6-bismuth-decoration.nix { }; 12 | klassy = prev.callPackage ./klassy.nix { }; 13 | invoiceninja-mine = prev.callPackage ./invoiceninja/package.nix { }; 14 | beets-dynamicrange = prev.callPackage ./beets-dynamicrange.nix { 15 | beets = prev.beetsPackages.beets-minimal; 16 | }; 17 | beets-filetote = prev.callPackage ./beets-filetote.nix { 18 | poetry-core = prev.python3Packages.poetry-core; 19 | beets = prev.beetsPackages.beets-minimal; 20 | }; 21 | }) 22 | ] 23 | -------------------------------------------------------------------------------- /pkgs/invoiceninja/invoiceninja-redis.patch: -------------------------------------------------------------------------------- 1 | --- config/database.php 2024-10-25 09:02:12.000000000 +0200 2 | +++ config/database.php 11:25:56.661620943 +0100 3 | @@ -160,6 +160,8 @@ 4 | 'client' => 'predis', 5 | 6 | 'default' => [ 7 | + 'scheme' => env('REDIS_SCHEME', 'tcp'), 8 | + 'path' => env('REDIS_PATH'), 9 | 'host' => env('REDIS_HOST', '127.0.0.1'), 10 | 'password' => env('REDIS_PASSWORD', null), 11 | 'port' => env('REDIS_PORT', 6379), 12 | @@ -167,6 +169,8 @@ 13 | ], 14 | 15 | 'cache' => [ 16 | + 'scheme' => env('REDIS_SCHEME', 'tcp'), 17 | + 'path' => env('REDIS_PATH'), 18 | 'host' => env('REDIS_HOST', '127.0.0.1'), 19 | 'password' => env('REDIS_PASSWORD', null), 20 | 'port' => env('REDIS_PORT', 6379), 21 | 22 | -------------------------------------------------------------------------------- /pkgs/invoiceninja/invoiceninja.patch: -------------------------------------------------------------------------------- 1 | diff --git a/config/database.php b/config/database.php 2 | index 32dedf8154..7052612d8a 100644 3 | --- a/config/database.php 4 | +++ b/config/database.php 5 | @@ -41,6 +41,7 @@ return [ 6 | 'username' => env('DB_USERNAME1', env('DB_USERNAME', 'forge')), 7 | 'password' => env('DB_PASSWORD1', env('DB_PASSWORD', '')), 8 | 'port' => env('DB_PORT1', env('DB_PORT', '3306')), 9 | + 'unix_socket' => env('DB_SOCKET1', env('DB_SOCKET', '')), 10 | 'charset' => 'utf8mb4', 11 | 'collation' => 'utf8mb4_unicode_ci', 12 | 'prefix' => '', 13 | @@ -175,6 +176,8 @@ return [ 14 | 'client' => 'predis', 15 | 16 | 'default' => [ 17 | + 'scheme' => env('REDIS_SCHEME', 'tcp'), 18 | + 'path' => env('REDIS_PATH'), 19 | 'host' => env('REDIS_HOST', '127.0.0.1'), 20 | 'password' => env('REDIS_PASSWORD', null), 21 | 'port' => env('REDIS_PORT', 6379), 22 | @@ -182,6 +185,8 @@ return [ 23 | ], 24 | 25 | 'cache' => [ 26 | + 'scheme' => env('REDIS_SCHEME', 'tcp'), 27 | + 'path' => env('REDIS_PATH'), 28 | 'host' => env('REDIS_HOST', '127.0.0.1'), 29 | 'password' => env('REDIS_PASSWORD', null), 30 | 'port' => env('REDIS_PORT', 6379), 31 | -------------------------------------------------------------------------------- /pkgs/invoiceninja/package.nix: -------------------------------------------------------------------------------- 1 | { 2 | stdenv, 3 | lib, 4 | fetchurl, 5 | dataDir ? "/var/lib/invoiceninja", 6 | runtimeDir ? "/run/invoiceninja", 7 | }: 8 | 9 | stdenv.mkDerivation (finalAttrs: { 10 | pname = "invoiceninja"; 11 | version = "5.10.43"; 12 | 13 | src = fetchurl { 14 | url = "https://github.com/invoiceninja/invoiceninja/releases/download/v${finalAttrs.version}/invoiceninja.tar"; 15 | hash = "sha256-nFO9nZOy3gFP+gm2JpGqwMWhMQ2gaLrJCmXUj8RVp6c="; 16 | }; 17 | 18 | sourceRoot = "."; 19 | 20 | patchFlags = [ "-p0" ]; 21 | patches = [ 22 | # support connection redis with unix domain sockets 23 | # upstream has not yet accepted this patch 24 | ./invoiceninja-redis.patch 25 | ]; 26 | 27 | installPhase = '' 28 | runHook preInstall 29 | 30 | mkdir -p $out/share/invoiceninja 31 | cp -r . $out/share/invoiceninja 32 | 33 | pushd $out/share/invoiceninja 34 | chmod +x artisan 35 | mv bootstrap bootstrap-static 36 | mv storage storage-static 37 | mv resources resources-static 38 | ln -s ${dataDir}/.env $out/share/invoiceninja 39 | ln -s ${dataDir}/storage $out/share/invoiceninja 40 | ln -s ${dataDir}/storage-public $out/share/invoiceninja/public/storage 41 | ln -s ${runtimeDir}/bootstrap $out/share/invoiceninja/bootstrap 42 | ln -s ${runtimeDir}/resources $out/share/invoiceninja/resources 43 | popd 44 | 45 | # Create standard directory structure 46 | #mkdir -p $out/bin 47 | 48 | # Create wrapper script 49 | #cat > $out/bin/invoiceninja < "$temp/persist/etc/ssh/ssh_host_ed25519_key" 45 | sops -d --extract "['ssh_host_ed25519_key_pub']" "$sops_secrets" > "$temp/persist/etc/ssh/ssh_host_ed25519_key.pub" 46 | 47 | # Set the correct permissions so sshd will accept the key 48 | chmod 600 "$temp/persist/etc/ssh/ssh_host_ed25519_key" 49 | 50 | 51 | nix run github:nix-community/nixos-anywhere/1.4.0 -- --flake ".#$host" --extra-files "$temp" "root@$host" 52 | 53 | echo "done" 54 | exit 0 55 | 56 | zpool import -l rpool 57 | mount rpool/encrypted/local/root /mnt/ -o X-mount.mkdir -o defaults -t zfs 58 | mount /dev/disk/by-partlabel/disk-vda-ESP /mnt/boot -t vfat -o defaults -o X-mount.mkdir 59 | mount rpool/encrypted/local/home /mnt/home -o X-mount.mkdir -o defaults -t zfs 60 | mount rpool/encrypted/local/nix /mnt/nix -o X-mount.mkdir -o defaults -t zfs 61 | mount rpool/encrypted/safe/persist /mnt/persist -o X-mount.mkdir -o defaults -t zfs 62 | 63 | umount /mnt/persist 64 | umount /mnt/nix 65 | umount /mnt/home 66 | umount /mnt/boot 67 | umount /mnt 68 | zpool export rpool 69 | -------------------------------------------------------------------------------- /scripts/enumerate-ports.py: -------------------------------------------------------------------------------- 1 | import yaml 2 | 3 | items = [ 4 | "9003/udp", 5 | "9100-9200/tcp", 6 | "30000-30010/tcp", 7 | "9330-9339/tcp", 8 | "49863/tcp", 9 | "52667/tcp", 10 | "52709/tcp", 11 | "63098-63100/tcp", 12 | ] 13 | 14 | 15 | def enumerate_ports(items): 16 | services = {} 17 | service_id = 0 18 | for item in items: 19 | if "-" in item: 20 | port_range, protocol = item.split("/") 21 | start_port, end_port = map(int, port_range.split("-")) 22 | for port in range(start_port, end_port + 1): 23 | services[f"service{service_id}"] = { 24 | "port": port, 25 | "protocol": protocol.upper(), 26 | } 27 | service_id += 1 28 | else: 29 | port, protocol = item.split("/") 30 | services[f"service{service_id}"] = { 31 | "port": int(port), 32 | "protocol": protocol.upper(), 33 | } 34 | service_id += 1 35 | return services 36 | 37 | 38 | services_dict = enumerate_ports(items) 39 | yaml_output = yaml.dump(services_dict, sort_keys=False) 40 | print(yaml_output) 41 | -------------------------------------------------------------------------------- /scripts/json2nix.py: -------------------------------------------------------------------------------- 1 | """Converts JSON objects into nix (hackishly).""" 2 | 3 | import sys 4 | import json 5 | 6 | 7 | INDENT = " " * 2 8 | 9 | 10 | def strip_comments(t): 11 | # fixme: doesn't work if JSON strings contain // 12 | return "\n".join(l.partition("//")[0] for l in t.split("\n")) 13 | 14 | 15 | def indent(s): 16 | return "\n".join(INDENT + i for i in s.split("\n")) 17 | 18 | 19 | def nix_stringify(s): 20 | # fixme: this doesn't handle string interpolation and possibly has more bugs 21 | return json.dumps(s) 22 | 23 | 24 | def sanitize_key(s): 25 | if s and s.isalnum() and not s[0].isdigit(): 26 | return s 27 | return nix_stringify(s) 28 | 29 | 30 | def flatten_obj_item(k, v): 31 | keys = [k] 32 | val = v 33 | while isinstance(val, dict) and len(val) == 1: 34 | k = next(iter(val.keys())) 35 | keys.append(k) 36 | val = val[k] 37 | return keys, val 38 | 39 | 40 | def fmt_object(obj, flatten): 41 | fields = [] 42 | for k, v in obj.items(): 43 | if flatten: 44 | keys, val = flatten_obj_item(k, v) 45 | formatted_key = ".".join(sanitize_key(i) for i in keys) 46 | else: 47 | formatted_key = sanitize_key(k) 48 | val = v 49 | fields.append(f"{formatted_key} = {fmt_any(val, flatten)};") 50 | 51 | return "{\n" + indent("\n".join(fields)) + "\n}" 52 | 53 | 54 | def fmt_array(o, flatten): 55 | body = indent("\n".join(fmt_any(i, flatten) for i in o)) 56 | return f"[\n{body}\n]" 57 | 58 | 59 | def fmt_any(o, flatten): 60 | if isinstance(o, str) or isinstance(o, bool) or isinstance(o, int): 61 | return json.dumps(o) 62 | if isinstance(o, list): 63 | return fmt_array(o, flatten) 64 | if isinstance(o, dict): 65 | return fmt_object(o, flatten) 66 | raise TypeError(f"Unknown type {type(o)!r}") 67 | 68 | 69 | def main(): 70 | flatten = "--flatten" in sys.argv 71 | args = [a for a in sys.argv[1:] if not a.startswith("--")] 72 | 73 | if len(args) < 1: 74 | print(f"Usage: {sys.argv[0]} [--flatten] ", file=sys.stderr) 75 | sys.exit(1) 76 | 77 | with open(args[0], "r") as f: 78 | data = json.loads(strip_comments(f.read())) 79 | 80 | print(fmt_any(data, flatten=flatten)) 81 | 82 | 83 | if __name__ == "__main__": 84 | main() 85 | -------------------------------------------------------------------------------- /scripts/pass.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import getpass 3 | from passlib.hash import sha512_crypt 4 | 5 | 6 | password = getpass.getpass("Enter password: ") 7 | 8 | # Hash passwords using SHA-512 9 | h = sha512_crypt.hash(password) 10 | 11 | 12 | print(f"password_hash: {h}") 13 | -------------------------------------------------------------------------------- /scripts/pgbackrest-restore.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -ex 3 | 4 | workdir=~/work/pg 5 | image="docker.io/library/postgres:15-bullseye" 6 | 7 | podman pull $image 8 | 9 | mkdir -p $workdir 10 | cd $workdir 11 | mkdir -p log spool 12 | podman run --name pg-restore --userns keep-id -p 127.0.0.1:5433:5432 -v $workdir:/var/lib/postgresql/data -e POSTGRES_PASSWORD=postgres -d $image 13 | 14 | until [ -f ./pg/global/pg_control ]; do 15 | sleep 1 16 | done 17 | 18 | sleep 1 19 | 20 | podman stop pg-restore 21 | 22 | rm ./pg/global/pg_control 23 | find ./pg -mindepth 1 -delete 24 | 25 | cat < ./pgbackrest.conf 26 | [global] 27 | archive-async=y 28 | archive-push-queue-max = 4GiB 29 | archive-timeout = 60 30 | compress-level = 9 31 | compress-type = lz4 32 | delta = y 33 | log-path = $PWD/log 34 | spool-path = $PWD/spool 35 | repo1-block = y 36 | repo1-bundle = y 37 | repo1-path = $PWD/matrix/repo1 38 | [db] 39 | pg1-path = $PWD/pg 40 | EOF 41 | 42 | pgbackrest --config $(pwd)/pgbackrest.conf --stanza=repo1 restore 43 | -------------------------------------------------------------------------------- /scripts/restic-restore.sh: -------------------------------------------------------------------------------- 1 | export AWS_ACCESS_KEY_ID=volsync-CHANGEME 2 | export AWS_SECRET_ACCESS_KEY='CHANGEME' 3 | export RESTIC_REPOSITORY="s3:https://s3.CHANGEME/volsync-CHANGEME/restic" 4 | export RESTIC_PASSWORD="CHANGEME" 5 | #restic --verbose unlock 6 | restic --no-lock --verbose restore latest --target ./restored/ 7 | -------------------------------------------------------------------------------- /secrets/age-disaster-recovery.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/secrets/age-disaster-recovery.pub -------------------------------------------------------------------------------- /secrets/age-keychain.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/secrets/age-keychain.pub -------------------------------------------------------------------------------- /secrets/age-mini-quine.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/secrets/age-mini-quine.pub -------------------------------------------------------------------------------- /secrets/global.nix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/secrets/global.nix -------------------------------------------------------------------------------- /secrets/home-ops.nix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/secrets/home-ops.nix -------------------------------------------------------------------------------- /secrets/ocis-work-csp.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/secrets/ocis-work-csp.yaml -------------------------------------------------------------------------------- /secrets/site.nix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/nixcfg/5d3addc0bf24921ebbaed6281ea89caf734990cf/secrets/site.nix -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | { 2 | system ? "x86_64-linux", 3 | pkgs ? import { inherit system; }, 4 | }: 5 | let 6 | packages = with pkgs; [ 7 | python3 8 | python3Packages.passlib 9 | python3Packages.ruamel-yaml 10 | python3Packages.pyyaml 11 | python3Packages.simple-term-menu 12 | ]; 13 | in 14 | pkgs.mkShell { 15 | buildInputs = packages; 16 | shellHook = '' 17 | export SHELL=${pkgs.zsh} 18 | ''; 19 | } 20 | --------------------------------------------------------------------------------