├── .envrc
├── .github
├── dependabot.yml
└── workflows
│ ├── check-flake.yml
│ ├── check-format.yml
│ ├── deploy.yml
│ └── update.yml
├── .gitignore
├── LICENSE
├── README.org
├── flake-parts
├── agenix.nix
├── cachix-deploy.nix
├── deploy.nix
├── emacs.nix
├── home-manager.nix
├── installers.nix
├── nixos.nix
├── pkgs.nix
└── treefmt.nix
├── flake.lock
├── flake.nix
├── homes
├── basic.nix
├── code.nix
├── core.nix
├── etc
│ ├── river
│ │ └── init
│ └── starship
│ │ └── starship.toml
├── extra.nix
├── graphical.nix
├── lib
│ └── waybar-config.nix
├── modules.nix
├── modules
│ ├── aider
│ │ ├── default.nix
│ │ └── interface.nix
│ ├── browser.nix
│ ├── crostini.nix
│ ├── direnv.nix
│ ├── dunst.nix
│ ├── fzy.nix
│ ├── git.nix
│ ├── gpg.nix
│ ├── hyprland.nix
│ ├── librewolf.nix
│ ├── password-store.nix
│ ├── psd.nix
│ ├── rebuild-home.nix
│ ├── rebuild-nixos.nix
│ ├── recoll.nix
│ ├── timoni.nix
│ ├── words.nix
│ ├── wslu.nix
│ ├── xdg.nix
│ └── zsh.nix
└── wsl.nix
├── machines
├── hui
│ ├── boot.nix
│ ├── default.nix
│ └── flake-module.nix
├── li
│ ├── boot.nix
│ ├── default.nix
│ ├── flake-module.nix
│ └── rpool5
│ │ ├── default.nix
│ │ └── extras.nix
├── metadata.toml
├── shu
│ ├── boot.nix
│ ├── default.nix
│ ├── disko.nix
│ └── flake-module.nix
├── voyage
│ └── home.nix
├── wang
│ ├── boot.nix
│ ├── default.nix
│ ├── flake-module.nix
│ └── fs
│ │ ├── annex.nix
│ │ ├── btrfs.nix
│ │ ├── default.nix
│ │ └── storage1.nix
├── yang
│ ├── boot.nix
│ ├── default.nix
│ ├── flake-module.nix
│ ├── fs
│ │ ├── btrfs.nix
│ │ ├── default.nix
│ │ └── rpool4.nix
│ └── lgtm-stack.nix
└── zheng
│ ├── default.nix
│ ├── flake-module.nix
│ ├── router.nix
│ ├── secrets
│ └── dhcp-hosts.age
│ └── usb-wifi.nix
├── nixos
├── models
│ └── asus-br1100
│ │ ├── flake-module.nix
│ │ └── modules
│ │ ├── acpi_call.nix
│ │ ├── default.nix
│ │ ├── r8168.nix
│ │ └── wireless.nix
├── profiles
│ ├── acme
│ │ ├── default.nix
│ │ ├── internal.nix
│ │ └── secrets
│ │ │ └── nicesunny.day.credentials.txt.age
│ ├── adb
│ │ └── default.nix
│ ├── adguard-home
│ │ └── default.nix
│ ├── agenix
│ │ └── default.nix
│ ├── containers
│ │ ├── default.nix
│ │ └── rootless.nix
│ ├── desktop
│ │ └── plasma.nix
│ ├── docker
│ │ ├── default.nix
│ │ ├── kind.nix
│ │ └── rootless.nix
│ ├── dpt-rp1
│ │ └── default.nix
│ ├── flatpak
│ │ └── default.nix
│ ├── home-manager
│ │ └── default.nix
│ ├── intel-arc
│ │ └── default.nix
│ ├── k3s
│ │ ├── single-node-for-testing.nix
│ │ └── single-node.nix
│ ├── livebook
│ │ ├── default.nix
│ │ └── interface.nix
│ ├── locale
│ │ └── default.nix
│ ├── microvm
│ │ ├── default.nix
│ │ └── ssh.nix
│ ├── minio
│ │ └── development.nix
│ ├── networking
│ │ └── usb-tether1.nix
│ ├── nginx
│ │ └── default.nix
│ ├── nix
│ │ ├── cachix-deploy.nix
│ │ └── default.nix
│ ├── nixpkgs
│ │ └── channels.nix
│ ├── ollama
│ │ └── default.nix
│ ├── onedev
│ │ └── default.nix
│ ├── openssh
│ │ └── default.nix
│ ├── pipewire
│ │ └── default.nix
│ ├── podman
│ │ ├── default.nix
│ │ └── rootless-docker.nix
│ ├── postgresql
│ │ └── development.nix
│ ├── rabbitmq
│ │ └── development.nix
│ ├── reverse-proxy
│ │ └── default.nix
│ ├── sudo
│ │ └── default.nix
│ ├── syncthing
│ │ └── default.nix
│ ├── tailscale
│ │ └── default.nix
│ ├── users
│ │ ├── 1000
│ │ │ └── on-server.nix
│ │ └── primary-group.nix
│ ├── virtualbox-host
│ │ ├── default.nix
│ │ └── generate.bash
│ ├── wayland
│ │ ├── cage
│ │ │ ├── emacs.nix
│ │ │ ├── firefox.nix
│ │ │ ├── foot.nix
│ │ │ └── makeWrapper.nix
│ │ ├── sessions.nix
│ │ ├── sway-utils.nix
│ │ ├── wlroots.nix
│ │ └── wm
│ │ │ ├── hyprland.nix
│ │ │ └── labwc.nix
│ ├── window-manager
│ │ └── generic.nix
│ └── yubikey
│ │ └── default.nix
└── suites
│ ├── base
│ └── default.nix
│ ├── desktop
│ └── default.nix
│ ├── graphical
│ └── default.nix
│ ├── hcloud-remote
│ └── default.nix
│ ├── hcloud
│ └── default.nix
│ ├── installer
│ └── default.nix
│ ├── iso
│ └── default.nix
│ ├── microvm-gui
│ └── default.nix
│ ├── microvm
│ └── default.nix
│ ├── remote-installer
│ └── default.nix
│ └── server
│ └── default.nix
├── secrets
├── aider-env.age
├── rekeyed
│ ├── yang
│ │ └── cde7a1a585cb8ea1ccfb2a2e1535f2ef-nicesunny.day.credentials.txt.age
│ └── zheng
│ │ └── e10023806a5bd15c8d5351e849343edd-dhcp-hosts.age
└── yubikey.pub
└── templates
├── flake-module.nix
├── home-manager
├── .gitignore
├── flake.nix
└── home.nix
└── nixos-wsl
├── .gitignore
├── README.md
├── flake.nix
└── justfile
/.envrc:
--------------------------------------------------------------------------------
1 | use flake . --accept-flake-config
2 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "github-actions"
4 | directory: "/"
5 | schedule:
6 | interval: "daily"
7 | labels:
8 | - "automation"
9 | - "actions"
10 |
--------------------------------------------------------------------------------
/.github/workflows/check-flake.yml:
--------------------------------------------------------------------------------
1 | name: Check the flake
2 | on:
3 | workflow_dispatch:
4 | pull_request:
5 | paths-ignore:
6 | - 'README.*'
7 | - '.github/**'
8 | push:
9 | branches:
10 | - master
11 | paths-ignore:
12 | - 'README.*'
13 | - '.github/**'
14 | - 'treefmt.nix'
15 | concurrency:
16 | group: ${{ github.workflow }}-${{ github.ref }}
17 | cancel-in-progress: true
18 | jobs:
19 | check:
20 | runs-on: ubuntu-latest
21 | steps:
22 | - uses: actions/checkout@v4
23 | - uses: cachix/install-nix-action@v31.4.0
24 | with:
25 | extra_nix_config: |
26 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
27 | accept-flake-config = true
28 | # It would be possible to add to here a cachix-action step to upload
29 | # everything built within this workflow, but I will choose to save space by
30 | # not uploading anything implicitly. If I have packages that should be
31 | # available from my binary cache, I will upload them from somewhere else or
32 | # use `cachix push` to explicitly specify them.
33 | - run: |
34 | nix flake update emacs-config
35 | nix flake check --print-build-logs --show-trace
36 |
--------------------------------------------------------------------------------
/.github/workflows/check-format.yml:
--------------------------------------------------------------------------------
1 | name: Check formatting
2 | on:
3 | workflow_dispatch:
4 | push:
5 | concurrency:
6 | group: ${{ github.workflow }}-${{ github.ref }}
7 | cancel-in-progress: true
8 | jobs:
9 | check:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v4
13 | - uses: cachix/install-nix-action@v31.4.0
14 | with:
15 | extra_nix_config: |
16 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
17 | accept-flake-config = true
18 | # This check is actually done as part of `nix flake check` in
19 | # ./check-flake.yml, but this formatting check requires less time, so run it
20 | # separately for failing fast.
21 | - name: Check formatting
22 | run: |
23 | nix build -L ".#checks.$(nix eval --expr builtins.currentSystem --impure --raw).treefmt"
24 |
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Cachix Deploy
2 | on:
3 | workflow_dispatch:
4 | push:
5 | branches:
6 | - master
7 | paths:
8 | - 'flake.lock'
9 | - 'machines/**'
10 | - 'profiles/**'
11 | - 'suites/**'
12 | - 'homes/**'
13 | schedule:
14 | - cron: '0 18 * * *' # 3:00 am JST
15 | env:
16 | dry: ${{ github.event.event_name == 'push' }}
17 | concurrency:
18 | group: ${{ github.workflow }}
19 | cancel-in-progress: true
20 | jobs:
21 | build-and-deploy:
22 | runs-on: ubuntu-latest
23 | env:
24 | CACHIX_ACTIVATE_TOKEN: ${{ secrets.CACHIX_ACTIVATE_TOKEN }}
25 | CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
26 | CACHIX_SIGNING_KEY: ${{ secrets.CACHIX_SIGNING_KEY }}
27 | steps:
28 | - uses: actions/checkout@v4
29 | - uses: cachix/install-nix-action@v31.4.0
30 | with:
31 | extra_nix_config: |
32 | accept-flake-config = true
33 | - uses: cachix/cachix-action@v16
34 | with:
35 | name: akirak
36 | authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
37 | skipPush: true
38 | pathsToPush: |
39 | # Specify paths to push
40 | # - run: |
41 | # nix flake check \
42 | # --override-input emacs-config github:akirak/emacs-config/develop
43 | - name: Build the deploys
44 | id: build
45 | # A timeout set arbitrary
46 | timeout-minutes: 90
47 | run: |
48 | nix flake update emacs-config
49 | spec=$(nix build .#cachix-deploys --print-out-paths --print-build-logs \
50 | ${{ env.dry == 'true' && '--dry-run' || '' }})
51 | echo "spec_path=$spec" >> "$GITHUB_OUTPUT"
52 | - name: Push to Cachix
53 | if: ${{ env.dry == 'false' }}
54 | run: |
55 | cachix push akirak "$DEPLOY_SPEC"
56 | env:
57 | DEPLOY_SPEC: ${{ steps.build.outputs.spec_path }}
58 | - name: Deploy
59 | if: ${{ env.dry == 'false' }}
60 | # Should be deployed instantly. Some machines may be offline, but then you
61 | # can rerun this workflow
62 | timeout-minutes: 1
63 | # It is very possible that some machines are offline which makes this step
64 | # fail. Don't mark the entire workflow run as a failure.
65 | continue-on-error: true
66 | run: |
67 | cachix deploy activate "$DEPLOY_SPEC"
68 | env:
69 | DEPLOY_SPEC: ${{ steps.build.outputs.spec_path }}
70 |
--------------------------------------------------------------------------------
/.github/workflows/update.yml:
--------------------------------------------------------------------------------
1 | name: Update the flake from the registry
2 | on:
3 | workflow_dispatch:
4 | repository_dispatch:
5 | types:
6 | - flake-update
7 | jobs:
8 | update:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v4
12 | - uses: cachix/install-nix-action@v31.4.0
13 | with:
14 | extra_nix_config: |
15 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
16 | accept-flake-config = true
17 | - uses: DeterminateSystems/update-flake-lock@v25
18 | with:
19 | token: ${{ secrets.PAT_FOR_PR }}
20 | pr-title: "Update flake.lock"
21 | pr-labels: |
22 | automation
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gcroots
2 | *.img
3 | result*
4 | .pre-commit-config.yaml
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022-2025 Akira Komamura
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.org:
--------------------------------------------------------------------------------
1 | # -*- org-id-link-to-org-use-id: nil; -*-
2 | * Home Lab
3 | This repository contains the configuration files of my NixOS machines.
4 |
--------------------------------------------------------------------------------
/flake-parts/agenix.nix:
--------------------------------------------------------------------------------
1 | { lib, inputs, ... }:
2 | let
3 | inherit (inputs) self;
4 |
5 | hostPubkeys = lib.pipe (lib.importTOML ../machines/metadata.toml).hosts [
6 | (lib.filterAttrs (_: attrs: attrs ? publicKey))
7 | (builtins.mapAttrs (_: attrs: attrs.publicKey))
8 | ];
9 | in
10 | {
11 | flake = {
12 | agenix-rekey = inputs.agenix-rekey.configure {
13 | userFlake = self;
14 | nixosConfigurations = builtins.intersectAttrs hostPubkeys self.nixosConfigurations;
15 | };
16 |
17 | lib = {
18 | inherit hostPubkeys;
19 | };
20 | };
21 |
22 | perSystem =
23 | { system, pkgs, ... }:
24 | {
25 | devShells = {
26 | default = pkgs.mkShell {
27 | buildInputs = [
28 | pkgs.age
29 | pkgs.age-plugin-yubikey
30 | ];
31 | nativeBuildInputs = [ inputs.agenix-rekey.packages.${system}.default ];
32 | };
33 | };
34 | };
35 | }
36 |
--------------------------------------------------------------------------------
/flake-parts/cachix-deploy.nix:
--------------------------------------------------------------------------------
1 | # Currently unused
2 | { lib, inputs, ... }:
3 | let
4 | inherit (inputs) self;
5 |
6 | nixosHosts = [
7 | "hui"
8 | ];
9 |
10 | homeHosts = [
11 | ];
12 | in
13 | {
14 | flake = {
15 | packages.x86_64-linux =
16 | let
17 | pkgs = inputs.unstable.legacyPackages.x86_64-linux;
18 | in
19 | {
20 | cachix-deploys = (inputs.cachix-deploy-flake.lib pkgs).spec {
21 | agents =
22 | (lib.genAttrs nixosHosts (name: self.nixosConfigurations.${name}.config.system.build.toplevel))
23 | // (lib.genAttrs homeHosts (name: self.homeConfigurations.${name}.activationPackage));
24 | };
25 | };
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/flake-parts/deploy.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | let
3 | inherit (inputs) self stable;
4 | in
5 | {
6 | perSystem =
7 | {
8 | pkgs,
9 | lib,
10 | system,
11 | ...
12 | }:
13 | let
14 | deployToHost =
15 | hostName:
16 | pkgs.writeShellApplication {
17 | name = "deploy";
18 | runtimeInputs = [ stable.legacyPackages.${system}.nixos-rebuild ];
19 | meta.description = "A nixos-rebuild wrapper that targets a host on LAN";
20 | text = ''
21 | target_host="${hostName}"
22 |
23 | usage() {
24 | echo "deploy [--target-host IP] switch|test ARGS"
25 | }
26 |
27 | while [[ $# -gt 0 ]]; do
28 | case "$1" in
29 | --help|-h)
30 | usage
31 | exit
32 | ;;
33 | --target-host)
34 | target_host="$2"
35 | shift; shift
36 | ;;
37 | *)
38 | mode="$1"
39 | shift
40 | break
41 | ;;
42 | esac
43 | done
44 |
45 | if ! [[ -v mode ]]; then
46 | echo >&2 "You need to specify one of the subcommands of nixos-rebuild"
47 | exit 1
48 | fi
49 |
50 | set -x
51 |
52 | # Don't look up known_hosts file because the host key is updated on every deploy
53 | NIX_SSHOPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" \
54 | nixos-rebuild "$mode" \
55 | --flake ".#${hostName}" \
56 | --target-host "root@''${target_host}" \
57 | --option accept-flake-config true \
58 | "$@"
59 | '';
60 | };
61 | in
62 | {
63 | packages = lib.mapAttrs' (
64 | hostName: _: lib.nameValuePair "deploy-${hostName}" (deployToHost hostName)
65 | ) self.nixosConfigurations;
66 | };
67 | }
68 |
--------------------------------------------------------------------------------
/flake-parts/emacs.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | {
3 | flake = {
4 | nixosModules = {
5 | twistHomeModule =
6 | { homeUser, ... }:
7 | {
8 | home-manager.users.${homeUser} = {
9 | imports = [ inputs.emacs-config.homeModules.twist ];
10 | };
11 | };
12 | };
13 | };
14 | }
15 |
--------------------------------------------------------------------------------
/flake-parts/home-manager.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | {
3 | flake = {
4 | nixosModules = {
5 | hmProfile = {
6 | nixpkgs.overlays = [ inputs.self.overlays.default ];
7 | imports = [
8 | # Use a home-manager channel corresponding to your OS
9 | # inputs.home-manager.nixosModules.home-manager
10 | inputs.self.nixosModules.twistHomeModule
11 | ../nixos/profiles/home-manager
12 | ];
13 | };
14 | };
15 | };
16 | }
17 |
--------------------------------------------------------------------------------
/flake-parts/installers.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | let
3 | inherit (inputs) stable unstable;
4 |
5 | overlayModule = {
6 | nixpkgs.overlays = [ inputs.self.overlays.default ];
7 | };
8 | in
9 | {
10 | flake = {
11 | packages.x86_64-linux = {
12 | remote-installer-image =
13 | (stable.lib.nixosSystem {
14 | system = "x86_64-linux";
15 | modules = [
16 | overlayModule
17 | ../nixos/suites/remote-installer
18 | (
19 | { modulesPath, ... }:
20 | {
21 | imports = [ (modulesPath + "/installer/cd-dvd/installation-cd-base.nix") ];
22 | }
23 | )
24 | ];
25 | }).config.system.build.isoImage;
26 | };
27 |
28 | packages.aarch64-linux = {
29 | bootstrap-sd-image =
30 | (unstable.lib.nixosSystem {
31 | system = "aarch64-linux";
32 | modules = [
33 | overlayModule
34 | (
35 | { modulesPath, ... }:
36 | {
37 | imports = [ (modulesPath + "/installer/sd-card/sd-image-aarch64.nix") ];
38 | }
39 | )
40 | ../nixos/suites/installer
41 | { networking.networkmanager.enable = true; }
42 | ];
43 | }).config.system.build.sdImage;
44 | };
45 | };
46 | }
47 |
--------------------------------------------------------------------------------
/flake-parts/nixos.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | let
3 | inherit (inputs) self flake-pins;
4 | in
5 | {
6 | flake = {
7 | nixosModules = {
8 | default =
9 | {
10 | # Explicitly pass as specialArg to prevent infinite recursion when
11 | # determining the modules to import
12 | hostPubkey,
13 | config,
14 | lib,
15 | ...
16 | }:
17 | let
18 | inherit (config.networking) hostName;
19 | configurationRevision = "${builtins.substring 0 8 self.lastModifiedDate}.${self.rev or "dirty"}";
20 | # hostPubkey = self.lib.hostPubkeys.${hostName} or null;
21 | in
22 | {
23 | system.configurationRevision = lib.mkIf (inputs.self ? lastModifiedDate) configurationRevision;
24 | nixpkgs.overlays = [ inputs.self.overlays.default ];
25 |
26 | imports =
27 | [
28 | inputs.disko.nixosModules.disko
29 | inputs.impermanence.nixosModules.impermanence
30 | flake-pins.nixosModules.nix-registry
31 | ]
32 | ++ lib.optionals (hostPubkey != null) [
33 | inputs.agenix.nixosModules.default
34 | inputs.agenix-rekey.nixosModules.default
35 | # You have to define these options for every host.
36 | {
37 | age.rekey = {
38 | inherit hostPubkey;
39 | masterIdentities = [ ../secrets/yubikey.pub ];
40 | storageMode = "local";
41 | localStorageDir = ../. + "/secrets/rekeyed/${hostName}";
42 | # TODO: Add backup keys
43 | # extraEncryptionPubkeys = [];
44 | };
45 | }
46 | ];
47 | };
48 |
49 | };
50 | };
51 | }
52 |
--------------------------------------------------------------------------------
/flake-parts/pkgs.nix:
--------------------------------------------------------------------------------
1 | { lib, inputs, ... }:
2 | let
3 | inherit (inputs) unstable;
4 |
5 | overlays = [
6 | inputs.flake-pins.overlays.default
7 | (_final: prev: {
8 | channels = lib.genAttrs [
9 | "hyprland-contrib"
10 | "fonts"
11 | "zsh-plugins"
12 | ] (name: inputs.${name}.packages.${prev.system});
13 | unstable = unstable.legacyPackages.${prev.system};
14 | # Explicit import from the small nixpkgs.
15 | unstable-small-unfree = import inputs.unstable-small {
16 | inherit (prev) system;
17 | config.allowUnfree = true;
18 | };
19 | # unstable-small = inputs.unstable-small.legacyPackages.${prev.system};
20 | disko = inputs.disko.packages.${prev.system}.disko;
21 | nix-index = inputs.nix-index-database.packages.${prev.system}.nix-index-with-db;
22 | })
23 | ];
24 | in
25 | {
26 | flake = {
27 | overlays.default = lib.composeManyExtensions overlays;
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/flake-parts/treefmt.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | {
3 | imports = [
4 | inputs.treefmt-nix.flakeModule
5 | ];
6 |
7 | perSystem = _: {
8 | treefmt = {
9 | projectRootFile = "README.org";
10 | programs = {
11 | # Previously alejandra had been used for formatting Nix, and I don't want to
12 | # reformat existing files until its' necessary. Thus I will disable
13 | # formatting checks on Nix code.
14 |
15 | # nixfmt-rfc-style.enable = true;
16 |
17 | deadnix.enable = true;
18 | shellcheck.enable = true;
19 | yamlfmt.enable = true;
20 | };
21 |
22 | settings.excludes = [
23 | "*.age"
24 | "*.pub"
25 | "*.org"
26 | ];
27 |
28 | settings.formatter = {
29 | shellcheck.excludes = [ ".envrc" ];
30 | };
31 | } ;
32 | };
33 | }
34 |
--------------------------------------------------------------------------------
/flake.nix:
--------------------------------------------------------------------------------
1 | {
2 | inputs = {
3 | flake-pins.url = "github:akirak/flake-pins";
4 |
5 | unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
6 | stable.url = "github:NixOS/nixpkgs/nixos-25.05";
7 |
8 | # More frequently input to use the newer versions of packages.
9 | unstable-small.url = "github:NixOS/nixpkgs/nixos-unstable-small";
10 |
11 | home-manager-stable.url = "github:nix-community/home-manager/release-25.05";
12 | home-manager-unstable.url = "github:nix-community/home-manager";
13 | nix-darwin.url = "github:LnL7/nix-darwin";
14 |
15 | nixos-hardware.url = "github:NixOS/nixos-hardware";
16 |
17 | home-manager-stable.inputs.nixpkgs.follows = "stable";
18 | home-manager-unstable.inputs.nixpkgs.follows = "unstable";
19 |
20 | flake-parts.url = "github:hercules-ci/flake-parts";
21 |
22 | disko = {
23 | url = "github:nix-community/disko";
24 | inputs.nixpkgs.follows = "unstable";
25 | };
26 |
27 | impermanence.url = "github:nix-community/impermanence";
28 |
29 | agenix.url = "github:ryantm/agenix";
30 | agenix-rekey.url = "github:oddlama/agenix-rekey";
31 | agenix-rekey.inputs.nixpkgs.follows = "unstable";
32 |
33 | # cachix-deploy-flake = {
34 | # url = "github:cachix/cachix-deploy-flake";
35 | # inputs.nixpkgs.follows = "stable";
36 | # inputs.home-manager.follows = "home-manager-stable";
37 | # inputs.darwin.follows = "nix-darwin";
38 | # };
39 |
40 | treefmt-nix.url = "github:numtide/treefmt-nix";
41 |
42 | nix-index-database = {
43 | url = "github:Mic92/nix-index-database";
44 | inputs.nixpkgs.follows = "unstable";
45 | };
46 |
47 | hyprland-contrib.url = "github:hyprwm/contrib";
48 |
49 | emacs-config = {
50 | url = "github:akirak/emacs-config/develop";
51 | inputs.twist.follows = "twist";
52 | };
53 | twist.url = "github:emacs-twist/twist.nix";
54 | };
55 |
56 | nixConfig = {
57 | extra-substituters = [
58 | "https://cachix.cachix.org"
59 | "https://hyprland.cachix.org"
60 | "https://akirak.cachix.org"
61 | "https://nix-community.cachix.org"
62 | ];
63 | extra-trusted-public-keys = [
64 | "cachix.cachix.org-1:eWNHQldwUO7G2VkjpnjDbWwy4KQ/HNxht7H4SSoMckM="
65 | "hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="
66 | "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
67 | "akirak.cachix.org-1:WJrEMdV1dYyALkOdp/kAECVZ6nAODY5URN05ITFHC+M="
68 | ];
69 | };
70 |
71 | outputs =
72 | {
73 | unstable,
74 | flake-parts,
75 | ...
76 | }@inputs:
77 | flake-parts.lib.mkFlake { inherit inputs; } {
78 | imports = [
79 | ./flake-parts/deploy.nix
80 | ./flake-parts/treefmt.nix
81 | ./flake-parts/agenix.nix
82 | ./flake-parts/installers.nix
83 | ./flake-parts/pkgs.nix
84 | ./flake-parts/emacs.nix
85 | ./flake-parts/nixos.nix
86 | ./flake-parts/home-manager.nix
87 | # ./flake-parts/cachix-deploy.nix
88 |
89 | ./templates/flake-module.nix
90 |
91 | ./nixos/models/asus-br1100/flake-module.nix
92 |
93 | ./machines/li/flake-module.nix
94 | ./machines/yang/flake-module.nix
95 | ./machines/wang/flake-module.nix
96 | ./machines/shu/flake-module.nix
97 | ./machines/hui/flake-module.nix
98 | ./machines/zheng/flake-module.nix
99 | ];
100 |
101 | systems = [
102 | "x86_64-linux"
103 | "aarch64-linux"
104 | ];
105 |
106 | perSystem =
107 | {
108 | system,
109 | ...
110 | }:
111 | {
112 | _module.args.pkgs = unstable.legacyPackages.${system};
113 | };
114 | };
115 | }
116 |
--------------------------------------------------------------------------------
/homes/basic.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 | {
3 | programs = {
4 | nix-index.enable = true;
5 | nix-index.enableZshIntegration = config.programs.nix-index.enable;
6 | password-store.enable = true;
7 | };
8 |
9 | home.packages = with pkgs; [
10 | # Nix
11 | nix-prefetch-git
12 | nix-output-monitor
13 |
14 | # Development
15 | gh
16 | difftastic
17 | duckdb
18 | tbls
19 | hyperfine
20 | just
21 | tailspin
22 |
23 | # Media
24 | git-annex
25 |
26 | # System
27 | btop
28 | dua
29 | duf
30 |
31 | # Net
32 | xh
33 | ];
34 |
35 | services = {
36 | recoll.enable = true;
37 | syncthing.enable = true;
38 | };
39 | }
40 |
--------------------------------------------------------------------------------
/homes/code.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | pkgs,
5 | ...
6 | }:
7 | let
8 | # Build an interpreter-only derivation for running a package directly.
9 | onlySingleBin =
10 | drv: name:
11 | (pkgs.callPackage (
12 | { runCommand, makeWrapper }:
13 | runCommand name
14 | {
15 | buildInputs = [
16 | makeWrapper
17 | ];
18 | propagatedBuildInputs = [ drv ];
19 | }
20 | ''
21 | mkdir -p $out/bin
22 | makeWrapper ${lib.getExe' drv name} $out/bin/${name} \
23 | --prefix PATH : ${lib.getBin drv}/bin
24 | ''
25 | ) { });
26 | in
27 | {
28 | # Custom module
29 | programs.aider = {
30 | enable = true;
31 | age = {
32 | identityFile = lib.mkDefault ../secrets/yubikey.pub;
33 | envFile = lib.mkDefault ../secrets/aider-env.age;
34 | };
35 | };
36 |
37 | programs.uv.enable = true;
38 |
39 | home.packages =
40 | (with pkgs; [
41 | yamlfmt
42 | vscode-langservers-extracted # Primarily for the JSON server
43 | nil # Nix
44 | just-lsp
45 |
46 | customPackages.codex-cli
47 | unstable-small-unfree.claude-code
48 |
49 | # Used to run MCP servers.
50 | (onlySingleBin pkgs.nodejs "npx")
51 | ])
52 | ++ (lib.optional (!config.programs.uv.enable) (onlySingleBin pkgs.uv "uvx"))
53 | ++ (lib.optionals pkgs.stdenv.isLinux [
54 | # Sandbox MCP scripts
55 | pkgs.bubblewrap
56 | ]);
57 | }
58 |
--------------------------------------------------------------------------------
/homes/core.nix:
--------------------------------------------------------------------------------
1 | {
2 | lib,
3 | pkgs,
4 | config,
5 | ...
6 | }: let
7 | enableDirenv = config.programs.direnv.enable;
8 | in {
9 | imports = import ./modules.nix {inherit lib;};
10 |
11 | programs = {
12 | bat.enable = true;
13 | eza.enable = true;
14 | git.enable = true; # ./modules/git.nix
15 | gpg.enable = true; # ./modules/gpg.nix
16 | direnv.enable = true; # ./modules/direnv.nix
17 | direnv.nix-direnv.enable = lib.mkIf enableDirenv true;
18 | };
19 |
20 | home.packages = with pkgs; [
21 | # Utilities
22 | ripgrep
23 | fd
24 | jq
25 | ];
26 | }
27 |
--------------------------------------------------------------------------------
/homes/etc/river/init:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # This is the example configuration file for river.
4 | #
5 | # If you wish to edit this, you will probably want to copy it to
6 | # $XDG_CONFIG_HOME/river/init or $HOME/.config/river/init first.
7 | #
8 | # See the river(1), riverctl(1), and rivertile(1) man pages for complete
9 | # documentation.
10 |
11 | # Note: the "Super" modifier is also known as Logo, GUI, Windows, Mod4, etc.
12 |
13 | # Also inspired by
14 | # https://github.com/4Dk3/Sway-waybar-and-river/blob/main/river/init
15 |
16 | waybar &
17 | foot --server &
18 | dunst &
19 |
20 | riverctl map normal Super+Shift Return spawn foot
21 |
22 | # Super+Q to close the focused view
23 | riverctl map normal Super Q close
24 |
25 | riverctl map normal Super P spawn 'fuzzel'
26 |
27 | riverctl map normal Super+Shift S spawn 'flameshot gui'
28 |
29 | riverctl map normal Super F9 spawn 'foot nixos-rebuild-and-notify'
30 |
31 | riverctl map normal Super E spawn 'emacsclient -c -a emacs'
32 |
33 | # Super+Shift+Q to exit river
34 | riverctl map normal Super+Shift Q exit
35 |
36 | # Super+J and Super+K to focus the next/previous view in the layout stack
37 | riverctl map normal Super J focus-view next
38 | riverctl map normal Super K focus-view previous
39 |
40 | # Super+Shift+J and Super+Shift+K to swap the focused view with the next/previous
41 | # view in the layout stack
42 | riverctl map normal Super+Shift J swap next
43 | riverctl map normal Super+Shift K swap previous
44 |
45 | # Super+] and Super+[ to focus the next/previous output
46 | riverctl map normal Super BracketRight focus-output next
47 | riverctl map normal Super BracketLeft focus-output previous
48 |
49 | # Super+Shift+{[,]} to send the focused view to the next/previous output
50 | riverctl map normal Super+Shift BracketRight send-to-output next
51 | riverctl map normal Super+Shift BracketLeftComma send-to-output previous
52 |
53 | # Super+Return to bump the focused view to the top of the layout stack
54 | riverctl map normal Super Return zoom
55 |
56 | # Super+H and Super+L to decrease/increase the main ratio of rivertile(1)
57 | riverctl map normal Super H send-layout-cmd rivertile "main-ratio -0.05"
58 | riverctl map normal Super L send-layout-cmd rivertile "main-ratio +0.05"
59 |
60 | # Super+Shift+H and Super+Shift+L to increment/decrement the main count of rivertile(1)
61 | riverctl map normal Super+Shift H send-layout-cmd rivertile "main-count +1"
62 | riverctl map normal Super+Shift L send-layout-cmd rivertile "main-count -1"
63 |
64 | # Super+Alt+{H,J,K,L} to move views
65 | riverctl map normal Super+Alt H move left 100
66 | riverctl map normal Super+Alt J move down 100
67 | riverctl map normal Super+Alt K move up 100
68 | riverctl map normal Super+Alt L move right 100
69 |
70 | # Super+Alt+Control+{H,J,K,L} to snap views to screen edges
71 | riverctl map normal Super+Alt+Control H snap left
72 | riverctl map normal Super+Alt+Control J snap down
73 | riverctl map normal Super+Alt+Control K snap up
74 | riverctl map normal Super+Alt+Control L snap right
75 |
76 | # Super+Alt+Shift+{H,J,K,L} to resize views
77 | riverctl map normal Super+Alt+Shift H resize horizontal -100
78 | riverctl map normal Super+Alt+Shift J resize vertical 100
79 | riverctl map normal Super+Alt+Shift K resize vertical -100
80 | riverctl map normal Super+Alt+Shift L resize horizontal 100
81 |
82 | # Super + Left Mouse Button to move views
83 | riverctl map-pointer normal Super BTN_LEFT move-view
84 |
85 | # Super + Right Mouse Button to resize views
86 | riverctl map-pointer normal Super BTN_RIGHT resize-view
87 |
88 | for i in $(seq 1 9)
89 | do
90 | tags=$((1 << ($i - 1)))
91 |
92 | # Super+[1-9] to focus tag [0-8]
93 | riverctl map normal Super $i set-focused-tags $tags
94 |
95 | # Super+Shift+[1-9] to tag focused view with tag [0-8]
96 | riverctl map normal Super+Shift $i set-view-tags $tags
97 |
98 | # Super+Ctrl+[1-9] to toggle focus of tag [0-8]
99 | riverctl map normal Super+Control $i toggle-focused-tags $tags
100 |
101 | # Super+Shift+Ctrl+[1-9] to toggle tag [0-8] of focused view
102 | riverctl map normal Super+Shift+Control $i toggle-view-tags $tags
103 | done
104 |
105 | # Super+0 to focus all tags
106 | # Super+Shift+0 to tag focused view with all tags
107 | all_tags=$(((1 << 32) - 1))
108 | riverctl map normal Super 0 set-focused-tags $all_tags
109 | riverctl map normal Super+Shift 0 set-view-tags $all_tags
110 |
111 | # Super+Space to toggle float
112 | riverctl map normal Super Space toggle-float
113 |
114 | # Super+F to toggle fullscreen
115 | riverctl map normal Super F toggle-fullscreen
116 |
117 | # Super+{Up,Right,Down,Left} to change layout orientation
118 | riverctl map normal Super Up send-layout-cmd rivertile "main-location top"
119 | riverctl map normal Super Right send-layout-cmd rivertile "main-location right"
120 | riverctl map normal Super Down send-layout-cmd rivertile "main-location bottom"
121 | riverctl map normal Super Left send-layout-cmd rivertile "main-location left"
122 |
123 | # Declare a passthrough mode. This mode has only a single mapping to return to
124 | # normal mode. This makes it useful for testing a nested wayland compositor
125 | riverctl declare-mode passthrough
126 |
127 | # Super+F11 to enter passthrough mode
128 | riverctl map normal Super F11 enter-mode passthrough
129 |
130 | # Super+F11 to return to normal mode
131 | riverctl map passthrough Super F11 enter-mode normal
132 |
133 | # Various media key mapping examples for both normal and locked mode which do
134 | # not have a modifier
135 | for mode in normal locked
136 | do
137 | # Eject the optical drive (well if you still have one that is)
138 | riverctl map $mode None XF86Eject spawn 'eject -T'
139 |
140 | # Control pulse audio volume with pamixer (https://github.com/cdemoulins/pamixer)
141 | riverctl map $mode None XF86AudioRaiseVolume spawn 'pamixer -i 3'
142 | riverctl map $mode Super Equal spawn 'pamixer -i 3'
143 | riverctl map $mode None XF86AudioLowerVolume spawn 'pamixer -d 3'
144 | riverctl map $mode Super Minus spawn 'pamixer -d 3'
145 | riverctl map $mode None XF86AudioMute spawn 'pamixer --toggle-mute'
146 | riverctl map $mode Super Delete spawn 'pamixer --toggle-mute'
147 |
148 | # Control MPRIS aware media players with playerctl (https://github.com/altdesktop/playerctl)
149 | riverctl map $mode None XF86AudioMedia spawn 'playerctl play-pause'
150 | riverctl map $mode None XF86AudioPlay spawn 'playerctl play-pause'
151 | riverctl map $mode None XF86AudioPrev spawn 'playerctl previous'
152 | riverctl map $mode None XF86AudioNext spawn 'playerctl next'
153 |
154 | # Control screen backlight brightness with light (https://github.com/haikarainen/light)
155 | riverctl map $mode None XF86MonBrightnessUp spawn 'light -A 5'
156 | riverctl map $mode None XF86MonBrightnessDown spawn 'light -U 5'
157 | done
158 |
159 | # Set background and border color
160 | riverctl background-color 0x002b36
161 | riverctl border-color-focused 0x93a1a1
162 | riverctl border-color-unfocused 0x586e75
163 |
164 | # Set keyboard repeat rate
165 | riverctl set-repeat 50 300
166 |
167 | # Make certain views start floating
168 | riverctl float-filter-add app-id float
169 | riverctl float-filter-add title "popup title with spaces"
170 |
171 | # Set app-ids and titles of views which should use client side decorations
172 | riverctl csd-filter-add app-id "gedit"
173 |
174 | # Set the default layout generator to be rivertile and start it.
175 | # River will send the process group of the init executable SIGTERM on exit.
176 | riverctl default-layout rivertile
177 | rivertile -view-padding 6 -outer-padding 6
178 |
--------------------------------------------------------------------------------
/homes/etc/starship/starship.toml:
--------------------------------------------------------------------------------
1 | "$schema" = 'https://starship.rs/config-schema.json'
2 |
3 | add_newline = true
4 |
5 | format = """
6 | $hostname\
7 | $directory\
8 | $git_branch\
9 | $git_state\
10 | $git_status\
11 | $line_break\
12 | $time\
13 | $status\
14 | $cmd_duration\
15 | $username\
16 | $jobs\
17 | [\\$](green) \
18 | """
19 |
20 | [character]
21 | disabled = true
22 |
23 | [package]
24 | disabled = true
25 |
26 | [cmd_duration]
27 | min_time = 20_000
28 | format = '[in $duration]($style) '
29 |
30 | [directory]
31 | truncation_length = 0
32 | truncate_to_repo = false
33 | read_only = 'RO'
34 |
35 | [direnv]
36 | disabled = true
37 |
38 | [git_branch]
39 | format = '[$symbol$branch(:$remote_branch)]($style) '
40 | symbol = ''
41 | truncation_length = 32
42 |
43 | [git_commit]
44 | disabled = true
45 |
46 | [git_state]
47 | disabled = false
48 |
49 | [git_metrics]
50 | disabled = true
51 |
52 | [git_status]
53 | disabled = false
54 |
55 | [hostname]
56 | disabled = false
57 | ssh_only = false
58 | format = '[$hostname]($style):'
59 |
60 | [username]
61 | disabled = false
62 | show_always = false
63 | format = 'as [$user]($style) '
64 |
65 | [status]
66 | disabled = false
67 | format = '[$status$symbol](bold red) '
68 | symbol = '✘'
69 | success_symbol = ''
70 |
71 | [time]
72 | disabled = false
73 | format = '[$time]($style) '
74 | time_format = '%R'
75 |
--------------------------------------------------------------------------------
/homes/extra.nix:
--------------------------------------------------------------------------------
1 | { pkgs, ... }:
2 | {
3 | home.packages = [
4 | # networking
5 | pkgs.dig
6 | pkgs.nmap
7 | pkgs.tcpdump
8 | pkgs.nssTools
9 | ];
10 | }
11 |
--------------------------------------------------------------------------------
/homes/graphical.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | pkgs,
5 | ...
6 | }:
7 | let
8 | enableFoot = config.programs.foot.enable;
9 | enableWayland = true;
10 |
11 | defaultBrowser =
12 | if config.programs.librewolf.enable then
13 | "librewolf.desktop"
14 | else if config.programs.firefox.enable then
15 | "firefox.desktop"
16 | else
17 | null;
18 |
19 | defaultApplications = {
20 | "image/svg+xml" = [
21 | defaultBrowser
22 | ];
23 | };
24 | in
25 | {
26 | programs = {
27 | # alacritty.enable = enableGraphical;
28 | mpv.enable = true;
29 | foot.enable = enableWayland;
30 | foot.server.enable = enableFoot;
31 | # TODO: Add font package
32 | foot.settings.main.font = "JetBrainsMono NF:size=10.5";
33 |
34 | # See modules/librewolf.nix for details
35 | librewolf.enable = true;
36 | # firefox.enable = true;
37 |
38 | # AI coding (Cline)
39 | # vscode.enable = true;
40 |
41 | # enable auto-notify plugin only in graphical environments
42 | zsh = {
43 | plugins = [
44 | {
45 | name = "auto-notify";
46 | src = pkgs.customZshPlugins.zsh-auto-notify;
47 | }
48 | ];
49 | sessionVariables = {
50 | # https://github.com/MichaelAquilina/zsh-auto-notify
51 | "AUTO_NOTIFY_THRESHOLD" = "60";
52 | };
53 | initContent = ''
54 | export AUTO_NOTIFY_IGNORE=("nix shell" "nix develop" "ssh" "agenix edit" "man" "less")
55 | '';
56 | };
57 | };
58 |
59 | home.packages =
60 | (with pkgs; [
61 | blanket
62 | pavucontrol
63 |
64 | # required by zsh-auto-notify plugin
65 | libnotify
66 |
67 | # API development
68 | # hoppscotch
69 |
70 | # database admin
71 | # beekeeper-studio
72 |
73 | # fonts
74 | customFontPackages.jetbrains-mono-nerdfont
75 | # Japanese
76 | ipafont
77 | ])
78 | ++ lib.optionals enableWayland [
79 | pkgs.wayshot
80 | pkgs.wf-recorder
81 | pkgs.slurp # Used with wayshot
82 | pkgs.wl-clipboard
83 |
84 | (pkgs.writeShellApplication {
85 | name = "lock-screen";
86 | runtimeInputs = [ pkgs.swaylock-effects ];
87 | # TODO: Use a color scheme
88 | text = ''
89 | swaylock -f --clock --fade-in 0.5
90 | '';
91 | })
92 | ];
93 |
94 | xdg.mime.enable = true;
95 | xdg.mimeApps = lib.mkIf (defaultBrowser != null) {
96 | enable = true;
97 | inherit defaultBrowser;
98 | inherit defaultApplications;
99 | associations.added = defaultApplications;
100 | };
101 |
102 | systemd.user.services.emacs = {
103 | Service = {
104 | Environment = lib.optionals enableWayland [
105 | "MOZ_ENABLE_WAYLAND=1"
106 | "WAYLAND_DISPLAY=wayland-1"
107 | ];
108 | };
109 | };
110 |
111 | systemd.user.services.foot = lib.mkIf config.programs.foot.server.enable {
112 | Service = {
113 | Environment = lib.mkForce [
114 | "WAYLAND_DISPLAY=wayland-1"
115 | "PATH=${
116 | lib.concatMapStrings (dir: dir + ":") config.home.sessionPath
117 | }${config.home.profileDirectory}/bin"
118 | ];
119 | };
120 | };
121 | }
122 |
--------------------------------------------------------------------------------
/homes/lib/waybar-config.nix:
--------------------------------------------------------------------------------
1 | let
2 | inherit (builtins) toJSON isFunction;
3 |
4 | defaultModulesRight = [
5 | "idle_inhibitor"
6 | "pulseaudio"
7 | "network"
8 | "cpu"
9 | "memory"
10 | "temperature"
11 | "backlight"
12 | "keyboard-state"
13 | # "custom/nixos"
14 | "clock"
15 | "tray"
16 | ];
17 | in
18 | {
19 | writeText,
20 | modulesCenter ? ["hyprland/window"],
21 | modulesLeft ? ["wlr/workspaces"],
22 | modulesRight ? defaultModulesRight,
23 | }:
24 | # Based on https://github.com/Alexays/Waybar/blob/master/resources/config
25 | writeText "config" ''
26 | {
27 | "height": 30,
28 | "spacing": 4,
29 | "modules-left": ${toJSON modulesLeft},
30 | "modules-center": ${toJSON modulesCenter},
31 | "modules-right": ${toJSON (
32 | if isFunction modulesRight
33 | then modulesRight defaultModulesRight
34 | else modulesRight
35 | )},
36 | "keyboard-state": {
37 | "numlock": true,
38 | "capslock": true,
39 | "format": "{name} {icon}",
40 | "format-icons": {
41 | "locked": "",
42 | "unlocked": ""
43 | }
44 | },
45 | "sway/mode": {
46 | "format": "{}"
47 | },
48 | "sway/scratchpad": {
49 | "format": "{icon} {count}",
50 | "show-empty": false,
51 | "format-icons": ["", ""],
52 | "tooltip": true,
53 | "tooltip-format": "{app}: {title}"
54 | },
55 | "wlr/workspaces": {
56 | "format": "{icon}",
57 | },
58 | "hyprland/window": {
59 | "format": "{}",
60 | "separate-outputs": true
61 | },
62 | "hyprland/submap": {
63 | "format": "✌️ {}",
64 | "max-length": 8,
65 | "tooltip": false
66 | },
67 | "idle_inhibitor": {
68 | "format": "{icon}",
69 | "format-icons": {
70 | "activated": "",
71 | "deactivated": ""
72 | }
73 | },
74 | "tray": {
75 | "spacing": 10
76 | },
77 | "clock": {
78 | "format-alt": "{:%Y-%m-%d}",
79 | "tooltip-format": "{:%Y %B}\n{calendar}"
80 | },
81 | "cpu": {
82 | "format": "{usage}% ",
83 | "tooltip": false
84 | },
85 | "memory": {
86 | "format": "{}% "
87 | },
88 | "temperature": {
89 | "critical-threshold": 80,
90 | "format": "{temperatureC}°C {icon}",
91 | "format-icons": ["", "", ""]
92 | },
93 | "backlight": {
94 | "format": "{percent}% {icon}",
95 | "format-icons": ["", "", "", "", "", "", "", "", ""]
96 | },
97 | "battery": {
98 | "states": {
99 | "warning": 30,
100 | "critical": 15
101 | },
102 | "format": "{capacity}% {icon}",
103 | "format-charging": "{capacity}% ",
104 | "format-plugged": "{capacity}% ",
105 | "format-alt": "{time} {icon}",
106 | "format-icons": ["", "", "", "", ""]
107 | },
108 | "battery#bat2": {
109 | "bat": "BAT2"
110 | },
111 | "network": {
112 | "format-wifi": "{essid} ({signalStrength}%) ",
113 | "format-ethernet": "{ipaddr}/{cidr} ",
114 | "tooltip-format": "{ifname} via {gwaddr} ",
115 | "format-linked": "{ifname} (No IP) ",
116 | "format-disconnected": "Disconnected ⚠",
117 | "format-alt": "{ifname}: {ipaddr}/{cidr}"
118 | },
119 | "pulseaudio": {
120 | "format": "{volume}% {icon} {format_source}",
121 | "format-bluetooth": "{volume}% {icon} {format_source}",
122 | "format-bluetooth-muted": " {icon} {format_source}",
123 | "format-muted": " {format_source}",
124 | "format-source": "{volume}% ",
125 | "format-source-muted": "",
126 | "format-icons": {
127 | "headphone": "",
128 | "hands-free": "",
129 | "headset": "",
130 | "phone": "",
131 | "portable": "",
132 | "car": "",
133 | "default": ["", "", ""]
134 | },
135 | "on-click": "pavucontrol"
136 | },
137 | "custom/nixos": {
138 | "interval": 60,
139 | "exec": "nixos-version --configuration-revision"
140 | }
141 | }
142 | ''
143 |
--------------------------------------------------------------------------------
/homes/modules.nix:
--------------------------------------------------------------------------------
1 | { lib }:
2 | let
3 | dir = ./modules;
4 |
5 | isModule =
6 | name: type: ((type == "regular") && (lib.hasSuffix ".nix" name)) || (type == "directory");
7 | in
8 | lib.pipe (builtins.readDir dir) [
9 | (lib.filterAttrs isModule)
10 | builtins.attrNames
11 | (builtins.map (filename: dir + "/${filename}"))
12 | ]
13 |
--------------------------------------------------------------------------------
/homes/modules/aider/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | imports = [
3 | ./interface.nix
4 | ];
5 | }
6 |
--------------------------------------------------------------------------------
/homes/modules/aider/interface.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | pkgs,
5 | ...
6 | }:
7 | let
8 | cfg = config.programs.aider;
9 |
10 | inherit (lib) mkOption mkEnableOption types;
11 |
12 | wrapped = cfg.package.overrideAttrs (old: {
13 | nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [
14 | pkgs.makeWrapper
15 | ];
16 | propagatedBuildInputs = (old.propagatedBuildInputs or [ ]) ++ [
17 | cfg.age.package
18 | ];
19 | # Store one or more multiple --api-key options in an age-encrypted
20 | # file and decrypt the content when the program starts.
21 | postInstall = ''
22 | wrapProgram $out/bin/aider \
23 | --inherit-argv0 \
24 | --run 'export $(${lib.getExe cfg.age.package} \
25 | -i ${cfg.age.identityFile} \
26 | --decrypt ${cfg.age.envFile})'
27 | '';
28 | });
29 | in
30 | {
31 | options = {
32 | programs.aider = {
33 | enable = mkEnableOption (lib.mdDoc "Whether to install a custom wrapped version of aider-chat");
34 |
35 | package = mkOption {
36 | type = types.package;
37 | description = lib.mdDoc "aider-chat package";
38 | default = pkgs.aider-chat;
39 | };
40 |
41 | age = {
42 | package = mkOption {
43 | type = types.package;
44 | description = lib.mdDoc "age package";
45 | default = pkgs.age;
46 | };
47 |
48 | envFile = mkOption {
49 | type = types.path;
50 | description = lib.mdDoc "Path to an age-encrypted secret";
51 | };
52 |
53 | identityFile = mkOption {
54 | type = types.path;
55 | description = lib.mdDoc "Path to an identity file";
56 | };
57 | };
58 | };
59 | };
60 |
61 | config = {
62 | home.packages = lib.optionals cfg.enable [
63 | wrapped
64 | ];
65 | };
66 | }
67 |
--------------------------------------------------------------------------------
/homes/modules/browser.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | ...
5 | }: let
6 | cfg = config.xdg.mimeApps.defaultBrowser;
7 | inherit (lib) types;
8 | in {
9 | options = {
10 | xdg.mimeApps.defaultBrowser = lib.mkOption {
11 | type = types.nullOr types.str;
12 | description = lib.mdDoc ''
13 | Desktop file for the browser. It should support both `text/html` and
14 | `x-scheme-handler/https`.
15 | '';
16 | default = null;
17 | };
18 | };
19 |
20 | config = {
21 | xdg.mimeApps.defaultApplications = lib.mkIf (cfg != null) {
22 | "text/html" = cfg;
23 | "x-scheme-handler/http" = cfg;
24 | "x-scheme-handler/https" = cfg;
25 | };
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/homes/modules/crostini.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | ...
5 | }: let
6 | inherit (lib) mkIf mkOption types;
7 |
8 | cfg = config.targets.crostini;
9 | in {
10 | options = {
11 | targets.crostini = {
12 | enable = mkOption {
13 | type = types.bool;
14 | default = false;
15 | description = ''
16 | Whether to enable settings that make Home Manager work better on
17 | Crostini (Linux container) on Chrome OS.
18 | '';
19 | };
20 | };
21 | };
22 |
23 | config = mkIf cfg.enable {
24 | targets.genericLinux.enable = true;
25 |
26 | xdg.configFile."systemd/user/cros-garcon.service.d/override.conf".text = ''
27 | [Service]
28 | Environment="PATH=${builtins.concatStringsSep ":"
29 | [
30 | "%h/.nix-profile/bin"
31 | "/usr/local/sbin"
32 | "/usr/local/bin"
33 | "/usr/local/games"
34 | "/usr/sbin"
35 | "/usr/bin"
36 | "/usr/games"
37 | "/sbin"
38 | "/bin"
39 | ]}" "XDG_DATA_DIRS=${builtins.concatStringsSep ":"
40 | [
41 | "%h/.nix-profile/share"
42 | "%h/.local/share"
43 | "/usr/local/share"
44 | "/usr/share"
45 | ]}"
46 | '';
47 | };
48 | }
49 |
--------------------------------------------------------------------------------
/homes/modules/direnv.nix:
--------------------------------------------------------------------------------
1 | {
2 | lib,
3 | config,
4 | ...
5 | }: let
6 | cfg = config.programs.direnv;
7 | in {
8 | programs.direnv = lib.mkIf cfg.enable (
9 | {
10 | enableZshIntegration = config.programs.zsh.enable;
11 | }
12 | // (
13 | if (builtins.compareVersions config.home.stateVersion "22.11" > 0)
14 | then {
15 | enableNushellIntegration =
16 | config.programs.nushell.enable;
17 | }
18 | else {}
19 | )
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/homes/modules/dunst.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | ...
5 | }: let
6 | cfg = config.services.dunst;
7 | in {
8 | config = lib.mkIf cfg.enable {
9 | services.dunst = {
10 | waylandDisplay = "wayland-1";
11 | settings = {
12 | global = {
13 | # monitor = 0;
14 | width = 300;
15 | height = 300;
16 | origin = "top-right";
17 | offset = "50x65";
18 |
19 | padding = 16;
20 | horizontal_padding = 16;
21 |
22 | transparency = 10;
23 |
24 | font = "JetBrainsMono Nerd Font 10";
25 | line_height = 4;
26 | format = ''%s\n%b'';
27 | };
28 | };
29 | };
30 | };
31 | }
32 |
--------------------------------------------------------------------------------
/homes/modules/fzy.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | home.packages = [
3 | (pkgs.writeShellApplication {
4 | name = "fzy-zfs-mount";
5 | runtimeInputs = [
6 | pkgs.fzy
7 | ];
8 | text = ''
9 | if fs=$(zfs list -Hp | cut -d $'\t' -f1 | fzy)
10 | then
11 | zfs mount "$fs"
12 | findmnt "$fs"
13 | fi
14 | '';
15 | })
16 | ];
17 | }
18 |
--------------------------------------------------------------------------------
/homes/modules/git.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | pkgs,
4 | lib,
5 | ...
6 | }:
7 | let
8 | inherit (lib) mkOption types;
9 |
10 | cfg = config.programs.git;
11 |
12 | makeGitConfig =
13 | {
14 | userName,
15 | userEmail,
16 | githubUser,
17 | signingKey,
18 | }:
19 | pkgs.writeText "config" (
20 | ''
21 | [user]
22 | name = "${userName}"
23 | email = "${userEmail}"
24 | ${lib.optionalString (signingKey != null) ''
25 | signingKey = "${signingKey}"
26 | ''}
27 | ''
28 | + lib.optionalString (githubUser != null) ''
29 | [github]
30 | user = "${githubUser}"
31 | ''
32 | );
33 |
34 | defaultIdentity = {
35 | email = "akira.komamura@gmail.com";
36 | fullName = "Akira Komamura";
37 | githubUser = "akirak";
38 | signingKey = "5B3390B01C01D3E";
39 | conditions = [
40 | "hasconfig:remote.*.url:git@github.com:akirak/**"
41 | "hasconfig:remote.*.url:git@github.com:emacs-twist/**"
42 | "hasconfig:remote.*.url:git@git.sr.ht:~akirak/**"
43 | "hasconfig:remote.*.url:https://github.com/akirak/**"
44 | "hasconfig:remote.*.url:https://github.com/emacs-twist/**"
45 | "hasconfig:remote.*.url:https://git.sr.ht/~akirak/**"
46 | "gitdir:~/work2/foss/"
47 | "gitdir:~/work2/learning/"
48 | "gitdir:~/work2/personal/"
49 | "gitdir:~/work2/prototypes/"
50 | "gitdir:/assets/"
51 | "gitdir:/git-annex/"
52 | ];
53 | };
54 |
55 | identityType = types.submodule {
56 | options = {
57 | email = mkOption {
58 | type = types.str;
59 | description = lib.mdDoc "E-mail address of the user";
60 | };
61 | fullName = mkOption {
62 | type = types.str;
63 | description = lib.mdDoc "Full name of the user";
64 | };
65 | githubUser = mkOption {
66 | type = types.nullOr types.str;
67 | description = lib.mdDoc "GitHub login of the user";
68 | default = null;
69 | };
70 | signingKey = mkOption {
71 | type = types.nullOr types.str;
72 | description = lib.mdDoc "GPG signing key";
73 | default = null;
74 | };
75 | conditions = mkOption {
76 | type = types.listOf types.str;
77 | description = lib.mdDoc "List of include conditions";
78 | };
79 | };
80 | };
81 | in
82 | {
83 | options.programs.git = {
84 | defaultIdentity = mkOption {
85 | type = types.nullOr identityType;
86 | description = lib.mdDoc "Default identity";
87 | default = defaultIdentity;
88 | };
89 |
90 | extraIdentities = mkOption {
91 | type = types.listOf identityType;
92 | description = lib.mdDoc "Extra list of identities";
93 | default = [ ];
94 | };
95 | };
96 |
97 | config = {
98 | programs.git = lib.mkIf cfg.enable {
99 | signing.format = lib.mkForce "openpgp";
100 |
101 | extraConfig = {
102 | pull.rebase = true;
103 |
104 | merge.conflictstyle = "diff3";
105 |
106 | "url \"git@github.com:\"".pushInsteadOf = "https://github.com/";
107 | "url \"git@git.sr.ht:\"".pushInsteadOf = "https://git.sr.ht/";
108 |
109 | core.autocrlf = "input";
110 |
111 | # Only on WSL
112 | # core.fileMode = false;
113 |
114 | # Increase the size of post buffers to prevent hung ups of git-push.
115 | # https://stackoverflow.com/questions/6842687/the-remote-end-hung-up-unexpectedly-while-git-cloning#6849424
116 | http.postBuffer = "524288000";
117 | };
118 |
119 | ignores = [
120 | ".direnv"
121 | "result"
122 | "result-*"
123 | "#*"
124 | ".git-bak*"
125 | ".aider*"
126 | # Non-standard
127 | "!.aider.conf.yml"
128 | "!.aiderignore"
129 | ];
130 |
131 | includes = lib.pipe ([ cfg.defaultIdentity ] ++ cfg.extraIdentities) [
132 | (builtins.filter (v: v != null))
133 | (builtins.map (
134 | {
135 | email,
136 | fullName,
137 | githubUser,
138 | signingKey,
139 | conditions,
140 | }:
141 | let
142 | configFile = makeGitConfig {
143 | inherit githubUser signingKey;
144 | userName = fullName;
145 | userEmail = email;
146 | };
147 | in
148 | builtins.map (condition: {
149 | path = configFile;
150 | inherit condition;
151 | }) conditions
152 | ))
153 | lib.flatten
154 | ];
155 | };
156 | };
157 | }
158 |
--------------------------------------------------------------------------------
/homes/modules/gpg.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | pkgs,
5 | ...
6 | }: let
7 | cfg = config.programs.gpg;
8 | in {
9 | services.gpg-agent = lib.mkIf cfg.enable {
10 | enable = true;
11 | enableSshSupport = true;
12 | defaultCacheTtl = 60;
13 | defaultCacheTtlSsh = 60;
14 | # Explicitly set the pinentry package when using a non-standard window
15 | # manager setting
16 | # https://discourse.nixos.org/t/help-with-pinentrypackage/41393/8
17 | pinentry.package = lib.mkForce pkgs.pinentry-gtk2;
18 | extraConfig = ''
19 | allow-emacs-pinentry
20 | allow-loopback-pinentry
21 | '';
22 | # pinentryFlavor = "gtk2";
23 | sshKeys = [
24 | "5B3390B01C01D3EE"
25 | ];
26 | };
27 |
28 | programs.bash.initExtra = lib.mkIf cfg.enable ''
29 | gpg-connect-agent /bye
30 | export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
31 | '';
32 | }
33 |
--------------------------------------------------------------------------------
/homes/modules/hyprland.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | pkgs,
4 | lib,
5 | ...
6 | }:
7 | let
8 | cfg = config.wayland.windowManager.hyprland or { enable = false; };
9 |
10 | footEnabled = config.programs.foot.enable;
11 |
12 | systemdTarget = "hyprland-session.target";
13 |
14 | systemdStartAfterThis = {
15 | Unit = {
16 | After = [ systemdTarget ];
17 | };
18 | Install = {
19 | WantedBy = [ systemdTarget ];
20 | };
21 | };
22 |
23 | runInTerminal = pkgs.writeShellScript "run-in-term" ''
24 | windowclass=$(basename "$1")
25 |
26 | options=()
27 | case "$windowclass" in
28 | hyprprop)
29 | options+=(--hold)
30 | ;;
31 | esac
32 |
33 | footclient -a "$windowclass" ''${options[@]} "$@"
34 | '';
35 | in
36 | {
37 | config = lib.mkIf cfg.enable {
38 | home.packages = with pkgs; [
39 | fuzzel
40 | dunst
41 | channels.hyprland-contrib.shellevents
42 | channels.hyprland-contrib.hyprprop
43 | ];
44 |
45 | programs.waybar = {
46 | enable = true;
47 | systemd.enable = true;
48 | systemd.target = systemdTarget;
49 | };
50 |
51 | xdg.configFile."waybar/config".source = pkgs.callPackage ../lib/waybar-config.nix {
52 | modulesCenter = [ "hyprland/window" ];
53 | modulesRight = ms: ms ++ [ "hyprland/submap" ];
54 | };
55 |
56 | programs.foot.server.enable = lib.mkIf footEnabled true;
57 | systemd.user.services.foot = lib.mkIf footEnabled systemdStartAfterThis;
58 |
59 | services.dunst = {
60 | enable = true;
61 | waylandDisplay = "wayland-1";
62 | };
63 | systemd.user.services.dunst = lib.mkIf config.services.dunst.enable systemdStartAfterThis;
64 |
65 | services.kanshi = {
66 | enable = true;
67 | systemdTarget = lib.mkForce systemdTarget;
68 | };
69 |
70 | wayland.windowManager.hyprland = {
71 | systemd.enable = true;
72 | xwayland.enable = true;
73 |
74 | settings = {
75 | "$mod" = "SUPER";
76 |
77 | input = {
78 | kb_layout = "us";
79 | kb_options = "ctrl:nocaps";
80 | };
81 |
82 | general = {
83 | border_size = 5;
84 | # TODO: Use a proper color scheme
85 | "col.active_border" = "rgba(ffaaff88)";
86 | "col.inactive_border" = "rgba(00000088)";
87 | gaps_in = 2;
88 | gaps_out = 5;
89 | };
90 |
91 | bindm = [
92 | "$mod ,mouse:272,movewindow"
93 | "$mod ,mouse:273,resizewindow"
94 | ];
95 |
96 | bind = [
97 | # Hyprland admin
98 | "$mod SHIFT , Q, exec, pkill Hyprland"
99 |
100 | # Launcher
101 | "$mod SHIFT , Return, exec, footclient"
102 | "$mod , Space, exec, fuzzel -T ${runInTerminal}"
103 | "$mod , E, exec, emacsclient -c -a emacs"
104 | "$mod SHIFT , S, exec, flameshot gui"
105 | "$mod , F9, exec, foot --title \"Rebuilding NixOS...\" nixos-rebuild-and-notify"
106 |
107 | # Window management
108 | "$mod , C , killactive"
109 | "$mod , T, togglefloating"
110 | "$mod , F, fullscreen"
111 | "$mod , ', pin"
112 |
113 | # Monitor
114 | "$mod , bracketleft, focusmonitor, -1"
115 | "$mod , bracketright, focusmonitor, 1"
116 | "$mod SHIFT , bracketleft, movewindow, mon:-1"
117 | "$mod SHIFT , bracketright, movewindow, mon:1"
118 | "$mod , Backspace, swapactiveworkspaces, current +1"
119 |
120 | # Master layout
121 | "$mod , Return, layoutmsg, swapwithmaster auto"
122 | "$mod , M, layoutmsg, focusmaster auto"
123 | "$mod , minus, splitratio, -0.15"
124 | "$mod , equal, splitratio, 0.15"
125 |
126 | # Move focus
127 | "$mod , h, movefocus, l"
128 | "$mod , j, movefocus, d"
129 | "$mod , k, movefocus, u"
130 | "$mod , l, movefocus, r"
131 | "$mod SHIFT , h, swapwindow, l"
132 | "$mod SHIFT , j, swapwindow, d"
133 | "$mod SHIFT , k, swapwindow, u"
134 | "$mod SHIFT , l, swapwindow, r"
135 | "$mod , period, focusurgentorlast"
136 | "$mod , comma, togglespecialworkspace"
137 | "$mod , s, movetoworkspace, special"
138 |
139 | # Workspace management
140 | "$mod , f5, exec, hyprctl keyword general:layout dwindle"
141 | "$mod , f6, exec, hyprctl keyword general:layout master"
142 |
143 | "$mod , 1, workspace, 1"
144 | "$mod SHIFT , 1, movetoworkspace, 1"
145 | "$mod , 2, workspace, 2"
146 | "$mod SHIFT , 2, movetoworkspace, 2"
147 | "$mod , 3, workspace, 3"
148 | "$mod SHIFT , 3, movetoworkspace, 3"
149 | "$mod , 4, workspace, 4"
150 | "$mod SHIFT , 4, movetoworkspace, 4"
151 | "$mod , 5, workspace, 5"
152 | "$mod SHIFT , 5, movetoworkspace, 5"
153 | ];
154 |
155 | windowrulev2 =
156 | let
157 | defaultDialogSize = "780 600";
158 |
159 | exactClass = className: "class:^(${className})$";
160 |
161 | exactTitle = className: "title:^(${className})$";
162 |
163 | andRules = builtins.concatStringsSep ",";
164 |
165 | generateRules =
166 | rules: windows:
167 | lib.flatten (builtins.map (window: (builtins.map (rule: "${rule},${window}") rules)) windows);
168 | in
169 | # FIXME: This doesn't work now.
170 | [ "workspace special,class:^(foot)$,title:^(Rebuilding)" ]
171 | ++ (generateRules
172 | [
173 | "float"
174 | "size 80% 80%"
175 | "center"
176 | ]
177 | [ (exactClass "btop") ]
178 | )
179 | ++ (generateRules
180 | [
181 | "float"
182 | "size 25% 25%"
183 | "move 74% 74%"
184 | ]
185 | [
186 | # This title is for Firefox which I use daily.
187 | (exactTitle "Picture-in-Picture")
188 | ]
189 | )
190 | ++ (generateRules
191 | [
192 | "float"
193 | "size ${defaultDialogSize}"
194 | "center"
195 | ]
196 | [
197 | (andRules [
198 | (exactClass "chromium")
199 | (exactTitle "Open Files")
200 | ])
201 | (exactTitle "Volume Control") # pavucontrol
202 | (exactClass "com.rafaelmardojai.Blanket")
203 | (exactTitle "Android Studio Setup Wizard")
204 | ]
205 | )
206 | ++ (generateRules
207 | [
208 | "float"
209 | "center"
210 | ]
211 | [
212 | (exactClass "mpv")
213 | (exactClass "VirtualBox Manager")
214 | ]
215 | );
216 | };
217 | };
218 | };
219 | }
220 |
--------------------------------------------------------------------------------
/homes/modules/librewolf.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | ...
5 | }:
6 | let
7 | cfg = config.programs.librewolf;
8 | in
9 | {
10 | # Basically just stolen from https://nixos.wiki/wiki/Librewolf
11 | programs.librewolf = lib.mkIf cfg.enable {
12 | # Enable WebGL, cookies and history
13 | settings = {
14 | "webgl.disabled" = false;
15 | "privacy.resistFingerprinting" = false;
16 | "privacy.clearOnShutdown.history" = false;
17 | "privacy.clearOnShutdown.cookies" = false;
18 | "network.cookie.lifetimePolicy" = 0;
19 | };
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/homes/modules/password-store.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | pkgs,
4 | lib,
5 | ...
6 | }:
7 | let
8 | cfg = config.programs.password-store;
9 |
10 | agePackage = pkgs.rage;
11 |
12 | passageRoot = "${config.home.homeDirectory}/secrets";
13 |
14 | # A wrapper for the steps described in https://github.com/FiloSottile/passage
15 | # for multiple YubiKey support
16 | passage-yubikey-update = pkgs.writeShellApplication {
17 | name = "passage-yubikey-update";
18 | runtimeInputs = [
19 | pkgs.age-plugin-yubikey
20 | ];
21 | text = ''
22 | if ! [[ -d "${cfg.settings.PASSAGE_DIR}" ]]; then
23 | echo >&2 "Error: ${cfg.settings.PASSAGE_DIR} must be created manually."
24 | exit 1
25 | fi
26 |
27 | identitiesFile="${cfg.settings.PASSAGE_IDENTITIES_FILE}"
28 | recipientsFile="${cfg.settings.PASSAGE_RECIPIENTS_FILE}"
29 |
30 | mkdir -p "$(dirname "$identitiesFile")"
31 | mkdir -p "$(dirname "$recipientsFile")"
32 |
33 | age-plugin-yubikey --identity >> "$identitiesFile"
34 | echo >&2 "Updated $identitiesFile"
35 |
36 | age-plugin-yubikey --list >> "$recipientsFile"
37 | echo >&2 "Updated $recipientsFile"
38 | '';
39 | };
40 | in
41 | {
42 | programs.password-store = {
43 | package = pkgs.passage;
44 | settings = {
45 | PASSAGE_DIR = "${passageRoot}/store";
46 | PASSAGE_AGE = lib.getExe agePackage;
47 | PASSAGE_IDENTITIES_FILE = "${passageRoot}/identities";
48 | PASSAGE_RECIPIENTS_FILE = "${passageRoot}/store/.age-recipients";
49 | };
50 | };
51 |
52 | home.packages = [
53 | passage-yubikey-update
54 | ];
55 | }
56 |
--------------------------------------------------------------------------------
/homes/modules/psd.nix:
--------------------------------------------------------------------------------
1 | {
2 | pkgs,
3 | lib,
4 | config,
5 | ...
6 | }: let
7 | inherit (builtins) concatStringsSep;
8 | # Enable only for selected browsers.
9 | browsers =
10 | (lib.optional config.programs.firefox.enable "firefox")
11 | ++ (lib.optional config.programs.chromium.enable "chromium");
12 | in {
13 | xdg.configFile."psd/psd.conf".text = ''
14 | USE_OVERLAYFS="${
15 | if pkgs.stdenv.targetPlatform.isLinux
16 | then "yes"
17 | else "no"
18 | }"
19 |
20 | BROWSERS=(${concatStringsSep " " browsers})
21 |
22 | BACKUP_LIMIT=3
23 | '';
24 | }
25 |
--------------------------------------------------------------------------------
/homes/modules/rebuild-home.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | pkgs,
5 | ...
6 | }: let
7 | inherit (lib) types;
8 |
9 | cfg = config.programs.rebuild-home;
10 |
11 | notify = "${pkgs.notify-desktop}/bin/notify-desktop -r home-manager";
12 | in {
13 | options = {
14 | programs.rebuild-home = {
15 | enable = lib.mkOption {
16 | type = types.bool;
17 | description = "Install rebuild-home script";
18 | default = config.targets.genericLinux.enable || pkgs.stdenv.isDarwin;
19 | };
20 |
21 | name = lib.mkOption {
22 | type = types.str;
23 | description = "Name of the home-manager configuration";
24 | };
25 |
26 | configDirectory = lib.mkOption {
27 | type = types.str;
28 | description = "Directory containing the home-manager configuration";
29 | default = "$HOME/build/nix-config";
30 | };
31 |
32 | emacsConfigDirectory = lib.mkOption {
33 | type = types.str;
34 | description = "Directory containing the Emacs configuration";
35 | default = "$HOME/build/emacs-config";
36 | };
37 | };
38 | };
39 |
40 | config = lib.mkIf cfg.enable {
41 | home.packages = [
42 | (pkgs.writeShellScriptBin "rebuild-home" ''
43 | emacs_config="${cfg.emacsConfigDirectory}"
44 | if [[ -d "''${emacs_config}" ]]
45 | then
46 | flags=(--override-input emacs-config $(readlink -f "''${emacs_config}")
47 | --override-input emacs-config/flake-pins github:akirak/flake-pins)
48 | else
49 | flags=()
50 | fi
51 |
52 | cd "${cfg.configDirectory}"
53 | if ${pkgs.nix-output-monitor}/bin/nom build "#homeConfigurations.${cfg.name}" \
54 | --option accept-flake-config true \
55 | --print-build-logs \
56 | ''${flags[@]} \
57 | && result/activate; then
58 | ${notify} -t 5000 'Successfully switched to a new home-manager generation'
59 | else
60 | ${notify} -t 5000 'Failed to switch to a new home-manager generation'
61 | read
62 | fi
63 | '')
64 | ];
65 | };
66 | }
67 |
--------------------------------------------------------------------------------
/homes/modules/rebuild-nixos.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | pkgs,
5 | ...
6 | }:
7 | let
8 | inherit (lib) types;
9 |
10 | cfg = config.programs.nixos-rebuild-and-notify;
11 |
12 | notify = "${pkgs.notify-desktop}/bin/notify-desktop -r nixos-rebuild";
13 | in
14 | {
15 | options = {
16 | programs.nixos-rebuild-and-notify = {
17 | enable = lib.mkEnableOption (lib.mdDoc "Install nixos-rebuild-and-notify script");
18 |
19 | directory = lib.mkOption {
20 | type = types.str;
21 | description = "Directory containing the NixOS configuration";
22 | default = "$HOME/build/nix-config";
23 | };
24 |
25 | emacsConfigDirectory = lib.mkOption {
26 | type = types.str;
27 | description = "Directory containing the Emacs configuration";
28 | default = "$HOME/build/emacs-config";
29 | };
30 | };
31 | };
32 |
33 | config = lib.mkIf cfg.enable {
34 | home.packages = [
35 | (pkgs.writeShellScriptBin "nixos-rebuild-and-notify" ''
36 | operation="''${1:-switch}"
37 |
38 | if emacs_config="$(readlink -e "${cfg.emacsConfigDirectory}")"
39 | then
40 | build_flags=(--override-input emacs-config "''${emacs_config}")
41 | else
42 | build_flags=()
43 | fi
44 |
45 | hostname="$(uname -n)"
46 |
47 | function build_and_switch() {
48 | local artifact
49 | cd "${cfg.directory}"
50 |
51 | nix flake update emacs-config
52 |
53 | artifact=$(${pkgs.nix-output-monitor}/bin/nom build \
54 | ".#nixosConfigurations.$hostname.config.system.build.toplevel" \
55 | --option accept-flake-config true \
56 | --no-write-lock-file \
57 | --print-out-paths \
58 | --no-link \
59 | --print-build-logs \
60 | ''${build_flags[@]})
61 | if [[ $? -eq 0 ]]
62 | then
63 | sudo nix-env -p /nix/var/nix/profiles/system --set "$artifact" \
64 | && sudo "$artifact/bin/switch-to-configuration" "$operation"
65 | else
66 | return 1
67 | fi
68 | }
69 |
70 | if build_and_switch; then
71 | ${notify} -t 5000 "nixos-rebuild $operation has finished successfully"
72 | else
73 | ${notify} -t 5000 "nixos-rebuild $operation has failed"
74 | read
75 | fi
76 | '')
77 | ];
78 | };
79 | }
80 |
--------------------------------------------------------------------------------
/homes/modules/recoll.nix:
--------------------------------------------------------------------------------
1 | {
2 | services.recoll.settings = {
3 | followLinks = true;
4 |
5 | # TODO: Add support for extra (private) top directories
6 | topdirs = [
7 | "~/resources/bundles"
8 | "~/resources/ebooks"
9 | "~/resources/sound"
10 | "~/resources/bundles"
11 | "~/notes-and-pdfs/notes"
12 | "~/notes-and-pdfs/ebooks"
13 | ];
14 |
15 | excludedmimetypes = [
16 | "text/html"
17 | "application/x-mobipocket-ebook"
18 | "audio/flac"
19 | ];
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/homes/modules/timoni.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | pkgs,
5 | ...
6 | }: let
7 | cfg = config.programs.timoni;
8 | inherit (lib) mkIf mkOption mkEnableOption types;
9 | in {
10 | options = {
11 | programs.timoni = {
12 | enable = mkEnableOption (lib.mdDoc "Install timoni for development.");
13 |
14 | enableZshIntegration = mkOption {
15 | type = types.bool;
16 | default = true;
17 | description = "Whether to enable Zsh integration.";
18 | };
19 | };
20 | };
21 |
22 | config = lib.mkIf cfg.enable {
23 | home.packages = [
24 | pkgs.timoni
25 | ];
26 |
27 | programs.zsh.initContent = mkIf cfg.enableZshIntegration ''
28 | source <(${pkgs.timoni}/bin/timoni completion zsh)
29 | compdef _timoni timoni
30 | '';
31 | };
32 | }
33 |
--------------------------------------------------------------------------------
/homes/modules/words.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | xdg.dataFile."dict/words".source =
3 | (pkgs.fetchFromGitHub {
4 | owner = "dwyl";
5 | repo = "english-words";
6 | rev = "a77cb15f4f5beb59c15b945f2415328a6b33c3b0";
7 | sha256 = "12mj9yas7z48cjy0zpi7jz09svipasr62v786lj3wkdssy8wrbfj";
8 | })
9 | + "/words_alpha.txt";
10 | }
11 |
--------------------------------------------------------------------------------
/homes/modules/wslu.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | pkgs,
5 | ...
6 | }: let
7 | cfg = config.programs.wslu;
8 | in {
9 | options = {
10 | programs.wslu = {
11 | enable = lib.mkEnableOption "Enable WSL utilities.";
12 | };
13 | };
14 |
15 | config = lib.mkIf cfg.enable {
16 | home.packages = [
17 | pkgs.wslu
18 | (pkgs.makeDesktopItem {
19 | name = "wslview";
20 | desktopName = "wslview";
21 | exec = "wslview";
22 | })
23 | ];
24 |
25 | xdg.mimeApps.defaultBrowser = lib.mkDefault "wslview.desktop";
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/homes/modules/xdg.nix:
--------------------------------------------------------------------------------
1 | {
2 | lib,
3 | pkgs,
4 | config,
5 | ...
6 | }: let
7 | inherit (lib) mkIf;
8 | inherit (pkgs.stdenv) isDarwin;
9 | inherit (config.home) homeDirectory;
10 | in {
11 | xdg.configHome = mkIf (!isDarwin) "${homeDirectory}/.config";
12 | xdg.cacheHome = mkIf (!isDarwin) "${homeDirectory}/.cache";
13 | xdg.dataHome = mkIf (!isDarwin) "${homeDirectory}/.local/share";
14 | }
15 |
--------------------------------------------------------------------------------
/homes/modules/zsh.nix:
--------------------------------------------------------------------------------
1 | { pkgs, ... }:
2 | {
3 | home.packages = with pkgs; [
4 | zsh
5 | nix-zsh-completions
6 | fzy
7 | ];
8 |
9 | programs.zsh = {
10 | enable = true;
11 | autosuggestion.enable = true;
12 | enableCompletion = true;
13 | dotDir = ".config/zsh";
14 | defaultKeymap = "emacs";
15 | history = {
16 | expireDuplicatesFirst = true;
17 | save = 5000;
18 | share = true;
19 | size = 5000;
20 | };
21 |
22 | plugins = [
23 | {
24 | name = "zsh-history-substring-search";
25 | src = pkgs.zsh-history-substring-search;
26 | }
27 | {
28 | name = "fzy";
29 | src = pkgs.customZshPlugins.zsh-fzy;
30 | }
31 | {
32 | name = "nix-shell";
33 | src = pkgs.customZshPlugins.zsh-nix-shell;
34 | }
35 | {
36 | name = "fast-syntax-highlighting";
37 | src = pkgs.customZshPlugins.zsh-fast-syntax-highlighting;
38 | }
39 | {
40 | name = "history-filter";
41 | src = pkgs.customZshPlugins.zsh-history-filter;
42 | }
43 | ];
44 |
45 | sessionVariables = {
46 | "DIRSTACKSIZE" = "20";
47 | "NIX_BUILD_SHELL" = "zsh";
48 | # "VAGRANT_WSL_WINDOWS_ACCESS" = "1";
49 | # Set locale archives
50 | # https://github.com/NixOS/nixpkgs/issues/38991
51 | "LOCALE_ARCHIVE_2_11" = "${pkgs.glibcLocales}/lib/locale/locale-archive";
52 | "LOCALE_ARCHIVE_2_27" = "${pkgs.glibcLocales}/lib/locale/locale-archive";
53 | };
54 |
55 | initContent = ''
56 | setopt auto_cd
57 | setopt cdable_vars
58 | setopt auto_name_dirs
59 | setopt auto_pushd
60 | setopt pushd_ignore_dups
61 | setopt pushdminus
62 |
63 | # Configuration for zsh-fzy plugin https://github.com/aperezdc/zsh-fzy
64 | bindkey '\eq' fzy-proc-widget
65 | bindkey '\ew' fzy-cd-widget
66 | bindkey '\ee' fzy-file-widget
67 | bindkey '\er' fzy-history-widget
68 | zstyle :fzy:file command fd -t f
69 | zstyle :fzy:cd command fd -t d
70 |
71 | # Support directory tracking on emacs-libvterm.
72 | # https://github.com/akermu/emacs-libvterm#directory-tracking
73 | function chpwd() {
74 | print -Pn "\e]51;A$(pwd)\e\\";
75 | }
76 |
77 | function pick() {
78 | local arg
79 | fzy | read -r arg && "$@" "$arg"
80 | }
81 |
82 | function mountpoints() {
83 | findmnt -oTARGET --list --noheadings
84 | }
85 |
86 | function remotes() {
87 | git rev-parse --show-toplevel >/dev/null || return 1
88 | git --no-pager config --local --list \
89 | | sed -n -E 's/^remote\..+?\.url=(.+)/\1/p' \
90 | | xargs realpath -q -s -e
91 | }
92 |
93 | function projects() {
94 | {
95 | tmp=$(mktemp -p "''${XDG_RUNTIME_DIR}")
96 | trap "rm -f '$tmp'" ERR EXIT
97 | # If the server isn't running, this script will exit with 1.
98 | emacsclient --eval "(with-temp-buffer
99 | (insert (string-join
100 | (thread-last
101 | (project-known-project-roots)
102 | (append (thread-last
103 | (frame-list)
104 | (mapcan #'window-list)
105 | (mapcar #'window-buffer)
106 | (mapcar (lambda (buffer)
107 | (buffer-local-value 'default-directory buffer)))))
108 | (mapcar #'expand-file-name)
109 | (seq-uniq))
110 | \"\\n\"))
111 | (write-region (point-min) (point-max) \"$tmp\"))" > /dev/null
112 | cat "$tmp"
113 | }
114 | }
115 |
116 | function project-subdirectories() {
117 | local root="$(git rev-parse --show-toplevel)"
118 | if [[ -z "$root" ]]; then
119 | return 1
120 | else
121 | ( cd "$root" && fd -a -L -t d )
122 | fi
123 | }
124 |
125 | function emacs-visible-directories() {
126 | tmp=$(mktemp -p "''${XDG_RUNTIME_DIR}")
127 | trap "rm -f '$tmp'" ERR EXIT
128 | # If the server isn't running, this script will exit with 1.
129 | emacsclient --eval "(with-temp-buffer
130 | (insert (string-join
131 | (thread-last
132 | (window-list)
133 | (mapcar #'window-buffer)
134 | (mapcar (lambda (buffer)
135 | (expand-file-name
136 | (buffer-local-value 'default-directory buffer))))
137 | (seq-uniq))
138 | \"\\n\"))
139 | (write-region (point-min) (point-max) \"$tmp\"))" > /dev/null
140 | cat "$tmp"
141 | }
142 |
143 | function cdv() {
144 | builtin cd "$1" && pwd
145 | }
146 |
147 | function cd() {
148 | case "$1" in
149 | -h)
150 | echo <<-HELP
151 | Usage: cd [-p|-m|-r|DIR]
152 |
153 | Options:
154 | -p: Select an Emacs project (requires an Emacs server running)
155 | -m: Select a mount point
156 | -r: Select a remote of the current Git repository
157 | -w: Select the directory of a visible buffer
158 | -d: Select a sub-directory inside the current Git repository
159 | -g: Go to the root of the current Git working tree
160 | HELP
161 | ;;
162 | -p|)
163 | projects | pick cdv
164 | ;;
165 | -m)
166 | mountpoints | pick cdv
167 | ;;
168 | -r)
169 | remotes | pick cdv
170 | ;;
171 | -w)
172 | emacs-visible-directories | pick cdv
173 | ;;
174 | -d)
175 | project-subdirectories | pick cdv
176 | ;;
177 | -g)
178 | local root="$(git rev-parse --show-toplevel)"
179 | if [[ -n "$root" ]]; then
180 | builtin cd "$root"
181 | fi
182 | ;;
183 | *)
184 | builtin cd "$@"
185 | ;;
186 | esac
187 | }
188 |
189 | function clone() {
190 | if [[ $# -eq 0 ]]
191 | then
192 | echo "Usage: clone URL" >&2
193 | return 1
194 | else
195 | dir=''${$(emacsclient --eval "(expand-file-name (akirak-git-clone-dir \"$1\"))")//\"/}
196 | cd "$dir"
197 | echo "$dir"
198 | fi
199 | }
200 |
201 | function clock() {
202 | emacsclient -n --eval "(akirak-capture-clock-in
203 | (org-dog-complete-file \"Clock into file: \")
204 | \"$*\"
205 | :body (format \"[[file:%s]]\n%%?\" (abbreviate-file-name \"$PWD/\")))"
206 | }
207 |
208 | export NIX_BUILD_SHELL=bash
209 |
210 | export EDITOR=emacsclient
211 |
212 | # Use gpg-agent as ssh-agent.
213 | gpg-connect-agent /bye
214 | export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
215 |
216 | export STARSHIP_CONFIG=${pkgs.writeText "starship.toml" (pkgs.lib.fileContents ../etc/starship/starship.toml)}
217 |
218 | eval "$(${pkgs.starship}/bin/starship init zsh)"
219 |
220 | # https://github.com/MichaelAquilina/zsh-history-filter
221 | export HISTORY_FILTER_EXCLUDE=("TOKEN")
222 | '';
223 | shellAliases = {
224 | ".." = "cd ..";
225 | "..." = "cd ../..";
226 | "rm" = "rm -i";
227 | "j" = "journalctl -xe";
228 | "e" = "emacsclient -n";
229 | "start" = "systemctl --user start";
230 | "stop" = "systemctl --user stop";
231 | "enable" = "systemctl --user enable";
232 | "disable" = "systemctl --user disable";
233 | "reload" = "systemctl --user daemon-reload";
234 | "status" = "systemctl --user --full status";
235 | "restart" = "systemctl --user restart";
236 | "ssh-ignore" = "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null";
237 | };
238 | };
239 | }
240 |
--------------------------------------------------------------------------------
/homes/wsl.nix:
--------------------------------------------------------------------------------
1 | /*
2 | Configuration for Windows Subsystem for Linux (WSL) with WSLg
3 | */
4 | {pkgs, ...}: {
5 | home.packages = [
6 | pkgs.blanket
7 | ];
8 |
9 | programs.wslu.enable = true;
10 | }
11 |
--------------------------------------------------------------------------------
/machines/hui/boot.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | boot.loader.systemd-boot.enable = true;
3 | boot.loader.efi.canTouchEfiVariables = true;
4 |
5 | environment.systemPackages = [
6 | pkgs.lshw
7 | pkgs.git
8 | ];
9 |
10 | boot.kernel.sysctl = {
11 | "vm.swappiness" = 10;
12 | };
13 |
14 | boot.initrd.kernelModules = [
15 | "usbcore"
16 | "nvme"
17 | "sdhci_pci"
18 | "mmc_block"
19 | "xhci_hcd"
20 | "usb-storage"
21 | ];
22 |
23 | boot.initrd.luks.reusePassphrases = true;
24 |
25 | boot.supportedFilesystems = ["btrfs"];
26 | boot.initrd.supportedFilesystems = ["btrfs"];
27 |
28 | boot.initrd.luks.devices.cryptroot = {
29 | device = "/dev/disk/by-uuid/78af0865-093e-4529-bf6a-841ee6b492e9";
30 | allowDiscards = true;
31 | };
32 |
33 | fileSystems = {
34 | "/" = {
35 | device = "/dev/mapper/cryptroot";
36 | fsType = "btrfs";
37 | neededForBoot = true;
38 | options = [
39 | "subvol=/root"
40 | "discard=async"
41 | ];
42 | };
43 |
44 | "/boot" = {
45 | device = "/dev/disk/by-uuid/8627-ED16";
46 | fsType = "vfat";
47 | neededForBoot = true;
48 | options = [
49 | "fmask=0137"
50 | "dmask=0027"
51 | ];
52 | };
53 |
54 | "/nix" = {
55 | device = "/dev/mapper/cryptroot";
56 | fsType = "btrfs";
57 | neededForBoot = true;
58 | options = [
59 | "subvol=/nix"
60 | "compress=lz4"
61 | "noatime"
62 | "discard=async"
63 | ];
64 | };
65 | };
66 |
67 | swapDevices = [
68 | {
69 | device = "/dev/disk/by-partuuid/109d2b63-22f6-4188-8dc5-8346617d3df3";
70 | randomEncryption = {
71 | enable = true;
72 | allowDiscards = true;
73 | };
74 | }
75 | ];
76 |
77 | boot.tmp.useTmpfs = true;
78 | boot.tmp.tmpfsSize = "4096m";
79 |
80 | boot.runSize = "64m";
81 | boot.devSize = "256m";
82 | boot.devShmSize = "256m";
83 | }
84 |
--------------------------------------------------------------------------------
/machines/hui/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | homeUser,
3 | pkgs,
4 | ...
5 | }:
6 | let
7 | stateVersion = "25.05";
8 | in
9 | {
10 | imports = [
11 | ./boot.nix
12 | ../../nixos/suites/base
13 | ../../nixos/suites/graphical
14 | ../../nixos/suites/desktop
15 | ../../nixos/profiles/locale
16 | ../../nixos/profiles/home-manager
17 | ../../nixos/profiles/nix
18 | ../../nixos/profiles/sudo
19 | ../../nixos/profiles/tailscale
20 | ../../nixos/profiles/wayland/wlroots.nix
21 | # ../../nixos/profiles/wayland/cage/emacs.nix
22 | ../../nixos/profiles/wayland/cage/foot.nix
23 | # ../../nixos/profiles/wayland/cage/firefox.nix
24 | # ../../nixos/profiles/wayland/wm/labwc.nix
25 | ../../nixos/profiles/wayland/wm/hyprland.nix
26 | # ../../nixos/profiles/nix/cachix-deploy.nix
27 | ../../nixos/profiles/dpt-rp1
28 | ];
29 |
30 | networking = {
31 | firewall.enable = true;
32 | useDHCP = false;
33 | networkmanager.enable = true;
34 | };
35 |
36 | system.stateVersion = stateVersion;
37 |
38 | hardware.graphics.enable = true;
39 |
40 | systemd.services.NetworkManager-wait-online.enable = false;
41 |
42 | services.journald.extraConfig = ''
43 | SystemMaxFiles=5
44 | '';
45 |
46 | services.auto-cpufreq.enable = true;
47 |
48 | zramSwap = {
49 | enable = true;
50 | };
51 |
52 | users.users.${homeUser} = {
53 | description = "Akira Komamura";
54 | uid = 1000;
55 | isNormalUser = true;
56 | hashedPassword = "$6$3LmgpFGu4WEeoTss$9NQpF4CEO8ivu0uJTlDYXdiB6ZPHBsLXDZr.6S59bBNxmNuhirmcOmHTwhccdgSwq7sJOz2JbOOzmOCivxdak0";
57 |
58 | extraGroups = [
59 | "wheel"
60 | "video"
61 | "audio"
62 | "disk"
63 | "networkmanager"
64 | "systemd-journal"
65 | # "docker"
66 | ];
67 | };
68 |
69 | services.greetd = {
70 | enable = true;
71 | settings.default_session = {
72 | # You have to install *.desktop files to the directory
73 | command = "${pkgs.greetd.tuigreet}/bin/tuigreet -t -s /etc/wayland-sessions";
74 | user = homeUser;
75 | };
76 | };
77 |
78 | home-manager.users.${homeUser} = {
79 | imports = [
80 | ../../homes/basic.nix
81 | ../../homes/extra.nix
82 | ../../homes/graphical.nix
83 | ];
84 |
85 | # wayland.windowManager.labwc.enable = true;
86 | wayland.windowManager.hyprland.enable = true;
87 |
88 | programs.gpg.enable = true;
89 |
90 | programs.emacs-twist = {
91 | enable = true;
92 | serviceIntegration.enable = false;
93 | settings = {
94 | extraFeatures = [
95 | "beancount"
96 | "OCaml"
97 | "Emacs"
98 | "Emacs__lisp"
99 | "Org"
100 | ];
101 | };
102 | };
103 | };
104 | }
105 |
--------------------------------------------------------------------------------
/machines/hui/flake-module.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | let
3 | channel = inputs.unstable;
4 | in
5 | {
6 | flake = {
7 | nixosConfigurations.hui = channel.lib.nixosSystem {
8 | system = "x86_64-linux";
9 |
10 | specialArgs = {
11 | homeUser = "akirakomamura";
12 | hostPubkey = null;
13 | inherit (inputs) emacs-config;
14 | };
15 |
16 | modules = [
17 | inputs.home-manager-unstable.nixosModules.home-manager
18 | inputs.self.nixosModules.asus-br1100
19 | inputs.self.nixosModules.twistHomeModule
20 | inputs.self.nixosModules.default
21 | ./.
22 | {
23 | networking.hostName = "hui";
24 | }
25 | ];
26 | };
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/machines/li/boot.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | pkgs,
4 | lib,
5 | ...
6 | }:
7 | let
8 | annex-dm = "local_annex";
9 | in
10 | {
11 | imports = [
12 | ../../nixos/profiles/intel-arc
13 | ];
14 |
15 | boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
16 |
17 | boot.loader.systemd-boot.enable = true;
18 | boot.loader.efi.canTouchEfiVariables = true;
19 | boot.initrd.availableKernelModules = [
20 | "xhci_pci"
21 | "ahci"
22 | "nvme"
23 | "usbhid"
24 | "usb_storage"
25 | "sd_mod"
26 | ];
27 | # This kernel module is needed if and only if unlock LUKS devices on boot
28 | # boot.initrd.kernelModules = [ "dm-snapshot" ];
29 | boot.kernelModules = [ "kvm-intel" ];
30 | boot.extraModulePackages = [ ];
31 |
32 | # ZFS support
33 | boot.supportedFilesystems.zfs = true;
34 | boot.initrd.supportedFilesystems.zfs = true;
35 | boot.zfs.requestEncryptionCredentials = true;
36 | services.zfs.autoSnapshot.enable = true;
37 | services.zfs.autoScrub.enable = true;
38 | # Configure ARC up to 4 GiB
39 | boot.kernelParams = [ "zfs.zfs_arc_max=4294967296" ];
40 |
41 | environment.systemPackages = [
42 | pkgs.lshw
43 | pkgs.git
44 | ];
45 |
46 | fileSystems."/" = {
47 | device = "tmpfs";
48 | fsType = "tmpfs";
49 | options = [
50 | "defaults"
51 | "size=10G"
52 | "mode=755"
53 | ];
54 | };
55 |
56 | fileSystems."/boot" = {
57 | device = "/dev/disk/by-uuid/B327-FDEA";
58 | fsType = "vfat";
59 | options = [
60 | "fmask=0137"
61 | "dmask=0027"
62 | ];
63 | };
64 |
65 | fileSystems."/nix" = {
66 | device = "/dev/disk/by-uuid/89ca01cd-558b-410a-b282-3af5601b9f97";
67 | fsType = "ext4";
68 | };
69 |
70 | boot.initrd.luks.devices.${annex-dm} = {
71 | device = "/dev/disk/by-uuid/2f67dfa5-200f-4d38-b96d-2aabbd9f5186";
72 | allowDiscards = true;
73 | };
74 |
75 | fileSystems."/git-annex/${config.networking.hostName}" = {
76 | device = "/dev/mapper/${annex-dm}";
77 | fsType = "ext4";
78 | options = [
79 | "relatime"
80 | "discard"
81 | ];
82 | };
83 |
84 | swapDevices = [ ];
85 |
86 | hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
87 |
88 | hardware.enableRedistributableFirmware = true;
89 |
90 | # hardware.bluetooth = {
91 | # enable = true;
92 | # };
93 |
94 | boot.runSize = "64m";
95 | boot.devSize = "256m";
96 | boot.devShmSize = "256m";
97 |
98 | services.smartd = {
99 | enable = true;
100 | devices = [
101 | { device = "/dev/disk/by-id/ata-CT1000MX500SSD1_2316E6CCB0BC"; }
102 | { device = "/dev/disk/by-id/ata-CT1000MX500SSD1_2316E6CCB574"; }
103 | ];
104 | };
105 |
106 | services.scrutiny = {
107 | enable = true;
108 | # Access only locally for now
109 | openFirewall = false;
110 | settings = {
111 | web.listen = {
112 | port = 9233;
113 | host = "127.0.0.1";
114 | };
115 | };
116 | };
117 | }
118 |
--------------------------------------------------------------------------------
/machines/li/default.nix:
--------------------------------------------------------------------------------
1 | { homeUser, pkgs, ... }:
2 | let
3 | stateVersion = "25.05";
4 |
5 | mainMonitor = {
6 | criteria = "Unknown VA32AQ K3LMAS000141 (HDMI-A-2)";
7 | mode = "2560x1440";
8 | position = "1920,0";
9 | };
10 |
11 | subMonitor = {
12 | criteria = "Dell Inc. DELL S2421HS CBPT223 (DP-1)";
13 | mode = "1920x1080";
14 | position = "0,380";
15 | };
16 | in
17 | {
18 | imports = [
19 | ./boot.nix
20 | ./rpool5
21 | ../../nixos/suites/base
22 | ../../nixos/suites/graphical
23 | ../../nixos/suites/desktop
24 | ../../nixos/profiles/locale
25 | ../../nixos/profiles/home-manager
26 | ../../nixos/profiles/nix
27 | ../../nixos/profiles/sudo
28 | ../../nixos/profiles/tailscale
29 | # ../../nixos/profiles/rabbitmq/development.nix
30 | ../../nixos/profiles/networking/usb-tether1.nix
31 | ../../nixos/profiles/wayland/wm/hyprland.nix
32 | ../../nixos/profiles/wayland/cage/foot.nix
33 | # ../../nixos/profiles/wayland/wm/river.nix
34 | # ../../nixos/profiles/nix/cachix-deploy.nix
35 | ../../nixos/profiles/postgresql/development.nix
36 | ../../nixos/profiles/livebook
37 | ../../nixos/profiles/ollama
38 | ../../nixos/profiles/virtualbox-host
39 | ../../nixos/profiles/dpt-rp1
40 | ../../nixos/profiles/podman/rootless-docker.nix
41 | # ../../nixos/profiles/docker/rootless.nix
42 | # ../../nixos/profiles/docker
43 | # ../../nixos/profiles/docker/kind.nix
44 | # ../../nixos/profiles/k3s/single-node-for-testing.nix
45 | ];
46 |
47 | hardware.graphics = {
48 | enable = true;
49 | extraPackages = [
50 | pkgs.intel-compute-runtime
51 | pkgs.intel-media-driver
52 | ];
53 | };
54 |
55 | system.stateVersion = stateVersion;
56 |
57 | # Needed for the ZFS pool.
58 | networking.hostId = "8425e349";
59 |
60 | # I didn't use disko when I first set up this machine.
61 | # disko.devices = import ./disko.nix {};
62 |
63 | networking = {
64 | useDHCP = false;
65 | networkmanager.enable = true;
66 | };
67 | # systemd.services.NetworkManager-wait-online.enable = true;
68 |
69 | environment.systemPackages = [
70 | pkgs.clinfo
71 | pkgs.hunspellDicts.en_US
72 | pkgs.hunspellDicts.en_GB-ise
73 |
74 | # Install Cloud Hypervisor for use with MicroVM
75 | pkgs.cloud-hypervisor
76 | ];
77 |
78 | services.journald.extraConfig = ''
79 | SystemMaxFiles=5
80 | '';
81 |
82 | services.auto-cpufreq.enable = true;
83 |
84 | zramSwap = {
85 | enable = true;
86 | };
87 |
88 | users.users.${homeUser} = {
89 | description = "Akira Komamura";
90 | uid = 1000;
91 | isNormalUser = true;
92 | hashedPassword = "$6$3LmgpFGu4WEeoTss$9NQpF4CEO8ivu0uJTlDYXdiB6ZPHBsLXDZr.6S59bBNxmNuhirmcOmHTwhccdgSwq7sJOz2JbOOzmOCivxdak0";
93 |
94 | extraGroups = [
95 | "wheel"
96 | "video"
97 | "audio"
98 | "disk"
99 | "networkmanager"
100 | "systemd-journal"
101 | "docker"
102 | "livebook"
103 | ];
104 | };
105 |
106 | services.greetd = {
107 | enable = true;
108 | settings.default_session = {
109 | # You have to install *.desktop files to the directory
110 | command = "${pkgs.greetd.tuigreet}/bin/tuigreet -t -s /etc/wayland-sessions";
111 | user = homeUser;
112 | };
113 | };
114 |
115 | services.my-livebook = {
116 | enable = true;
117 | settings = {
118 | ipAddress = "127.0.0.1";
119 | port = 8200;
120 | enableNix = true;
121 | };
122 | };
123 |
124 | services.ollama.acceleration = false;
125 |
126 | services.postgresql = {
127 | package = pkgs.postgresql_17;
128 | };
129 |
130 | home-manager.users.${homeUser} = {
131 | imports = [
132 | ../../homes/basic.nix
133 | ../../homes/extra.nix
134 | ../../homes/code.nix
135 | ../../homes/graphical.nix
136 | ];
137 |
138 | programs.chromium = {
139 | enable = true;
140 | package = pkgs.ungoogled-chromium;
141 | extensions = [
142 | {
143 | # Google Input Tools
144 | id = "mclkkofklkfljcocdinagocijmpgbhab";
145 | }
146 | ];
147 | };
148 |
149 | programs.uv.settings = {
150 | # ZFS
151 | link-mode = "copy";
152 | };
153 |
154 | home.stateVersion = stateVersion;
155 |
156 | home.packages = [
157 | pkgs.rclone
158 | # pkgs.steam-run
159 | # pkgs.wine
160 | # pkgs.tenacity
161 | # pkgs.microsoft-edge
162 | # pkgs.zoom-us
163 | ];
164 |
165 | home.file.".npmrc".text = ''
166 | # Required because of the network instability
167 | fetch-retries = 5
168 | # Required because of ZFS
169 | package-import-method=copy
170 | '';
171 |
172 | services.kanshi.settings = [
173 | {
174 | profile.name = "docked";
175 | profile.outputs = [
176 | mainMonitor
177 | subMonitor
178 | ];
179 | }
180 | {
181 | profile.name = "undocked";
182 | profile.outputs = [ mainMonitor ];
183 | }
184 | {
185 | profile.name = "as_secondary";
186 | profile.outputs = [ subMonitor ];
187 | }
188 | ];
189 |
190 | wayland.windowManager.hyprland.enable = true;
191 |
192 | # programs.river.enable = true;
193 |
194 | programs.gpg.enable = true;
195 |
196 | programs.emacs-twist = {
197 | enable = true;
198 | settings = {
199 | extraFeatures = [
200 | "beancount"
201 | "OCaml"
202 | "Emacs"
203 | "Emacs__lisp"
204 | "Org"
205 | "MCP"
206 | # "Coq"
207 | # "Lean4"
208 | # "lsp_mode"
209 | ];
210 | };
211 | };
212 | };
213 | }
214 |
--------------------------------------------------------------------------------
/machines/li/flake-module.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | let
3 | channel = inputs.unstable;
4 | in
5 | {
6 | flake = {
7 | nixosConfigurations.li = channel.lib.nixosSystem {
8 | system = "x86_64-linux";
9 |
10 | specialArgs = {
11 | homeUser = "akirakomamura";
12 | hostPubkey = null;
13 | inherit (inputs) emacs-config;
14 | };
15 |
16 | modules = [
17 | inputs.home-manager-unstable.nixosModules.home-manager
18 | inputs.nixos-hardware.nixosModules.common-gpu-intel
19 | inputs.self.nixosModules.twistHomeModule
20 | inputs.self.nixosModules.default
21 | ./.
22 | {
23 | networking.hostName = "li";
24 | }
25 | ];
26 | };
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/machines/li/rpool5/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | imports = [ ./extras.nix ];
3 |
4 | fileSystems."/persist" = {
5 | device = "rpool5/safe/persist";
6 | fsType = "zfs";
7 | neededForBoot = true;
8 | };
9 |
10 | fileSystems."/home" = {
11 | device = "rpool5/safe/home";
12 | fsType = "zfs";
13 | };
14 |
15 | # You will require github:nix-community/impermanence to use this
16 | environment.persistence."/persist" = {
17 | directories = [
18 | "/var/log"
19 | "/var/tmp"
20 | "/var/lib/nixos"
21 | "/var/lib/bluetooth"
22 | "/var/lib/livebook"
23 | "/var/lib/rabbitmq"
24 | "/etc/NetworkManager/system-connections"
25 | ];
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/machines/li/rpool5/extras.nix:
--------------------------------------------------------------------------------
1 | {
2 | lib,
3 | config,
4 | homeUser,
5 | ...
6 | }:
7 | let
8 | rootlessStoragePath = "/home/${homeUser}/.local/share/containers";
9 | in
10 | {
11 | # fileSystems."/backup" = {
12 | # device = "/dev/mapper/backup_rpool5";
13 | # fsType = "ext4";
14 | # neededForBoot = true;
15 | # };
16 |
17 | fileSystems."/var/lib/postgresql" = {
18 | # This pool name was a mistake
19 | device = "rpool5/safe/postgresql";
20 | fsType = "zfs";
21 | neededForBoot = true;
22 | };
23 |
24 | # You always have to backup databases. Automatic snapshots of ZFS do not work
25 | # for database backups, so set up a dataset (with optional automatic
26 | # snapshots) for backups and run pgbackup periodically.
27 | fileSystems.${config.services.postgresqlBackup.location} = {
28 | device = "rpool5/safe/pgbackup";
29 | fsType = "zfs";
30 | neededForBoot = true;
31 | };
32 |
33 | # Enable the transparent compression of ZFS
34 | services.postgresqlBackup = lib.mkIf config.services.postgresqlBackup.enable {
35 | compression = "none";
36 | };
37 |
38 | fileSystems."/var/lib/private" = {
39 | device = "rpool5/local/ollama";
40 | fsType = "zfs";
41 | # The root directory of this file system needs to have 0700 permission.
42 | };
43 |
44 | fileSystems."/var/lib/containers" = {
45 | device = "rpool5/local/containers";
46 | fsType = "zfs";
47 | };
48 |
49 | fileSystems.${rootlessStoragePath} = {
50 | device = "rpool5/local/containers-rootless";
51 | fsType = "zfs";
52 | };
53 | virtualisation.containers.storage.settings.storage.rootless_storage_path = rootlessStoragePath;
54 |
55 | fileSystems."/media/virtualbox" = {
56 | device = "rpool5/safe/virtualbox";
57 | fsType = "zfs";
58 | };
59 | }
60 |
--------------------------------------------------------------------------------
/machines/metadata.toml:
--------------------------------------------------------------------------------
1 | # Use `ssh-keyscan -t ed25519 ...` to get the public key(s) remotely
2 | [hosts.zheng]
3 | ipAddress = "192.168.10.1"
4 | publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPok1B5NsawQoyxJ2Is3wynnfqZ51o1fyueJ3gpLLCa5"
5 |
6 | [hosts.li]
7 | ipAddress = "192.168.10.60"
8 | syncthingId = "FWMZWNO-CIL5HZL-5IOA5IZ-UGXYQK6-DYK76L4-VDQAOZP-VHDLLC4-JYUSAAU"
9 |
10 | [hosts.yang]
11 | ipAddress = "192.168.10.10"
12 | publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBBqIBetzQSQhJeOgBXCcNwwyWToSGh2ZUMLEROwwxeF"
13 |
14 | [hosts.wang]
15 | ipAddress = "192.168.10.11"
16 |
17 | [networks.home]
18 | subnet = "192.168.10.0/16"
19 |
--------------------------------------------------------------------------------
/machines/shu/boot.nix:
--------------------------------------------------------------------------------
1 | {config, ...}: let
2 | cryptName = "cryptroot";
3 | cryptDevice = "/dev/sda3";
4 | in {
5 | boot.kernelModules = ["virtio_net"];
6 | boot.loader.efi.canTouchEfiVariables = false;
7 |
8 | boot.initrd = {
9 | enable = true;
10 |
11 | # Network card drivers.
12 | kernelModules = ["virtio_net"];
13 |
14 | luks.devices.${cryptName} = {
15 | device = cryptDevice;
16 | allowDiscards = true;
17 | };
18 |
19 | network = {
20 | enable = true;
21 |
22 | ssh = {
23 | enable = true;
24 | port = 222;
25 |
26 | hostKeys = [
27 | "/persist/boot_ed25519_key"
28 | ];
29 |
30 | authorizedKeys = config.users.users.root.openssh.authorizedKeys.keys;
31 | };
32 | };
33 | };
34 |
35 | networking = {
36 | useDHCP = false;
37 | interfaces.eth0.useDHCP = true;
38 | };
39 |
40 | boot.supportedFilesystems = ["zfs"];
41 | boot.initrd.supportedFilesystems = ["zfs"];
42 | boot.zfs.requestEncryptionCredentials = true;
43 | boot.kernelParams = ["zfs.zfs_arc_max=805306368"];
44 | services.zfs.autoSnapshot.enable = true;
45 | services.zfs.autoScrub.enable = true;
46 | }
47 |
--------------------------------------------------------------------------------
/machines/shu/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | imports = [
3 | ../../nixos/suites/hcloud-remote
4 | ../../nixos/suites/base
5 | ../../nixos/profiles/tailscale
6 | ../../nixos/profiles/nginx
7 | ../../nixos/profiles/nix/cachix-deploy.nix
8 | ./boot.nix
9 | (import ./disko.nix {})
10 | ];
11 |
12 | networking.hostId = "9bc2dd3d";
13 | time.timeZone = "America/Los_Angeles";
14 |
15 | nix.settings.allowed-users = ["root"];
16 |
17 | services.journald.extraConfig = ''
18 | SystemMaxUse=1G
19 | MaxFileSec=10day
20 | '';
21 | }
22 |
--------------------------------------------------------------------------------
/machines/shu/disko.nix:
--------------------------------------------------------------------------------
1 | # Based on https://github.com/numtide/nixos-remote-examples/blob/9768e438b1467ec55d42e096860e7199bd1ef43d/disk-config.nix
2 | {
3 | disks ? [ "/dev/sda" ],
4 | luksKey ? "/persist/luks-cryptroot.key",
5 | ...
6 | }:
7 | {
8 | disko.devices = {
9 | disk.sda = {
10 | device = builtins.elemAt disks 0;
11 | type = "disk";
12 | content = {
13 | type = "gpt";
14 | partitions = {
15 | boot = {
16 | start = "0";
17 | end = "1M";
18 | type = "EF02";
19 | };
20 |
21 | ESP = {
22 | start = "1MiB";
23 | end = "100MiB";
24 | content = {
25 | type = "filesystem";
26 | format = "vfat";
27 | mountpoint = "/boot";
28 | mountOptions = [
29 | "defaults"
30 | ];
31 | };
32 | };
33 |
34 | luks = {
35 | start = "100MiB";
36 | end = "100%";
37 | content = {
38 | type = "luks";
39 | name = "cryptroot";
40 | keyFile = luksKey;
41 | content = {
42 | type = "zfs";
43 | pool = "zroot";
44 | };
45 | };
46 | };
47 | };
48 | };
49 | };
50 |
51 | zpool = {
52 | zroot = {
53 | type = "zpool";
54 | # mode = "mirror";
55 | rootFsOptions = {
56 | "com.sun:auto-snapshot" = "false";
57 | };
58 |
59 | mountpoint = "/";
60 |
61 | datasets = {
62 | nix = {
63 | type = "zfs_fs";
64 | mountpoint = "/nix";
65 | options = {
66 | compression = "lz4";
67 | "com.sun:auto-snapshot" = "true";
68 | };
69 | };
70 | persist = {
71 | type = "zfs_fs";
72 | mountpoint = "/persist";
73 | options = {
74 | "com.sun:auto-snapshot" = "true";
75 | };
76 | };
77 | var = {
78 | type = "zfs_fs";
79 | mountpoint = "/var";
80 | options = {
81 | compression = "lz4";
82 | "com.sun:auto-snapshot" = "true";
83 | };
84 | };
85 | };
86 | };
87 | };
88 | };
89 | }
90 |
--------------------------------------------------------------------------------
/machines/shu/flake-module.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | let
3 | channel = inputs.stable;
4 | in
5 | {
6 | flake = {
7 | diskoConfigurations.shu = import ./disko.nix;
8 | nixosConfigurations.shu = channel.lib.nixosSystem {
9 | system = "x86_64-linux";
10 |
11 | specialArgs = {
12 | hostPubkey = null;
13 | };
14 |
15 | modules = [
16 | ./.
17 | inputs.self.nixosModules.default
18 | {
19 | networking.hostName = "shu";
20 | }
21 | ];
22 | };
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/machines/voyage/home.nix:
--------------------------------------------------------------------------------
1 | {homeUser, ...}: {
2 | home.username = homeUser;
3 | home.homeDirectory = "/home/${homeUser}";
4 |
5 | imports = [
6 | ../../homes/core.nix
7 | ];
8 |
9 | targets.crostini.enable = true;
10 |
11 | services.cachix-agent = {
12 | enable = true;
13 | name = "voyage";
14 | };
15 |
16 | programs.rebuild-home.name = "voyage";
17 |
18 | programs.emacs-twist = {
19 | enable = true;
20 | settings = {
21 | extraFeatures = [
22 | ];
23 | };
24 | };
25 | }
26 |
--------------------------------------------------------------------------------
/machines/wang/boot.nix:
--------------------------------------------------------------------------------
1 | {
2 | pkgs,
3 | config,
4 | ...
5 | }:
6 | {
7 | boot.extraModulePackages = [
8 | (config.boot.kernelPackages.r8168.overrideAttrs (
9 | import ../../modules/overrides/r8168.nix { inherit pkgs; }
10 | ))
11 | ];
12 |
13 | boot.loader = {
14 | efi.canTouchEfiVariables = false;
15 | systemd-boot.enable = true;
16 | timeout = 3;
17 | };
18 |
19 | boot.kernelParams = [ "ip=dhcp" ];
20 |
21 | boot.supportedFilesystems = {
22 | zfs = true;
23 | btrfs = true;
24 | ext4 = true;
25 | };
26 |
27 | boot.initrd = {
28 | enable = true;
29 |
30 | supportedFilesystems = {
31 | zfs = true;
32 | btrfs = true;
33 | ext4 = true;
34 | };
35 |
36 | availableKernelModules = [
37 | "xhci_pci"
38 | "r8169"
39 | # To temporarily access removable USB storage devices
40 | "uas"
41 | "sd_mod"
42 | ];
43 |
44 | network = {
45 | enable = true;
46 |
47 | ssh = {
48 | enable = true;
49 | port = 222;
50 |
51 | hostKeys = [
52 | # Generate a key pair using ssh-keygen
53 | "/persist/initrd-ssh-hostkey"
54 | ];
55 |
56 | authorizedKeys = config.users.users.root.openssh.authorizedKeys.keys;
57 | };
58 |
59 | postCommands = ''
60 | zpool import storage1
61 | echo "zfs load-key -r storage1; /bin/cryptsetup-askpass" >> /root/.profile
62 | '';
63 | };
64 | };
65 |
66 | boot.tmp = {
67 | tmpfsSize = "1G";
68 | useTmpfs = true;
69 | };
70 |
71 | boot.zfs = {
72 | # The default is true, but it is highly recommended to turn it off for
73 | # increased reliability.
74 | forceImportRoot = false;
75 | };
76 | }
77 |
--------------------------------------------------------------------------------
/machines/wang/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | pkgs,
3 | modulesPath,
4 | ...
5 | }:
6 | let
7 | stateVersion = "25.05";
8 | in
9 | {
10 | imports = [
11 | # basics
12 | (modulesPath + "/profiles/hardened.nix")
13 | (modulesPath + "/profiles/headless.nix")
14 | ../../nixos/suites/server
15 | ./fs
16 | ./boot.nix
17 |
18 | # Create a non-wheel user for hosting some personal data.
19 | ../../nixos/profiles/users/1000/on-server.nix
20 | ];
21 |
22 | system.stateVersion = stateVersion;
23 |
24 | # Needed for the ZFS pool.
25 | # Use `cat /etc/machine-id | cut -c1-8`
26 | networking.hostId = "4cc22902";
27 |
28 | boot.runSize = "64m";
29 | boot.devSize = "256m";
30 | boot.devShmSize = "256m";
31 |
32 | services.auto-cpufreq.enable = true;
33 | powerManagement.cpuFreqGovernor = "ondemand";
34 |
35 | environment.systemPackages = [
36 | pkgs.lshw
37 | pkgs.usbutils
38 | pkgs.pkgs.git
39 | pkgs.git-annex
40 | # Install gdisk to allow working with new storage devices while the server
41 | # is online.
42 | pkgs.gptfdisk
43 | ];
44 |
45 | time.timeZone = "Asia/Tokyo";
46 | }
47 |
--------------------------------------------------------------------------------
/machines/wang/flake-module.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | let
3 | channel = inputs.stable;
4 | in
5 | {
6 | flake = {
7 | nixosConfigurations.wang = channel.lib.nixosSystem {
8 | system = "x86_64-linux";
9 |
10 | specialArgs = {
11 | hostPubkey = null;
12 | };
13 |
14 | modules = [
15 | ./.
16 | inputs.self.nixosModules.default
17 | {
18 | networking.hostName = "wang";
19 | }
20 | ];
21 | };
22 | };
23 | }
24 |
--------------------------------------------------------------------------------
/machines/wang/fs/annex.nix:
--------------------------------------------------------------------------------
1 | {
2 | boot.initrd.luks.reusePassphrases = true;
3 |
4 | boot.initrd.luks.devices = {
5 | annex1 = {
6 | device = "/dev/disk/by-partuuid/31efb973-e795-4dcf-b72b-19cc7faefb14";
7 | };
8 | annex2 = {
9 | device = "/dev/disk/by-partuuid/a3e493bc-346d-4df0-9491-3d6bb986a0ed";
10 | };
11 | };
12 |
13 | fileSystems = {
14 | "/git-annex/wang-annex1" = {
15 | device = "/dev/mapper/annex1";
16 | fsType = "ext4";
17 | options = [
18 | "noatime"
19 | ];
20 | };
21 | "/git-annex/wang-annex2" = {
22 | device = "/dev/mapper/annex2";
23 | fsType = "ext4";
24 | options = [
25 | "noatime"
26 | ];
27 | };
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/machines/wang/fs/btrfs.nix:
--------------------------------------------------------------------------------
1 | # Use a non-ZFS encrypted partition for a Nix store, downloads, git-annex
2 | # repositories, and other temporary files.
3 | {
4 | device,
5 | }:
6 | {
7 | fileSystems =
8 | builtins.mapAttrs
9 | (
10 | _mountpoint:
11 | {
12 | subvol,
13 | mountOptions ? [ ],
14 | neededForBoot ? false,
15 | }:
16 | {
17 | inherit device neededForBoot;
18 | fsType = "btrfs";
19 | options = [
20 | "subvol=${subvol}"
21 | "compress=zstd"
22 | ] ++ mountOptions;
23 | }
24 | )
25 | {
26 | "/" = {
27 | subvol = "root";
28 | neededForBoot = true;
29 | };
30 | "/nix" = {
31 | subvol = "nix";
32 | mountOptions = [ "noatime" ];
33 | neededForBoot = true;
34 | };
35 | "/var/log" = {
36 | subvol = "var/log";
37 | neededForBoot = true;
38 | };
39 | # Other persistent files (e.g. /var/tmp) and static data that should not
40 | # be put in the world-wide Nix store
41 | "/persist" = {
42 | subvol = "persist";
43 | neededForBoot = true;
44 | };
45 | };
46 |
47 | environment.persistence."/persist" = {
48 | directories = [
49 | "/etc/nixos"
50 | "/var/lib/nixos"
51 | "/var/lib/systemd/coredump"
52 | # # Required for some services
53 | "/var/lib/private"
54 | ];
55 | files = [
56 | "/etc/machine-id"
57 | "/etc/ssh/ssh_host_rsa_key"
58 | "/etc/ssh/ssh_host_rsa_key.pub"
59 | "/etc/ssh/ssh_host_ed25519_key"
60 | "/etc/ssh/ssh_host_ed25519_key.pub"
61 | ];
62 | # Add minimal settings for user files.
63 | # users.akirakomamura = {};
64 | };
65 | }
66 |
--------------------------------------------------------------------------------
/machines/wang/fs/default.nix:
--------------------------------------------------------------------------------
1 | { lib, ... }:
2 | let
3 | systemSsd = "/dev/disk/by-id/ata-CT500BX500SSD1_2432E8BE667B";
4 | cryptBtrfs = "root";
5 | decryptedDevice = "/dev/mapper/${cryptBtrfs}";
6 | in
7 | {
8 | imports = [
9 | (import ./btrfs.nix {
10 | device = decryptedDevice;
11 | })
12 | ./storage1.nix
13 | ./annex.nix
14 | ];
15 |
16 | boot.initrd.luks.devices.${cryptBtrfs} = {
17 | device = "${systemSsd}-part2";
18 | allowDiscards = true;
19 | };
20 |
21 | # Required for impermanence. See
22 | # https://github.com/nix-community/impermanence?tab=readme-ov-file#btrfs-subvolumes
23 | boot.initrd.postDeviceCommands = lib.mkAfter ''
24 | mkdir /btrfs_tmp
25 | mount ${decryptedDevice} /btrfs_tmp
26 | if [[ -e /btrfs_tmp/root ]]; then
27 | mkdir -p /btrfs_tmp/old_roots
28 | timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/root)" "+%Y-%m-%-d_%H:%M:%S")
29 | mv /btrfs_tmp/root "/btrfs_tmp/old_roots/$timestamp"
30 | fi
31 |
32 | delete_subvolume_recursively() {
33 | IFS=$'\n'
34 | for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
35 | delete_subvolume_recursively "/btrfs_tmp/$i"
36 | done
37 | btrfs subvolume delete "$1"
38 | }
39 |
40 | for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +30); do
41 | delete_subvolume_recursively "$i"
42 | done
43 |
44 | btrfs subvolume create /btrfs_tmp/root
45 | umount /btrfs_tmp
46 | '';
47 |
48 | fileSystems = {
49 | "/boot" = {
50 | device = "${systemSsd}-part1";
51 | fsType = "vfat";
52 | options = [
53 | "fmask=0137"
54 | "dmask=0027"
55 | ];
56 | };
57 | };
58 |
59 | services.smartd = {
60 | enable = true;
61 | devices = [
62 | { device = systemSsd; }
63 | {
64 | device = "/dev/disk/by-id/ata-TOSHIBA_MG08ADA800E_74G0A1ZQFCXH";
65 | }
66 | {
67 | device = "/dev/disk/by-id/ata-TOSHIBA_MG08ADA800E_74G0A203FCXH";
68 | }
69 | ];
70 | };
71 | }
72 |
--------------------------------------------------------------------------------
/machines/wang/fs/storage1.nix:
--------------------------------------------------------------------------------
1 | {
2 | boot.zfs = {
3 | requestEncryptionCredentials = [
4 | "storage1"
5 | ];
6 | };
7 |
8 | services.zfs = {
9 | autoSnapshot.enable = true;
10 | autoScrub.enable = true;
11 | };
12 |
13 | boot.kernelParams = [
14 | # 20 GiB
15 | "zfs.zfs_arc_max=21474836480"
16 | ];
17 | }
18 |
--------------------------------------------------------------------------------
/machines/yang/boot.nix:
--------------------------------------------------------------------------------
1 | { config, ... }:
2 | {
3 | boot.loader = {
4 | efi.canTouchEfiVariables = false;
5 | systemd-boot.enable = true;
6 | timeout = 3;
7 | };
8 |
9 | boot.kernelParams = [ "ip=dhcp" ];
10 |
11 | boot.supportedFilesystems = {
12 | "zfs" = true;
13 | "btrfs" = true;
14 | };
15 |
16 | boot.initrd = {
17 | enable = true;
18 |
19 | supportedFilesystems = {
20 | "zfs" = true;
21 | "btrfs" = true;
22 | };
23 |
24 | availableKernelModules = [
25 | "xhci_hcd"
26 | "r8169"
27 | ];
28 |
29 | # systemd.users.root.shell = "/bin/cryptsetup-askpass";
30 |
31 | network = {
32 | enable = true;
33 |
34 | ssh = {
35 | enable = true;
36 | port = 222;
37 |
38 | hostKeys = [
39 | # Generate a key pair using ssh-keygen
40 | "/persist/initrd-ssh-hostkey"
41 | ];
42 |
43 | authorizedKeys = config.users.users.root.openssh.authorizedKeys.keys;
44 | };
45 |
46 | postCommands = ''
47 | zpool import rpool4
48 | echo "zfs load-key -r rpool4; /bin/cryptsetup-askpass" >> /root/.profile
49 | '';
50 | };
51 | };
52 |
53 | boot.zfs = {
54 | # The default is true, but it is suggested to turn it off.
55 | forceImportRoot = false;
56 | };
57 | }
58 |
--------------------------------------------------------------------------------
/machines/yang/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | pkgs,
4 | lib,
5 | modulesPath,
6 | ...
7 | }:
8 | let
9 | stateVersion = "25.05";
10 |
11 | metadata = lib.importTOML ../metadata.toml;
12 |
13 | ip = metadata.hosts.yang.ipAddress;
14 |
15 | inherit (config.services) reverse-proxy;
16 |
17 | hostsTextForReverseProxy = lib.pipe reverse-proxy.subdomains [
18 | builtins.attrNames
19 | (builtins.map (name: "${ip} ${name} ${name}.${reverse-proxy.domain}"))
20 | (builtins.concatStringsSep "\n")
21 | ];
22 | in
23 | {
24 | imports = [
25 | (modulesPath + "/profiles/hardened.nix")
26 | # Create a non-wheel user for hosting some personal data.
27 | ../../nixos/profiles/users/1000/on-server.nix
28 | ../../nixos/profiles/agenix
29 | ../../nixos/profiles/openssh
30 | ../../nixos/profiles/onedev
31 | ../../nixos/profiles/docker
32 | ../../nixos/profiles/reverse-proxy
33 | ../../nixos/profiles/acme/internal.nix
34 | ./fs
35 | ./boot.nix
36 | ./lgtm-stack.nix
37 | ../../nixos/profiles/syncthing
38 | ];
39 |
40 | system.stateVersion = stateVersion;
41 |
42 | # Needed for the ZFS pool.
43 | # Use `cat /etc/machine-id | cut -c1-8`
44 | networking.hostId = "8425e349";
45 |
46 | # This option is enabled by default in nixos/modules/profiles/hardened.nix,
47 | # but needed to be turned off to load br_netfilter module for Docker.
48 | security.lockKernelModules = false;
49 |
50 | boot.runSize = "64m";
51 | boot.devSize = "256m";
52 | boot.devShmSize = "256m";
53 |
54 | services.auto-cpufreq.enable = true;
55 | powerManagement.cpuFreqGovernor = "ondemand";
56 |
57 | environment.systemPackages = [
58 | # Tools for diagnostics
59 | pkgs.tcpdump
60 | pkgs.dig
61 | ];
62 |
63 | services.reverse-proxy = {
64 | enable = true;
65 | domain = "nicesunny.day";
66 | };
67 |
68 | services.coredns = {
69 | enable = true;
70 | config = ''
71 | nicesunny.day {
72 | # Bypass requests for ACME challenges
73 | forward _acme-challenge.nicesunny.day 1.1.1.1
74 | hosts {
75 | ${ip} test test.nicesunny.day
76 | ${hostsTextForReverseProxy}
77 | ${lib.pipe metadata.hosts [
78 | (lib.filterAttrs (_: attrs: attrs ? ipAddress))
79 | (lib.mapAttrsToList (name: attrs: "${attrs.ipAddress} ${name} ${name}.nicesunny.day"))
80 | (builtins.concatStringsSep "\n")
81 | ]}
82 | fallthrough
83 | }
84 | log
85 | }
86 |
87 | . {
88 | # acme-v02.api.letsencrypt.org should be discoverable from the host
89 | forward . 1.1.1.1 8.8.8.8 9.9.9.9
90 | }
91 | '';
92 | };
93 |
94 | services.resolved.enable = false;
95 |
96 | networking.firewall.allowedTCPPorts = [
97 | 2019 # Allow installation of local certificates for caddy
98 | 53 # DNS
99 | ];
100 | networking.firewall.allowedUDPPorts = [
101 | 53 # DNS
102 | ];
103 |
104 | networking = {
105 | useNetworkd = true;
106 | };
107 |
108 | systemd.network = {
109 | networks = {
110 | "20-lan" = {
111 | matchConfig.Name = "enp1s0";
112 | networkConfig = {
113 | DHCP = "ipv4";
114 | Address = metadata.hosts.${config.networking.hostName}.ipAddress;
115 | Gateway = metadata.hosts.zheng.ipAddress;
116 | DNS = metadata.hosts.zheng.ipAddress;
117 | };
118 | };
119 | };
120 | };
121 |
122 | virtualisation.docker = {
123 | storageDriver = "zfs";
124 | };
125 |
126 | users.users.akirakomamura = {
127 | # Provide minimal packages needed for specific needs.
128 | packages = [
129 | pkgs.git
130 | pkgs.git-annex
131 | ];
132 | };
133 |
134 | time.timeZone = "Asia/Tokyo";
135 | }
136 |
--------------------------------------------------------------------------------
/machines/yang/flake-module.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | let
3 | channel = inputs.unstable;
4 | in
5 | {
6 | flake = {
7 | nixosConfigurations.yang = channel.lib.nixosSystem {
8 | system = "x86_64-linux";
9 |
10 | specialArgs = {
11 | hostPubkey = inputs.self.lib.hostPubkeys.yang;
12 | };
13 |
14 | modules = [
15 | ./.
16 | inputs.self.nixosModules.default
17 | {
18 | networking.hostName = "yang";
19 | }
20 | ];
21 | };
22 | };
23 |
24 | perSystem =
25 | { pkgs, ... }:
26 | {
27 | devShells = {
28 | # Provide caddy and certutils to install certificates from caddy
29 | # into the root store
30 | caddy = pkgs.mkShell {
31 | buildInputs = [
32 | pkgs.caddy
33 | pkgs.nssTools # certutils
34 | ];
35 | };
36 | };
37 | };
38 | }
39 |
--------------------------------------------------------------------------------
/machines/yang/fs/btrfs.nix:
--------------------------------------------------------------------------------
1 | # Use a non-ZFS encrypted partition for a Nix store, downloads, git-annex
2 | # repositories, and other temporary files.
3 | {
4 | device,
5 | hostName,
6 | }: {
7 | fileSystems =
8 | builtins.mapAttrs (_mountpoint: {
9 | subvol,
10 | mountOptions,
11 | neededForBoot ? false,
12 | }: {
13 | inherit device neededForBoot;
14 | fsType = "btrfs";
15 | options =
16 | [
17 | "subvol=${subvol}"
18 | "compress=zstd"
19 | ]
20 | ++ mountOptions;
21 | }) {
22 | "/nix" = {
23 | subvol = "nix";
24 | mountOptions = ["noatime"];
25 | neededForBoot = true;
26 | };
27 | # Working space for applications
28 | "/home" = {
29 | subvol = "home";
30 | mountOptions = ["relatime"];
31 | };
32 | # Storage for disposable files, e.g. downloads
33 | "/cache" = {
34 | subvol = "cache";
35 | mountOptions = ["noatime"];
36 | neededForBoot = true;
37 | };
38 | # Other persistent files (e.g. /var/tmp) and static data that should not
39 | # be put in the world-wide Nix store
40 | "/persist" = {
41 | subvol = "persist";
42 | mountOptions = ["noatime"];
43 | neededForBoot = true;
44 | };
45 | "/git-annex/${hostName}" = {
46 | subvol = "git-annex";
47 | mountOptions = ["noatime"];
48 | };
49 | };
50 |
51 | environment.persistence."/cache" = {
52 | directories = [
53 | "/var/cache"
54 | "/var/db/dhcpcd"
55 | ];
56 | };
57 |
58 | environment.persistence."/persist" = {
59 | directories = [
60 | "/var/tmp"
61 | "/var/lib/nixos"
62 | ];
63 | files = [
64 | "/etc/ssh/ssh_host_ed25519_key"
65 | "/etc/ssh/ssh_host_ed25519_key.pub"
66 | ];
67 | };
68 | }
69 |
--------------------------------------------------------------------------------
/machines/yang/fs/default.nix:
--------------------------------------------------------------------------------
1 | {config, ...}: let
2 | sataSsd = "/dev/disk/by-id/ata-Samsung_SSD_860_QVO_1TB_S59HNG0N413450P";
3 | cryptBtrfs = "crypted";
4 | in {
5 | imports = [
6 | (import ./btrfs.nix {
7 | device = "/dev/mapper/${cryptBtrfs}";
8 | hostName = config.networking.hostName;
9 | })
10 | ./rpool4.nix
11 | ];
12 |
13 | boot.initrd.luks.devices.${cryptBtrfs} = {
14 | device = "${sataSsd}-part3";
15 | allowDiscards = true;
16 | };
17 |
18 | fileSystems = {
19 | "/" = {
20 | device = "tmpfs";
21 | fsType = "tmpfs";
22 | options = ["defaults" "size=1G" "mode=755"];
23 | };
24 |
25 | "/boot" = {
26 | device = "${sataSsd}-part1";
27 | fsType = "vfat";
28 | options = ["fmask=0137" "dmask=0027"];
29 | };
30 | };
31 | }
32 |
--------------------------------------------------------------------------------
/machines/yang/fs/rpool4.nix:
--------------------------------------------------------------------------------
1 | {
2 | boot.zfs = {
3 | requestEncryptionCredentials = [
4 | "rpool4"
5 | ];
6 | };
7 | services.zfs = {
8 | autoSnapshot.enable = true;
9 | autoScrub.enable = true;
10 | };
11 |
12 | boot.kernelParams = [
13 | # 3 GiB
14 | "zfs.zfs_arc_max=3221225472"
15 | ];
16 |
17 | fileSystems =
18 | builtins.mapAttrs (_mountPoint: device: {
19 | inherit device;
20 | fsType = "zfs";
21 | }) {
22 | "/var/log" = "rpool4/log";
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/machines/yang/lgtm-stack.nix:
--------------------------------------------------------------------------------
1 | # Configuration of the LGTM (Logs, Grafana, Traces, and Metrics) stack
2 | #
3 | # This configuration is mostly based on the following resources:
4 | #
5 | # https://xeiaso.net/blog/prometheus-grafana-loki-nixos-2020-11-20/
6 | # https://gist.github.com/rickhull/895b0cb38fdd537c1078a858cf15d63e
7 | { config, ... }:
8 | let
9 | grafanaSettings = config.services.grafana.settings;
10 |
11 | prometheusExporters = config.services.prometheus.exporters;
12 |
13 | domain = "nicesunny.day";
14 | in
15 | {
16 | imports = [ ../../nixos/profiles/reverse-proxy ];
17 |
18 | services.reverse-proxy.subdomains.grafana = {
19 | # TODO: Proxy web sockets?
20 | reverse-proxy = "localhost:${toString grafanaSettings.server.http_port}";
21 | };
22 |
23 | # Set the domain to avoid "Origin not allowed" error.
24 | services.grafana = {
25 | enable = true;
26 | settings.server = {
27 | domain = "grafana.${domain}";
28 | http_addr = "127.0.0.1";
29 | http_port = 2342;
30 | };
31 | };
32 |
33 | services.prometheus = {
34 | enable = true;
35 | port = 9001;
36 |
37 | exporters = {
38 | node = {
39 | enable = true;
40 | enabledCollectors = [ "systemd" ];
41 | port = 9002;
42 | };
43 | };
44 |
45 | scrapeConfigs = [
46 | {
47 | job_name = "node-localhost";
48 | static_configs = [ { targets = [ "127.0.0.1:${toString prometheusExporters.node.port}" ]; } ];
49 | }
50 | ];
51 | };
52 | }
53 |
--------------------------------------------------------------------------------
/machines/zheng/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | pkgs,
3 | lib,
4 | ...
5 | }: let
6 | stateVersion = "25.05";
7 | in {
8 | imports = [
9 | # (modulesPath + "/profiles/headless.nix")
10 | # ../../nixos/profiles/nix/cachix-deploy.nix
11 | ../../nixos/profiles/openssh
12 | ./router.nix
13 | ];
14 |
15 | nixpkgs.overlays = [
16 | (_final: super: {
17 | makeModulesClosure = x:
18 | super.makeModulesClosure (x // {allowMissing = true;});
19 | })
20 | ];
21 |
22 | boot.loader.timeout = 6;
23 |
24 | # Replace the raspberry-pi-4 nixos-hardware module with an explicit list of
25 | # kernel modules. See
26 | # https://www.eisfunke.com/posts/2023/nixos-on-raspberry-pi-4.html
27 | boot.initrd.availableKernelModules = [
28 | "usbhid"
29 | "usb_storage"
30 | "vc4"
31 | "pcie_brcmstb"
32 | "reset-raspberrypi"
33 | ];
34 |
35 | boot.supportedFilesystems = {
36 | btrfs = true;
37 | vfat = true;
38 | # Force no ZFS
39 | zfs = lib.mkForce false;
40 | # Just unnecessary for the system
41 | ntfs = lib.mkForce false;
42 | reiserfs = lib.mkForce false;
43 | cifs = lib.mkForce false;
44 | };
45 |
46 | hardware.deviceTree = {
47 | kernelPackage = pkgs.linux_rpi4;
48 | };
49 |
50 | hardware.enableRedistributableFirmware = true;
51 |
52 | system.stateVersion = stateVersion;
53 |
54 | time.timeZone = "Asia/Tokyo";
55 |
56 | nix.settings.allowed-users = ["root"];
57 |
58 | services.journald.extraConfig = ''
59 | SystemMaxUse=1G
60 | MaxFileSec=10day
61 | '';
62 |
63 | boot.tmp.cleanOnBoot = true;
64 |
65 | powerManagement.cpuFreqGovernor = "ondemand";
66 |
67 | zramSwap.enable = true;
68 |
69 | sdImage.compressImage = false;
70 | }
71 |
--------------------------------------------------------------------------------
/machines/zheng/flake-module.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | let
3 | channel = inputs.stable;
4 | in
5 | {
6 | flake = {
7 | nixosConfigurations.zheng = channel.lib.nixosSystem {
8 | system = "aarch64-linux";
9 |
10 | specialArgs = {
11 | hostPubkey = inputs.self.lib.hostPubkeys.zheng;
12 | };
13 |
14 | modules = [
15 | ./.
16 | inputs.self.nixosModules.default
17 | (channel + "/nixos/modules/installer/sd-card/sd-image-aarch64.nix")
18 | {
19 | networking.hostName = "zheng";
20 | }
21 | ];
22 | };
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/machines/zheng/router.nix:
--------------------------------------------------------------------------------
1 | { config, lib, ... }:
2 | # This configuration is mostly based on the following awesome blog post:
3 | # https://github.com/ghostbuster91/blogposts/blob/a2374f0039f8cdf4faddeaaa0347661ffc2ec7cf/router2023-part2/main.md
4 | let
5 | metadata = lib.importTOML ../metadata.toml;
6 |
7 | routerAddress = metadata.hosts.zheng.ipAddress;
8 |
9 | subnet = metadata.networks.home.subnet;
10 |
11 | modules = [
12 | "uas"
13 | "genet"
14 | ];
15 |
16 | adguardhome = config.services.adguardhome;
17 |
18 | # To disable name resolution of *.nicesunny.day with CoreDNS, make this to
19 | # false
20 | useInternalDns = true;
21 | in
22 | {
23 | imports = [
24 | ./usb-wifi.nix
25 | ../../nixos/profiles/adguard-home
26 | ];
27 |
28 | boot.kernelModules = modules;
29 |
30 | # https://github.com/ghostbuster91/blogposts/blob/a2374f0039f8cdf4faddeaaa0347661ffc2ec7cf/router2023-part2/main.md#kernel
31 | boot.kernel = {
32 | sysctl = {
33 | "net.ipv4.conf.all.forwarding" = true;
34 | "net.ipv6.conf.all.forwarding" = false;
35 |
36 | # Filter out Martian packets. See
37 | # https://github.com/ghostbuster91/blogposts/blob/a2374f0039f8cdf4faddeaaa0347661ffc2ec7cf/router2023-part2/main.md#security
38 | "net.ipv4.conf.default.rp_filter" = 1;
39 | "net.ipv4.conf.wan.rp_filter" = 1;
40 | "net.ipv4.conf.br-lan.rp_filter" = 0;
41 | };
42 | };
43 |
44 | # https://github.com/ghostbuster91/blogposts/blob/a2374f0039f8cdf4faddeaaa0347661ffc2ec7cf/router2023-part2/main.md#interfaces
45 | systemd.network = {
46 | wait-online.anyInterface = true;
47 |
48 | netdevs = {
49 | # Create the bridge interface
50 | "20-br-lan" = {
51 | netdevConfig = {
52 | Kind = "bridge";
53 | Name = "br-lan";
54 | };
55 | };
56 | };
57 |
58 | links = {
59 | # Enable USB tethering.
60 | "40-usb0" = {
61 | matchConfig = {
62 | Driver = "rndis_host";
63 | };
64 | linkConfig = {
65 | Name = "usb0";
66 | };
67 | };
68 | };
69 |
70 | networks = {
71 | "30-lan0" = {
72 | matchConfig.Name = "end0";
73 | linkConfig.RequiredForOnline = "enslaved";
74 | networkConfig = {
75 | Bridge = "br-lan";
76 | ConfigureWithoutCarrier = true;
77 | };
78 | };
79 | # There is also a built-in wifi, wlan0, but it doesn't allow enslaving to
80 | # a bridge.
81 | "40-br-lan" = {
82 | matchConfig.Name = "br-lan";
83 | bridgeConfig = { };
84 | address = [ "${routerAddress}/24" ];
85 | networkConfig = {
86 | ConfigureWithoutCarrier = true;
87 | };
88 | };
89 | "50-wan" = {
90 | matchConfig.Name = "usb0";
91 | networkConfig = {
92 | # start a DHCP Client for IPv4 Addressing/Routing
93 | DHCP = "ipv4";
94 | DNSOverTLS = true;
95 | DNSSEC = true;
96 | IPv6PrivacyExtensions = false;
97 | IPv4Forwarding = true;
98 | };
99 | # make routing on this interface a dependency for network-online.target
100 | linkConfig.RequiredForOnline = "routable";
101 | };
102 | };
103 | };
104 |
105 | networking = {
106 | useNetworkd = true;
107 | useDHCP = false;
108 |
109 | nat.enable = false;
110 | firewall.enable = false;
111 |
112 | nftables = {
113 | enable = true;
114 | # https://wiki.nftables.org/wiki-nftables/index.php/Simple_ruleset_for_a_home_router
115 | ruleset = ''
116 | define DEV_PRIVATE = br-lan
117 | define DEV_WORLD = usb0
118 | define NET_PRIVATE = ${subnet}
119 |
120 | table ip global {
121 |
122 | chain inbound_world {
123 | # accepting ping (icmp-echo-request) for diagnostic purposes.
124 | # However, it also lets probes discover this host is alive.
125 | # This sample accepts them within a certain rate limit:
126 | #
127 | # icmp type echo-request limit rate 5/second accept
128 |
129 | # allow SSH connections from some well-known internet host
130 | # ip saddr 81.209.165.42 tcp dport ssh accept
131 | }
132 |
133 | chain inbound_private {
134 | # accepting ping (icmp-echo-request) for diagnostic purposes.
135 | icmp type echo-request limit rate 5/second accept
136 |
137 | # allow DHCP, DNS and SSH from the private network
138 | # also allow access to the admin of AdguardHome
139 | ip protocol . th dport vmap { tcp . 22 : accept, udp . 53 : accept, tcp . 53 : accept, udp . 67 : accept, tcp . 3000 : accept }
140 | }
141 |
142 | chain inbound {
143 | type filter hook input priority 0; policy drop;
144 |
145 | # Allow traffic from established and related packets, drop invalid
146 | ct state vmap { established : accept, related : accept, invalid : drop }
147 |
148 | # allow loopback traffic, anything else jump to chain for further evaluation
149 | iifname vmap { lo : accept, $DEV_WORLD : jump inbound_world, $DEV_PRIVATE : jump inbound_private }
150 |
151 | # the rest is dropped by the above policy
152 | }
153 |
154 | chain forward {
155 | type filter hook forward priority 0; policy drop;
156 |
157 | # Allow traffic from established and related packets, drop invalid
158 | ct state vmap { established : accept, related : accept, invalid : drop }
159 |
160 | # connections from the internal net to the internet or to other
161 | # internal nets are allowed
162 | iifname $DEV_PRIVATE accept
163 |
164 | # the rest is dropped by the above policy
165 | }
166 |
167 | chain postrouting {
168 | type nat hook postrouting priority 100; policy accept;
169 |
170 | # masquerade private IP addresses
171 | ip saddr $NET_PRIVATE oifname $DEV_WORLD masquerade
172 | }
173 | }
174 | '';
175 | };
176 | };
177 |
178 | # systemd-resolved listens on port 53, which conflicts with dnsmasq, so
179 | # disable it.
180 | services.resolved.enable = false;
181 |
182 | # dhcp-hosts contains the MAC address of each host. It's probably safe to put
183 | # them in a public repository, but just in case.
184 | age.secrets = {
185 | "dhcp-hosts" = {
186 | rekeyFile = ./secrets/dhcp-hosts.age;
187 | owner = "dnsmasq";
188 | group = "dnsmasq";
189 | };
190 | };
191 |
192 | services.dnsmasq = {
193 | enable = true;
194 |
195 | resolveLocalQueries = !useInternalDns;
196 |
197 | settings = {
198 | # upstream DNS servers
199 | server =
200 | (
201 | if adguardhome.enable then
202 | [ "127.0.0.1#${builtins.toString adguardhome.settings.dns.port}" ]
203 | else
204 | [
205 | "1.1.1.1"
206 | "8.8.8.8"
207 | "9.9.9.9"
208 | ]
209 | )
210 | ++ (lib.optional useInternalDns "/nicesunny.day/${metadata.hosts.yang.ipAddress}");
211 | # sensible behaviours
212 | domain-needed = true;
213 | bogus-priv = true;
214 | no-resolv = true;
215 |
216 | # Use as the primary DNS for the network
217 | port = 53;
218 |
219 | # Cache dns queries.
220 | cache-size = 1000;
221 |
222 | dhcp-range = [ "br-lan,192.168.10.50,192.168.10.254,24h" ];
223 | interface = "br-lan";
224 | dhcp-host = routerAddress;
225 | dhcp-authoritative = true;
226 | # dhcp-sequential-ip = true;
227 | dhcp-option = [
228 | "3,${routerAddress}"
229 | "6,${routerAddress}"
230 | ];
231 |
232 | dhcp-hostsfile = config.age.secrets."dhcp-hosts".path;
233 |
234 | # local domains
235 | # https://datatracker.ietf.org/doc/html/rfc6762#appendix-G
236 | local = lib.mkIf (!useInternalDns) "/nicesunny.day/";
237 | domain = "nicesunny.day";
238 | expand-hosts = true;
239 |
240 | # don't use /etc/hosts as this would advertise surfer as localhost
241 | no-hosts = true;
242 | address = [
243 | "/zheng/${routerAddress}"
244 | "/zheng.nicesunny.day/${routerAddress}"
245 | ];
246 | };
247 | };
248 |
249 | services.hostapd = {
250 | enable = true;
251 | radios = {
252 | wlp1s0u1u4 = {
253 | band = "2g";
254 | countryCode = "JP";
255 | channel = 8;
256 |
257 | settings.bridge = "br-lan";
258 |
259 | wifi4 = {
260 | enable = true;
261 | capabilities = [
262 | "RX-STBC1"
263 | "SHORT-GI-40"
264 | "SHORT-GI-20"
265 | "DSSS_CCK-40"
266 | "MAX-AMSDU-7935"
267 | ];
268 | };
269 |
270 | networks = {
271 | wlp1s0u1u4 = {
272 | ssid = "nicky";
273 | authentication = {
274 | # Use the transition mode to support older devices. wpa3-sae is
275 | # more secure and hence would be more desirable.
276 | mode = "wpa3-sae-transition";
277 | saePasswordsFile = "/etc/hostapd/password";
278 | # Provide both sae and wpa passwords for the transition mode.
279 | wpaPasswordFile = "/etc/hostapd/password";
280 | };
281 | };
282 | };
283 | };
284 | };
285 | };
286 |
287 | services.adguardhome.settings = lib.mkIf adguardhome.enable {
288 | dns.bind_hosts = [
289 | "127.0.0.1"
290 | "192.168.10.1"
291 | ];
292 | };
293 | }
294 |
--------------------------------------------------------------------------------
/machines/zheng/secrets/dhcp-hosts.age:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akirak/homelab/982762f4dc21623c268a852ceffeafff210fe3c5/machines/zheng/secrets/dhcp-hosts.age
--------------------------------------------------------------------------------
/machines/zheng/usb-wifi.nix:
--------------------------------------------------------------------------------
1 | {
2 | pkgs,
3 | config,
4 | ...
5 | }: {
6 | environment.systemPackages = [
7 | # Add lshw for ease of debugging. Use `lshw -c network` to find
8 | # `driver=8192eu`
9 | pkgs.lshw
10 | ];
11 |
12 | boot.extraModulePackages = [
13 | (config.boot.kernelPackages.rtl8192eu.overrideAttrs (old: {
14 | # Set flags specific to Raspberry Pi.
15 | makeFlags =
16 | (old.makeFlags or [])
17 | ++ [
18 | "CONFIG_PLATFORM_I386_PC=n"
19 | "CONFIG_PLATFORM_ARM_RPI=y"
20 | ];
21 |
22 | src = old.src.override {
23 | rev = "7ef82518547dcb5aacd8797e370332337b37d601";
24 | sha256 = "sha256-HK4VYEfe7tcXxQBqQ9reaOypubkKVRqa6zyNaQUhlxQ=";
25 | };
26 |
27 | meta.broken = false;
28 | }))
29 | ];
30 |
31 | boot.blacklistedKernelModules = [
32 | "rtl8xxxu"
33 | ];
34 | }
35 |
--------------------------------------------------------------------------------
/nixos/models/asus-br1100/flake-module.nix:
--------------------------------------------------------------------------------
1 | { inputs, ... }:
2 | let
3 | inherit (inputs) stable;
4 |
5 | overlayModule = {
6 | nixpkgs.overlays = [ inputs.self.overlays.default ];
7 | };
8 | in
9 | {
10 | flake = {
11 | nixosModules = {
12 | asus-br1100 = import ./modules { inherit (inputs) nixos-hardware; };
13 | };
14 |
15 | packages.x86_64-linux = {
16 | asus-br1100-iso =
17 | (stable.lib.nixosSystem {
18 | system = "x86_64-linux";
19 | modules = [
20 | overlayModule
21 | inputs.self.nixosModules.asus-br1100
22 | ../../suites/iso
23 | ];
24 | }).config.system.build.isoImage;
25 | };
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/nixos/models/asus-br1100/modules/acpi_call.nix:
--------------------------------------------------------------------------------
1 | {config, ...}: {
2 | boot.kernelModules = ["acpi_call"];
3 | boot.extraModulePackages = with config.boot.kernelPackages; [
4 | acpi_call
5 | ];
6 | }
7 |
--------------------------------------------------------------------------------
/nixos/models/asus-br1100/modules/default.nix:
--------------------------------------------------------------------------------
1 | {nixos-hardware}: {...}: {
2 | imports = [
3 | (nixos-hardware.outPath + "/common/pc/laptop")
4 | (nixos-hardware.outPath + "/common/gpu/intel")
5 | ./r8168.nix
6 | ./wireless.nix
7 | ./acpi_call.nix
8 | ];
9 |
10 | # I don't know if this parameter is necessary.
11 | boot.kernelParams = ["nouveau.modeset=0"];
12 |
13 | # boot.kernelPackages = pkgs.linuxKernel.packages.linux_6_0;
14 | }
15 |
--------------------------------------------------------------------------------
/nixos/models/asus-br1100/modules/r8168.nix:
--------------------------------------------------------------------------------
1 | {
2 | pkgs,
3 | config,
4 | ...
5 | }:
6 | {
7 | # At present, wired interface does not work even with this kernel module due
8 | # to a common "ucsi_acpi usbc000:00: ppm init failed" error. This issue may be
9 | # fixed at some point, but I am not sure.
10 | boot.extraModulePackages = [
11 | (config.boot.kernelPackages.r8168.overrideAttrs (
12 | _: super: rec {
13 | version = "8.054.00";
14 | src = pkgs.fetchFromGitHub {
15 | owner = "mtorromeo";
16 | repo = "r8168";
17 | rev = version;
18 | sha256 = "sha256-KyycAe+NBmyDDH/XkAM4PpGvXI5J1CuMW4VuHcOm0UQ=";
19 | };
20 | meta = super.meta // {
21 | broken = false;
22 | };
23 | }
24 | ))
25 | ];
26 | boot.blacklistedKernelModules = [ "r8169" ];
27 | }
28 |
--------------------------------------------------------------------------------
/nixos/models/asus-br1100/modules/wireless.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | boot.kernelModules = ["iwlwifi"];
3 | hardware.firmware = [pkgs.wireless-regdb];
4 | hardware.enableRedistributableFirmware = true;
5 | }
6 |
--------------------------------------------------------------------------------
/nixos/profiles/acme/default.nix:
--------------------------------------------------------------------------------
1 | { config, lib, ... }:
2 | let
3 | defaultEmail = "akira.komamura@gmail.com";
4 | in
5 | {
6 | security.acme = {
7 | acceptTerms = true;
8 | defaults.email = defaultEmail;
9 | };
10 |
11 | users.users.nginx = lib.mkIf config.services.nginx.enable { extraGroups = [ "acme" ]; };
12 | }
13 |
--------------------------------------------------------------------------------
/nixos/profiles/acme/internal.nix:
--------------------------------------------------------------------------------
1 | { config, pkgs, ... }:
2 | let
3 | domain = "nicesunny.day";
4 |
5 | credentialsPath = "nicesunny.day.credentials.txt";
6 | in
7 | {
8 | imports = [ ./. ];
9 |
10 | age.secrets = {
11 | ${credentialsPath} = {
12 | rekeyFile = ./secrets/nicesunny.day.credentials.txt.age;
13 | # path = "/etc/acme/secrets/nicesunnyday.txt";
14 | # mode = "";
15 | # owner = "";
16 | # group = "";
17 | };
18 | };
19 |
20 | security.acme.certs.${domain} = {
21 | inherit domain;
22 | extraDomainNames = [ "*.${domain}" ];
23 | dnsProvider = "cloudflare";
24 | dnsResolver = "1.1.1.1:53";
25 | # We don't need to wait for propagation since this is a local DNS server
26 | dnsPropagationCheck = false;
27 | environmentFile = config.age.secrets.${credentialsPath}.path;
28 | };
29 |
30 | services.caddy = {
31 | package = pkgs.caddy.withPlugins {
32 | plugins = [
33 | "github.com/caddy-dns/cloudflare@v0.0.0-20250228175314-1fb64108d4de"
34 | ];
35 | hash = "sha256-YYpsf8HMONR1teMiSymo2y+HrKoxuJMKIea5/NEykGc=";
36 | };
37 | globalConfig = ''
38 | acme_dns cloudflare {env.CLOUDFLARE_DNS_API_TOKEN}
39 | '';
40 | };
41 |
42 | systemd.services.caddy.serviceConfig = {
43 | EnvironmentFile = [
44 | config.age.secrets.${credentialsPath}.path
45 | ];
46 | };
47 | }
48 |
--------------------------------------------------------------------------------
/nixos/profiles/acme/secrets/nicesunny.day.credentials.txt.age:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akirak/homelab/982762f4dc21623c268a852ceffeafff210fe3c5/nixos/profiles/acme/secrets/nicesunny.day.credentials.txt.age
--------------------------------------------------------------------------------
/nixos/profiles/adb/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | pkgs,
3 | homeUser,
4 | ...
5 | }: {
6 | programs.adb.enable = true;
7 | users.users.${homeUser}.extraGroups = [
8 | "adbusers"
9 | ];
10 | home-manager.users.${homeUser} = {
11 | home.packages = [
12 | pkgs.android-studio
13 | ];
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/nixos/profiles/adguard-home/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | services.adguardhome = {
3 | enable = true;
4 | mutableSettings = false;
5 | settings = {
6 | dhcp = {
7 | enabled = false;
8 | };
9 | dns = {
10 | # Use the AdguardHome DNS only for external traffic
11 | port = 5353;
12 | bootstrap_dns = [
13 | # Cloudflare
14 | "1.1.1.1"
15 | "1.0.0.1"
16 | ];
17 | upstream_dns = [
18 | "1.1.1.1"
19 | "8.8.8.8"
20 | "9.9.9.9"
21 | ];
22 | upstream_mode = "fastest_addr";
23 | };
24 | };
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/nixos/profiles/agenix/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | age.identityPaths = [
3 | "/etc/ssh/ssh_host_ed25519_key"
4 | ];
5 | }
6 |
--------------------------------------------------------------------------------
/nixos/profiles/containers/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | virtualisation.containers.enable = true;
3 | }
4 |
--------------------------------------------------------------------------------
/nixos/profiles/containers/rootless.nix:
--------------------------------------------------------------------------------
1 | {
2 | imports = [
3 | ./.
4 | ];
5 |
6 | virtualisation.containers = {
7 | # Based on https://carlosvaz.com/posts/rootless-podman-and-docker-compose-on-nixos/
8 | storage.settings = {
9 | storage = {
10 | driver = "overlay";
11 | runroot = "/run/containers/storage";
12 | graphroot = "/var/lib/containers/storage";
13 | # The size can be large, so don't store the directory on tmpfs.
14 | # Instead, you can create a separate file system.
15 | # rootless_storage_path = "/tmp/containers-$USER";
16 | options.overlay.mountopt = "nodev,metacopy=on";
17 | };
18 | };
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/nixos/profiles/desktop/plasma.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | ...
5 | }: {
6 | services.xserver.displayManager.sddm.enable = true;
7 | services.xserver.desktopManager.plasma5.enable = true;
8 |
9 | services.xrdp.defaultWindowManager =
10 | lib.mkIf config.services.xrdp.enable "startplasma-x11";
11 | }
12 |
--------------------------------------------------------------------------------
/nixos/profiles/docker/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | virtualisation.docker.enable = true;
3 | }
4 |
--------------------------------------------------------------------------------
/nixos/profiles/docker/kind.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | imports = [
3 | ./.
4 | ];
5 |
6 | environment.systemPackages = [
7 | pkgs.kind
8 | pkgs.kubectl
9 | ];
10 | }
11 |
--------------------------------------------------------------------------------
/nixos/profiles/docker/rootless.nix:
--------------------------------------------------------------------------------
1 | {
2 | imports = [
3 | ./default.nix
4 | ];
5 |
6 | virtualisation.docker.rootless = {
7 | enable = true;
8 | setSocketVariable = true;
9 | };
10 | }
11 |
--------------------------------------------------------------------------------
/nixos/profiles/dpt-rp1/default.nix:
--------------------------------------------------------------------------------
1 | # Connectivity with Fujitsu Quaderno using dpt-rp1-py
2 | # https://github.com/janten/dpt-rp1-py
3 | { pkgs, ... }:
4 | {
5 | environment.systemPackages = [
6 | pkgs.dpt-rp1-py
7 |
8 | # I use this program to set the mode of the device to CDC/ECM manually. See
9 | # https://github.com/janten/dpt-rp1-py/blob/master/docs/linux-ethernet-over-usb.md#switching-the-usb-mode-the-ethernet-over-usb
10 | # for an instruction.
11 | pkgs.picocom
12 | ];
13 |
14 | services.avahi = {
15 | enable = true;
16 | # Check the interface name
17 | allowInterfaces = [
18 | "usb1"
19 | ];
20 | # Only IPv6 is used by the program
21 | ipv6 = true;
22 | nssmdns6 = true;
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/nixos/profiles/flatpak/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | # You may have to restart the window manager to enable environment variables
3 | # (e.g. XDG_DATA_DIRS) required to run
4 | services.flatpak.enable = true;
5 | }
6 |
--------------------------------------------------------------------------------
/nixos/profiles/home-manager/default.nix:
--------------------------------------------------------------------------------
1 | /*
2 | Default integration with home-manager
3 |
4 | You also have to import home-manager.nixosModules.home-manager
5 | */
6 | {
7 | homeUser,
8 | config,
9 | pkgs,
10 | lib,
11 | ...
12 | }: {
13 | imports = [
14 | ../nixpkgs/channels.nix
15 | ];
16 |
17 | users.defaultUserShell =
18 | if config.programs.zsh.enable
19 | then pkgs.zsh
20 | else pkgs.bash;
21 |
22 | programs.zsh.enable = true;
23 |
24 | users.users.${homeUser}.extraGroups =
25 | (lib.optional config.virtualisation.docker.enable "docker")
26 | ++ (lib.optionals config.virtualisation.virtualbox.host.enable [
27 | "vboxusers"
28 | "vboxsf"
29 | ]);
30 |
31 | home-manager = {
32 | useGlobalPkgs = true;
33 | useUserPackages = true;
34 |
35 | users.${homeUser} = {
36 | imports = [
37 | ../../../homes/core.nix
38 | ];
39 |
40 | programs.nixos-rebuild-and-notify.enable = true;
41 |
42 | home.stateVersion = lib.mkDefault config.system.stateVersion;
43 | };
44 | };
45 | }
46 |
--------------------------------------------------------------------------------
/nixos/profiles/intel-arc/default.nix:
--------------------------------------------------------------------------------
1 | # Based on https://github.com/VTimofeenko/monorepo-machine-config/blob/4c1f85c700c45a5d3a8a38956194d2c97753b8ba/nixosConfigurations/neon/configuration/hw-acceleration.nix#L24
2 | #
3 | # Also add inputs.nixos-hardware.nixosModules.common-gpu-intel to the module
4 | # list in flake.nix
5 | { pkgs, ... }:
6 | {
7 | hardware.graphics = {
8 | enable = true;
9 | extraPackages = with pkgs; [
10 | intel-media-driver
11 | intel-ocl
12 | # nixos-unstable
13 | vpl-gpu-rt
14 | intel-media-sdk
15 | intel-compute-runtime
16 | intel-vaapi-driver
17 | ];
18 | };
19 |
20 | boot.kernelParams = [
21 | # Check the ID by running `lspci -k | grep -EA3 'VGA|3D|Display'`
22 | "i915.force_probe=6021"
23 | "i915.enable_guc=3"
24 | ];
25 |
26 | environment.sessionVariables = {
27 | VDPAU_DRIVER = "va_gl";
28 | LIBVA_DRIVER_NAME = "iHD";
29 | };
30 | hardware.intelgpu.driver = "xe";
31 |
32 | # Use the latest kernel for the intel driver that supports ZFS
33 | boot.kernelPackages = pkgs.linuxPackages_6_12;
34 |
35 | environment.systemPackages = with pkgs; [
36 | libva-utils
37 | intel-gpu-tools
38 | ];
39 | }
40 |
--------------------------------------------------------------------------------
/nixos/profiles/k3s/single-node-for-testing.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | imports = [
3 | ./single-node.nix
4 | ];
5 |
6 | services.k3s = {
7 | # https://0to1.nl/post/k3s-kubectl-permission/
8 | environmentFile = pkgs.writeText "environment" ''
9 | K3S_KUBECONFIG_MODE="644"
10 | '';
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/nixos/profiles/k3s/single-node.nix:
--------------------------------------------------------------------------------
1 | /*
2 | Single-node k3s configuration.
3 |
4 | Based on https://nixos.wiki/wiki/K3s#Single_node_setup
5 | */
6 | {pkgs, ...}: {
7 | # This is required so that pod can reach the API server (running on port 6443 by default)
8 | networking.firewall.allowedTCPPorts = [6443];
9 | services.k3s.enable = true;
10 | services.k3s.role = "server";
11 | services.k3s.extraFlags = toString [
12 | # "--kubelet-arg=v=4" # Optionally add additional args to k3s
13 | ];
14 | environment.systemPackages = [pkgs.k3s];
15 | }
16 |
--------------------------------------------------------------------------------
/nixos/profiles/livebook/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | imports = [
3 | ./interface.nix
4 | ];
5 | }
6 |
--------------------------------------------------------------------------------
/nixos/profiles/livebook/interface.nix:
--------------------------------------------------------------------------------
1 | /*
2 | Options taken from pleroma.nix
3 | at
4 | in https://github.com/NixOS/nixpkgs
5 | */
6 | {
7 | config,
8 | lib,
9 | pkgs,
10 | ...
11 | }: let
12 | cfg = config.services.my-livebook;
13 |
14 | openScript = pkgs.writers.writeBashBin "open-livebook" ''
15 | set -euo pipefail
16 |
17 | LIVEBOOK_SERVICE="''${LIVEBOOK_SERVICE:-livebook.service}"
18 |
19 | if [[ ! -v DISPLAY ]] && [[ ! -v WAYLAND_DISPLAY ]]
20 | then
21 | echo "This command can be run only in a graphical environment" >&2
22 | exit 1
23 | fi
24 |
25 | err() {
26 | echo "$@" >&2
27 | ${pkgs.notify-desktop}/bin/notify-desktop --app-name=Livebook "$@"
28 | exit 1
29 | }
30 |
31 | if ! systemctl is-active "''${LIVEBOOK_SERVICE}" >/dev/null
32 | then
33 | err "''${LIVEBOOK_SERVICE} is not running"
34 | fi
35 |
36 | if [[ $(systemctl show "''${LIVEBOOK_SERVICE}" --property=MainPID) =~ MainPID=([[:digit:]]+) ]]
37 | then
38 | pid=''${BASH_REMATCH[1]}
39 | else
40 | err "Failed to parse the main PID of the service"
41 | fi
42 |
43 | out="$(journalctl --no-pager -t livebook -g "Application running at" | tail -1)"
44 |
45 | if [[ -z "$out" ]]
46 | then
47 | ${pkgs.notify-desktop}/bin/notify-desktop 'Restarting livebook service to retrieve the PID'
48 | systemctl restart --wait "''${LIVEBOOK_SERVICE}"
49 | LIVEBOOK_SERVICE="''${LIVEBOOK_SERVICE}" exec "$0"
50 | fi
51 |
52 | if [[ $out =~ livebook\[([[:digit:]]+)\] ]] \
53 | && [[ ''${BASH_REMATCH[1]} = $pid ]] \
54 | && [[ $out =~ http://[^[:space:]]+ ]]
55 | then
56 | url="''${BASH_REMATCH[0]}"
57 | else
58 | err "Failed to parse the output of journalctl"
59 | fi
60 |
61 | echo "Opening $url"
62 |
63 | if ! ${pkgs.handlr}/bin/handlr open "$url"
64 | then
65 | err "Failed to open the URL $url"
66 | fi
67 | '';
68 | in {
69 | options = {
70 | services.my-livebook = with lib; {
71 | enable = mkEnableOption (lib.mdDoc "Elixir Livebook");
72 |
73 | package = mkOption {
74 | type = types.package;
75 | default = pkgs.livebook;
76 | defaultText = literalExpression "pkgs.livebook";
77 | description = lib.mdDoc "Livebook package to use.";
78 | };
79 |
80 | user = mkOption {
81 | type = types.str;
82 | default = "livebook";
83 | };
84 |
85 | group = mkOption {
86 | type = types.str;
87 | default = "livebook";
88 | };
89 |
90 | dataDir = mkOption {
91 | type = types.str;
92 | default = "/var/lib/livebook/data";
93 | readOnly = true;
94 | description = "Directory to be used as LIVEBOOK_DATA_PATH.";
95 | };
96 |
97 | settings = {
98 | ipAddress = mkOption {
99 | type = types.str;
100 | default = "127.0.0.1";
101 | description = "LIVEBOOK_IP";
102 | };
103 |
104 | port = mkOption {
105 | type = types.port;
106 | default = 0;
107 | description = "LIVEBOOK_PORT";
108 | };
109 |
110 | homeDirectory = mkOption {
111 | type = types.str;
112 | default = "/var/lib/livebook";
113 | description = "LIVEBOOK_HOME";
114 | };
115 |
116 | enableNix = mkOption {
117 | type = types.bool;
118 | default = false;
119 | description = "Enable Nix package manager for the user.";
120 | };
121 |
122 | extraPackages = mkOption {
123 | type = types.listOf types.package;
124 | default = [];
125 | description = lib.mdDoc "List of packages that are made available to the user.";
126 | };
127 | };
128 | };
129 | };
130 |
131 | config = lib.mkIf cfg.enable {
132 | ids = {
133 | # Check nixos/modules/misc/ids.nix in nixpkgs to ensure there is no
134 | # collision
135 | #
136 | # If the user/group has been already created with a different numeric ID,
137 | # first disable the livebook service to remove the user and group and
138 | # then re-enable it to recreate them.
139 | uids.livebook = 293;
140 | gids.livebook = 293;
141 | };
142 |
143 | users = {
144 | users.${cfg.user} = {
145 | description = "Livebook user";
146 | group = cfg.group;
147 | isSystemUser = true;
148 | createHome = true;
149 | home = "/var/lib/livebook";
150 | homeMode = "750";
151 | # Provide a shell with dependencies to allow administration. For
152 | # example, you can enter a shell with `sudo su - livebook` and install
153 | # hex by running `mix local.hex`.
154 | useDefaultShell = true;
155 | packages = cfg.package.nativeBuildInputs ++ cfg.package.buildInputs;
156 | uid = config.ids.uids.livebook;
157 | };
158 | groups.${cfg.group} = {
159 | gid = config.ids.gids.livebook;
160 | };
161 | };
162 |
163 | nix.settings.allowed-users = lib.optionals cfg.settings.enableNix [
164 | cfg.user
165 | ];
166 |
167 | environment.systemPackages = [
168 | openScript
169 | (pkgs.makeDesktopItem {
170 | name = "open-livebook";
171 | desktopName = "Open Livebook";
172 | exec = "open-livebook";
173 | tryExec = "${openScript}/bin/open-livebook";
174 | })
175 | ];
176 |
177 | # Without epmd already running, livebook tries to start it on its own, which
178 | # can conflict with another instance of epmd required by other services,
179 | # e.g. rabbitmq.
180 | services.epmd.enable = true;
181 |
182 | systemd.services.livebook = {
183 | description = "Elixir Livebook";
184 | wantedBy = ["multi-user.target"];
185 | requires = [
186 | "epmd.socket"
187 | ];
188 | after = [
189 | "epmd.socket"
190 | ];
191 |
192 | path =
193 | [
194 | # osmon fails if /bin is not in the PATH.
195 | # Based on information at
196 | #
197 | ""
198 | ]
199 | # This is not a proper way to add Nix packages to the environment, but I
200 | # was unable to find other way. Adding packages to
201 | # users.users.livebook.packages didn't work :(
202 | ++ cfg.settings.extraPackages
203 | ++ (lib.optionals cfg.settings.enableNix [
204 | config.nix.package
205 | "${cfg.settings.homeDirectory}/.nix-profile"
206 | ]);
207 |
208 | environment = {
209 | LIVEBOOK_DATA_PATH = cfg.dataDir;
210 | LIVEBOOK_IP = cfg.settings.ipAddress;
211 | LIVEBOOK_PORT = builtins.toString cfg.settings.port;
212 | LIVEBOOK_HOME = cfg.settings.homeDirectory;
213 | RELEASE_COOKIE = "${cfg.settings.homeDirectory}/.cookie";
214 | };
215 |
216 | serviceConfig = {
217 | User = cfg.user;
218 | Group = cfg.group;
219 |
220 | Type = "exec";
221 |
222 | StandardOutput = "journal";
223 | StandardError = "journal";
224 |
225 | ExecStart = "${cfg.package}/bin/livebook start";
226 |
227 | # Create a release cookie. The code is based on
228 | # https://github.com/nixos/nixpkgs/blob/nil/nixos/modules/services/networking/pleroma.nix
229 | ExecStartPre = "${pkgs.writers.writeBashBin "write-cookie" ''
230 | RELEASE_COOKIE="${cfg.settings.homeDirectory}/.cookie"
231 |
232 | if [[ ! -f "''${RELEASE_COOKIE}" ]]
233 | then
234 | dd if=/dev/urandom bs=1 count=16 | ${pkgs.hexdump}/bin/hexdump -e '16/1 "%02x"' > "''${RELEASE_COOKIE}"
235 | fi
236 | ''}/bin/write-cookie";
237 |
238 | # If you ran a public instance, it might be important to set these
239 | # options properly, but I am only running a local private instance, so I
240 | # don't find it worth the effort.
241 | PrivateTmp = true;
242 | # ProtectHome = true;
243 | # ProtectSystem = "full";
244 | # PrivateDevices = false;
245 | # NoNewPrivileges = true;
246 | # CapabilityBoundingSet = "~CAP_SYS_ADMIN";
247 | };
248 | };
249 | };
250 | }
251 |
--------------------------------------------------------------------------------
/nixos/profiles/locale/default.nix:
--------------------------------------------------------------------------------
1 | /*
2 | My preferred locale settings
3 | */
4 | let
5 | defaultLocale = "en_US.UTF-8";
6 | in {
7 | i18n = {
8 | inherit defaultLocale;
9 | extraLocaleSettings = {
10 | LC_CTYPE = defaultLocale;
11 | # LC_COLLATE = "C.UTF-8";
12 | # LC_TIME = "en_DK.UTF-8";
13 | };
14 | supportedLocales = [
15 | "en_US.UTF-8/UTF-8"
16 | "en_GB.UTF-8/UTF-8"
17 | "zh_CN.UTF-8/UTF-8"
18 | "zh_TW.UTF-8/UTF-8"
19 | "ja_JP.UTF-8/UTF-8"
20 | ];
21 | };
22 | }
23 |
--------------------------------------------------------------------------------
/nixos/profiles/microvm/default.nix:
--------------------------------------------------------------------------------
1 | # Based on flake.nix for github:astro/microvm.nix
2 | {
3 | hypervisor,
4 | config,
5 | lib,
6 | ...
7 | }: let
8 | inherit (builtins) elem;
9 |
10 | hypervisorsWith9p = ["qemu"];
11 | hypervisorsWithUserNet = ["qemu" "kvmtool"];
12 | in {
13 | microvm.hypervisor = hypervisor;
14 |
15 | microvm.shares = lib.optional (elem hypervisor hypervisorsWith9p) {
16 | tag = "ro-store";
17 | source = "/nix/store";
18 | mountPoint = "/nix/.ro-store";
19 | };
20 | microvm.writableStoreOverlay = "/nix/.rw-store";
21 | microvm.volumes = [
22 | {
23 | image = "nix-store-overlay.img";
24 | mountPoint = config.microvm.writableStoreOverlay;
25 | size = 2048;
26 | }
27 | ];
28 |
29 | microvm.interfaces = lib.optional (elem hypervisor hypervisorsWithUserNet) {
30 | type = "user";
31 | id = "qemu";
32 | mac = "02:00:00:01:01:01";
33 | };
34 | }
35 |
--------------------------------------------------------------------------------
/nixos/profiles/microvm/ssh.nix:
--------------------------------------------------------------------------------
1 | {...}: let
2 | sshPort = 22;
3 | in {
4 | microvm.forwardPorts = [
5 | {
6 | host.port = 2222;
7 | guest.port = sshPort;
8 | }
9 | ];
10 |
11 | networking.firewall.enable = true;
12 |
13 | services.openssh = {
14 | enable = true;
15 | ports = [sshPort];
16 | openFirewall = true;
17 | settings = {
18 | PermitRootLogin = "yes";
19 | };
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/nixos/profiles/minio/development.nix:
--------------------------------------------------------------------------------
1 | {
2 | services.minio = {
3 | enable = true;
4 | listenAddress = "127.0.0.1:9000";
5 | consoleAddress = "127.0.0.1:9001";
6 | rootCredentialsFile = "/persist/minio-root-credentials";
7 | };
8 | }
9 |
--------------------------------------------------------------------------------
/nixos/profiles/networking/usb-tether1.nix:
--------------------------------------------------------------------------------
1 | {
2 | systemd.network.links."20-usb1" = {
3 | matchConfig = {
4 | Driver = "rndis_host";
5 | };
6 | linkConfig = {
7 | Name = "usb1";
8 | };
9 | };
10 | }
11 |
--------------------------------------------------------------------------------
/nixos/profiles/nginx/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | services.nginx = {
3 | enable = true;
4 | };
5 |
6 | networking.firewall.allowedTCPPorts = [
7 | 80
8 | 443
9 | ];
10 | }
11 |
--------------------------------------------------------------------------------
/nixos/profiles/nix/cachix-deploy.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | environment.systemPackages = [
3 | pkgs.cachix
4 | ];
5 |
6 | # To start an agent, you have to create /etc/cachix-agent.token file which
7 | # contains an CACHIX_AGENT_TOKEN environment entry. The file is not created in
8 | # nixos-rebuild.
9 | services.cachix-agent.enable = true;
10 | }
11 |
--------------------------------------------------------------------------------
/nixos/profiles/nix/default.nix:
--------------------------------------------------------------------------------
1 | /*
2 | Nix options for desktop machines
3 |
4 | If you don't build Nix on the host, don't import this profile.
5 | */
6 | {
7 | nix = {
8 | gc = {
9 | dates = "monthly";
10 | automatic = true;
11 | };
12 | optimise.automatic = false;
13 |
14 | settings = {
15 | # sandbox = true;
16 | allowed-users = [ "@wheel" ];
17 | trusted-users = [
18 | "root"
19 | "@wheel"
20 | ];
21 |
22 | substituters = [
23 | "https://cache.nixos.org/"
24 | "https://nix-community.cachix.org"
25 | "https://akirak.cachix.org"
26 | ];
27 |
28 | trusted-substituters = [
29 | "https://emacs-ci.cachix.org"
30 | ];
31 |
32 | trusted-public-keys = [
33 | "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
34 | "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
35 | "akirak.cachix.org-1:WJrEMdV1dYyALkOdp/kAECVZ6nAODY5URN05ITFHC+M="
36 | "emacs-ci.cachix.org-1:B5FVOrxhXXrOL0S+tQ7USrhjMT5iOPH+QN9q0NItom4="
37 | ];
38 | };
39 |
40 | extraOptions = ''
41 | # min-free = 536870912
42 | # keep-outputs = true
43 | # keep-derivations = true
44 | # fallback = true
45 | experimental-features = nix-command flakes
46 | '';
47 | };
48 | }
49 |
--------------------------------------------------------------------------------
/nixos/profiles/nixpkgs/channels.nix:
--------------------------------------------------------------------------------
1 | {lib, ...}: {
2 | nixpkgs.config = {
3 | allowUnfreePredicate = pkg:
4 | builtins.elem (lib.getName pkg) [
5 | # Explicitly select unfree packages.
6 | "wpsoffice"
7 | "steam-run"
8 | "steam-original"
9 | "symbola"
10 | "vscode"
11 | "microsoft-edge-stable"
12 | "android-studio-stable"
13 | "zoom"
14 | "Oracle_VM_VirtualBox_Extension_Pack" # older
15 | "Oracle_VirtualBox_Extension_Pack" # newer
16 | "google-chrome"
17 | "intel-ocl"
18 | "cursor"
19 | "steam-unwrapped"
20 | "windsurf"
21 | "claude-code"
22 | "copilot-language-server"
23 | "tokenizer.json"
24 | ];
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/nixos/profiles/ollama/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | services.ollama = {
3 | enable = true;
4 | loadModels = [
5 | "mistral"
6 | "gemma3:4b"
7 | "phi4-mini"
8 | ];
9 | # /var/lib/private should be on a persistent file system
10 | };
11 | }
12 |
--------------------------------------------------------------------------------
/nixos/profiles/onedev/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | virtualisation.oci-containers = {
3 | # Not sure if it works with podman. There is no specific recommendation for
4 | # OneDev itself, but I will follow the documentation for now.
5 | backend = "docker";
6 |
7 | # docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock -v $(pwd)/onedev:/opt/onedev -p 6610:6610 -p 6611:6611 1dev/server
8 | containers.onedev = {
9 | image = "1dev/server";
10 | ports = [
11 | "6610:6610"
12 | "6611:6611"
13 | ];
14 | volumes = [
15 | "/var/lib/onedev:/opt/onedev"
16 | "/var/run/docker.sock:/var/run/docker.sock"
17 | ];
18 | };
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/nixos/profiles/openssh/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | lib,
3 | config,
4 | ...
5 | }: {
6 | services.openssh = {
7 | enable = true;
8 |
9 | ports = lib.mkIf config.services.tailscale.enable [
10 | 2022
11 | ];
12 |
13 | openFirewall = true;
14 |
15 | # Most of these options have been stolen from
16 | # https://xeiaso.net/blog/paranoid-nixos-2021-07-18
17 | settings = {
18 | PasswordAuthentication = false;
19 | KbdInteractiveAuthentication = false;
20 | };
21 | allowSFTP = false;
22 | extraConfig = ''
23 | AllowTcpForwarding yes
24 | X11Forwarding no
25 | AllowAgentForwarding no
26 | AllowStreamLocalForwarding no
27 | AuthenticationMethods publickey
28 | '';
29 |
30 | # Disable generation of an RSA key. See https://xeiaso.net/blog/move-away-rsa-ssh
31 | hostKeys = [
32 | {
33 | path = "/etc/ssh/ssh_host_ed25519_key";
34 | type = "ed25519";
35 | }
36 | ];
37 | };
38 |
39 | users.users.root = {
40 | openssh.authorizedKeys.keys = [
41 | "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEHKzdRvr0KjzLNGVV7eNcjh0m8liuXR2JLj2UA0Qa0yep3yZuVEc/I3l57z4FF27YvFVgxhLAAzXupeI98l3QTYXfaL4SF64/IZHElSC4pH5hHNNDMF37DCVLBAeAxesSkqhVoUMsG8lDiLSHy24GQBt9mKxFk461eViyVxLnPwzs7NsDo2sKVLFkPIG+SFI9wFrvRZK30l/twgljNefSoJc5xlIr6XXme3rKp00T4DMPb2sC2a9yYG5SgihQuB1RJkPXrp1gvp0wD1vc+lmniGiJEWbSefq3Ntaue48+o+yMgnazCQXSc/ozxmoK2ZISztEW+CBk5V9uD9TU8w5V cardno:11 482 161"
42 | ];
43 | };
44 | }
45 |
--------------------------------------------------------------------------------
/nixos/profiles/pipewire/default.nix:
--------------------------------------------------------------------------------
1 | { pkgs, ... }:
2 | {
3 | environment.systemPackages = [
4 | pkgs.pavucontrol
5 | ];
6 |
7 | # Based on https://nixos.wiki/wiki/PipeWire
8 | security.rtkit.enable = true;
9 | services.pipewire = {
10 | enable = true;
11 | alsa.enable = true;
12 | alsa.support32Bit = true;
13 | pulse.enable = true;
14 | # If you want to use JACK applications, uncomment this
15 | #jack.enable = true;
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/nixos/profiles/podman/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | virtualisation = {
3 | oci-containers.backend = "podman";
4 | podman = {
5 | enable = true;
6 | };
7 | };
8 | }
9 |
--------------------------------------------------------------------------------
/nixos/profiles/podman/rootless-docker.nix:
--------------------------------------------------------------------------------
1 | # Provide a podman-based environment for using podman-compose with docker
2 | # compatibility to run a bunch of examples in Docker-based tutorials.
3 | #
4 | # Based on https://carlosvaz.com/posts/rootless-podman-and-docker-compose-on-nixos/
5 | { pkgs, ... }:
6 | {
7 | imports = [
8 | ./.
9 | ../containers/rootless.nix
10 | ];
11 |
12 | virtualisation.podman = {
13 | # Make docker command available.
14 | dockerCompat = true;
15 | };
16 |
17 | environment.systemPackages = [
18 | pkgs.podman-compose
19 | ];
20 | }
21 |
--------------------------------------------------------------------------------
/nixos/profiles/postgresql/development.nix:
--------------------------------------------------------------------------------
1 | { lib, pkgs, ... }:
2 | {
3 | services = {
4 | postgresql = {
5 | enable = true;
6 |
7 | settings = {
8 | # Default: 5432
9 | port = 5432;
10 |
11 | # Enable logical replication for certain use cases.
12 | # See https://kinsta.com/blog/postgresql-replication/ and
13 | # https://electric-sql.com/docs/usage/installation/postgres
14 | wal_level = "logical";
15 | };
16 |
17 | # Specify an explicit major version
18 | # package = pkgs.postgresql_14;
19 |
20 | # Trust local access
21 | authentication = pkgs.lib.mkOverride 12 ''
22 | local all all trust
23 | host all all localhost trust
24 | '';
25 |
26 | ensureUsers = [ { name = "postgres"; } ];
27 |
28 | enableTCPIP = false;
29 |
30 | # Set the data directory explicitly
31 | # dataDir = "/var/lib/postgresql/14";
32 | };
33 |
34 | pgadmin = {
35 | # Currently fails to build
36 | # enable = true;
37 | # Default
38 | port = 5050;
39 | initialEmail = "akira.komamura@gmail.com";
40 | initialPasswordFile = "/persist/etc/pgpasswd";
41 | };
42 |
43 | postgresqlBackup = {
44 | enable = true;
45 | # PostgreSQL dump and ZFS snapshot must not occur simultaneously.
46 | startAt = "*-*-* *:05,20,35,50:00";
47 | location = "/var/backup/postgresql";
48 | backupAll = lib.mkDefault true;
49 | };
50 | };
51 | }
52 |
--------------------------------------------------------------------------------
/nixos/profiles/rabbitmq/development.nix:
--------------------------------------------------------------------------------
1 | {
2 | services.rabbitmq = {
3 | enable = true;
4 | managementPlugin.enable = true;
5 |
6 | # These values are the default, but set explicitly to ensure the service is
7 | # private.
8 | listenAddress = "127.0.0.1";
9 | };
10 | }
11 |
--------------------------------------------------------------------------------
/nixos/profiles/reverse-proxy/default.nix:
--------------------------------------------------------------------------------
1 | { config, lib, ... }:
2 | let
3 | inherit (lib) types mkOption mkEnableOption;
4 |
5 | cfg = config.services.reverse-proxy;
6 |
7 | httpPort = 80;
8 |
9 | httpsPort = 443;
10 |
11 | subdomainType = types.submodule {
12 | options.reverse-proxy = mkOption {
13 | type = types.str;
14 | example = "localhost:8080";
15 | };
16 | };
17 | in
18 | {
19 | options.services.reverse-proxy = {
20 | enable = mkEnableOption (lib.mdDoc "Enable a reverse-proxy service for loopback services.");
21 |
22 | domain = mkOption {
23 | type = types.str;
24 | description = lib.mdDoc ''
25 | Public DNS domain on which the services should be served as subdomains.
26 | '';
27 | };
28 |
29 | useACMEHost = mkOption {
30 | type = types.str;
31 | default = cfg.domain;
32 | description = lib.mdDoc ''
33 | ACME host
34 | '';
35 | };
36 |
37 | subdomains = mkOption {
38 | type = types.attrsOf subdomainType;
39 | description = lib.mdDoc ''
40 | Subdomains served via the reverse proxy.
41 | '';
42 | };
43 | };
44 |
45 | config = {
46 | services.caddy = {
47 | enable = lib.mkIf cfg.enable true;
48 | virtualHosts = lib.optionalAttrs cfg.enable (
49 | lib.concatMapAttrs (name: attrs: {
50 | "${name}.${cfg.domain}" = {
51 | inherit (cfg) useACMEHost;
52 | extraConfig = ''
53 | reverse_proxy ${attrs.reverse-proxy}
54 | '';
55 | };
56 | "${name}:${builtins.toString httpPort}" = {
57 | extraConfig = ''
58 | redir https://${name}.${cfg.domain}
59 | '';
60 | };
61 | }) cfg.subdomains
62 | );
63 | };
64 |
65 | networking.firewall.allowedTCPPorts = lib.optionals cfg.enable [
66 | httpPort
67 | httpsPort
68 | ];
69 | };
70 | }
71 |
--------------------------------------------------------------------------------
/nixos/profiles/sudo/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | security.sudo = {
3 | enable = true;
4 | wheelNeedsPassword = false;
5 | execWheelOnly = true;
6 | };
7 | }
8 |
--------------------------------------------------------------------------------
/nixos/profiles/syncthing/default.nix:
--------------------------------------------------------------------------------
1 | { lib, config, ... }:
2 | let
3 | inherit (builtins) toString;
4 |
5 | cfg = config.services.syncthing;
6 |
7 | devices = lib.pipe (lib.importTOML ../../../machines/metadata.toml).hosts [
8 | (lib.filterAttrs (_: attrs: attrs ? syncthingId))
9 | (builtins.mapAttrs (_: attrs: { id = attrs.syncthingId; }))
10 | ];
11 |
12 | inherit (config.networking) hostName;
13 |
14 | otherDevicesByHostName = lib.remove hostName;
15 |
16 | allDevices = otherDevicesByHostName (builtins.attrNames devices);
17 |
18 | enableReverseProxy = config.services.reverse-proxy.enable;
19 |
20 | guiPort = 8384;
21 | in
22 | {
23 | services.syncthing = {
24 | enable = true;
25 | # Just the default dataDir. This needs to be on a dedicated ZFS dataset.
26 | dataDir = "/var/lib/syncthing";
27 | overrideDevices = true;
28 | overrideFolders = true;
29 | openDefaultPorts = true;
30 | guiAddress =
31 | if enableReverseProxy then "127.0.0.1:${toString guiPort}" else "0.0.0.0:${toString guiPort}";
32 | settings = {
33 | devices = lib.filterAttrs (name: _: name != hostName) devices;
34 | folders = {
35 | "org" = {
36 | path = cfg.dataDir + "/org";
37 | devices = allDevices;
38 | id = "v3msx-gwdqt";
39 | };
40 | "notes-and-pdfs" = {
41 | path = cfg.dataDir + "/notes-and-pdfs";
42 | devices = otherDevicesByHostName [
43 | "li"
44 | ];
45 | id = "4warh-yejmn";
46 | };
47 | "private" = {
48 | path = cfg.dataDir + "/private";
49 | devices = otherDevicesByHostName [
50 | "li"
51 | "yang"
52 | ];
53 | id = "gstwc-lxb3v";
54 | };
55 | };
56 | # Prevent "Host check error"
57 | # https://docs.syncthing.net/users/faq.html#why-do-i-get-host-check-error-in-the-gui-api
58 | gui.insecureSkipHostCheck = lib.mkIf enableReverseProxy true;
59 |
60 | # Wait for the PR
61 | # gui.user = "akirak";
62 | # inherit guiPasswordFile;
63 | };
64 | };
65 |
66 | services.reverse-proxy = lib.mkIf enableReverseProxy {
67 | subdomains.syncthing = {
68 | reverse-proxy = "localhost:${toString guiPort}";
69 | };
70 | };
71 |
72 | # The other ports are opened via openDefaultPorts, so only the web port needs
73 | # to be explicitly opened.
74 | networking.firewall = lib.mkIf (config.networking.firewall.enable && !enableReverseProxy) {
75 | allowedTCPPorts = [ 8384 ];
76 | };
77 |
78 | # The password is unencrypted, so it's basically useless. Wait for the PR on
79 | # guiPasswordFile option to get merged.
80 |
81 | # services.syncthing.settings.gui = {
82 | # user = "akirak";
83 | # password = "$2y$10$epya6R5qrkZzGGCUZFQ5duA9NBvPesWkNp1QBnyJE8JWp1zenEEdq";
84 | # };
85 | }
86 |
--------------------------------------------------------------------------------
/nixos/profiles/tailscale/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | pkgs,
3 | config,
4 | ...
5 | }: let
6 | cfg = config.services.tailscale;
7 | in {
8 | services.tailscale = {
9 | enable = true;
10 | package = pkgs.unstable.tailscale;
11 | };
12 |
13 | networking.firewall = {
14 | trustedInterfaces = ["tailscale0"];
15 | checkReversePath = "loose";
16 |
17 | allowedTCPPorts = [
18 | cfg.port
19 | ];
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/nixos/profiles/users/1000/on-server.nix:
--------------------------------------------------------------------------------
1 | let
2 | login = "akirakomamura";
3 | group = login;
4 | in
5 | {
6 | users = {
7 | users.${login} = {
8 | description = "Akira Komamura";
9 | createHome = true;
10 | uid = 1000;
11 | inherit group;
12 | isNormalUser = true;
13 | openssh.authorizedKeys.keys = [
14 | "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEHKzdRvr0KjzLNGVV7eNcjh0m8liuXR2JLj2UA0Qa0yep3yZuVEc/I3l57z4FF27YvFVgxhLAAzXupeI98l3QTYXfaL4SF64/IZHElSC4pH5hHNNDMF37DCVLBAeAxesSkqhVoUMsG8lDiLSHy24GQBt9mKxFk461eViyVxLnPwzs7NsDo2sKVLFkPIG+SFI9wFrvRZK30l/twgljNefSoJc5xlIr6XXme3rKp00T4DMPb2sC2a9yYG5SgihQuB1RJkPXrp1gvp0wD1vc+lmniGiJEWbSefq3Ntaue48+o+yMgnazCQXSc/ozxmoK2ZISztEW+CBk5V9uD9TU8w5V cardno:11 482 161"
15 | ];
16 | };
17 |
18 | groups.${group} = {
19 | gid = 1000;
20 | };
21 | };
22 | }
23 |
--------------------------------------------------------------------------------
/nixos/profiles/users/primary-group.nix:
--------------------------------------------------------------------------------
1 | {
2 | homeUser,
3 | lib,
4 | config,
5 | ...
6 | }: let
7 | groupName = homeUser;
8 | in {
9 | users = {
10 | users.${homeUser}.group = groupName;
11 |
12 | groups.${groupName}.gid = lib.mkDefault config.users.users.${homeUser}.uid;
13 | };
14 | }
15 |
--------------------------------------------------------------------------------
/nixos/profiles/virtualbox-host/default.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: let
2 | virtualboxDesktopItemsGenerator = pkgs.writeShellApplication {
3 | name = "virtualbox-generate-desktop-items";
4 |
5 | text = builtins.readFile ./generate.bash;
6 | };
7 | in {
8 | virtualisation.virtualbox.host = {
9 | enable = true;
10 | enableExtensionPack = true;
11 | };
12 |
13 | environment.systemPackages = [
14 | virtualboxDesktopItemsGenerator
15 | ];
16 | }
17 |
--------------------------------------------------------------------------------
/nixos/profiles/virtualbox-host/generate.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | vm_dir="${VIRTUALBOX_VM_DIR:-$HOME/VirtualBox VMs}"
4 | data_home="${XDG_DATA_HOME:-$HOME/.local/share}"
5 | data_dir="${data_home}/virtualbox-items"
6 | applications_dir="${data_home}/applications"
7 |
8 | boxes=()
9 |
10 | function prepareDirectory() {
11 | mkdir -p "${data_dir}" "${applications_dir}"
12 | find "${data_dir}" -name '*.desktop' -delete
13 | }
14 |
15 | function generateDesktopItem() {
16 | local name="$1"
17 | cat <<-CONTENT
18 | [Desktop Entry]
19 | Type=Application
20 | Name=$name on VirtualBox
21 | TryExec=VirtualBoxVM
22 | Exec=VirtualBoxVM --startvm "$name"
23 | Icon=virtualbox-vbox
24 | CONTENT
25 | }
26 |
27 | function createItems() {
28 | for box in "${boxes[@]}"; do
29 | outfile="${data_dir}/$box.desktop"
30 | generateDesktopItem "$box" > "$outfile"
31 | ln -sf -t "${applications_dir}" "$outfile"
32 | echo "$box"
33 | done
34 | }
35 |
36 | function cleanupObsoleteItems() {
37 | while read -r f; do
38 | dest=$(readlink "$f")
39 | if [[ $dest = ${data_dir}/* ]] && ! [[ -e "$dest" ]]; then
40 | rm -v "$f"
41 | fi
42 | done < <(find "${applications_dir}" -maxdepth 1 -name '*.desktop')
43 | }
44 |
45 | if ! [[ -d "${vm_dir}" ]]; then
46 | echo >&2 "Directory ${vm_dir} does not exist"
47 | echo >&2 "Consider setting VIRTUALBOX_VM_DIR to the directory containing VMs"
48 | exit 0
49 | fi
50 |
51 | while read -r filename; do
52 | boxes+=("$filename")
53 | done < <(find "${vm_dir}" -maxdepth 3 -name '*.vbox' -exec basename -s .vbox {} \;)
54 |
55 | if [[ ${#boxes[@]} -eq 0 ]]; then
56 | echo >&2 "No vbox file exists in ${vm_dir}"
57 | exit 0
58 | fi
59 |
60 | prepareDirectory
61 | createItems
62 | cleanupObsoleteItems
63 |
64 | xdg-desktop-menu forceupdate
65 |
--------------------------------------------------------------------------------
/nixos/profiles/wayland/cage/emacs.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | imports = [
3 | ../sessions.nix
4 | ];
5 |
6 | environment.systemPackages = [
7 | (pkgs.callPackage ./makeWrapper.nix {
8 | sessionName = "emacs-session";
9 | command = "emacs";
10 | })
11 | ];
12 |
13 | wayland.sessions = [
14 | {
15 | name = "emacs-session";
16 | }
17 | ];
18 | }
19 |
--------------------------------------------------------------------------------
/nixos/profiles/wayland/cage/firefox.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | imports = [
3 | ../sessions.nix
4 | ];
5 |
6 | environment.systemPackages = [
7 | (pkgs.callPackage ./makeWrapper.nix {
8 | sessionName = "firefox-session";
9 | command = "firefox";
10 | })
11 | ];
12 |
13 | wayland.sessions = [
14 | {
15 | name = "firefox-session";
16 | }
17 | ];
18 | }
19 |
--------------------------------------------------------------------------------
/nixos/profiles/wayland/cage/foot.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | imports = [
3 | ../sessions.nix
4 | ];
5 |
6 | environment.systemPackages = [
7 | (pkgs.callPackage ./makeWrapper.nix {
8 | sessionName = "foot-session";
9 | command = "foot";
10 | })
11 | ];
12 |
13 | wayland.sessions = [
14 | {
15 | name = "foot-session";
16 | }
17 | ];
18 | }
19 |
--------------------------------------------------------------------------------
/nixos/profiles/wayland/cage/makeWrapper.nix:
--------------------------------------------------------------------------------
1 | {
2 | writeShellScriptBin,
3 | cage,
4 | sessionName,
5 | command,
6 | }:
7 | writeShellScriptBin sessionName ''
8 | export XKB_DEFAULT_LAYOUT=us
9 | export XKB_DEFAULT_OPTIONS=ctrl:nocaps
10 | export XDG_SESSION_TYPE=wayland
11 | export XDG_SESSION_DESKTOP=sway
12 | export XDG_CURRENT_DESKTOP=sway
13 | export MOZ_ENABLE_WAYLAND=1
14 | # Set SWAYSOCK to use swaymsg and other sway-compatible utilities
15 | export SWAYSOCK=''${XDG_RUNTIME_DIR}/wayland-1
16 | exec ${cage}/bin/cage ${command}
17 | ''
18 |
--------------------------------------------------------------------------------
/nixos/profiles/wayland/sessions.nix:
--------------------------------------------------------------------------------
1 | {
2 | config,
3 | lib,
4 | ...
5 | }: let
6 | inherit (lib) mkOption types;
7 |
8 | session = types.submodule {
9 | options.name = mkOption {
10 | type = types.str;
11 | example = "firefox-session";
12 | };
13 | options.desktopName = mkOption {
14 | type = types.nullOr types.str;
15 | example = "Firefox Session";
16 | default = null;
17 | };
18 | options.exec = mkOption {
19 | type = types.nullOr types.str;
20 | example = "firefox-session";
21 | default = null;
22 | };
23 | };
24 | in {
25 | options = {
26 | wayland.sessions = mkOption {
27 | type = types.listOf session;
28 | default = [];
29 | };
30 | };
31 |
32 | config = {
33 | environment.etc = builtins.listToAttrs (builtins.map
34 | ({
35 | name,
36 | desktopName,
37 | exec,
38 | }: {
39 | name = "wayland-sessions/${name}.desktop";
40 | value = {
41 | text = ''
42 | [Desktop Entry]
43 | Name=${
44 | if desktopName != null
45 | then desktopName
46 | else name
47 | }
48 | Exec=${
49 | if exec != null
50 | then exec
51 | else name
52 | }
53 | Type=Application
54 | '';
55 | };
56 | })
57 | config.wayland.sessions);
58 | };
59 | }
60 |
--------------------------------------------------------------------------------
/nixos/profiles/wayland/sway-utils.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | environment.systemPackages = with pkgs; [
3 | (pkgs.writeShellApplication {
4 | name = "lock-screen";
5 | runtimeInputs = [pkgs.swaylock-effects];
6 | # TODO: Use a color scheme
7 | text = ''
8 | swaylock -f --clock --fade-in 0.5
9 | '';
10 | })
11 |
12 | # screenshot and screen recording
13 | wayshot
14 | wf-recorder
15 | slurp # Used with wayshot
16 |
17 | fuzzel
18 | ];
19 | }
20 |
--------------------------------------------------------------------------------
/nixos/profiles/wayland/wlroots.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | imports = [
3 | ../window-manager/generic.nix
4 | ./sway-utils.nix
5 | ];
6 |
7 | environment.systemPackages = [
8 | pkgs.xdg-utils
9 | pkgs.wlr-randr
10 | ];
11 |
12 | xdg.portal = {
13 | enable = true;
14 | wlr = {
15 | enable = true;
16 | };
17 | xdgOpenUsePortal = true;
18 | config = {
19 | common.default = "*";
20 | };
21 | };
22 |
23 | security.pam.services.swaylock = {};
24 | }
25 |
--------------------------------------------------------------------------------
/nixos/profiles/wayland/wm/hyprland.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | imports = [
3 | ../sessions.nix
4 | ];
5 |
6 | environment.systemPackages = [
7 | pkgs.wev
8 | ];
9 |
10 | wayland.sessions = [
11 | {
12 | name = "Hyprland";
13 | }
14 | ];
15 | }
16 |
--------------------------------------------------------------------------------
/nixos/profiles/wayland/wm/labwc.nix:
--------------------------------------------------------------------------------
1 | {...}: {
2 | imports = [
3 | ../sessions.nix
4 | ];
5 |
6 | wayland.sessions = [
7 | {
8 | name = "labwc";
9 | }
10 | ];
11 | }
12 |
--------------------------------------------------------------------------------
/nixos/profiles/window-manager/generic.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | environment.systemPackages = [
3 | pkgs.networkmanagerapplet
4 | pkgs.elementary-xfce-icon-theme
5 | ];
6 |
7 | services.xserver = {
8 | xkb.options = "ctrl:nocaps";
9 | enableCtrlAltBackspace = true;
10 | # startDbusSession = true;
11 | };
12 | services.libinput = {
13 | enable = true;
14 | mouse = {
15 | disableWhileTyping = true;
16 | };
17 | };
18 |
19 | services.dbus = {
20 | enable = true;
21 | # socketActivated = true;
22 | packages = [pkgs.dconf];
23 | };
24 |
25 | # services.gnome.gnome-keyring.enable = true;
26 |
27 | services.blueman.enable = true;
28 |
29 | xdg.portal.extraPortals = [
30 | pkgs.xdg-desktop-portal-gtk
31 | ];
32 | }
33 |
--------------------------------------------------------------------------------
/nixos/profiles/yubikey/default.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | services.yubikey-agent.enable = true;
3 |
4 | services.udev.packages = [
5 | pkgs.yubikey-personalization
6 | ];
7 |
8 | services.pcscd = {
9 | enable = true;
10 | };
11 |
12 | environment.systemPackages = [
13 | pkgs.yubikey-manager
14 | pkgs.yubioath-flutter
15 | pkgs.age-plugin-yubikey
16 | ];
17 | }
18 |
--------------------------------------------------------------------------------
/nixos/suites/base/default.nix:
--------------------------------------------------------------------------------
1 | {...}: {
2 | imports = [
3 | ../../profiles/openssh
4 | ];
5 |
6 | networking.firewall.enable = true;
7 |
8 | nix = {
9 | settings = {
10 | auto-optimise-store = true;
11 | };
12 | gc.automatic = true;
13 | };
14 | }
15 |
--------------------------------------------------------------------------------
/nixos/suites/desktop/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | modulesPath,
3 | pkgs,
4 | lib,
5 | config,
6 | ...
7 | }:
8 | {
9 | imports = [
10 | (modulesPath + "/profiles/base.nix")
11 | ../../profiles/yubikey
12 | ../../profiles/users/primary-group.nix
13 | ];
14 |
15 | environment.systemPackages = [
16 | pkgs.lsof
17 | pkgs.psmisc
18 | pkgs.handlr
19 | pkgs.libnotify
20 | ] ++ lib.optional config.services.postgresql.enable pkgs.pgcli;
21 |
22 | environment.sessionVariables = {
23 | "TMPDIR" = "/tmp";
24 | };
25 |
26 | networking.usePredictableInterfaceNames = true;
27 |
28 | time.timeZone = "Asia/Tokyo";
29 |
30 | services.earlyoom.enable = true;
31 | services.psd.enable = true;
32 |
33 | # Allow mounting FUSE filesystems as a user.
34 | # https://discourse.nixos.org/t/fusermount-systemd-service-in-home-manager/5157
35 | environment.etc."fuse.conf".text = ''
36 | user_allow_other
37 | '';
38 |
39 | programs.nix-ld.enable = true;
40 | }
41 |
--------------------------------------------------------------------------------
/nixos/suites/graphical/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | lib,
3 | pkgs,
4 | ...
5 | }:
6 | {
7 | imports = [
8 | ../../profiles/pipewire
9 | ];
10 |
11 | environment.systemPackages = with pkgs; [
12 | # flameshot
13 | handlr
14 | ];
15 |
16 | fonts = {
17 | packages = with pkgs; [
18 | customFontPackages.jetbrains-mono-nerdfont
19 | merriweather
20 | lato
21 | ];
22 |
23 | fontconfig.defaultFonts = {
24 | monospace = [ "JetBrains Mono NF" ];
25 |
26 | sansSerif = [ "Lato" ];
27 |
28 | serif = [ "Merriweather" ];
29 | };
30 | };
31 |
32 | systemd.services.setxkbmap = {
33 | enable = true;
34 | after = [ "post-resume.target" ];
35 | description = "Run setxkbmap";
36 |
37 | script = "/run/current-system/sw/bin/setxkbmap -option ctrl:nocaps";
38 | environment = {
39 | DISPLAY = ":0";
40 | };
41 | };
42 |
43 | services.xserver.xkb.layout = lib.mkDefault "us";
44 | }
45 |
--------------------------------------------------------------------------------
/nixos/suites/hcloud-remote/default.nix:
--------------------------------------------------------------------------------
1 | # This profile can be used for fresh NixOS installation from kexec.
2 | # See https://github.com/numtide/nixos-remote
3 | {modulesPath, ...}: {
4 | imports = [
5 | (modulesPath + "/installer/scan/not-detected.nix")
6 | (modulesPath + "/profiles/qemu-guest.nix")
7 | (modulesPath + "/profiles/hardened.nix")
8 | (modulesPath + "/profiles/headless.nix")
9 | ];
10 |
11 | boot.initrd.availableKernelModules = [
12 | "ata_piix"
13 | "uhci_hcd"
14 | "xen_blkfront"
15 | "vmw_pvscsi"
16 | ];
17 | boot.initrd.kernelModules = ["nvme"];
18 |
19 | zramSwap.enable = true;
20 | boot.tmp.cleanOnBoot = true;
21 |
22 | boot.loader.grub = {
23 | device = "/dev/sda";
24 | efiSupport = true;
25 | efiInstallAsRemovable = true;
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/nixos/suites/hcloud/default.nix:
--------------------------------------------------------------------------------
1 | # This profile can be used for NixOS installation with nixos-infect.
2 | {modulesPath, ...}: {
3 | imports = [
4 | (modulesPath + "/profiles/qemu-guest.nix")
5 | (modulesPath + "/profiles/hardened.nix")
6 | (modulesPath + "/profiles/headless.nix")
7 | ];
8 |
9 | boot.initrd.availableKernelModules = ["ata_piix" "uhci_hcd" "xen_blkfront" "vmw_pvscsi"];
10 | boot.initrd.kernelModules = ["nvme"];
11 |
12 | zramSwap.enable = true;
13 | boot.tmp.cleanOnBoot = true;
14 |
15 | fileSystems."/" = {
16 | device = "/dev/sda1";
17 | fsType = "ext4";
18 | };
19 |
20 | boot.loader.grub.enable = true;
21 | boot.loader.grub.device = "/dev/sda";
22 | }
23 |
--------------------------------------------------------------------------------
/nixos/suites/installer/default.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | imports = [
3 | ../base
4 | ../../profiles/nix
5 | ];
6 |
7 | environment.systemPackages = [
8 | pkgs.emacs
9 | pkgs.gnupg
10 |
11 | pkgs.git
12 | # Provided from disko flake via overlayModule
13 | pkgs.disko
14 | pkgs.git-annex
15 |
16 | # Import useful packages from the package list in
17 | # nixos/modules/profiles/base.nix of nixpkgs.
18 | pkgs.gptfdisk
19 | pkgs.efibootmgr
20 | pkgs.efivar
21 | pkgs.parted
22 | pkgs.gptfdisk
23 | pkgs.ddrescue
24 | pkgs.ccrypt
25 | pkgs.cryptsetup
26 | pkgs.mkpasswd
27 |
28 | pkgs.fuse
29 | pkgs.fuse3
30 | pkgs.rsync
31 | pkgs.socat
32 |
33 | pkgs.ntfsprogs
34 | pkgs.dosfstools
35 | pkgs.mtools
36 | pkgs.xfsprogs.bin
37 | pkgs.jfsutils
38 | pkgs.f2fs-tools
39 | pkgs.btrfs-progs
40 | pkgs.zfs
41 |
42 | pkgs.lshw
43 |
44 | pkgs.unzip
45 | pkgs.zip
46 | ];
47 | }
48 |
--------------------------------------------------------------------------------
/nixos/suites/iso/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | lib,
3 | modulesPath,
4 | ...
5 | }: {
6 | imports = [
7 | ../installer
8 | (modulesPath + "/installer/cd-dvd/channel.nix")
9 | (modulesPath + "/installer/cd-dvd/installation-cd-minimal.nix")
10 | ];
11 |
12 | nix.extraOptions = ''
13 | experimental-features = nix-command flakes
14 | '';
15 |
16 | nix.settings = {
17 | substituters = [
18 | "https://cache.nixos.org/"
19 | "https://nix-community.cachix.org"
20 | "https://akirak.cachix.org"
21 | ];
22 | trusted-public-keys = [
23 | "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
24 | "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
25 | "akirak.cachix.org-1:WJrEMdV1dYyALkOdp/kAECVZ6nAODY5URN05ITFHC+M="
26 | ];
27 | };
28 |
29 | # Faster compression algorithm. See https://nixos.wiki/wiki/Creating_a_NixOS_live_CD
30 | isoImage.squashfsCompression = "gzip -Xcompression-level 1";
31 |
32 | system.stateVersion = lib.mkDefault lib.trivial.release;
33 | }
34 |
--------------------------------------------------------------------------------
/nixos/suites/microvm-gui/default.nix:
--------------------------------------------------------------------------------
1 | /*
2 | MicroVM with GUI for rapid prototyping of a desktop environment
3 |
4 | Based on https://github.com/astro/microvm.nix/blob/main/flake.nix
5 | */
6 | {config, ...}: let
7 | xrdpPort = 3389;
8 | in {
9 | imports = [
10 | ../../profiles/microvm
11 | ../../profiles/microvm/ssh.nix
12 | ];
13 |
14 | # Set a message printed to the console before login.
15 | services.getty.helpLine = ''
16 | Connect to the RDP server using xfreerdp/wlfreerdp:
17 |
18 | xfreerdp /u:root /v:localhost:${builtins.toString xrdpPort}
19 |
20 | From this console, you can log in as "root" with an empty password.
21 | '';
22 |
23 | # login: "root", password: empty
24 | users.users.root.password = "";
25 |
26 | microvm = {
27 | mem = 4096;
28 | vcpu = 2;
29 | };
30 |
31 | nixpkgs.config.permittedInsecurePackages = [
32 | "xrdp-0.9.9"
33 | ];
34 |
35 | services.xserver = {
36 | enable = true;
37 | };
38 |
39 | services.xrdp = {
40 | enable = true;
41 | openFirewall = true;
42 | port = xrdpPort;
43 | };
44 |
45 | microvm.forwardPorts = [
46 | {
47 | host.port = xrdpPort;
48 | guest.port = xrdpPort;
49 | }
50 | ];
51 | }
52 |
--------------------------------------------------------------------------------
/nixos/suites/microvm/default.nix:
--------------------------------------------------------------------------------
1 | /*
2 | Based on https://github.com/astro/microvm.nix/blob/main/flake.nix
3 | */
4 | {...}: {
5 | imports = [
6 | ../../profiles/microvm
7 | ];
8 |
9 | services.getty.helpLine = ''
10 | From this console, you can log in as "root" with an empty password.
11 | '';
12 |
13 | users.users.root.password = "";
14 |
15 | microvm = {
16 | mem = 2048;
17 | vcpu = 2;
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/nixos/suites/remote-installer/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | lib,
3 | config,
4 | ...
5 | }: {
6 | imports = [
7 | ../installer
8 | ../../profiles/openssh
9 | ];
10 |
11 | nix.extraOptions = ''
12 | experimental-features = nix-command flakes
13 | '';
14 |
15 | nix.settings = {
16 | substituters = [
17 | "https://cache.nixos.org/"
18 | "https://nix-community.cachix.org"
19 | "https://akirak.cachix.org"
20 | ];
21 | trusted-public-keys = [
22 | "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
23 | "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
24 | "akirak.cachix.org-1:WJrEMdV1dYyALkOdp/kAECVZ6nAODY5URN05ITFHC+M="
25 | ];
26 | };
27 |
28 | networking = {
29 | useDHCP = false;
30 | wireless.enable = false;
31 | networkmanager.enable = true;
32 | };
33 |
34 | system.stateVersion = lib.mkDefault lib.trivial.release;
35 |
36 | users.users.nixos = {
37 | uid = 1000;
38 | isNormalUser = true;
39 |
40 | extraGroups = [
41 | "wheel"
42 | "networkmanager"
43 | ];
44 |
45 | openssh.authorizedKeys.keys = config.users.users.root.openssh.authorizedKeys.keys;
46 | };
47 | }
48 |
--------------------------------------------------------------------------------
/nixos/suites/server/default.nix:
--------------------------------------------------------------------------------
1 | {pkgs, ...}: {
2 | imports = [
3 | ../base
4 | ];
5 |
6 | environment.systemPackages = with pkgs; [
7 | duf
8 | du-dust
9 | ];
10 | }
11 |
--------------------------------------------------------------------------------
/secrets/aider-env.age:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akirak/homelab/982762f4dc21623c268a852ceffeafff210fe3c5/secrets/aider-env.age
--------------------------------------------------------------------------------
/secrets/rekeyed/yang/cde7a1a585cb8ea1ccfb2a2e1535f2ef-nicesunny.day.credentials.txt.age:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akirak/homelab/982762f4dc21623c268a852ceffeafff210fe3c5/secrets/rekeyed/yang/cde7a1a585cb8ea1ccfb2a2e1535f2ef-nicesunny.day.credentials.txt.age
--------------------------------------------------------------------------------
/secrets/rekeyed/zheng/e10023806a5bd15c8d5351e849343edd-dhcp-hosts.age:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akirak/homelab/982762f4dc21623c268a852ceffeafff210fe3c5/secrets/rekeyed/zheng/e10023806a5bd15c8d5351e849343edd-dhcp-hosts.age
--------------------------------------------------------------------------------
/secrets/yubikey.pub:
--------------------------------------------------------------------------------
1 | # Serial: 11482161, Slot: 2
2 | # Name: age identity 33298455
3 | # Created: Thu, 01 Aug 2024 10:35:29 +0000
4 | # PIN policy: Once (A PIN is required once per session, if set)
5 | # Touch policy: Cached (A physical touch is required for decryption, and is cached for 15 seconds)
6 | # Recipient: age1yubikey1qdlq02upxrg2q379tchjr2f9avrkj2dpmyssgd0jh0e3c662d3ejs4yl452
7 | AGE-PLUGIN-YUBIKEY-1XY627QYRXV5CG4GE25EVR
8 |
--------------------------------------------------------------------------------
/templates/flake-module.nix:
--------------------------------------------------------------------------------
1 | {
2 | flake = {
3 | # Templates can be defined only once
4 | templates = {
5 | home-manager = {
6 | path = ./home-manager;
7 | description = "An example configuration repository for home-manager";
8 | };
9 | nixos-wsl = {
10 | path = ./nixos-wsl;
11 | description = "An example configuration flake for NixOS-WSL";
12 | };
13 | };
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/templates/home-manager/.gitignore:
--------------------------------------------------------------------------------
1 | result*
2 | *~
3 |
--------------------------------------------------------------------------------
/templates/home-manager/flake.nix:
--------------------------------------------------------------------------------
1 | {
2 | inputs = {
3 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.05";
4 | unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
5 | home-manager = {
6 | url = "github:nix-community/home-manager";
7 | inputs.nixpkgs.follows = "nixpkgs";
8 | };
9 |
10 | flake-parts.url = "github:hercules-ci/flake-parts";
11 |
12 | my-overlay.url = "github:akirak/nixpkgs-overlay";
13 | emacs-config.url = "github:akirak/emacs-config/develop";
14 | homelab.url = "github:akirak/homelab";
15 | };
16 |
17 | nixConfig = {
18 | registry = "https://raw.githubusercontent.com/akirak/flake-pins/master/registry.json";
19 | extra-substituters = [
20 | "https://akirak.cachix.org"
21 | ];
22 | extra-trusted-public-keys = [
23 | "akirak.cachix.org-1:WJrEMdV1dYyALkOdp/kAECVZ6nAODY5URN05ITFHC+M="
24 | ];
25 | };
26 |
27 | outputs = {
28 | self,
29 | nixpkgs,
30 | flake-parts,
31 | home-manager,
32 | ...
33 | } @ inputs: let
34 | inherit (nixpkgs) lib;
35 |
36 | overlays = [
37 | (_final: prev: {
38 | unstable = inputs.unstable.legacyPackages.${prev.system};
39 | zsh-plugins = inputs.my-overlay.zsh-plugins;
40 | })
41 | inputs.my-overlay.overlays.default
42 | ];
43 |
44 | allowUnfreePredicate = pkg:
45 | builtins.elem (lib.getName pkg) [
46 | # Explicitly select unfree packages.
47 | "symbola"
48 | ];
49 |
50 | pkgsForSystem = system:
51 | import nixpkgs {
52 | inherit system;
53 | inherit overlays;
54 | config = {
55 | inherit allowUnfreePredicate;
56 | };
57 | };
58 |
59 | systems = [
60 | "x86_64-linux"
61 | ];
62 | in
63 | flake-parts.lib.mkFlake {inherit inputs;} {
64 | inherit systems;
65 |
66 | flake = {
67 | homeConfigurations = {
68 | penguin = home-manager.lib.homeManagerConfiguration {
69 | pkgs = pkgsForSystem "x86_64-linux";
70 | extraSpecialArgs = {
71 | homeUser = "akirakomamura";
72 | inherit (inputs) emacs-config;
73 | };
74 | modules = [
75 | {
76 | home.stateVersion = "23.05";
77 | }
78 | ./home.nix
79 | (inputs.homelab.outPath + "/homes/core.nix")
80 | inputs.emacs-config.homeModules.twist
81 | ];
82 | };
83 | };
84 |
85 | checks = lib.genAttrs systems (system:
86 | lib.pipe inputs.self.homeConfigurations [
87 | (lib.filterAttrs (_: hc: hc.pkgs.system == system))
88 | (builtins.mapAttrs (_: hc: hc.activationPackage))
89 | ]);
90 | };
91 | };
92 | }
93 |
--------------------------------------------------------------------------------
/templates/home-manager/home.nix:
--------------------------------------------------------------------------------
1 | {homeUser, ...}: {
2 | home.username = homeUser;
3 | home.homeDirectory = "/home/${homeUser}";
4 |
5 | programs.emacs-twist = {
6 | enable = true;
7 | settings = {
8 | extraFeatures = [
9 | ];
10 | };
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/templates/nixos-wsl/.gitignore:
--------------------------------------------------------------------------------
1 | result*
2 | *~
3 |
--------------------------------------------------------------------------------
/templates/nixos-wsl/README.md:
--------------------------------------------------------------------------------
1 | # Flake Template for NixOS-WSL
2 |
3 | This is a flake template for quickly setting up my custom NixOS environment for
4 | development on Windows Subsystem for Linux.
5 |
6 | ## How to use
7 |
8 | First follow [the
9 | instruction](https://github.com/nix-community/NixOS-WSL?tab=readme-ov-file#quick-start)
10 | to create a NixOS container.
11 |
12 | ``` shell
13 | nix-shell -p git
14 | alias nix='nix --extra-experimental-features nix-command --extra-experimental-features flakes'
15 | nix flake new -t github:akirak/homelab#nixos-wsl ~/config-local
16 | cd ~/config-local
17 | git init
18 | git add flake.nix
19 | ```
20 |
21 | Tweak `flake.nix` as needed and run:
22 |
23 | ``` shell
24 | # Make `just` available
25 | nix develop
26 | # Run nixos-rebuild build
27 | just build
28 | # Run nixos-rebuild switch
29 | just switch
30 | ```
31 |
--------------------------------------------------------------------------------
/templates/nixos-wsl/flake.nix:
--------------------------------------------------------------------------------
1 | {
2 | inputs = {
3 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
4 | home-manager = {
5 | url = "github:nix-community/home-manager/release-23.11";
6 | inputs.nixpkgs.follows = "nixpkgs";
7 | };
8 | nixos-wsl = {
9 | url = "github:nix-community/NixOS-WSL";
10 | inputs.nixpkgs.follows = "nixpkgs";
11 | };
12 |
13 | flake-parts.url = "github:hercules-ci/flake-parts";
14 |
15 | emacs-config = {
16 | url = "github:akirak/emacs-config/develop";
17 | inputs.flake-pins.follows = "flake-pins";
18 | };
19 | flake-pins.url = "github:akirak/flake-pins";
20 | homelab.url = "github:akirak/homelab";
21 | };
22 |
23 | outputs = {
24 | nixpkgs,
25 | flake-parts,
26 | ...
27 | } @ inputs: let
28 | inherit (nixpkgs) lib;
29 | in
30 | flake-parts.lib.mkFlake {inherit inputs;} {
31 | systems = [
32 | "x86_64-linux"
33 | ];
34 |
35 | perSystem = {pkgs, ...}: {
36 | devShells.default = pkgs.mkShell {
37 | buildInputs = [
38 | pkgs.just
39 | ];
40 | };
41 | };
42 |
43 | flake = {
44 | nixosConfigurations = {
45 | wsl-private = inputs.homelab.lib.mkSystem (throw "Set the host name") {
46 | system = "x86_64-linux";
47 | self' = inputs.self;
48 | channel = nixpkgs;
49 | specialArgs = {
50 | homeUser = throw "Set the user name";
51 | inherit (inputs) emacs-config;
52 | };
53 | extraModules = [
54 | # Mandatory settings for NixOS-WSL
55 | (inputs.nixos-wsl.outPath + "/modules")
56 | ({homeUser, ...}: {
57 | wsl.enable = true;
58 | wsl.defaultUser = homeUser;
59 | system.stateVersion = "23.11";
60 | time.timeZone = throw "Set your time zone";
61 | })
62 |
63 | inputs.home-manager.nixosModules.home-manager
64 | inputs.homelab.nixosModules.hmProfile
65 |
66 | # Add profiles as needed
67 | (inputs.homelab.outPath + "/profiles/nix")
68 | (inputs.homelab.outPath + "/profiles/locale")
69 | # (inputs.homelab.outPath + "/profiles/docker/rootless.nix")
70 |
71 | # My custom settings
72 | ({homeUser, ...}: {
73 | home-manager.users.${homeUser} = {
74 | imports = [
75 | (inputs.homelab.outPath + "/homes/basic.nix")
76 | (inputs.homelab.outPath + "/homes/wsl.nix")
77 | ];
78 |
79 | home.username = homeUser;
80 | home.homeDirectory = "/home/${homeUser}";
81 | home.stateVersion = "23.11";
82 |
83 | programs.git.extraIdentities = [
84 | {
85 | email = throw "E-mail address";
86 | fullName = throw "Full Name";
87 | conditions = [
88 | (throw "Please set conditions")
89 | "hasconfig:remote.*.url:git@YOURORG.com:XXX/**"
90 | "hasconfig:remote.*.url:https://YOURORG.com/XXX/**"
91 | "gitdir:~/work2/XXX/"
92 | ];
93 | }
94 | ];
95 |
96 | programs.emacs-twist = {
97 | enable = true;
98 | serviceIntegration.enable = true;
99 | settings = {
100 | extraFeatures = [
101 | ];
102 | };
103 | };
104 | };
105 | })
106 | ];
107 | };
108 | };
109 | };
110 | };
111 | }
112 |
--------------------------------------------------------------------------------
/templates/nixos-wsl/justfile:
--------------------------------------------------------------------------------
1 | host := "wsl-private"
2 |
3 | overrides := "--override-input emacs-config github:akirak/emacs-config/develop"
4 |
5 | upstream := "github:akirak/homelab"
6 |
7 | build:
8 | nixos-rebuild build --flake .\#{{host}}
9 |
10 | test:
11 | nixos-rebuild test --flake .\#{{host}} --use-remote-sudo
12 |
13 | switch:
14 | nixos-rebuild switch --flake .\#{{host}} --use-remote-sudo
15 |
16 | update:
17 | nix flake update --inputs-from {{upstream}} {{overrides}}
18 |
--------------------------------------------------------------------------------