1 Commits
Author SHA1 Message Date
Renovate Bot 20606d09c7 chore(deps): lock file maintenance 2026-07-18 19:01:25 +00:00
542 changed files with 6469 additions and 11067 deletions
-27
View File
@@ -1,27 +0,0 @@
# Reference: https://github.com/ryoppippi/dotfiles/blob/main/.github/workflows/nix-build.yaml
name: Check NixOS configurations
description: Build every NixOS configuration and the Registry tests
runs:
using: composite
steps:
- name: Build every NixOS configuration
shell: bash
run: |
set -euo pipefail
mapfile -t hosts < <(
nix eval --raw .#nixosConfigurations \
--apply 'configs: builtins.concatStringsSep "\n" (builtins.attrNames configs)'
)
installables=(.#checks.x86_64-linux.registry)
for host in "${hosts[@]}"; do
installables+=(".#nixosConfigurations.${host}.config.system.build.toplevel")
done
nix build \
--keep-going \
--no-link \
--print-build-logs \
--show-trace \
"${installables[@]}"
-22
View File
@@ -1,22 +0,0 @@
# Reference: https://github.com/ryoppippi/dotfiles/blob/main/.github/actions/setup-nix/action.yaml
name: Setup Nix
description: Install Nix and cache the Nix store
runs:
using: composite
steps:
- name: Allow unprivileged user namespaces
if: runner.os == 'Linux'
shell: bash
run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 2>/dev/null || true
- name: Install Nix
uses: nixbuild/nix-quick-install-action@9f63be77f412a248c9d9a65a4c82cf066cdf8f0c # v35
with:
nix_conf: |
accept-flake-config = true
max-jobs = auto
- name: Cache Nix store
uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7.0.2
with:
primary-key: nix-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('flake.lock') }}
restore-prefixes-first-match: nix-${{ runner.os }}-${{ runner.arch }}-
gc-max-store-size-linux: 4G
+150
View File
@@ -0,0 +1,150 @@
name: NixOS CI
on:
pull_request:
branches:
- main
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
concurrency:
group: nixos-ci-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
validate:
name: Validate flake
runs-on: ubuntu-latest
timeout-minutes: 30
outputs:
hosts: ${{ steps.hosts.outputs.hosts }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Install Nix
uses: cachix/install-nix-action@630ae543ea3a38a9a4166f03376c02c50f408342 # v31.11.0
with:
extra_nix_config: |
experimental-features = nix-command flakes
accept-flake-config = true
access-tokens = github.com=${{ github.token }}
- name: Check flake and evaluate all outputs
run: nix flake check --all-systems --no-build --show-trace
- name: Discover NixOS hosts
id: hosts
run: |
hosts=$(nix eval --json '.#nixosConfigurations' --apply 'configs: builtins.attrNames configs')
echo "hosts=$hosts" >> "$GITHUB_OUTPUT"
echo "Discovered hosts: $hosts"
build:
name: Build ${{ matrix.host }}
needs: validate
if: ${{ needs.validate.outputs.hosts != '[]' }}
runs-on: ubuntu-latest
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
host: ${{ fromJSON(needs.validate.outputs.hosts) }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Install Nix
uses: cachix/install-nix-action@630ae543ea3a38a9a4166f03376c02c50f408342 # v31.11.0
with:
extra_nix_config: |
experimental-features = nix-command flakes
accept-flake-config = true
access-tokens = github.com=${{ github.token }}
- name: Build NixOS system
run: |
nix build ".#nixosConfigurations.${{ matrix.host }}.config.system.build.toplevel" \
--no-link \
--print-build-logs \
--show-trace
report-main-status:
name: Report main status
needs:
- validate
- build
if: ${{ always() && !cancelled() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
issues: write
env:
CI_FAILED: ${{ needs.validate.result == 'failure' || needs.build.result == 'failure' }}
JOB_RESULTS: ${{ toJSON(needs) }}
steps:
- name: Create or resolve failure issue
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const title = "NixOS CI is failing on main";
const marker = "<!-- nixos-ci-main-failure -->";
const failed = process.env.CI_FAILED === "true";
const jobs = JSON.parse(process.env.JOB_RESULTS);
const failedJobs = Object.entries(jobs)
.filter(([, job]) => job.result === "failure")
.map(([name]) => `\`${name}\``)
.join(", ");
const runUrl = `${context.serverUrl}/${owner}/${repo}/actions/runs/${context.runId}`;
const commitUrl = `${context.serverUrl}/${owner}/${repo}/commit/${context.sha}`;
const issues = await github.paginate(github.rest.issues.listForRepo, {
owner,
repo,
state: "open",
per_page: 100,
});
const existing = issues.find(
(issue) => !issue.pull_request && issue.title === title && issue.body?.includes(marker),
);
if (failed) {
const body = [
marker,
"The NixOS CI workflow failed after a push to `main`.",
"",
`- Failed jobs: ${failedJobs || "unknown"}`,
`- Commit: [\`${context.sha.slice(0, 7)}\`](${commitUrl})`,
`- Workflow run: [${context.runId}](${runUrl})`,
"",
"This issue is updated on subsequent failures and closed automatically after CI recovers.",
].join("\n");
if (existing) {
await github.rest.issues.update({
owner,
repo,
issue_number: existing.number,
body,
});
} else {
await github.rest.issues.create({ owner, repo, title, body });
}
return;
}
if (existing) {
await github.rest.issues.createComment({
owner,
repo,
issue_number: existing.number,
body: `CI recovered in [workflow run ${context.runId}](${runUrl}).`,
});
await github.rest.issues.update({
owner,
repo,
issue_number: existing.number,
state: "closed",
state_reason: "completed",
});
}
-51
View File
@@ -1,51 +0,0 @@
# Reference: https://github.com/ryoppippi/dotfiles/blob/main/.github/workflows/nix-build.yaml
name: "CI: NixOS"
on:
push:
branches:
- main
paths:
- flake.nix
- flake.lock
- "flake/**"
- "hosts/**"
- "libs/**"
- "modules/**"
- "overlays/**"
- "shells/**"
- "tests/**"
- ".github/actions/check-nixos/**"
- ".github/actions/setup-nix/**"
- ".github/workflows/nixos.yaml"
pull_request:
paths:
- flake.nix
- flake.lock
- "flake/**"
- "hosts/**"
- "libs/**"
- "modules/**"
- "overlays/**"
- "shells/**"
- "tests/**"
- ".github/actions/check-nixos/**"
- ".github/actions/setup-nix/**"
- ".github/workflows/nixos.yaml"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
check:
name: Check all NixOS configurations
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Setup Nix
uses: ./.github/actions/setup-nix
- name: Check NixOS configurations
uses: ./.github/actions/check-nixos
+64
View File
@@ -0,0 +1,64 @@
name: Publish Nix cache
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: write
packages: write
concurrency:
group: publish-nixcache-${{ github.ref }}
cancel-in-progress: false
jobs:
publish:
name: Build and publish uncached paths
runs-on: ubuntu-latest
timeout-minutes: 180
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: true
- name: Install Nix
uses: cachix/install-nix-action@630ae543ea3a38a9a4166f03376c02c50f408342 # v31.11.0
with:
extra_nix_config: |
experimental-features = nix-command flakes
accept-flake-config = true
access-tokens = github.com=${{ github.token }}
- name: Configure cache signing
env:
NIX_SIGNING_KEY: ${{ secrets.NIX_SIGNING_KEY }}
run: |
set -euo pipefail
test -n "$NIX_SIGNING_KEY" || {
echo "NIX_SIGNING_KEY is required; refusing to publish unsigned cache paths." >&2
exit 1
}
signing_key="$RUNNER_TEMP/nixcache-signing-key"
umask 077
printf '%s' "$NIX_SIGNING_KEY" > "$signing_key"
nix key convert-secret-to-public < "$signing_key" > nixcache-public-key.txt
echo "NIXCACHE_SIGNING_KEY_FILE=$signing_key" >> "$GITHUB_ENV"
- name: Commit cache public key
run: |
set -euo pipefail
if git diff --quiet -- nixcache-public-key.txt; then
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add nixcache-public-key.txt
git commit -m "chore: publish Nix cache signing key"
git push
- name: Build and publish uncached store paths
env:
GITHUB_TOKEN: ${{ github.token }}
NIXCACHE_REPO: ${{ github.repository }}
NIXCACHE_CONFIG_DIR: .
run: |
set -euo pipefail
nixcache_source="$(nix flake archive --json --no-write-lock-file github:cmspam/nixcache-oci/fb6006b5575da494dbbfc582e841d976ec06be6e | jq -r .path)"
source "$nixcache_source/lib/cache-builder.sh"
full_pipeline
+31
View File
@@ -0,0 +1,31 @@
name: Renovate
on:
schedule:
# Every day at 03:00 JST (18:00 UTC on the previous day).
- cron: "0 18 * * *"
workflow_dispatch:
permissions:
contents: read
concurrency:
group: renovate
cancel-in-progress: false
jobs:
renovate:
name: Update Nix flake inputs
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
# Use a PAT or GitHub App token so Renovate PRs trigger the other workflows.
- name: Run Renovate
uses: renovatebot/github-action@22e0a16091fc706b04affe6ae53d5e3358ac4023 # v46.1.19
with:
renovate-version: 43.262.1
token: ${{ secrets.RENOVATE_TOKEN }}
env:
LOG_LEVEL: info
RENOVATE_PLATFORM: github
RENOVATE_REPOSITORIES: ${{ github.repository }}
-48
View File
@@ -1,48 +0,0 @@
# Reference: https://github.com/ryoppippi/dotfiles/blob/main/.github/workflows/update-flake.yaml
name: "Bot: Update flake inputs"
on:
schedule:
- cron: "0 6 * * *"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: write
pull-requests: write
jobs:
update:
name: Update and validate flake inputs
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Setup Nix
uses: ./.github/actions/setup-nix
- name: Update flake inputs
id: update
run: |
nix flake update
if git diff --quiet -- flake.lock; then
echo 'changed=false' >> "$GITHUB_OUTPUT"
else
echo 'changed=true' >> "$GITHUB_OUTPUT"
fi
- name: Check updated NixOS configurations
if: steps.update.outputs.changed == 'true'
uses: ./.github/actions/check-nixos
- name: Create update pull request
if: steps.update.outputs.changed == 'true'
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
add-paths: flake.lock
branch: automation/update-flake-lock
delete-branch: true
commit-message: "flake: update inputs"
title: "flake: update inputs"
body: |
Automated update of `flake.lock`.
The updated inputs passed the Registry tests and a build of every NixOS configuration.
+10 -15
View File
@@ -4,7 +4,6 @@
!README.md
!LICENSE
!AGENTS.md
!/docs/
!.github/
!.gitea/
@@ -15,19 +14,15 @@
!/flake.nix
!/flake.lock
!/renovate.json
!shells/
!hosts/
!overlays/
!profiles/
!modules/
!docs/
!images/
!secrets/
!/shells/
!/flake/
!/overlays/
!/images/
!/secrets/
!/windows/
!/hosts/
!/libs/
!/modules/
!/tests/
!/skills/
-2
View File
@@ -3,7 +3,6 @@ keys:
- &host_x1g13 age12g85cuvg4kjfr79lqf5fx2k0d82tchrgv88xgkt7ukk2cfcsw98s2rjyat
- &host_ops age18rtm2dq2r62zvnhwdq0gkm24hu85r7zyleyk3jqv22zpdtw064eq7ay7dl
- &host_internal-app-01 age1mcp5gma7y0k59equhzqfsnn0ed335ljjtn0k08ua77htlxf0x54qsravch
- &host_galleria age1wh7r9wnvyrgt5efjvg2324khsf4w6e9atpmz2udr4uw7frhnvvwquzcu72
creation_rules:
- path_regex: ^secrets/common/[^/]+\.ya?ml$
key_groups:
@@ -12,7 +11,6 @@ creation_rules:
- *host_x1g13
- *host_ops
- *host_internal-app-01
- *host_galleria
- path_regex: ^secrets/hosts/x1g13/[^/]+\.ya?ml$
key_groups:
- age:
+340 -814
View File
File diff suppressed because it is too large Load Diff
+211 -2
View File
@@ -1,3 +1,212 @@
# moons14 dotfiles
# dotfiles
My NixOS + Home Manager configurations build with flake.
My NixOS + Home Manager configurations built with flake-parts.
## Overview
- **OS**: NixOS 26.05 (stable) + nixpkgs-unstable
- **Window Manager**: Niri (Wayland)
- **Shell**: Zsh
- **Terminal**: Ghostty
- **Editor**: Neovim (nixvim), VSCode
- **Launcher**: Vicinae
- **Theme**: Stylix (Dracula)
- **Secrets**: sops-nix + age + YubiKey
## Hosts
| Host | Description | Profiles |
| ------------- | --------------- | -------------------------------------------- |
| `x1g13` | ThinkPad laptop | gui, thinkpad, dev, personal, secure-storage |
| `nix-example` | VM | cli-interactive, vm, dev, remote |
| `installer` | NixOS installer | (standalone) |
## Directory Structure
```
.
├── flake.nix # Flake inputs and outputs
├── flake/
│ ├── formatter.nix # treefmt configuration (nixfmt, deadnix, statix, etc.)
│ └── git-hooks.nix # pre-commit hooks
├── hosts/
│ ├── default.nix # mkSystem helper and host definitions
│ ├── x1g13/ # ThinkPad host config
│ ├── nix-example/ # VM host config
│ └── installer/ # Installer ISO config
├── modules/
│ ├── applications/ # Application configs (NixOS + Home Manager)
│ │ ├── niri/ # Wayland compositor
│ │ ├── ghostty/ # Terminal emulator
│ │ ├── vim/ # Neovim (nixvim)
│ │ ├── vscode/ # VSCode
│ │ ├── zsh/ # Shell
│ │ ├── zellij/ # Terminal multiplexer
│ │ ├── git/ # Git config
│ │ ├── docker.nix # Container runtime
│ │ ├── tailscale.nix # VPN
│ │ ├── claude/ # Claude Code
│ │ ├── opencode.nix # OpenCode
│ │ └── ... # chrome, discord, zoom, slack, etc.
│ ├── system/ # NixOS system configs
│ │ ├── audio.nix # PipeWire
│ │ ├── boot/ # Bootloader (systemd-boot, lanzaboote)
│ │ ├── disko.nix # Disk partitioning
│ │ ├── fonts.nix # Fonts
│ │ ├── network/ # Networking
│ │ ├── sops.nix # Secrets management
│ │ ├── user/ # User accounts
│ │ └── ...
│ ├── features/ # Feature bundles (abstraction layer)
│ │ ├── application/ # browser, communication
│ │ ├── boot/ # UEFI
│ │ ├── cli/ # base, interactive, shell
│ │ ├── connect/ # WiFi, Bluetooth
│ │ ├── dev/ # agent, nix, python, bun, java, arduino
│ │ ├── gui/ # desktop, terminal, audio, editor, capture
│ │ ├── identity/ # SSH key, fingerprint
│ │ ├── network/ # Tailscale
│ │ ├── services/ # container, KDE
│ │ └── storage/ # disko
│ ├── drivers/ # Hardware drivers (Intel)
│ └── integrations/ # Home Manager integration
├── profiles/
│ ├── interfaces/ # cli-minimal, cli-interactive, gui
│ ├── platforms/ # desktop, laptop, thinkpad, vm
│ └── workloads/ # dev, personal, srv, remote, secure-storage
├── overlays/ # nixpkgs overlays
├── shells/ # devShells (pre-commit hooks, sops, age)
├── secrets/ # Encrypted secrets (sops)
└── docs/ # Documentation
```
## Architecture
```
profile (enable features)
→ features (bundle applications/system + add packages)
→ applications (system.nix + home.nix)
→ system (NixOS config)
```
### Module Patterns
**Simple Module** — Single file for NixOS-only or Home Manager-only configs:
```nix
{ lib, config, ... }:
let cfg = config.my.system.audio;
in {
options.my.system.audio.enable = lib.mkEnableOption "Audio";
config = lib.mkIf cfg.enable { ... };
}
```
**Complex Module** — Directory with `default.nix`, `system.nix`, `home.nix`:
```
modules/applications/<app>/
├── default.nix # Master enable + imports
├── system.nix # NixOS config
└── home.nix # Home Manager config (sharedModules)
```
**Feature Module** — Bundles multiple applications/system modules:
```nix
{ lib, config, ... }:
let cfg = config.my.features.gui.desktop;
in {
options.my.features.gui.desktop.enable = lib.mkEnableOption "Desktop";
config = lib.mkIf cfg.enable {
my.applications = { niri.enable = true; gtk.enable = true; ... };
};
}
```
**Profile** — Thin layer that only enables features:
```nix
{
my.features = {
gui.desktop.enable = true;
dev.agent.enable = true;
};
}
```
## Packages
### CLI
- **Shell**: Zsh with zoxide, direnv
- **Terminal multiplexer**: Zellij
- **Editor**: Neovim (nixvim)
- **Tools**: ripgrep, curl, wget, htop, btop, fastfetch, unzip, unrar
### GUI
- **Compositor**: Niri
- **Terminal**: Ghostty, Alacritty
- **Editor**: VSCode
- **Browser**: Chrome
- **Launcher**: Vicinae
- **File manager**: Nautilus
- **Communication**: Discord, Zoom, Slack
### Development
- **AI agents**: Claude Code, Codex, OpenCode, Grok
- **Languages**: Python, Bun (JavaScript/TypeScript), Java, Arduino
- **Container**: Docker
- **Nix**: nh, nixfmt, deadnix, statix
### System
- **VPN**: Tailscale
- **Secrets**: sops-nix, age
- **Boot**: systemd-boot, lanzaboote (Secure Boot)
- **Disk**: disko
- **Theme**: Stylix
## Commands
```sh
nix flake update # Update flake inputs
nix fmt # Format code
nix develop .#dotnix # Enter dev shell
sudo nixos-rebuild switch --flake .#<host> # Apply config
sudo nixos-rebuild build --flake .#<host> # Build without applying
```
## Nix Binary Cache
All normal hosts run `nixcache-oci` as a local proxy for
`ghcr.io/moons-14/dotfiles/nix-cache`. The `Publish Nix cache` workflow builds
the flake on pushes to `main` and uploads only store paths that were built by
the runner rather than substituted from an existing cache. Nix still uses the
official cache and configured Cachix caches for all other paths.
The cache must remain public and signed:
1. Generate a signing key outside this repository and save its contents as the
`NIX_SIGNING_KEY` GitHub Actions secret.
2. Run the `Publish Nix cache` workflow. It commits `nixcache-public-key.txt`,
which clients trust on their next configuration rebuild.
3. In GitHub Packages, make the `nix-cache` container package public.
```sh
nix key generate-secret > /tmp/nixcache-signing-key
# Copy the contents into the NIX_SIGNING_KEY GitHub Actions secret, then delete the local file.
```
## Inspired
- [Zaney/zaneyos](https://gitlab.com/Zaney/zaneyos)
- [fa0311/.zshrc](https://gist.github.com/fa0311/d37d53ff39c73c54c883379e8e3732df)
- [AsianLovesLinux/Niri](https://github.com/AsianLovesLinux/Niri)
- [natsukium/dotfiles](https://github.com/natsukium/dotfiles)
- [dracula](https://github.com/dracula)
- [akazdayo/nix-configs](https://github.com/akazdayo/nix-configs)
- [yutakobayashidev/dotnix](https://github.com/yutakobayashidev/dotnix)
- [kawaemon/dotfiles](https://github.com/kawaemon/dotfiles)
-153
View File
@@ -1,153 +0,0 @@
# NixOSインストール手順(SOPSなし・ディスク暗号化なし)
この手順は、SOPSによるシークレット管理とLUKSによるディスク暗号化を
使用しないホスト向けの、独立したインストール手順である。
SOPSとディスク暗号化を使用する場合は、[暗号化ありの手順](install.md)を参照。
## 事前準備
1. [ISOビルド](iso-build.md)を参照してISOを作成
2. USBに書き込んで対象マシンでブート
## ネットワーク接続
### 有線LAN
DHCPで自動設定される。
### Wi-Fi(有線が使えない場合)
```bash
nmcli device wifi connect <SSID> --ask
```
## SSH接続
コンソールに表示されたIPアドレスに接続:
```bash
ssh root@<ip-address>
```
## インストール手順
### 1. dotfilesのクローン
```bash
git clone [email protected]:moons-14/dotfiles.git ~/dotfiles
cd ~/dotfiles
```
### 2. ホスト設定の作成
`hosts/<hostname>/nixos.nix`を作成し、`hosts/default.nix`にホストと使用する
プロファイルを登録する。ホスト固有の設定だけをホストディレクトリに置き、
再利用可能な設定は適切なunitまたはprofileに置く。
### 3. インストール先ディスクの確認
```bash
lsblk -o NAME,PATH,SIZE,MODEL,SERIAL,TYPE,FSTYPE,MOUNTPOINTS
ls -l /dev/disk/by-id/
```
以降の操作では指定したディスクの既存データが消去される。対象を必ず確認し、
可能であれば`/dev/sda`や`/dev/nvme0n1`ではなく、安定した
`/dev/disk/by-id/...`パスを使用する。
### 4. Disko設定の作成
`hosts/<hostname>/disko.nix`を作成する:
```nix
_:
{
disko.enableConfig = true;
disko.devices.disk.main = {
type = "disk";
device = "/dev/disk/by-id/<target-disk>";
content = {
type = "gpt";
partitions = {
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
}
```
`<target-disk>`を手順3で確認した実際のディスクIDに置き換える。指定した
ディスクの既存データは消去される。
### 5. パーティション作成とマウント
```bash
disko --mode destroy,format,mount hosts/<hostname>/disko.nix
```
Diskoの実行結果を確認する:
```bash
findmnt /mnt
findmnt /mnt/boot
```
### 6. ハードウェア設定の生成
```bash
nixos-generate-config --no-filesystems --root /mnt --show-hardware-config \
> ~/dotfiles/hosts/<hostname>/hardware-configuration.nix
```
### 7. ホストモジュールから設定を読み込む
`hosts/<hostname>/nixos.nix`で、生成したハードウェア設定とDisko設定を読み込む:
```nix
{
imports = [
./hardware-configuration.nix
./disko.nix
];
}
```
### 8. NixOSインストール
```bash
nixos-install --flake ~/dotfiles#<hostname>
```
SOPSを使用しないため、age鍵の登録、シークレットの再暗号化、SSHホストキーの
事前生成とコピーは不要である。OpenSSHを有効にしたホストでは、SSHホストキーは
通常の初回起動時に生成される。
### 9. 再起動
```bash
reboot
```
## インストール後の確認
- 正しいディスクから起動できるか
- `/`と`/boot`が意図したファイルシステムからマウントされているか
- ネットワークと、設定している場合はSSH接続が利用できるか
+44 -32
View File
@@ -1,10 +1,4 @@
# NixOSインストール手順(SOPS・ディスク暗号化あり)
この手順は、SOPSによるシークレット管理とLUKSによるディスク暗号化を
使用するホスト向けである。
どちらも使用しない場合は、
[SOPSなし・ディスク暗号化なしの手順](install-simple.md)を参照。
# NixOSインストール手順
## 事前準備
@@ -89,36 +83,54 @@ sops updatekeys secrets/hosts/<hostname>/*.yaml
新しいホスト用の`hosts/<hostname>/disko.nix`を作成。
LUKS暗号化とbtrfsの構成は`hosts/x1g13/disko.nix`を参照。
#### シンプル構成(暗号化なし)
```nix
_:
{
disko.enableConfig = true;
disko.devices.disk.main = {
type = "disk";
device = "/dev/sda";
content = {
type = "gpt";
partitions = {
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
}
```
#### LUKS暗号化 + btrfs
`hosts/x1g13/disko.nix`を参照。
### 7. ディスクのパーティション
```bash
cd ~/dotfiles
disko --mode destroy,format,mount hosts/<hostname>/disko.nix
nix run github:nix-community/disko -- --mode disko hosts/<hostname>/disko.nix
```
### 8. ハードウェア設定の生成
対象マシンのハードウェア設定を生成し、新しいホストのディレクトリへ直接保存:
```bash
nixos-generate-config --no-filesystems --root /mnt --show-hardware-config \
> ~/dotfiles/hosts/<hostname>/hardware-configuration.nix
```
`hosts/<hostname>/nixos.nix`から生成した設定とDisko設定を読み込む:
```nix
{
imports = [
./hardware-configuration.nix
./disko.nix
];
}
```
### 9. ホストキーのコピー
### 8. ホストキーのコピー
```bash
mkdir -p /mnt/etc/ssh
@@ -126,13 +138,13 @@ cp /tmp/ssh_host_ed25519_key* /mnt/etc/ssh/
chmod 600 /mnt/etc/ssh/ssh_host_ed25519_key
```
### 10. NixOSインストール
### 9. NixOSインストール
```bash
nixos-install --flake ~/dotfiles#<hostname>
```
### 11. 再起動
### 10. 再起動
```bash
reboot
-119
View File
@@ -1,119 +0,0 @@
# iOS Simulator 初期セットアップ
この手順は `m2` の macOS 環境で、stable Xcode と最新の stable iOS Simulator Runtime を使える状態にするためのもの。
## 前提
- `m2` が `workload.development` profile を有効にしていること
- Mac App Store に Apple Account でサインイン済みであること
- dotfiles を最新化していること
Xcode 本体は `applications.xcode` が Mac App Store 版を管理する。Simulator Runtime は Apple が管理する mutable state のため、Nix store には入れず専用 dev shell から導入する。
## 1. macOS 設定を反映する
リポジトリ直下で nix-darwin の設定を反映する。
```bash
sudo darwin-rebuild switch --flake .#m2
```
これにより `/Applications/Xcode.app` に stable Xcode がインストールされる。
Xcode のインストールで Mac App Store の認証エラーになる場合は、App Store を一度開いてサインイン状態を確認してから再実行する。
## 2. iOS Simulator Runtime を導入する
初回セットアップは次の1コマンドで行う。
```bash
nix develop .#ios -c ios-simulator-install
```
`ios-simulator-install` は次を順に実行する。
1. `/Applications/Xcode.app` が存在することを確認
2. `xcode-select` の Developer Directory を stable Xcode に切り替え
3. Xcode の first-launch components を導入
4. 利用可能な新しい hardware support components を確認
5. 選択中の Xcode に対応する最新の iOS Simulator Runtime をダウンロードしてインストール
6. Xcode のバージョンとインストール済み Simulator Runtime を表示
途中で `sudo` の認証を求められる場合がある。
## 3. インストールを確認する
```bash
xcodebuild -version
xcode-select -p
xcrun simctl list runtimes
xcrun simctl list devices available
```
`xcode-select -p` は次を指していること。
```text
/Applications/Xcode.app/Contents/Developer
```
`xcrun simctl list runtimes` に iOS runtime が表示されればセットアップ完了。
## 4. Simulator を起動する
```bash
open -a Simulator
```
Simulator の Device メニューから、インストール済み runtime で利用可能な iPhone を選択する。
## Runtime の更新
Xcode を stable の新しいバージョンへ更新した後は、同じコマンドを再実行する。
```bash
nix develop .#ios -c ios-simulator-install
```
Xcode の選択、first-launch components、hardware support、iOS Simulator Runtime の状態をまとめて更新できる。
## トラブルシューティング
### Xcode が見つからない
次のエラーが出る場合、先に nix-darwin の設定を反映する。
```text
Xcode is not installed at /Applications/Xcode.app.
```
```bash
sudo darwin-rebuild switch --flake .#m2
```
### Simulator Runtime が見えない
まず runtime 一覧を確認する。
```bash
xcrun simctl list runtimes
```
iOS runtime がない場合は再度インストーラーを実行する。
```bash
nix develop .#ios -c ios-simulator-install
```
### Command Line Tools 側を参照している
```bash
xcode-select -p
```
が `/Library/Developer/CommandLineTools` を指している場合でも、`ios-simulator-install` が `/Applications/Xcode.app/Contents/Developer` へ切り替える。
手動で直す場合は次を実行する。
```bash
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
```
+12 -72
View File
@@ -1,86 +1,26 @@
# カスタムインストーラー ISO
`hosts/installer` から、NixOS 26.05 ベースの `x86_64-linux` 用インストーラー
ISO を作成する。installer ホストは Home Manager を使用せず、`base` プロファイルと
ホスト固有のインストール支援設定だけを含む。
# カスタムISOビルド
## ビルド
flake 対応の Nix が利用できる環境で、リポジトリのルートから実行する。
`x86_64-linux` 以外のマシンで実行する場合は、対応する Linux リモートビルダーが
必要になる。
```bash
nix build .#nixosConfigurations.installer.config.system.build.isoImage
```
生成された ISO は次の場所にある。
```text
result/iso/nixos-minimal-*-x86_64-linux.iso
```
ファイル名に含まれる NixOS のバージョンとリビジョンは、`flake.lock` の更新に応じて
変わる。生成物を確認するには次を実行する。
## ISO書き込み
```bash
ls -lh result/iso/*.iso
sha256sum result/iso/*.iso
```
# USBデバイスの確認
lsblk
## USB メモリへの書き込み
書き込み先はパーティション(例: `/dev/sdX1`)ではなく、USB デバイス全体
(例: `/dev/sdX`)を指定する。この操作は指定したデバイスの内容を上書きするため、
サイズ、モデル、マウント先を確認する。
```bash
lsblk -p -o NAME,SIZE,TYPE,MODEL,MOUNTPOINTS
```
USB のマウント済みパーティションをアンマウントしてから、`/dev/sdX` と
`/dev/sdX1` を確認した実際のデバイス名に置き換えて書き込む。パーティションが
複数ある場合は、それぞれをアンマウントする。
```bash
sudo umount /dev/sdX1
sudo dd if=result/iso/nixos-minimal-*-x86_64-linux.iso \
of=/dev/sdX bs=4M conv=fsync status=progress
# 書き込み(/dev/sdXは実際のデバイスに置き換える)
sudo dd if=./result/nixos-minimal-*.iso of=/dev/sdX bs=4M status=progress
sync
```
書き込み完了後、USB を安全に取り外して対象マシンから起動する。
## ISOの特徴
## 起動後の接続
有線 LAN は DHCP で自動設定される。Wi-Fi を使用する場合は、インストーラーの
コンソールで NetworkManager を使って接続する。
```bash
nmcli device wifi list
nmcli device wifi connect <SSID> --ask
```
起動時にコンソールへ IPv4 アドレスと簡易ヘルプが表示される。表示されたアドレスへ
登録済みの SSH 鍵で接続する。
```bash
ssh root@<ip-address>
```
root のパスワードログインとキーボード対話認証は無効で、
`hosts/installer/nixos.nix` に登録された公開鍵だけが利用できる。
以降の作業は、構成に応じて次の手順を参照する:
- [SOPSなし・ディスク暗号化なし](install-simple.md)
- [SOPS・ディスク暗号化あり](install.md)
## ISO に含まれる主な設定とツール
- Nix flakes と `nix-command`
- NetworkManager、OpenSSH、起動時の IP アドレス表示
- `disko`、`parted`、`cryptsetup`、`btrfs-progs`、`efibootmgr`
- `sops`、`age`、`ssh-to-age`
- `age-plugin-yubikey`、`yubikey-manager`、`pcsc-tools` と `pcscd`
- `sbctl`、`tpm2-tools`
- `git`、`rsync`、`vim`、`wget`、`curl`、`jq`、`pciutils`、`util-linux`
- SSH鍵認証でrootログイン可能
- 有線LANはDHCPで自動設定
- WiFiは`nmcli`で手動設定可能
- disko/sops/ageなどのツールを内蔵
- ブート時にIPアドレスとヘルプを表示
Generated
+300 -869
View File
File diff suppressed because it is too large Load Diff
+20 -27
View File
@@ -11,11 +11,6 @@
inputs.nixpkgs.follows = "nixpkgs";
};
nix-darwin = {
url = "github:nix-darwin/nix-darwin/nix-darwin-26.05";
inputs.nixpkgs.follows = "nixpkgs";
};
# Hardware / Platform
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
nixos-wsl.url = "github:nix-community/NixOS-WSL";
@@ -23,11 +18,6 @@
# Desktop
niri-flake.url = "github:sodiboo/niri-flake";
nix-hazkey = {
url = "github:aster-void/nix-hazkey";
inputs.nixpkgs.follows = "nixpkgs";
};
stylix = {
url = "github:nix-community/stylix";
inputs.nixpkgs.follows = "nixpkgs";
@@ -35,7 +25,7 @@
# Terminal
ghostty = {
url = "github:ghostty-org/ghostty";
url = "github:moons-14/ghostty";
};
# Shell / Launcher
@@ -46,7 +36,10 @@
inputs.nixpkgs.follows = "nixpkgs";
};
noctalia.url = "github:noctalia-dev/noctalia/cachix";
noctalia = {
url = "github:noctalia-dev/noctalia";
inputs.nixpkgs.follows = "nixpkgs";
};
# Editor
nixvim = {
@@ -85,17 +78,12 @@
# LLM agents
llm-agents = {
url = "github:numtide/llm-agents.nix";
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
codex-desktop-linux = {
url = "github:ilysenko/codex-desktop-linux";
};
codex-session-usage.url = "github:moons-14/codex-session-usage";
skills = {
url = "github:mattpocock/skills";
flake = false;
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
# Index / Search
@@ -104,17 +92,20 @@
inputs.nixpkgs.follows = "nixpkgs";
};
# Systems
systems.url = "github:nix-systems/default";
browser-previews = {
url = "github:nix-community/browser-previews";
# Binary cache
nixcache-oci = {
url = "github:cmspam/nixcache-oci";
inputs.nixpkgs.follows = "nixpkgs";
};
nani-translate-linux.url = "git+https://github.com/zunoser/nani-translate-linux.git";
# Systems
systems.url = "github:nix-systems/default-linux";
containerlab.url = "github:srl-labs/containerlab";
# Japanese Input Method
nix-hazkey = {
url = "github:aster-void/nix-hazkey";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
@@ -128,8 +119,10 @@
imports = [
./overlays
./hosts
./shells
./flake
./flake/formatter.nix
./flake/git-hooks.nix
];
};
}
-7
View File
@@ -1,7 +0,0 @@
{
imports = [
./formatter.nix
./git-hooks.nix
./registry.nix
];
}
-54
View File
@@ -1,54 +0,0 @@
{
inputs,
lib,
...
}:
let
dotfilesLib = import ../libs {
inherit inputs lib;
root = ../.;
};
hostSpecsPath = ../hosts/default.nix;
hostSpecs =
if builtins.pathExists hostSpecsPath then
let
value = import hostSpecsPath;
in
if builtins.isFunction value then
value (
builtins.intersectAttrs (builtins.functionArgs value) {
inherit inputs lib;
}
)
else
value
else
{ };
configurations = dotfilesLib.hosts.mkConfigurations hostSpecs;
in
{
flake = {
inherit (configurations) darwinConfigurations nixosConfigurations;
lib = dotfilesLib;
};
perSystem =
{ pkgs, system, ... }:
let
nixosChecks =
lib.mapAttrs' (name: nixos: lib.nameValuePair "nixos-${name}" nixos.config.system.build.toplevel)
(
lib.filterAttrs (
_: nixos: nixos.pkgs.stdenv.hostPlatform.system == system
) configurations.nixosConfigurations
);
in
{
checks = {
registry = import ../tests/registry.nix {
inherit inputs lib pkgs;
};
}
// nixosChecks;
};
}
+107 -138
View File
@@ -1,144 +1,113 @@
{
nix-builder = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./nix-builder;
inputs,
config,
lib,
...
}:
let
inherit (inputs.nixpkgs.lib) nixosSystem;
profiles = [
"base"
"interface.minimal"
"platform.vm"
"workload.remote-access"
];
username = "moons";
mkSystem =
{
host,
system,
profiles ? [ ],
extraModules ? [ ],
}:
let
unstable = import inputs.nixpkgs-unstable {
inherit system;
config = {
allowUnfree = true;
};
};
in
assert lib.assertMsg (lib.elem system config.systems)
"mkSystem: system '${system}' not in valid systems: ${lib.generators.toPretty { } config.systems}";
nixosSystem {
inherit system;
modules = [
{
nixpkgs.config.allowUnfree = true;
nixpkgs.overlays = builtins.attrValues inputs.self.overlays;
}
../modules
./${host}/default.nix
]
++ map (p: ../profiles/${p}.nix) profiles
++ extraModules;
specialArgs = {
inherit
inputs
username
unstable
host
;
};
};
nixosConfigurations = {
nix-example = mkSystem {
host = "nix-example";
system = "x86_64-linux";
profiles = [
"interfaces/cli-interactive"
"platforms/vm"
"workloads/dev"
"workloads/remote"
];
};
ops = mkSystem {
host = "ops";
system = "x86_64-linux";
profiles = [
"interfaces/cli-interactive"
"platforms/vm"
"workloads/remote"
];
};
internal-app-01 = mkSystem {
host = "internal-app-01";
system = "x86_64-linux";
profiles = [
"interfaces/cli-interactive"
"platforms/vm"
"workloads/srv"
];
};
x1g13 = mkSystem {
host = "x1g13";
system = "x86_64-linux";
profiles = [
"interfaces/gui"
"platforms/thinkpad"
"workloads/dev"
"workloads/personal"
"workloads/secure-storage"
"workloads/tailscale/client"
];
};
installer = nixosSystem {
system = "x86_64-linux";
modules = [
./installer/default.nix
];
specialArgs = {
inherit inputs;
};
};
};
in
{
flake = {
inherit nixosConfigurations;
ops = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./ops;
profiles = [
"base"
"interface.minimal"
"platform.vm"
"workload.remote-access"
"workload.deploy-rs-target"
];
};
netsrv-01 = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./netsrv-01;
profiles = [
"base"
"interface.minimal"
"platform.vm"
"workload.remote-access"
"workload.deploy-rs-target"
"workload.server"
];
};
installer = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./installer;
homeManager = false;
profiles = [ "base" ];
};
x1g9 = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./x1g9;
profiles = [
"base"
"interface.cli"
"interface.labwc"
"interface.niri"
"platform.thinkpad-x1"
"security.fingerprint"
# "security.secrets"
"workload.personal"
];
};
x1g13 = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./x1g13;
profiles = [
"base"
"interface.cli"
"interface.labwc"
"interface.niri"
"networking.tailscale-client"
"platform.thinkpad-x1"
"security.fingerprint"
"security.secrets"
"security.secure-boot"
"security.tpm-storage"
"workload.development"
"workload.game"
"workload.network-lab"
"workload.personal"
];
};
galleria = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./galleria;
profiles = [
"base"
"interface.cli"
"interface.labwc"
"interface.niri"
"networking.tailscale-client"
"platform.intel-nvidia-desktop"
"security.secrets"
"security.secure-boot"
"security.tpm-storage"
"security.fingerprint"
"workload.development"
"workload.game"
"workload.machine-learning"
"workload.network-lab"
"workload.personal"
"workload.photography"
"workload.camera"
];
};
m2 = {
system = "aarch64-darwin";
stateVersion = "26.05";
user = "moons";
path = ./m2;
profiles = [
"base"
"interface.cli"
"interface.macos"
"security.fingerprint"
# "security.secrets"
"workload.development"
"workload.game"
"workload.personal"
];
checks.x86_64-linux = lib.mapAttrs' (
name: nixos: lib.nameValuePair "nixos-${name}" nixos.config.system.build.toplevel
) nixosConfigurations;
};
}
-91
View File
@@ -1,91 +0,0 @@
_:
let
espPart = "/dev/disk/by-partuuid/008b04ef-9c06-4049-bffb-3906f5c3a9c1";
nixosPart = "/dev/disk/by-partuuid/04295552-cbb8-4511-ac1e-1171ec20f8d1";
btrfsMountOptions = [
"compress=zstd"
"noatime"
"ssd"
"space_cache=v2"
];
in
{
disko.enableConfig = true;
# These are deliberately partition paths, not the whole Windows disk. Disko
# must never own or destroy the disk's GPT or any Windows partition.
disko.devices.disk = {
esp = {
type = "disk";
device = espPart;
destroy = false;
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
nixos = {
type = "disk";
device = nixosPart;
destroy = false;
content = {
type = "luks";
name = "cryptroot";
askPassword = true;
settings.allowDiscards = true;
extraFormatArgs = [
"--type"
"luks2"
"--pbkdf"
"argon2id"
"--label"
"NixOS-LUKS"
];
content = {
type = "btrfs";
extraArgs = [
"-f"
"-L"
"NixOS"
];
subvolumes = {
"@root" = {
mountpoint = "/";
mountOptions = btrfsMountOptions;
};
"@home" = {
mountpoint = "/home";
mountOptions = btrfsMountOptions;
};
"@nix" = {
mountpoint = "/nix";
mountOptions = btrfsMountOptions;
};
"@log" = {
mountpoint = "/var/log";
mountOptions = btrfsMountOptions;
};
"@swap" = {
mountpoint = "/.swapvol";
mountOptions = [ "noatime" ];
swap.swapfile.size = "32G";
};
};
};
};
};
};
}
-30
View File
@@ -1,30 +0,0 @@
# Do not modify this file! It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"xhci_pci"
"ahci"
"nvme"
"usbhid"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
-51
View File
@@ -1,51 +0,0 @@
{
lib,
config,
...
}:
{
# This desktop is permanently connected to AC power.
systemd.user.services.swayidle.Service.Environment = [
"SWAYIDLE_ASSUME_AC=1"
];
services.kanshi = {
enable = true;
settings = [
{
profile = {
name = "galleria";
outputs = [
{
criteria = "HDMI-A-1";
status = "enable";
position = "0,0";
scale = 1.5;
}
{
criteria = "DP-1";
status = "enable";
position = "2560,0";
}
{
criteria = "DP-2";
status = "enable";
position = "5120,0";
scale = 1.5;
}
];
};
}
];
};
home.file.".wallpapers" = {
source = lib.mkForce (
config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/Pictures/wallpapers"
);
recursive = lib.mkForce false;
};
}
-21
View File
@@ -1,21 +0,0 @@
{ inputs, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
./disko.nix
];
boot.initrd.luks.devices.cryptroot.device =
"/dev/disk/by-partuuid/04295552-cbb8-4511-ac1e-1171ec20f8d1";
# Keep Windows data and recovery partitions out of UDisks-based file
# managers. The shared EFI System Partition stays available as /boot.
services.udev.extraRules = ''
ENV{ID_PART_ENTRY_UUID}=="0480f887-d1f9-489d-b8fe-78549ced1938", ENV{UDISKS_IGNORE}="1"
ENV{ID_PART_ENTRY_UUID}=="6c70041b-3f65-4eb1-8b08-18ed20001877", ENV{UDISKS_IGNORE}="1"
'';
environment.systemPackages = with inputs.browser-previews.packages.${pkgs.system}; [
google-chrome-beta
];
}
@@ -5,7 +5,9 @@
...
}:
{
imports = [ "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix" ];
imports = [
"${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix"
];
boot.zfs.forceImportRoot = false;
@@ -31,32 +33,26 @@
users.users.root.openssh.authorizedKeys.keys = [
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIKhxDkucmeCor6CKoXAua7DgDSzuXrZOtpdkyzQxz5+aAAAABHNzaDo= moons@moons14.com"
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIN6hZJyng/5LgFKPjR6uZAd/00UkO0vN0uQOoIvfSELdAAAABHNzaDo= moons@moons14.com"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLwReAiwhXoO34S2+MrvqUhi8IWp4IzUq4OSp3niJdq"
];
environment.systemPackages = with pkgs; [
git
disko
sops
age
ssh-to-age
age-plugin-yubikey
yubikey-manager
pcsc-tools
mkpasswd
rsync
vim
wget
curl
jq
parted
cryptsetup
btrfs-progs
efibootmgr
pciutils
sbctl
tpm2-tools
util-linux
git # Clone dotfiles repository
disko # Disk partitioning
sops # Secrets management
age # Age encryption
ssh-to-age # Convert SSH keys to age
age-plugin-yubikey # YubiKey support
yubikey-manager # YubiKey management
pcsc-tools # Smart card tools
mkpasswd # Password hash generation
rsync # File synchronization
vim # Text editor
wget # Download files
curl # HTTP client
jq # JSON processor
parted # Partition tools
cryptsetup # LUKS encryption
btrfs-progs # Btrfs filesystem tools
];
services.pcscd.enable = true;
@@ -76,12 +72,6 @@
║ ║
║ Installation Workflow: ║
║ ║
║ Choose a guide after cloning: ║
║ Simple: docs/install-simple.md ║
║ SOPS + LUKS: docs/install.md ║
║ ║
║ The workflow below is for SOPS + LUKS: ║
║ ║
║ 1. Clone dotfiles: ║
║ git clone git@github.com:moons-14/dotfiles.git ~/dotfiles║
║ ║
@@ -109,25 +99,37 @@
║ # See hosts/x1g13/disko.nix for reference ║
║ ║
║ 7. Partition disk with disko: ║
║ disko --mode destroy,format,mount \ ║
║ hosts/<host>/disko.nix ║
║ nix run github:nix-community/disko -- \ ║
║ --mode disko hosts/<host>/disko.nix ║
║ ║
║ 8. Generate hardware configuration: ║
║ nixos-generate-config --no-filesystems --root /mnt \ ║
║ --show-hardware-config > \ ║
║ ~/dotfiles/hosts/<host>/hardware-configuration.nix ║
║ # Import hardware-configuration.nix and disko.nix ║
║ # from hosts/<host>/nixos.nix ║
║ ║
║ 9. Copy host key to installed system: ║
║ 8. Copy host key to installed system: ║
║ mkdir -p /mnt/etc/ssh ║
║ cp /tmp/ssh_host_ed25519_key* /mnt/etc/ssh/ ║
║ chmod 600 /mnt/etc/ssh/ssh_host_ed25519_key ║
║ ║
║ 10. Install NixOS: ║
║ 9. Install NixOS: ║
║ nixos-install --flake ~/dotfiles#<host> ║
║ ║
║ LUKS + btrfs (see hosts/x1g13/disko.nix): ║
║ Disko Configuration Examples: ║
║ ║
║ Simple (no encryption): ║
║ disko.devices.disk.main = { ║
║ type = "disk"; ║
║ device = "/dev/sda"; ║
║ content = { ║
║ type = "gpt"; ║
║ partitions = { ║
║ ESP = { size = "512M"; type = "EF00"; ║
║ content = { type = "filesystem"; ║
║ format = "vfat"; mountpoint = "/boot"; }; }; ║
║ root = { size = "100%"; ║
║ content = { type = "filesystem"; ║
║ format = "ext4"; mountpoint = "/"; }; }; ║
║ }; ║
║ }; ║
║ }; ║
║ ║
║ LUKS + btrfs (see hosts/x1g13/disko.nix): ║
║ - Use partuuid for device path ║
║ - Set askPassword = true for LUKS ║
║ - Configure btrfs subvolumes ║
@@ -186,4 +188,6 @@
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
system.stateVersion = "26.05";
}
@@ -1,3 +1,4 @@
{ ... }:
{
imports = [
./hardware-configuration.nix
@@ -20,6 +20,20 @@
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/1b12ab98-2537-4207-a3f4-bb8ba7b53b00";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/8365-C778";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
-10
View File
@@ -1,10 +0,0 @@
{ hostName, ... }:
{
# networking.hostName and networking.localHostName are derived from the
# registry name; computerName controls the user-visible macOS name.
networking.computerName = hostName;
# Keep this value stable after the first activation. It is independent of
# the Home Manager stateVersion in hosts/default.nix.
system.stateVersion = 7;
}
-30
View File
@@ -1,30 +0,0 @@
_: {
disko.enableConfig = true;
disko.devices.disk.main = {
type = "disk";
device = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi0";
content = {
type = "gpt";
partitions = {
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
}
@@ -1,27 +0,0 @@
# QEMU hardware baseline. Replace this with the output of
# `nixos-generate-config` after provisioning the VM if its hardware differs.
{
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
-40
View File
@@ -1,40 +0,0 @@
{
networking = {
interfaces = {
ens18 = {
useDHCP = false;
ipv4.addresses = [
{
address = "10.50.65.11";
prefixLength = 24;
}
];
};
ens19 = {
useDHCP = false;
ipv4.addresses = [
{
address = "10.50.66.10";
prefixLength = 24;
}
];
};
ens20 = {
useDHCP = false;
ipv4.addresses = [
{
address = "10.50.77.21";
prefixLength = 24;
}
];
};
};
defaultGateway = {
address = "10.50.66.1";
interface = "ens19";
};
};
}
-66
View File
@@ -1,66 +0,0 @@
_:
let
osDisk = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi0";
in
{
disko.enableConfig = true;
# The VM disks already contain live filesystems. Model each existing
# filesystem without giving Disko ownership of their partitioning or data.
disko.devices.disk = {
boot = {
type = "disk";
device = "${osDisk}-part1";
destroy = false;
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
root = {
type = "disk";
device = "${osDisk}-part2";
destroy = false;
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
nix-build = {
type = "disk";
device = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi1";
destroy = false;
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/var/lib/nix-build";
mountOptions = [ "noatime" ];
};
};
nix-store = {
type = "disk";
device = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi2";
destroy = false;
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/nix/store";
mountOptions = [ "noatime" ];
};
};
};
fileSystems."/nix/store".neededForBoot = true;
nix.settings.build-dir = "/var/lib/nix-build";
services.fstrim.enable = true;
}
-83
View File
@@ -1,83 +0,0 @@
{
config,
pkgs,
primaryUser,
...
}:
let
homeDirectory = "/home/${primaryUser}";
fleetDirectory = "${homeDirectory}/srv/nix-fleet";
stateDirectory = "/var/lib/nix-fleet";
sourceDirectory = "${stateDirectory}/source";
git = "${pkgs.git}/bin/git";
nix = "${config.nix.package}/bin/nix";
rsync = "${pkgs.rsync}/bin/rsync";
cleanCheckoutConditions = [
"${git} -C ${fleetDirectory} diff --quiet"
"${git} -C ${fleetDirectory} diff --cached --quiet"
];
in
{
systemd.services.nix-fleet-converge = {
description = "Update inputs, build the fleet, and deploy changed hosts";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
environment = {
HOME = homeDirectory;
NIX_CONFIG = ''
accept-flake-config = true
max-jobs = 4
cores = 3
'';
};
serviceConfig = {
Type = "oneshot";
User = primaryUser;
Restart = "on-failure";
RestartSec = "5min";
StateDirectory = "nix-fleet";
StateDirectoryMode = "0750";
WorkingDirectory = stateDirectory;
UMask = "0077";
ExecCondition = cleanCheckoutConditions;
EnvironmentFile = "${fleetDirectory}/.env";
# Work in a disposable copy so updating the dotfiles lock never dirties
# the operator's nix-fleet checkout.
ExecStart = [
"${git} -C ${fleetDirectory} pull --ff-only"
"${rsync} --archive --delete --exclude=.git/ --exclude=.direnv/ --exclude=.env --exclude=result --exclude=result-* ${fleetDirectory}/ ${sourceDirectory}/"
"${nix} flake update --flake ${sourceDirectory} dotfiles"
"${nix} run ${sourceDirectory}#converge -- ${sourceDirectory} ${stateDirectory}"
];
};
};
systemd.timers.nix-fleet-converge = {
description = "Periodically converge the NixOS fleet";
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = "2min";
OnUnitInactiveSec = "5min";
RandomizedDelaySec = "30s";
Persistent = true;
Unit = "nix-fleet-converge.service";
};
};
# Only an actual successful deployment touches gc-request. This starts the
# builder's root nh-clean unit; remote host stores are never cleaned here.
systemd.paths.nix-fleet-gc = {
description = "Garbage-collect superseded fleet builds on nix-builder";
wantedBy = [ "multi-user.target" ];
pathConfig = {
PathChanged = "${stateDirectory}/gc-request";
Unit = "nh-clean.service";
};
};
}
-37
View File
@@ -1,37 +0,0 @@
{
lib,
...
}:
{
nix.settings = {
build-dir = "/var/lib/nix-build";
secret-key-files = [
"/var/lib/secrets/nix-cache-signing-key"
];
auto-optimise-store = lib.mkForce false;
keep-outputs = false;
keep-derivations = true;
};
services.harmonia.cache = {
enable = true;
signKeyPaths = [
"/var/lib/secrets/nix-cache-signing-key"
];
settings = {
bind = "[::]:5000";
priority = 30;
workers = 4;
};
};
networking.firewall.allowedTCPPorts = [
5000
];
}
-40
View File
@@ -1,40 +0,0 @@
{
networking = {
interfaces = {
ens18 = {
useDHCP = false;
ipv4.addresses = [
{
address = "10.50.65.10";
prefixLength = 24;
}
];
};
ens19 = {
useDHCP = false;
ipv4.addresses = [
{
address = "10.50.77.10";
prefixLength = 24;
}
];
};
ens20 = {
useDHCP = false;
ipv4.addresses = [
{
address = "10.50.68.10";
prefixLength = 24;
}
];
};
};
defaultGateway = {
address = "10.50.68.1";
interface = "ens20";
};
};
}
-9
View File
@@ -1,9 +0,0 @@
{
imports = [
./fleet-automation.nix
./disko.nix
./hardware-configuration.nix
./harmonia.nix
./networking.nix
];
}
@@ -1,7 +1,6 @@
{ ... }:
{
imports = [
./hardware-configuration.nix
./disko.nix
./networking.nix
];
}
@@ -0,0 +1,43 @@
# Do not modify this file! It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/8f0eaec6-5dc9-4821-aa8d-fb6809b5a5bf";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/201C-961B";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
@@ -1,11 +1,18 @@
{ ... }:
{
imports = [
./hardware-configuration.nix
];
networking = {
useDHCP = false;
interfaces = {
ens18 = {
useDHCP = false;
ipv4.addresses = [
{
address = "10.50.65.100";
address = "10.50.128.20";
prefixLength = 24;
}
];
@@ -15,7 +22,7 @@
useDHCP = false;
ipv4.addresses = [
{
address = "10.50.80.10";
address = "10.50.7.101";
prefixLength = 24;
}
];
@@ -23,18 +30,27 @@
ens20 = {
useDHCP = false;
ipv4.routes = [
{
address = "10.50.64.0";
prefixLength = 24;
via = "10.50.82.1";
}
];
ipv4.addresses = [
{
address = "10.50.77.20";
address = "10.50.82.10";
prefixLength = 24;
}
];
};
};
defaultGateway = {
address = "10.50.80.1";
interface = "ens19";
address = "10.50.128.1";
interface = "ens18";
};
};
}
-30
View File
@@ -1,30 +0,0 @@
_: {
disko.enableConfig = true;
disko.devices.disk.main = {
type = "disk";
device = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi0";
content = {
type = "gpt";
partitions = {
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
}
+16
View File
@@ -24,5 +24,21 @@
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/69fa2193-1e4f-438a-8898-5de8a3f36e5b";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/D09B-4277";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
-7
View File
@@ -1,7 +0,0 @@
{
imports = [
./hardware-configuration.nix
./networking.nix
./disko.nix
];
}
@@ -1,3 +1,4 @@
{ ... }:
{
imports = [
./hardware-configuration.nix
+13 -3
View File
@@ -1,6 +1,7 @@
_:
let
espPart = "/dev/disk/by-partuuid/a53e3b19-67de-40de-9ded-3eac3117689a";
nixosPart = "/dev/disk/by-partuuid/311d0f9c-f35f-42e6-b6fc-a4d67dd21b2e";
btrfsMountOptions = [
@@ -23,7 +24,9 @@ in
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
mountOptions = [
"umask=0077"
];
};
};
@@ -35,8 +38,12 @@ in
content = {
type = "luks";
name = "cryptroot";
askPassword = true;
settings.allowDiscards = true;
settings = {
allowDiscards = true;
};
extraFormatArgs = [
"--type"
@@ -78,7 +85,10 @@ in
"@swap" = {
mountpoint = "/.swapvol";
mountOptions = [ "noatime" ];
mountOptions = [
"noatime"
];
swap.swapfile.size = "32G";
};
};
+3 -2
View File
@@ -1,5 +1,6 @@
# Do not modify this file! It was generated by `nixos-generate-config`
# and may be overwritten by future invocations. Make changes in nixos.nix.
# Do not modify this file! It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
-22
View File
@@ -1,22 +0,0 @@
{
services.kanshi = {
enable = true;
settings = [
{
profile = {
name = "x1g13";
outputs = [
{
criteria = "eDP-1";
status = "enable";
position = "0,0";
scale = 1.5;
}
];
};
}
];
};
}
-52
View File
@@ -1,52 +0,0 @@
# Do not modify this file! It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"xhci_pci"
"thunderbolt"
"nvme"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/16b29578-6836-414b-a5e1-863bc21c5fc3";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/209A-C8C9";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
-17
View File
@@ -1,17 +0,0 @@
{
inputs,
lib ? inputs.nixpkgs.lib,
root,
}:
let
registry = import ./registry.nix {
inherit inputs lib;
modulesRoot = root + "/modules";
};
hosts = import ./hosts.nix {
inherit inputs lib registry;
};
in
{
inherit hosts registry;
}
-191
View File
@@ -1,191 +0,0 @@
{
inputs,
lib,
registry,
}:
let
ensure =
condition: message: value:
if condition then value else throw "host registry: ${message}";
isLinux = system: lib.hasSuffix "-linux" system;
isDarwin = system: lib.hasSuffix "-darwin" system;
hostFile =
spec: name:
let
path = spec.path + "/${name}";
in
if builtins.pathExists path then path else null;
selectedUnits =
spec:
[ "users.${spec.user}" ]
++ map (name: "profiles.${name}") (spec.profiles or [ ])
++ map (name: "applications.${name}") (spec.applications or [ ])
++ (spec.units or [ ]);
validateSpec =
name: spec:
ensure (builtins.isAttrs spec) "${name}: host specification must be an attribute set" (
ensure (spec ? system && builtins.isString spec.system) "${name}: system is required" (
ensure (isLinux spec.system || isDarwin spec.system)
"${name}: unsupported system '${spec.system}'; expected a Linux NixOS or Darwin system"
(
ensure (spec ? user && builtins.isString spec.user && spec.user != "") "${name}: user is required" (
ensure (spec ? path && builtins.pathExists spec.path)
"${name}: path must name an existing host directory"
(
ensure
(
spec ? stateVersion
&& builtins.isString spec.stateVersion
&& builtins.match "[0-9][0-9]\\.[0-9][0-9]" spec.stateVersion != null
)
"${name}: stateVersion is required and must have the form YY.MM"
(
ensure
(lib.all
(field: builtins.isList (spec.${field} or [ ]) && lib.all builtins.isString (spec.${field} or [ ]))
[
"profiles"
"applications"
"units"
]
)
"${name}: profiles, applications, and units must be lists of strings"
(ensure (builtins.isBool (spec.homeManager or true)) "${name}: homeManager must be a boolean" spec)
)
)
)
)
)
);
mkSpecialArgs = name: spec: {
inherit inputs registry;
inherit (spec) system;
hostName = name;
primaryUser = spec.user;
};
mkHomeManagerModule =
name: spec: selected:
let
homePath = hostFile spec "home.nix";
homeModules = [
(registry.mkModule {
class = "home";
systemClass = "nixos";
})
(registry.mkSelectionModule selected)
{ home.stateVersion = spec.stateVersion; }
]
++ lib.optional (homePath != null) homePath;
in
{
imports = [ inputs.home-manager.nixosModules.home-manager ];
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = mkSpecialArgs name spec;
users.${spec.user}.imports = homeModules;
};
};
mkDarwinHomeManagerModule =
name: spec: selected:
let
homePath = hostFile spec "home.nix";
homeModules = [
(registry.mkModule {
class = "home";
systemClass = "darwin";
})
(registry.mkSelectionModule selected)
{ home.stateVersion = spec.stateVersion; }
]
++ lib.optional (homePath != null) homePath;
in
{
imports = [ inputs.home-manager.darwinModules.home-manager ];
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = mkSpecialArgs name spec;
users.${spec.user}.imports = homeModules;
};
};
mkNixos =
name: rawSpec:
let
spec = validateSpec name rawSpec;
selected = registry.validateUnitIds (selectedUnits spec);
nixosPath = hostFile spec "nixos.nix";
modules = [
(registry.mkModule { class = "nixos"; })
(registry.mkSelectionModule selected)
{
networking.hostName = lib.mkDefault name;
system.stateVersion = spec.stateVersion;
}
]
++ lib.optional (spec.homeManager or true) (mkHomeManagerModule name spec selected)
++ lib.optional (nixosPath != null) nixosPath;
in
inputs.nixpkgs.lib.nixosSystem {
inherit (spec) system;
specialArgs = mkSpecialArgs name spec;
inherit modules;
};
mkDarwin =
name: rawSpec:
let
spec = validateSpec name rawSpec;
selected = registry.validateUnitIds (selectedUnits spec);
darwinPath = hostFile spec "darwin.nix";
modules = [
(registry.mkModule { class = "darwin"; })
(registry.mkSelectionModule selected)
{
networking.hostName = lib.mkDefault name;
system.primaryUser = lib.mkDefault spec.user;
}
]
++ lib.optional (spec.homeManager or true) (mkDarwinHomeManagerModule name spec selected)
++ lib.optional (darwinPath != null) darwinPath;
in
ensure (inputs ? nix-darwin) "${name}: the nix-darwin input is required" (
inputs.nix-darwin.lib.darwinSystem {
inherit (spec) system;
specialArgs = mkSpecialArgs name spec;
inherit modules;
}
);
mkConfigurations =
hostSpecs:
let
validated = lib.mapAttrs validateSpec hostSpecs;
in
{
nixosConfigurations = lib.mapAttrs mkNixos (
lib.filterAttrs (_: spec: isLinux spec.system) validated
);
darwinConfigurations = lib.mapAttrs mkDarwin (
lib.filterAttrs (_: spec: isDarwin spec.system) validated
);
};
in
{
inherit
mkConfigurations
mkDarwin
mkNixos
selectedUnits
;
}
-386
View File
@@ -1,386 +0,0 @@
{
inputs,
lib,
modulesRoot,
}:
let
rootFragmentFiles = {
common = "common.nix";
nixos = "nixos.nix";
darwin = "darwin.nix";
home = "home.nix";
meta = "meta.nix";
};
homeFragmentFiles = {
homeCommon = "common.nix";
homeNixos = "nixos.nix";
homeDarwin = "darwin.nix";
};
fragmentFileNames = rootFragmentFiles // lib.mapAttrs (_: name: "home/${name}") homeFragmentFiles;
isFile = kind: kind == "regular" || kind == "symlink";
ensure =
condition: message: value:
if condition then value else throw "unit registry: ${message}";
callWithAvailableArgs =
value: availableArgs:
if builtins.isFunction value then
value (builtins.intersectAttrs (builtins.functionArgs value) availableArgs)
else
value;
pathFor =
relativePath:
if relativePath == [ ] then
modulesRoot
else
modulesRoot + "/${lib.concatStringsSep "/" relativePath}";
entryIsFile = entries: name: builtins.hasAttr name entries && isFile entries.${name};
normalizeMeta =
unit:
let
metaPath = unit.fragments.meta;
importedValue =
if metaPath == null then
{ }
else
callWithAvailableArgs (import metaPath) {
inherit inputs lib unit;
};
imported =
ensure (builtins.isAttrs importedValue) "${unit.id}: meta.nix must return an attribute set"
importedValue;
allowedKeys = [
"description"
"includes"
"imports"
];
unknownKeys = lib.filter (name: !(builtins.elem name allowedKeys)) (builtins.attrNames imported);
description = imported.description or null;
includes = imported.includes or [ ];
imports = imported.imports or { };
allowedImportKeys = [
"nixos"
"darwin"
"home"
];
unknownImportKeys =
if builtins.isAttrs imports then
lib.filter (name: !(builtins.elem name allowedImportKeys)) (builtins.attrNames imports)
else
[ ];
normalized = {
inherit description includes;
imports = {
nixos = imports.nixos or [ ];
darwin = imports.darwin or [ ];
home = imports.home or [ ];
};
};
in
ensure (unknownKeys == [ ])
"${unit.id}: meta.nix has unsupported keys: ${lib.concatStringsSep ", " unknownKeys}"
(
ensure (description == null || builtins.isString description)
"${unit.id}: meta.description must be a string"
(
ensure (builtins.isList includes && lib.all builtins.isString includes)
"${unit.id}: meta.includes must be a list of fully qualified unit IDs"
(
ensure (lib.unique includes == includes) "${unit.id}: meta.includes contains duplicate unit IDs" (
ensure (builtins.isAttrs imports) "${unit.id}: meta.imports must be an attribute set" (
ensure (unknownImportKeys == [ ])
"${unit.id}: meta.imports has unsupported classes: ${lib.concatStringsSep ", " unknownImportKeys}"
(
ensure (lib.all builtins.isList [
normalized.imports.nixos
normalized.imports.darwin
normalized.imports.home
]) "${unit.id}: every meta.imports.<class> value must be a list" normalized
)
)
)
)
)
);
makeUnit =
relativePath: entries: homeEntries:
let
directory = pathFor relativePath;
id = lib.concatStringsSep "." relativePath;
rootFragments = lib.mapAttrs (
_class: fileName: if entryIsFile entries fileName then directory + "/${fileName}" else null
) rootFragmentFiles;
homeFragments = lib.mapAttrs (
_class: fileName: if entryIsFile homeEntries fileName then directory + "/home/${fileName}" else null
) homeFragmentFiles;
fragments = rootFragments // homeFragments;
baseUnit = {
inherit
id
directory
fragments
relativePath
;
optionPath = [ "my" ] ++ relativePath ++ [ "enable" ];
kind = builtins.head relativePath;
name = lib.last relativePath;
}
//
lib.optionalAttrs (builtins.length relativePath > 2 && builtins.head relativePath == "profiles")
{
group = builtins.elemAt relativePath 1;
};
in
ensure (relativePath != [ ]) "the modules root cannot itself be a unit" (
ensure (lib.all (component: component != "" && !(lib.hasInfix "." component)) relativePath)
"${id}: path components must be non-empty and must not contain dots"
(baseUnit // { meta = normalizeMeta baseUnit; })
);
walk =
relativePath:
let
directory = pathFor relativePath;
entries = builtins.readDir directory;
homeEntries =
if relativePath != [ ] && (entries.home or null) == "directory" then
builtins.readDir (directory + "/home")
else
{ };
hasRootFragment = lib.any (fileName: entryIsFile entries fileName) (
builtins.attrValues rootFragmentFiles
);
hasHomeFragment = lib.any (fileName: entryIsFile homeEntries fileName) (
builtins.attrValues homeFragmentFiles
);
hasFragment = hasRootFragment || hasHomeFragment;
childDirectories = lib.filter (
name: entries.${name} == "directory" && !(name == "home" && hasHomeFragment)
) (builtins.attrNames entries);
current = lib.optional hasFragment (makeUnit relativePath entries homeEntries);
children = lib.concatMap (name: walk (relativePath ++ [ name ])) childDirectories;
in
current ++ children;
discoveredUnits =
ensure (builtins.pathExists modulesRoot) "modules root does not exist: ${toString modulesRoot}"
(walk [ ]);
unitsById = builtins.listToAttrs (map (unit: lib.nameValuePair unit.id unit) discoveredUnits);
dependencyValidation = lib.foldl' (
valid: unit:
lib.foldl' (
inner: includedId:
if builtins.hasAttr includedId unitsById then
inner
else
throw "unit registry: ${unit.id} includes missing unit '${includedId}'"
) valid unit.meta.includes
) true discoveredUnits;
units = builtins.seq dependencyValidation unitsById;
unitIds = builtins.attrNames units;
getUnit =
id: if builtins.hasAttr id units then units.${id} else throw "unit registry: unknown unit '${id}'";
validateUnitIds =
ids:
ensure (
builtins.isList ids && lib.all builtins.isString ids
) "selected units must be a list of strings" (map (id: builtins.seq (getUnit id) id) ids);
optionDefinitions = lib.foldl' lib.recursiveUpdate { } (
map (
unit:
lib.setAttrByPath unit.optionPath (
lib.mkOption {
type = lib.types.bool;
default = false;
description =
if unit.meta.description == null then
"Whether to enable the ${unit.id} unit."
else
"Whether to enable ${unit.meta.description}.";
}
)
) discoveredUnits
);
enabled = config: unit: lib.getAttrFromPath unit.optionPath config;
enableUnit = id: lib.setAttrByPath (getUnit id).optionPath true;
includeConfig =
config: unit: lib.mkIf (enabled config unit) (lib.mkMerge (map enableUnit unit.meta.includes));
fragmentClasses = {
nixos = [
"common"
"nixos"
];
darwin = [
"common"
"darwin"
];
home = {
nixos = [
"home"
"homeCommon"
"homeNixos"
];
darwin = [
"home"
"homeCommon"
"homeDarwin"
];
};
};
fragmentClassesFor =
{
class,
systemClass,
}:
ensure (builtins.hasAttr class fragmentClasses) "unsupported module class '${class}'" (
if class == "home" then
ensure
(builtins.elem systemClass [
"nixos"
"darwin"
])
"the home module class requires systemClass to be 'nixos' or 'darwin'"
fragmentClasses.home.${systemClass}
else
ensure (
systemClass == null
) "systemClass is only supported for the home module class" fragmentClasses.${class}
);
applyFragment =
{
config,
fragmentName,
fragmentPath,
options,
specialArgs,
unit,
}:
let
fragment = import fragmentPath;
directArgs = specialArgs // {
inherit
config
lib
options
specialArgs
unit
;
};
fragmentArgSpec = builtins.functionArgs fragment;
fragmentArgs = builtins.listToAttrs (
lib.concatMap (
name:
if builtins.hasAttr name directArgs then
[ (lib.nameValuePair name directArgs.${name}) ]
else if fragmentArgSpec.${name} then
[ ]
else
[ (lib.nameValuePair name config._module.args.${name}) ]
) (builtins.attrNames fragmentArgSpec)
);
resultValue = if builtins.isFunction fragment then fragment fragmentArgs else fragment;
result =
ensure (builtins.isAttrs resultValue) "${unit.id}: ${fragmentName} must return an attribute set"
resultValue;
forbiddenKeys = lib.filter (name: builtins.hasAttr name result) [
"imports"
"options"
"config"
];
in
ensure (forbiddenKeys == [ ])
"${unit.id}: ${fragmentName} is a configuration fragment and cannot define top-level ${lib.concatStringsSep ", " forbiddenKeys}"
result;
externalImports = class: lib.concatMap (unit: unit.meta.imports.${class}) discoveredUnits;
mkModule =
{
class,
systemClass ? null,
}:
let
selectedFragmentClasses = fragmentClassesFor { inherit class systemClass; };
in
builtins.seq selectedFragmentClasses (
builtins.seq dependencyValidation (
{
config,
lib,
options,
specialArgs,
...
}:
let
fragmentConfigs = lib.concatMap (
unit:
lib.filter (value: value != null) (
map (
fragmentClass:
let
fragmentName = fragmentFileNames.${fragmentClass};
fragmentPath = unit.fragments.${fragmentClass};
in
if fragmentPath == null then
null
else
lib.mkIf (enabled config unit) (applyFragment {
inherit
config
fragmentName
fragmentPath
options
specialArgs
unit
;
})
) selectedFragmentClasses
)
) discoveredUnits;
in
{
imports = externalImports class;
options = optionDefinitions;
config = lib.mkMerge ((map (includeConfig config) discoveredUnits) ++ fragmentConfigs);
}
)
);
mkSelectionModule =
selectedIds:
let
checkedIds = validateUnitIds (lib.unique selectedIds);
in
{
config = lib.mkMerge (map enableUnit checkedIds);
};
in
{
inherit
getUnit
mkModule
mkSelectionModule
unitIds
units
validateUnitIds
;
}
+26
View File
@@ -0,0 +1,26 @@
{
lib,
config,
...
}:
let
cfg = config.my.applications."1password";
in
{
options.my.applications."1password" = {
enable = lib.mkEnableOption "1Password password manager";
};
config = lib.mkIf cfg.enable {
programs._1password.enable = true;
programs._1password-gui = {
enable = true;
polkitPolicyOwners = [ "moons" ];
};
programs.ssh.startAgent = lib.mkForce false;
programs.gnupg.agent.enableSSHSupport = lib.mkForce false;
services.gnome.gcr-ssh-agent.enable = lib.mkForce false;
};
}
@@ -1,4 +0,0 @@
_: {
programs._1password-gui.enable = true;
programs._1password.enable = true;
}
-9
View File
@@ -1,9 +0,0 @@
{ primaryUser, lib, ... }:
{
programs._1password-gui.polkitPolicyOwners = [ primaryUser ];
# 1Password SSH Agentと競合するagentを無効化
programs.ssh.startAgent = lib.mkForce false;
programs.gnupg.agent.enableSSHSupport = lib.mkForce false;
services.gnome.gcr-ssh-agent.enable = lib.mkForce false;
}
@@ -1,8 +0,0 @@
{
homebrew.casks = [ "activitywatch" ];
launchd.agents.activitywatch = {
command = "/usr/bin/open -gja ActivityWatch";
serviceConfig.RunAtLoad = true;
};
}
@@ -1,11 +0,0 @@
{ pkgs, ... }:
{
services.activitywatch = {
enable = true;
watchers.aw-awatcher = {
package = pkgs.awatcher;
executable = "awatcher";
};
};
}
@@ -1,3 +0,0 @@
{
description = "ActivityWatch automated time tracker";
}
+29
View File
@@ -0,0 +1,29 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.arduino;
arduinoIdeX11 = pkgs.arduino-ide.overrideAttrs (old: {
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ pkgs.makeWrapper ];
postFixup = (old.postFixup or "") + ''
wrapProgram $out/bin/arduino-ide \
--add-flags "--ozone-platform=x11"
'';
});
in
{
options.my.applications.arduino = {
enable = lib.mkEnableOption "Arduino development tools";
};
config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; [
arduino-cli # Arduino command-line interface
arduinoIdeX11 # Arduino IDE with X11 support
];
};
}
-4
View File
@@ -1,4 +0,0 @@
{ pkgs, ... }:
{
home.packages = [ pkgs.arduino-cli ];
}
-14
View File
@@ -1,14 +0,0 @@
{ pkgs, ... }:
let
arduinoIdeX11 = pkgs.arduino-ide.overrideAttrs (old: {
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ pkgs.makeWrapper ];
postFixup = (old.postFixup or "") + ''
wrapProgram $out/bin/arduino-ide \
--add-flags "--ozone-platform=x11"
'';
});
in
{
environment.systemPackages = [ arduinoIdeX11 ];
}
-9
View File
@@ -1,9 +0,0 @@
{
programs.atuin = {
enable = true;
enableZshIntegration = true;
enableBashIntegration = true;
enableFishIntegration = true;
};
}
-4
View File
@@ -1,4 +0,0 @@
{ pkgs, ... }:
{
home.packages = [ pkgs.baobab ];
}
+23
View File
@@ -0,0 +1,23 @@
{
lib,
config,
...
}:
let
cfg = config.my.applications.btop;
in
{
imports = [
./home.nix
./system.nix
];
options.my.applications.btop = {
enable = lib.mkEnableOption "btop system monitor";
};
config = lib.mkIf cfg.enable {
my.applications.btop.system.enable = lib.mkDefault true;
my.applications.btop.homeManager.enable = lib.mkDefault true;
};
}
+3 -3
View File
@@ -1,5 +1,5 @@
# Bashtop theme with Nord palette (https://www.nordtheme.com)
# by Justin Zobel <[email protected]>
#Bashtop theme with nord palette (https://www.nordtheme.com)
#by Justin Zobel <[email protected]>
# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255"
# example for white: "#ffffff", "#ff" or "255 255 255".
@@ -18,7 +18,7 @@ theme[main_fg]="#BD93F9"
# Title color for boxes
theme[title]="#f8f8f2"
# Highlight color for keyboard shortcuts
# Higlight color for keyboard shortcuts
theme[hi_fg]="#ff79c6"
# Background color of selected item in processes box
+22 -5
View File
@@ -1,8 +1,25 @@
{
programs.btop = {
enable = true;
settings.color_theme = "dracula";
themes.dracula = builtins.readFile ./dracula.theme;
lib,
config,
...
}:
let
cfg = config.my.applications.btop.homeManager;
in
{
options.my.applications.btop.homeManager = {
enable = lib.mkEnableOption "btop home-manager configuration";
};
config.home-manager.sharedModules = [
{
config = lib.mkIf cfg.enable {
programs.btop = {
enable = true;
settings.color_theme = "dracula";
themes.dracula = builtins.readFile ./dracula.theme;
};
};
}
];
}
+20
View File
@@ -0,0 +1,20 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.btop.system;
in
{
options.my.applications.btop.system = {
enable = lib.mkEnableOption "btop system configuration";
};
config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; [
btop # Resource monitor that shows usage and stats
];
};
}
@@ -1,31 +0,0 @@
{ pkgs, ... }:
{
home.packages = [ pkgs.celluloid ];
xdg.mimeApps = {
enable = true;
defaultApplicationPackages = [ pkgs.celluloid ];
defaultApplications = builtins.listToAttrs (
map
(mime: {
name = mime;
value = [ "io.github.celluloid_player.Celluloid.desktop" ];
})
[
"video/3gpp"
"video/3gpp2"
"video/mp2t"
"video/mp4"
"video/mpeg"
"video/ogg"
"video/quicktime"
"video/webm"
"video/x-flv"
"video/x-m4v"
"video/x-matroska"
"video/x-msvideo"
"video/x-ms-wmv"
]
);
};
}
+44
View File
@@ -0,0 +1,44 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.chrome;
in
{
options.my.applications.chrome = {
enable = lib.mkEnableOption "Google Chrome browser";
};
config = lib.mkIf cfg.enable {
home-manager.sharedModules = [
{
home.packages = with pkgs; [
google-chrome # Popular web browser from Google
];
xdg.desktopEntries."google-chrome" = {
name = "Google Chrome";
genericName = "Web Browser";
exec = "${pkgs.google-chrome}/bin/google-chrome-stable --enable-features=TouchpadOverscrollHistoryNavigation %U";
terminal = false;
icon = "google-chrome";
categories = [
"Network"
"WebBrowser"
];
startupNotify = true;
type = "Application";
};
xdg.mimeApps.defaultApplications = {
"text/html" = "google-chrome.desktop";
"x-scheme-handler/http" = "google-chrome.desktop";
"x-scheme-handler/https" = "google-chrome.desktop";
};
}
];
};
}
-6
View File
@@ -1,6 +0,0 @@
{
homebrew = {
enable = true;
casks = [ "google-chrome" ];
};
}
@@ -1,47 +0,0 @@
{
config,
lib,
pkgs,
...
}:
let
chrome = pkgs.google-chrome.overrideAttrs (old: {
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ pkgs.makeWrapper ];
postFixup = (old.postFixup or "") + ''
wrapProgram $out/bin/google-chrome-stable \
--set LIBVA_DRIVER_NAME nvidia \
--set NVD_BACKEND direct
'';
});
features = [
"MiddleClickAutoscroll"
"AcceleratedVideoDecoder"
"AcceleratedVideoDecodeLinuxGL"
"PlatformHEVCDecoderSupport"
]
++ lib.optional config.my.hardwares.nvidia.enable "VaapiOnNvidiaGPUs";
in
{
programs.google-chrome = {
enable = true;
package = if config.my.hardwares.nvidia.enable then chrome else pkgs.google-chrome;
commandLineArgs = [
"--enable-features=${lib.concatStringsSep "," features}"
"--use-gl=angle"
"--use-angle=gl"
];
};
xdg.mimeApps = {
enable = true;
defaultApplications = {
"text/html" = "google-chrome.desktop";
"x-scheme-handler/http" = "google-chrome.desktop";
"x-scheme-handler/https" = "google-chrome.desktop";
};
};
}
+23
View File
@@ -0,0 +1,23 @@
{
lib,
config,
...
}:
let
cfg = config.my.applications.claude;
in
{
imports = [
./home.nix
./system.nix
];
options.my.applications.claude = {
enable = lib.mkEnableOption "Claude Code AI assistant";
};
config = lib.mkIf cfg.enable {
my.applications.claude.system.enable = lib.mkDefault true;
my.applications.claude.homeManager.enable = lib.mkDefault true;
};
}
+21 -12
View File
@@ -1,18 +1,27 @@
{
inputs,
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.claude.homeManager;
in
{
home.packages = [
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.claude-code
];
home.file.".claude/settings.json".text = builtins.toJSON {
statusLine = {
type = "command";
command = "bun x ccusage statusline --no-offline";
padding = 0;
};
options.my.applications.claude.homeManager = {
enable = lib.mkEnableOption "Claude Code home-manager configuration";
};
config.home-manager.sharedModules = [
{
config = lib.mkIf cfg.enable {
home.file.".claude/settings.json".text = builtins.toJSON {
statusLine = {
type = "command";
command = "bun x ccusage statusline --no-offline";
padding = 0;
};
};
};
}
];
}
+20
View File
@@ -0,0 +1,20 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.claude.system;
in
{
options.my.applications.claude.system = {
enable = lib.mkEnableOption "Claude Code system configuration";
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [
pkgs.llm-agents.claude-code # AI coding assistant
];
};
}
+65
View File
@@ -0,0 +1,65 @@
{
inputs,
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.codexDesktop;
codexCliPackage = pkgs.llm-agents.codex;
codexDesktopPackage =
inputs.codex-desktop-linux.packages.${pkgs.stdenv.hostPlatform.system}.codex-desktop-computer-use-ui;
codexDesktopLauncher = pkgs.makeDesktopItem {
name = "codex";
desktopName = "Codex";
genericName = "ChatGPT Desktop";
comment = "Run Codex Desktop on Linux";
exec = "env CODEX_CLI_PATH=${lib.getExe' codexCliPackage "codex"} BAMF_DESKTOP_FILE_HINT=codex.desktop CHROME_DESKTOP=codex.desktop ${lib.getExe' codexDesktopPackage "codex-desktop"} %u";
icon = "codex-desktop";
terminal = false;
categories = [ "Development" ];
keywords = [
"codex"
"chatgpt"
"openai"
"ai"
"assistant"
];
startupNotify = true;
startupWMClass = "codex-desktop";
actions = {
new-window = {
name = "New Window";
exec = "env CODEX_CLI_PATH=${lib.getExe' codexCliPackage "codex"} BAMF_DESKTOP_FILE_HINT=codex.desktop CHROME_DESKTOP=codex.desktop CODEX_MULTI_LAUNCH=1 ${lib.getExe' codexDesktopPackage "codex-desktop"} --new-instance";
};
};
extraConfig = {
X-GNOME-WMClass = "codex-desktop";
};
};
in
{
imports = [
inputs.codex-desktop-linux.nixosModules.default
];
options.my.applications.codexDesktop = {
enable = lib.mkEnableOption "ChatGPT Desktop for Linux";
};
config = lib.mkIf cfg.enable {
my.applications.codex.enable = true;
programs.codexDesktopLinux = {
enable = true;
package = codexDesktopPackage;
cliPackage = codexCliPackage;
computerUseUi.enable = true;
};
environment.systemPackages = [
codexDesktopLauncher # Vicinae-searchable Codex Desktop launcher alias
];
};
}
@@ -1,8 +0,0 @@
{
# The former Codex app cask is deprecated in favor of ChatGPT, whose desktop
# application includes the current Codex experience on macOS.
homebrew = {
enable = true;
casks = [ "chatgpt" ];
};
}
@@ -1,5 +0,0 @@
_: {
description = "Codex Desktop for Linux";
includes = [ "applications.codex" ];
}
@@ -1,10 +0,0 @@
{
inputs,
pkgs,
...
}:
{
environment.systemPackages = [
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.chatgpt
];
}
@@ -1,52 +0,0 @@
{
lib,
pkgs,
inputs,
...
}:
let
codexSessionUsage = inputs.codex-session-usage.packages.${pkgs.stdenv.hostPlatform.system}.default;
in
{
home.packages = [ codexSessionUsage ];
xdg.dataFile = {
"vicinae/scripts/codex-session-usage/start" = {
executable = true;
text = ''
#!${lib.getExe pkgs.bash}
# @vicinae.schemaVersion 1
# @vicinae.title Start Codex Session Usage
# @vicinae.description Start the local Codex session usage dashboard
# @vicinae.mode compact
# @vicinae.icon 📊
# @vicinae.argument1 { "type": "text", "placeholder": "Port (optional)", "optional": true }
if [[ -z "$1" ]]; then
exec ${lib.getExe codexSessionUsage} start
fi
if [[ "$1" =~ ^[0-9]+$ ]] && (( 10#$1 >= 1 && 10#$1 <= 65535 )); then
exec ${lib.getExe codexSessionUsage} start --port "$1"
fi
printf '%s\n' 'Port must be an integer between 1 and 65535.' >&2
exit 2
'';
};
"vicinae/scripts/codex-session-usage/stop" = {
executable = true;
text = ''
#!${lib.getExe pkgs.bash}
# @vicinae.schemaVersion 1
# @vicinae.title Stop Codex Session Usage
# @vicinae.description Stop the local Codex session usage dashboard
# @vicinae.mode compact
# @vicinae.icon 📊
exec ${lib.getExe codexSessionUsage} stop
'';
};
};
}
+20
View File
@@ -0,0 +1,20 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.codex;
in
{
options.my.applications.codex = {
enable = lib.mkEnableOption "Codex AI coding assistant";
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [
pkgs.llm-agents.codex # OpenAI Codex CLI
];
};
}
-13
View File
@@ -1,13 +0,0 @@
model = "gpt-5.6-sol"
model_reasoning_effort = "medium"
approval_policy = "on-request"
approvals_reviewer = "auto_review"
sandbox_mode = "workspace-write"
web_search = "cached"
[sandbox_workspace_write]
network_access = false
[projects."/home/moons/dotfiles"]
trust_level = "trusted"
-36
View File
@@ -1,36 +0,0 @@
{
config,
inputs,
lib,
pkgs,
...
}:
let
configDirectory =
if config.home.preferXdgDirectories then
"${config.xdg.configHome}/codex"
else
"${config.home.homeDirectory}/.codex";
configFile = "${configDirectory}/config.toml";
in
{
programs.codex = {
enable = true;
package = inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.codex;
skills = {
grilling = inputs.skills + "/skills/productivity/grilling";
};
};
# Keep the repository copy as an initial value. Codex may mutate the live
# file between activations; each Home Manager switch resets it from here.
home.activation.resetCodexConfig = {
after = [ "writeBoundary" ];
before = [ ];
data = ''
${pkgs.coreutils}/bin/mkdir -p ${lib.escapeShellArg configDirectory}
${pkgs.coreutils}/bin/install -m 0600 ${./config.toml} ${lib.escapeShellArg configFile}
'';
};
}
@@ -1,8 +0,0 @@
{ inputs, ... }:
{
description = "Container-based networking labs";
includes = [ "services.docker" ];
imports.nixos = [ inputs.containerlab.nixosModules.default ];
}
@@ -1,17 +0,0 @@
{
inputs,
pkgs,
primaryUser,
}:
{
programs.containerlab.enable = true;
users.users.${primaryUser}.extraGroups = [ "clab_admins" ];
programs.containerlab.package =
inputs.containerlab.packages.${pkgs.stdenv.hostPlatform.system}.default.overrideAttrs
(_old: {
vendorHash = "sha256-QIJDPSO/504oYSeHzCSmdt7CtU/P/v74oub2feDXWXY=";
});
}
@@ -1,22 +0,0 @@
{
inputs,
osConfig,
pkgs,
...
}:
let
unstable = import inputs.nixpkgs-unstable {
inherit (pkgs.stdenv.hostPlatform) system;
# Keep default CUDA targets so dependencies match the CUDA binary cache.
config = pkgs.config // {
cudaSupport = osConfig.my.hardwares.nvidia.enable;
};
};
in
{
home.packages = [
(unstable.darktable.override {
withAi = true;
})
];
}
+46
View File
@@ -0,0 +1,46 @@
{
imports = [
./1password.nix
./arduino.nix
./btop
./chrome.nix
./claude
./codex-desktop.nix
./codex.nix
./direnv.nix
./discord.nix
./docker.nix
./fcitx5
./ghostty
./git
./gnupg
./grok.nix
./gnome.nix
./greetd.nix
./ly
./gtk
./java
./kde.nix
./nautilus.nix
./nh.nix
./niri
./nix-index
./noctalia
./opencode.nix
./openssh.nix
./slack.nix
./ssh
./swayidle.nix
./swaylock
./tailscale.nix
./vicinae.nix
./vim
./vscode
./wayland.nix
./yazi.nix
./zellij
./zoom.nix
./zoxide.nix
./zsh
];
}
+16
View File
@@ -0,0 +1,16 @@
{ lib, config, ... }:
let
cfg = config.my.applications.direnv;
in
{
options.my.applications.direnv = {
enable = lib.mkEnableOption "direnv environment variable manager";
};
config = lib.mkIf cfg.enable {
programs.direnv = {
enable = true;
nix-direnv.enable = true;
};
};
}
-10
View File
@@ -1,10 +0,0 @@
{
programs.direnv = {
enable = true;
nix-direnv.enable = true;
config.global = {
warn_timeout = "10s";
};
};
}
+23
View File
@@ -0,0 +1,23 @@
{
lib,
config,
...
}:
let
cfg = config.my.applications.discord;
in
{
options.my.applications.discord = {
enable = lib.mkEnableOption "Discord (Vesktop)";
};
config = lib.mkIf cfg.enable {
home-manager.sharedModules = [
{
programs.vesktop = {
enable = true;
};
}
];
};
}
-108
View File
@@ -1,108 +0,0 @@
{
inputs,
pkgs,
...
}:
let
unstable = inputs.nixpkgs-unstable.legacyPackages.${pkgs.stdenv.hostPlatform.system};
in
{
programs.vesktop = {
enable = true;
package = unstable.vesktop;
settings = {
discordBranch = "stable";
hardwareAcceleration = true;
hardwareVideoAcceleration = true;
tray = true;
minimizeToTray = true;
# Discord Rich Presence
arRPC = true;
openLinksWithElectron = false;
# Keep WebRTC on the public interface selected by the default route.
# Secondary private interfaces can otherwise stall voice at DTLS.
webRTCIPHandlingPolicy = "default_public_interface_only";
spellCheckLanguages = [
"ja-JP"
"en-US"
];
};
vencord = {
useSystem = false;
settings = {
autoUpdate = true;
autoUpdateNotification = false;
useQuickCss = false;
cloud.settingsSync = false;
notifications = {
position = "bottom-right";
useNative = "not-focused";
timeout = 5000;
logLimit = 50;
};
plugins = {
# プライバシー・安全性
NoTrack.enabled = true;
ClearURLs.enabled = true;
# 設定・セッション
BetterSettings.enabled = true;
BetterSessions.enabled = true;
# 画像・添付ファイル
FixImagesQuality.enabled = true;
ImageZoom.enabled = true;
ViewIcons.enabled = true;
CopyFileContents.enabled = true;
# メッセージ操作
QuickReply.enabled = true;
SendTimestamps.enabled = true;
FullSearchContext.enabled = true;
MessageLinkEmbeds.enabled = true;
Unindent.enabled = true;
ValidReply.enabled = true;
# 通知・誤操作対策
ReadAllNotificationsButton.enabled = true;
NoReplyMention.enabled = true;
NotificationVolume.enabled = true;
# UI・パフォーマンス
NoTypingAnimation.enabled = true;
FavoriteEmojiFirst.enabled = true;
KeepCurrentChannel.enabled = true;
# サーバー・権限確認
PermissionsViewer.enabled = true;
MemberCount.enabled = true;
# ボイス・アクティビティ
CallTimer.enabled = true;
GameActivityToggle.enabled = true;
# Vesktop向け
WebKeybinds.enabled = true;
WebScreenShareFixes.enabled = true;
# Message history
MessageLogger.enabled = true;
ShowHiddenChannels.enabled = true;
};
};
};
};
}
+34
View File
@@ -0,0 +1,34 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.docker;
in
{
options.my.applications.docker = {
enable = lib.mkEnableOption "Docker container runtime";
};
config = lib.mkIf cfg.enable {
virtualisation.docker = {
enable = true;
autoPrune = {
enable = true;
dates = "weekly";
};
daemon.settings = {
ipv6 = true;
"fixed-cidr-v6" = "fd00:30::/64";
ip6tables = true;
};
};
environment.systemPackages = with pkgs; [
docker # Container runtime
oxker # Docker TUI Tool
];
};
}
-6
View File
@@ -1,6 +0,0 @@
{
homebrew = {
enable = true;
casks = [ "orbstack" ];
};
}
@@ -1,6 +0,0 @@
{ pkgs, ... }:
{
home.packages = [
pkgs.docker-client
];
}
@@ -1,6 +0,0 @@
{ pkgs, ... }:
{
home.packages = [
pkgs.oxker
];
}
-5
View File
@@ -1,5 +0,0 @@
{
description = "Docker command-line client and NixOS daemon";
includes = [ "services.docker" ];
}
-4
View File
@@ -1,4 +0,0 @@
{ pkgs, ... }:
{
home.packages = [ pkgs.drawio ];
}
@@ -1,4 +0,0 @@
{ pkgs, ... }:
{
home.packages = [ pkgs.easyeffects ];
}
+69
View File
@@ -0,0 +1,69 @@
[Hotkey]
# トリガーキーを押すたびに切り替える
EnumerateWithTriggerKeys=False
# 一時的に第1入力メソッドに切り替える
AltTriggerKeys=
# 切り替え時は第1入力メソッドをスキップする
EnumerateSkipFirst=False
# Time limit in milliseconds for triggering modifier key shortcuts
ModifierOnlyKeyTimeout=250
[Hotkey/TriggerKeys]
1=Zenkaku_Hankaku
[Hotkey/ActivateKeys]
0=Henkan
[Hotkey/DeactivateKeys]
0=Muhenkan
[Hotkey/PrevPage]
0=Up
[Hotkey/NextPage]
0=Down
[Hotkey/PrevCandidate]
0=Shift+Tab
[Hotkey/NextCandidate]
0=Tab
[Hotkey/TogglePreedit]
0=Control+Alt+P
[Behavior]
# デフォルトで有効にする
ActiveByDefault=False
# フォーカス時に状態をリセット
resetStateWhenFocusIn=No
# 入力状態を共有する
ShareInputState=No
# アプリケーションにプリエディットを表示する
PreeditEnabledByDefault=True
# 入力メソッドを切り替える際に入力メソッドの情報を表示する
ShowInputMethodInformation=True
# フォーカスを変更する際に入力メソッドの情報を表示する
showInputMethodInformationWhenFocusIn=False
# 入力メソッドの情報をコンパクトに表示する
CompactInputMethodInformation=True
# 第1入力メソッドの情報を表示する
ShowFirstInputMethodInformation=True
# デフォルトのページサイズ
DefaultPageSize=5
# XKB オプションより優先する
OverrideXkbOption=False
# カスタム XKB オプション
CustomXkbOption=
# Force Enabled Addons
EnabledAddons=
# Force Disabled Addons
DisabledAddons=
# Preload input method to be used by default
PreloadInputMethod=True
# パスワード欄に入力メソッドを許可する
AllowInputMethodForPassword=False
# パスワード入力時にプリエディットテキストを表示する
ShowPreeditForPassword=False
# ユーザーデータを保存する間隔(分)
AutoSavePeriod=30
+23
View File
@@ -0,0 +1,23 @@
{
lib,
config,
...
}:
let
cfg = config.my.applications.fcitx5;
in
{
imports = [
./home.nix
./system.nix
];
options.my.applications.fcitx5 = {
enable = lib.mkEnableOption "fcitx5 input method";
};
config = lib.mkIf cfg.enable {
my.applications.fcitx5.system.enable = lib.mkDefault true;
my.applications.fcitx5.homeManager.enable = lib.mkDefault true;
};
}
+24
View File
@@ -0,0 +1,24 @@
{
lib,
config,
...
}:
let
cfg = config.my.applications.fcitx5.homeManager;
in
{
options.my.applications.fcitx5.homeManager = {
enable = lib.mkEnableOption "fcitx5 home-manager configuration";
};
config.home-manager.sharedModules = [
{
config = lib.mkIf cfg.enable {
home.file.".config/fcitx5/config" = {
recursive = true;
source = ./config;
};
};
}
];
}
@@ -1,82 +0,0 @@
{ inputs, pkgs, ... }:
{
services.hazkey = {
enable = true;
server.package =
inputs.nix-hazkey.packages.${pkgs.stdenv.hostPlatform.system}.hazkey-server.override
{ enableVulkan = true; };
};
i18n.inputMethod = {
enable = true;
type = "fcitx5";
fcitx5 = {
waylandFrontend = true;
addons = with pkgs; [
fcitx5-gtk
kdePackages.fcitx5-qt
qt6Packages.fcitx5-configtool
];
settings = {
inputMethod = {
GroupOrder."0" = "Default";
"Groups/0" = {
Name = "Default";
"Default Layout" = "jp";
DefaultIM = "hazkey";
};
"Groups/0/Items/0" = {
Name = "keyboard-jp";
};
"Groups/0/Items/1" = {
Name = "hazkey";
};
};
globalOptions = {
Hotkey = {
EnumerateWithTriggerKeys = false;
EnumerateSkipFirst = false;
ModifierOnlyKeyTimeout = 250;
};
"Hotkey/TriggerKeys"."1" = "Zenkaku_Hankaku";
"Hotkey/ActivateKeys"."0" = "Henkan";
"Hotkey/DeactivateKeys"."0" = "Muhenkan";
"Hotkey/PrevPage"."0" = "Up";
"Hotkey/NextPage"."0" = "Down";
"Hotkey/PrevCandidate"."0" = "Shift+Tab";
"Hotkey/NextCandidate"."0" = "Tab";
"Hotkey/TogglePreedit"."0" = "Control+Alt+P";
Behavior = {
ActiveByDefault = false;
resetStateWhenFocusIn = "No";
ShareInputState = "No";
PreeditEnabledByDefault = true;
ShowInputMethodInformation = true;
showInputMethodInformationWhenFocusIn = false;
CompactInputMethodInformation = true;
ShowFirstInputMethodInformation = true;
DefaultPageSize = 5;
OverrideXkbOption = false;
CustomXkbOption = "";
EnabledAddons = "";
DisabledAddons = "";
PreloadInputMethod = true;
AllowInputMethodForPassword = false;
ShowPreeditForPassword = false;
AutoSavePeriod = 30;
};
};
};
};
};
}
-6
View File
@@ -1,6 +0,0 @@
{ inputs, ... }:
{
description = "Fcitx 5 input method framework with Hazkey Japanese input";
imports.home = [ inputs.nix-hazkey.homeModules.hazkey ];
}

Some files were not shown because too many files have changed in this diff Show More