mirror of
https://github.com/moons-14/dotfiles.git
synced 2026-10-06 05:48:12 +09:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2ee175609 | ||
|
|
66bf009afd |
@@ -351,7 +351,6 @@ modules/profiles/
|
|||||||
├── base/
|
├── base/
|
||||||
├── interface/
|
├── interface/
|
||||||
│ ├── cli/
|
│ ├── cli/
|
||||||
│ ├── minimal/
|
|
||||||
│ ├── gui/
|
│ ├── gui/
|
||||||
│ ├── macos/
|
│ ├── macos/
|
||||||
│ ├── linux-desktop/
|
│ ├── linux-desktop/
|
||||||
@@ -368,14 +367,8 @@ modules/profiles/
|
|||||||
│ ├── desktop/
|
│ ├── desktop/
|
||||||
│ └── vm/
|
│ └── vm/
|
||||||
├── workload/
|
├── workload/
|
||||||
│ ├── camera/
|
|
||||||
│ ├── deploy-rs-target/
|
|
||||||
│ ├── development/
|
│ ├── development/
|
||||||
│ ├── game/
|
|
||||||
│ ├── machine-learning/
|
|
||||||
│ ├── network-lab/
|
|
||||||
│ ├── personal/
|
│ ├── personal/
|
||||||
│ ├── photography/
|
|
||||||
│ ├── server/
|
│ ├── server/
|
||||||
│ └── remote-access/
|
│ └── remote-access/
|
||||||
└── security/
|
└── security/
|
||||||
@@ -396,21 +389,16 @@ The profile layers have these responsibilities:
|
|||||||
- `base` contains only invariants required by every supported host. It includes
|
- `base` contains only invariants required by every supported host. It includes
|
||||||
`systems.nix` and the universal Atuin, tealdeer, trippy, and xh CLI tools;
|
`systems.nix` and the universal Atuin, tealdeer, trippy, and xh CLI tools;
|
||||||
optional secrets, interface, hardware, and workloads do not belong there.
|
optional secrets, interface, hardware, and workloads do not belong there.
|
||||||
- `interface` describes how the host is operated. `interface.minimal` is shared
|
- `interface` describes how the host is operated. `interface.cli` is shared by
|
||||||
by NixOS and macOS and provides the remote-administration CLI baseline,
|
NixOS and macOS and includes `tio`. `interface.gui` owns cross-platform
|
||||||
including SSH, Nano, htop, Git, Zellij, and Zsh. `interface.cli` includes that
|
graphical interface applications such as Vicinae. `interface.macos` owns the
|
||||||
baseline and adds the full interactive command-line environment, including
|
macOS Finder, Dock, trackpad, and shared default preferences and includes
|
||||||
the configured Neovim, Yazi, and `tio`. `interface.gui` owns
|
`interface.gui`.
|
||||||
cross-platform graphical interface applications such as Vicinae.
|
|
||||||
`interface.macos` owns the macOS Finder, Dock, trackpad, and shared default
|
|
||||||
preferences and includes `interface.gui`.
|
|
||||||
`interface.linux-desktop` owns the common labwc/niri desktop selection,
|
`interface.linux-desktop` owns the common labwc/niri desktop selection,
|
||||||
including Ghostty and Nautilus, and also includes `interface.gui`. Labwc and
|
including Ghostty and Nautilus, and also includes `interface.gui`. Labwc and
|
||||||
niri remain independently selectable and do not imply CLI or personal
|
niri remain independently selectable and do not imply CLI or personal
|
||||||
workloads.
|
workloads.
|
||||||
- `platform` describes NixOS foundations and physical or virtual form factors.
|
- `platform` describes NixOS foundations and physical or virtual form factors.
|
||||||
`platform.nixos` selects the shared network foundation and `services.clatd`;
|
|
||||||
VM, laptop, and desktop platform profiles inherit both.
|
|
||||||
macOS does not need an empty symmetric platform profile.
|
macOS does not need an empty symmetric platform profile.
|
||||||
- `workload` describes optional host uses. `workload.development` and
|
- `workload` describes optional host uses. `workload.development` and
|
||||||
`workload.personal` are cross-platform profiles, not `*-linux` variants.
|
`workload.personal` are cross-platform profiles, not `*-linux` variants.
|
||||||
@@ -550,26 +538,9 @@ A host registry may use a specification like this:
|
|||||||
|
|
||||||
profiles = [
|
profiles = [
|
||||||
"base"
|
"base"
|
||||||
"interface.minimal"
|
"interface.cli"
|
||||||
"platform.vm"
|
"platform.vm"
|
||||||
"workload.remote-access"
|
"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"
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -581,7 +552,7 @@ A host registry may use a specification like this:
|
|||||||
|
|
||||||
profiles = [
|
profiles = [
|
||||||
"base"
|
"base"
|
||||||
"interface.minimal"
|
"interface.cli"
|
||||||
"platform.vm"
|
"platform.vm"
|
||||||
"workload.server"
|
"workload.server"
|
||||||
];
|
];
|
||||||
@@ -631,9 +602,7 @@ A host registry may use a specification like this:
|
|||||||
"security.secrets"
|
"security.secrets"
|
||||||
"security.secure-boot"
|
"security.secure-boot"
|
||||||
"security.tpm-storage"
|
"security.tpm-storage"
|
||||||
"workload.camera"
|
|
||||||
"workload.development"
|
"workload.development"
|
||||||
"workload.network-lab"
|
|
||||||
"workload.personal"
|
"workload.personal"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
@@ -655,10 +624,7 @@ A host registry may use a specification like this:
|
|||||||
"security.tpm-storage"
|
"security.tpm-storage"
|
||||||
"workload.development"
|
"workload.development"
|
||||||
"workload.game"
|
"workload.game"
|
||||||
"workload.machine-learning"
|
|
||||||
"workload.network-lab"
|
|
||||||
"workload.personal"
|
"workload.personal"
|
||||||
"workload.photography"
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -681,22 +647,14 @@ A host registry may use a specification like this:
|
|||||||
```
|
```
|
||||||
|
|
||||||
The current role assignment is intentional: nix-example is the development VM;
|
The current role assignment is intentional: nix-example is the development VM;
|
||||||
ops is the minimal-interface remote-access VM with host-specific static
|
ops is the remote-access VM with host-specific static networking;
|
||||||
networking; netsrv-01 is the deploy-rs-managed container server VM;
|
internal-app-01 is the container server VM; and installer builds the minimal
|
||||||
internal-app-01 is the minimal-interface container server VM;
|
installation ISO without Home Manager. x1g9 is a full NixOS desktop with niri,
|
||||||
nix-builder is the minimal-interface remote Nix build VM with dedicated build
|
|
||||||
and store disks; and installer builds the minimal installation ISO without Home
|
|
||||||
Manager. x1g9 is a full NixOS desktop with niri,
|
|
||||||
labwc, ly, the shared Linux desktop applications, and the personal workload.
|
labwc, ly, the shared Linux desktop applications, and the personal workload.
|
||||||
x1g13 is the secure NixOS development and personal ThinkPad, with the same
|
x1g13 is the secure NixOS development and personal ThinkPad, with the same
|
||||||
desktop sessions plus Tailscale client, SOPS, Secure Boot, and TPM-backed disk
|
desktop sessions plus Tailscale client, SOPS, Secure Boot, and TPM-backed disk
|
||||||
unlock. galleria is the Intel/NVIDIA physical desktop shared with Windows; it
|
unlock. galleria is the Intel/NVIDIA physical desktop shared with Windows; it
|
||||||
uses dedicated NixOS partitions, LUKS, Secure Boot, and TPM-backed disk unlock.
|
uses dedicated NixOS partitions, LUKS, Secure Boot, and TPM-backed disk unlock.
|
||||||
It selects `workload.photography` for AI-enabled darktable. The application
|
|
||||||
chooses CUDA support from the NVIDIA hardware unit's enable state and keeps
|
|
||||||
the default CUDA targets, including RTX 3060 Ti support, to reuse binary caches.
|
|
||||||
galleria and x1g13 select `workload.network-lab` for containerlab, Docker, and
|
|
||||||
the NanoKVM-USB desktop client with serial-port access.
|
|
||||||
m2 is the daily-use macOS development and personal machine with the macOS
|
m2 is the daily-use macOS development and personal machine with the macOS
|
||||||
interface defaults. Keep the desktop sessions independently selectable, and
|
interface defaults. Keep the desktop sessions independently selectable, and
|
||||||
keep the development and personal profiles usable across NixOS and Darwin.
|
keep the development and personal profiles usable across NixOS and Darwin.
|
||||||
@@ -729,15 +687,6 @@ configuration fragments. For example:
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
hosts/
|
hosts/
|
||||||
├── nix-builder/
|
|
||||||
│ ├── disko.nix
|
|
||||||
│ ├── hardware-configuration.nix
|
|
||||||
│ └── nixos.nix
|
|
||||||
├── netsrv-01/
|
|
||||||
│ ├── disko.nix
|
|
||||||
│ ├── hardware-configuration.nix
|
|
||||||
│ ├── networking.nix
|
|
||||||
│ └── nixos.nix
|
|
||||||
├── installer/
|
├── installer/
|
||||||
│ └── nixos.nix
|
│ └── nixos.nix
|
||||||
├── internal-app-01/
|
├── internal-app-01/
|
||||||
@@ -767,15 +716,12 @@ hosts/
|
|||||||
```
|
```
|
||||||
|
|
||||||
`hosts/x1g9/nixos.nix` explicitly loads `hardware-configuration.nix` with the
|
`hosts/x1g9/nixos.nix` explicitly loads `hardware-configuration.nix` with the
|
||||||
normal top-level Nix module `imports`. `hosts/nix-builder/nixos.nix` and
|
normal top-level Nix module `imports`. `hosts/x1g13/nixos.nix` loads its
|
||||||
`hosts/x1g13/nixos.nix` load their generated hardware configuration and
|
generated hardware configuration and host-local `disko.nix` the same way. Do
|
||||||
host-local `disko.nix` the same way. The nix-builder Disko definition mounts its
|
not confuse these host imports with the prohibition on top-level `imports` in
|
||||||
existing VM filesystems by stable QEMU SCSI IDs and does not take destructive
|
unit configuration fragments. `hosts/galleria/disko.nix` manages only the two
|
||||||
ownership of them. Do not confuse these host imports with the prohibition on
|
dedicated NixOS partitions by PARTUUID and deliberately excludes the Windows
|
||||||
top-level `imports` in unit configuration fragments. `hosts/galleria/disko.nix`
|
disk, Windows partitions, and the Windows EFI System Partition.
|
||||||
manages only the two dedicated NixOS partitions by PARTUUID and deliberately
|
|
||||||
excludes the Windows disk, Windows partitions, and the Windows EFI System
|
|
||||||
Partition.
|
|
||||||
|
|
||||||
Derive the system class from the host's `system`:
|
Derive the system class from the host's `system`:
|
||||||
|
|
||||||
@@ -878,9 +824,8 @@ For profile changes, additionally:
|
|||||||
`homebrew.casks` selection as well as module evaluation.
|
`homebrew.casks` selection as well as module evaluation.
|
||||||
- Preserve the intended host roles: nix-example remains the development VM;
|
- Preserve the intended host roles: nix-example remains the development VM;
|
||||||
ops remains the statically networked remote-access VM; internal-app-01 remains
|
ops remains the statically networked remote-access VM; internal-app-01 remains
|
||||||
the container server VM; netsrv-01 remains the deploy-rs-managed container
|
the container server VM; installer remains the Home Manager-free installation
|
||||||
server VM; installer remains the Home Manager-free installation ISO; x1g9
|
ISO; x1g9 provides niri, labwc, ly, and the personal application set; x1g13
|
||||||
provides niri, labwc, ly, and the personal application set; x1g13
|
|
||||||
additionally provides the development, Tailscale client, secrets, Secure Boot,
|
additionally provides the development, Tailscale client, secrets, Secure Boot,
|
||||||
and TPM storage roles; galleria remains the Intel/NVIDIA dual-boot desktop
|
and TPM storage roles; galleria remains the Intel/NVIDIA dual-boot desktop
|
||||||
with LUKS, Secure Boot, and TPM storage; m2 remains the daily-use development
|
with LUKS, Secure Boot, and TPM storage; m2 remains the daily-use development
|
||||||
|
|||||||
@@ -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
@@ -1,10 +1,4 @@
|
|||||||
# NixOSインストール手順(SOPS・ディスク暗号化あり)
|
# NixOSインストール手順
|
||||||
|
|
||||||
この手順は、SOPSによるシークレット管理とLUKSによるディスク暗号化を
|
|
||||||
使用するホスト向けである。
|
|
||||||
|
|
||||||
どちらも使用しない場合は、
|
|
||||||
[SOPSなし・ディスク暗号化なしの手順](install-simple.md)を参照。
|
|
||||||
|
|
||||||
## 事前準備
|
## 事前準備
|
||||||
|
|
||||||
@@ -89,36 +83,54 @@ sops updatekeys secrets/hosts/<hostname>/*.yaml
|
|||||||
|
|
||||||
新しいホスト用の`hosts/<hostname>/disko.nix`を作成。
|
新しいホスト用の`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. ディスクのパーティション
|
### 7. ディスクのパーティション
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd ~/dotfiles
|
cd ~/dotfiles
|
||||||
disko --mode destroy,format,mount hosts/<hostname>/disko.nix
|
nix run github:nix-community/disko -- --mode disko hosts/<hostname>/disko.nix
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8. ハードウェア設定の生成
|
### 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. ホストキーのコピー
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir -p /mnt/etc/ssh
|
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
|
chmod 600 /mnt/etc/ssh/ssh_host_ed25519_key
|
||||||
```
|
```
|
||||||
|
|
||||||
### 10. NixOSインストール
|
### 9. NixOSインストール
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
nixos-install --flake ~/dotfiles#<hostname>
|
nixos-install --flake ~/dotfiles#<hostname>
|
||||||
```
|
```
|
||||||
|
|
||||||
### 11. 再起動
|
### 10. 再起動
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
reboot
|
reboot
|
||||||
|
|||||||
@@ -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
@@ -1,86 +1,26 @@
|
|||||||
# カスタムインストーラー ISO
|
# カスタムISOビルド
|
||||||
|
|
||||||
`hosts/installer` から、NixOS 26.05 ベースの `x86_64-linux` 用インストーラー
|
|
||||||
ISO を作成する。installer ホストは Home Manager を使用せず、`base` プロファイルと
|
|
||||||
ホスト固有のインストール支援設定だけを含む。
|
|
||||||
|
|
||||||
## ビルド
|
## ビルド
|
||||||
|
|
||||||
flake 対応の Nix が利用できる環境で、リポジトリのルートから実行する。
|
|
||||||
`x86_64-linux` 以外のマシンで実行する場合は、対応する Linux リモートビルダーが
|
|
||||||
必要になる。
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
nix build .#nixosConfigurations.installer.config.system.build.isoImage
|
nix build .#nixosConfigurations.installer.config.system.build.isoImage
|
||||||
```
|
```
|
||||||
|
|
||||||
生成された ISO は次の場所にある。
|
## ISO書き込み
|
||||||
|
|
||||||
```text
|
|
||||||
result/iso/nixos-minimal-*-x86_64-linux.iso
|
|
||||||
```
|
|
||||||
|
|
||||||
ファイル名に含まれる NixOS のバージョンとリビジョンは、`flake.lock` の更新に応じて
|
|
||||||
変わる。生成物を確認するには次を実行する。
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ls -lh result/iso/*.iso
|
# USBデバイスの確認
|
||||||
sha256sum result/iso/*.iso
|
lsblk
|
||||||
```
|
|
||||||
|
|
||||||
## USB メモリへの書き込み
|
# 書き込み(/dev/sdXは実際のデバイスに置き換える)
|
||||||
|
sudo dd if=./result/nixos-minimal-*.iso of=/dev/sdX bs=4M status=progress
|
||||||
書き込み先はパーティション(例: `/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
|
|
||||||
sync
|
sync
|
||||||
```
|
```
|
||||||
|
|
||||||
書き込み完了後、USB を安全に取り外して対象マシンから起動する。
|
## ISOの特徴
|
||||||
|
|
||||||
## 起動後の接続
|
- SSH鍵認証でrootログイン可能
|
||||||
|
- 有線LANはDHCPで自動設定
|
||||||
有線 LAN は DHCP で自動設定される。Wi-Fi を使用する場合は、インストーラーの
|
- WiFiは`nmcli`で手動設定可能
|
||||||
コンソールで NetworkManager を使って接続する。
|
- disko/sops/ageなどのツールを内蔵
|
||||||
|
- ブート時にIPアドレスとヘルプを表示
|
||||||
```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`
|
|
||||||
|
|||||||
Generated
+306
-627
File diff suppressed because it is too large
Load Diff
@@ -38,6 +38,12 @@
|
|||||||
url = "github:ghostty-org/ghostty";
|
url = "github:ghostty-org/ghostty";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Speech to text
|
||||||
|
handy = {
|
||||||
|
url = "github:cjpais/Handy";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
# Shell / Launcher
|
# Shell / Launcher
|
||||||
vicinae.url = "github:vicinaehq/vicinae";
|
vicinae.url = "github:vicinaehq/vicinae";
|
||||||
|
|
||||||
@@ -91,13 +97,6 @@
|
|||||||
url = "github:ilysenko/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;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Index / Search
|
# Index / Search
|
||||||
nix-index-database = {
|
nix-index-database = {
|
||||||
url = "github:nix-community/nix-index-database";
|
url = "github:nix-community/nix-index-database";
|
||||||
@@ -114,7 +113,6 @@
|
|||||||
|
|
||||||
nani-translate-linux.url = "git+https://github.com/zunoser/nani-translate-linux.git";
|
nani-translate-linux.url = "git+https://github.com/zunoser/nani-translate-linux.git";
|
||||||
|
|
||||||
containerlab.url = "github:srl-labs/containerlab";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs =
|
outputs =
|
||||||
|
|||||||
+8
-17
@@ -1,14 +1,15 @@
|
|||||||
{
|
{
|
||||||
nix-builder = {
|
nix-example = {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
stateVersion = "26.05";
|
stateVersion = "26.05";
|
||||||
user = "moons";
|
user = "moons";
|
||||||
path = ./nix-builder;
|
path = ./nix-example;
|
||||||
|
|
||||||
profiles = [
|
profiles = [
|
||||||
"base"
|
"base"
|
||||||
"interface.minimal"
|
"interface.cli"
|
||||||
"platform.vm"
|
"platform.vm"
|
||||||
|
"workload.development"
|
||||||
"workload.remote-access"
|
"workload.remote-access"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
@@ -21,25 +22,22 @@
|
|||||||
|
|
||||||
profiles = [
|
profiles = [
|
||||||
"base"
|
"base"
|
||||||
"interface.minimal"
|
"interface.cli"
|
||||||
"platform.vm"
|
"platform.vm"
|
||||||
"workload.remote-access"
|
"workload.remote-access"
|
||||||
"workload.deploy-rs-target"
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
netsrv-01 = {
|
internal-app-01 = {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
stateVersion = "26.05";
|
stateVersion = "26.05";
|
||||||
user = "moons";
|
user = "moons";
|
||||||
path = ./netsrv-01;
|
path = ./internal-app-01;
|
||||||
|
|
||||||
profiles = [
|
profiles = [
|
||||||
"base"
|
"base"
|
||||||
"interface.minimal"
|
"interface.cli"
|
||||||
"platform.vm"
|
"platform.vm"
|
||||||
"workload.remote-access"
|
|
||||||
"workload.deploy-rs-target"
|
|
||||||
"workload.server"
|
"workload.server"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
@@ -91,10 +89,8 @@
|
|||||||
"security.tpm-storage"
|
"security.tpm-storage"
|
||||||
"workload.development"
|
"workload.development"
|
||||||
"workload.game"
|
"workload.game"
|
||||||
"workload.network-lab"
|
|
||||||
"workload.personal"
|
"workload.personal"
|
||||||
];
|
];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
galleria = {
|
galleria = {
|
||||||
@@ -108,7 +104,6 @@
|
|||||||
"interface.cli"
|
"interface.cli"
|
||||||
"interface.labwc"
|
"interface.labwc"
|
||||||
"interface.niri"
|
"interface.niri"
|
||||||
"networking.tailscale-client"
|
|
||||||
"platform.intel-nvidia-desktop"
|
"platform.intel-nvidia-desktop"
|
||||||
"security.secrets"
|
"security.secrets"
|
||||||
"security.secure-boot"
|
"security.secure-boot"
|
||||||
@@ -116,11 +111,7 @@
|
|||||||
"security.fingerprint"
|
"security.fingerprint"
|
||||||
"workload.development"
|
"workload.development"
|
||||||
"workload.game"
|
"workload.game"
|
||||||
"workload.machine-learning"
|
|
||||||
"workload.network-lab"
|
|
||||||
"workload.personal"
|
"workload.personal"
|
||||||
"workload.photography"
|
|
||||||
"workload.camera"
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,6 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
# This desktop is permanently connected to AC power.
|
|
||||||
systemd.user.services.swayidle.Service.Environment = [
|
|
||||||
"SWAYIDLE_ASSUME_AC=1"
|
|
||||||
];
|
|
||||||
|
|
||||||
services.kanshi = {
|
services.kanshi = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,6 @@
|
|||||||
boot.initrd.luks.devices.cryptroot.device =
|
boot.initrd.luks.devices.cryptroot.device =
|
||||||
"/dev/disk/by-partuuid/04295552-cbb8-4511-ac1e-1171ec20f8d1";
|
"/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}; [
|
environment.systemPackages = with inputs.browser-previews.packages.${pkgs.system}; [
|
||||||
google-chrome-beta
|
google-chrome-beta
|
||||||
];
|
];
|
||||||
|
|||||||
+24
-19
@@ -31,7 +31,6 @@
|
|||||||
users.users.root.openssh.authorizedKeys.keys = [
|
users.users.root.openssh.authorizedKeys.keys = [
|
||||||
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIKhxDkucmeCor6CKoXAua7DgDSzuXrZOtpdkyzQxz5+aAAAABHNzaDo= moons@moons14.com"
|
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIKhxDkucmeCor6CKoXAua7DgDSzuXrZOtpdkyzQxz5+aAAAABHNzaDo= moons@moons14.com"
|
||||||
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIN6hZJyng/5LgFKPjR6uZAd/00UkO0vN0uQOoIvfSELdAAAABHNzaDo= moons@moons14.com"
|
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIN6hZJyng/5LgFKPjR6uZAd/00UkO0vN0uQOoIvfSELdAAAABHNzaDo= moons@moons14.com"
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLwReAiwhXoO34S2+MrvqUhi8IWp4IzUq4OSp3niJdq"
|
|
||||||
];
|
];
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
@@ -76,12 +75,6 @@
|
|||||||
║ ║
|
║ ║
|
||||||
║ Installation Workflow: ║
|
║ 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: ║
|
║ 1. Clone dotfiles: ║
|
||||||
║ git clone git@github.com:moons-14/dotfiles.git ~/dotfiles║
|
║ git clone git@github.com:moons-14/dotfiles.git ~/dotfiles║
|
||||||
║ ║
|
║ ║
|
||||||
@@ -109,25 +102,37 @@
|
|||||||
║ # See hosts/x1g13/disko.nix for reference ║
|
║ # See hosts/x1g13/disko.nix for reference ║
|
||||||
║ ║
|
║ ║
|
||||||
║ 7. Partition disk with disko: ║
|
║ 7. Partition disk with disko: ║
|
||||||
║ disko --mode destroy,format,mount \ ║
|
║ nix run github:nix-community/disko -- \ ║
|
||||||
║ hosts/<host>/disko.nix ║
|
║ --mode disko hosts/<host>/disko.nix ║
|
||||||
║ ║
|
║ ║
|
||||||
║ 8. Generate hardware configuration: ║
|
║ 8. Copy host key to installed system: ║
|
||||||
║ 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: ║
|
|
||||||
║ mkdir -p /mnt/etc/ssh ║
|
║ mkdir -p /mnt/etc/ssh ║
|
||||||
║ cp /tmp/ssh_host_ed25519_key* /mnt/etc/ssh/ ║
|
║ cp /tmp/ssh_host_ed25519_key* /mnt/etc/ssh/ ║
|
||||||
║ chmod 600 /mnt/etc/ssh/ssh_host_ed25519_key ║
|
║ chmod 600 /mnt/etc/ssh/ssh_host_ed25519_key ║
|
||||||
║ ║
|
║ ║
|
||||||
║ 10. Install NixOS: ║
|
║ 9. Install NixOS: ║
|
||||||
║ nixos-install --flake ~/dotfiles#<host> ║
|
║ 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 ║
|
║ - Use partuuid for device path ║
|
||||||
║ - Set askPassword = true for LUKS ║
|
║ - Set askPassword = true for LUKS ║
|
||||||
║ - Configure btrfs subvolumes ║
|
║ - Configure btrfs subvolumes ║
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# Do not modify this file! It was generated by `nixos-generate-config` and may
|
||||||
|
# be overwritten by future invocations.
|
||||||
|
{ 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/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";
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
imports = [ ./hardware-configuration.nix ];
|
||||||
|
}
|
||||||
@@ -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";
|
|
||||||
}
|
|
||||||
@@ -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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
imports = [
|
|
||||||
./hardware-configuration.nix
|
|
||||||
./disko.nix
|
|
||||||
./networking.nix
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,26 +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.
|
|
||||||
{ 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 = [ ];
|
|
||||||
|
|
||||||
swapDevices = [ ];
|
|
||||||
|
|
||||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
imports = [
|
|
||||||
./fleet-automation.nix
|
|
||||||
./disko.nix
|
|
||||||
./hardware-configuration.nix
|
|
||||||
./harmonia.nix
|
|
||||||
./networking.nix
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# Do not modify this file! It was generated by `nixos-generate-config` and may
|
||||||
|
# be overwritten by future invocations.
|
||||||
|
{ 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";
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
imports = [ ./hardware-configuration.nix ];
|
||||||
|
}
|
||||||
@@ -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,16 +1,8 @@
|
|||||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
# Do not modify this file! It was generated by `nixos-generate-config` and may
|
||||||
# and may be overwritten by future invocations. Please make changes
|
# be overwritten by future invocations.
|
||||||
# to /etc/nixos/configuration.nix instead.
|
{ lib, modulesPath, ... }:
|
||||||
{
|
{
|
||||||
lib,
|
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
|
||||||
modulesPath,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
(modulesPath + "/profiles/qemu-guest.nix")
|
|
||||||
];
|
|
||||||
|
|
||||||
boot.initrd.availableKernelModules = [
|
boot.initrd.availableKernelModules = [
|
||||||
"ata_piix"
|
"ata_piix"
|
||||||
@@ -24,5 +16,21 @@
|
|||||||
boot.kernelModules = [ ];
|
boot.kernelModules = [ ];
|
||||||
boot.extraModulePackages = [ ];
|
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";
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
networking = {
|
|
||||||
interfaces = {
|
|
||||||
ens18 = {
|
|
||||||
useDHCP = false;
|
|
||||||
ipv4.addresses = [
|
|
||||||
{
|
|
||||||
address = "10.50.65.100";
|
|
||||||
prefixLength = 24;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
ens19 = {
|
|
||||||
useDHCP = false;
|
|
||||||
ipv4.addresses = [
|
|
||||||
{
|
|
||||||
address = "10.50.80.10";
|
|
||||||
prefixLength = 24;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
ens20 = {
|
|
||||||
useDHCP = false;
|
|
||||||
ipv4.addresses = [
|
|
||||||
{
|
|
||||||
address = "10.50.77.20";
|
|
||||||
prefixLength = 24;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
defaultGateway = {
|
|
||||||
address = "10.50.80.1";
|
|
||||||
interface = "ens19";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
+49
-5
@@ -1,7 +1,51 @@
|
|||||||
{
|
{
|
||||||
imports = [
|
imports = [ ./hardware-configuration.nix ];
|
||||||
./hardware-configuration.nix
|
|
||||||
./networking.nix
|
networking = {
|
||||||
./disko.nix
|
useDHCP = false;
|
||||||
];
|
|
||||||
|
interfaces = {
|
||||||
|
ens18 = {
|
||||||
|
useDHCP = false;
|
||||||
|
ipv4.addresses = [
|
||||||
|
{
|
||||||
|
address = "10.50.128.20";
|
||||||
|
prefixLength = 24;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
ens19 = {
|
||||||
|
useDHCP = false;
|
||||||
|
ipv4.addresses = [
|
||||||
|
{
|
||||||
|
address = "10.50.7.101";
|
||||||
|
prefixLength = 24;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
ens20 = {
|
||||||
|
useDHCP = false;
|
||||||
|
ipv4.routes = [
|
||||||
|
{
|
||||||
|
address = "10.50.64.0";
|
||||||
|
prefixLength = 24;
|
||||||
|
via = "10.50.82.1";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
ipv4.addresses = [
|
||||||
|
{
|
||||||
|
address = "10.50.82.10";
|
||||||
|
prefixLength = 24;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
defaultGateway = {
|
||||||
|
address = "10.50.128.1";
|
||||||
|
interface = "ens18";
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,9 @@
|
|||||||
{
|
_: {
|
||||||
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 = {
|
programs.google-chrome = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = if config.my.hardwares.nvidia.enable then chrome else pkgs.google-chrome;
|
|
||||||
|
|
||||||
commandLineArgs = [
|
commandLineArgs = [
|
||||||
"--enable-features=${lib.concatStringsSep "," features}"
|
"--enable-features=MiddleClickAutoscroll"
|
||||||
"--use-gl=angle"
|
|
||||||
"--use-angle=gl"
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
_: {
|
{ inputs, ... }:
|
||||||
|
{
|
||||||
description = "Codex Desktop for Linux";
|
description = "Codex Desktop for Linux";
|
||||||
|
|
||||||
includes = [ "applications.codex" ];
|
includes = [ "applications.codex" ];
|
||||||
|
|
||||||
|
imports.nixos = [
|
||||||
|
inputs.codex-desktop-linux.nixosModules.default
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,15 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
environment.systemPackages = [
|
programs.codexDesktopLinux = {
|
||||||
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.chatgpt
|
enable = true;
|
||||||
];
|
cliPackage = inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.codex;
|
||||||
|
remoteControl.enable = true;
|
||||||
|
remoteMobileControl.enable = true;
|
||||||
|
computerUseUi.enable = false;
|
||||||
|
linuxFeatures = [
|
||||||
|
"appshots"
|
||||||
|
"open-target-discovery"
|
||||||
|
];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -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"
|
|
||||||
@@ -1,36 +1,6 @@
|
|||||||
|
{ inputs, pkgs, ... }:
|
||||||
{
|
{
|
||||||
config,
|
home.packages = [
|
||||||
inputs,
|
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.codex
|
||||||
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-xp6YIoqJdUu1zEzw7s7+lh8iGJD4THokF5NPbxLH6zc=";
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,6 @@
|
|||||||
{
|
_: {
|
||||||
inputs,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
unstable = inputs.nixpkgs-unstable.legacyPackages.${pkgs.stdenv.hostPlatform.system};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
programs.vesktop = {
|
programs.vesktop = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = unstable.vesktop;
|
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
discordBranch = "stable";
|
discordBranch = "stable";
|
||||||
@@ -25,10 +16,6 @@ in
|
|||||||
|
|
||||||
openLinksWithElectron = false;
|
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 = [
|
spellCheckLanguages = [
|
||||||
"ja-JP"
|
"ja-JP"
|
||||||
"en-US"
|
"en-US"
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
home.packages = [ pkgs.ffmpeg ];
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,6 @@
|
|||||||
{ inputs, system, ... }: {
|
{ inputs, system, ... }: {
|
||||||
programs.ghostty = {
|
programs.ghostty = {
|
||||||
# Labwc's Close action correctly targets one xdg-toplevel, but Ghostty's
|
systemd.enable = true;
|
||||||
# systemd service runs every window in one GTK single-instance process.
|
|
||||||
# If that process exits while handling the request, every Ghostty window
|
|
||||||
# disappears together. Keep each launcher invocation independent instead.
|
|
||||||
systemd.enable = false;
|
|
||||||
package = inputs.ghostty.packages.${system}.default;
|
package = inputs.ghostty.packages.${system}.default;
|
||||||
|
|
||||||
settings.gtk-single-instance = false;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ in
|
|||||||
|
|
||||||
ignores = [
|
ignores = [
|
||||||
".direnv/"
|
".direnv/"
|
||||||
|
".envrc"
|
||||||
|
"!.envrc.example"
|
||||||
];
|
];
|
||||||
|
|
||||||
signing = {
|
signing = {
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
homebrew.casks = [ "handy" ];
|
||||||
|
|
||||||
|
launchd.agents.handy = {
|
||||||
|
command = "/usr/bin/open -gja Handy --args --start-hidden";
|
||||||
|
serviceConfig.RunAtLoad = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
inputs,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
handy = inputs.handy.packages.${pkgs.stdenv.hostPlatform.system}.handy;
|
||||||
|
settingsFile = "${config.xdg.configHome}/com.pais.handy/settings_store.json";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.packages = [
|
||||||
|
handy
|
||||||
|
pkgs.wtype
|
||||||
|
];
|
||||||
|
|
||||||
|
# Handy has no disabled-shortcut setting. Empty bindings are rejected before
|
||||||
|
# registration, leaving niri and labwc as the sole owners of Ctrl+Space.
|
||||||
|
home.activation.disableHandyGlobalShortcuts = {
|
||||||
|
after = [ "writeBoundary" ];
|
||||||
|
before = [ ];
|
||||||
|
data = ''
|
||||||
|
settingsFile=${lib.escapeShellArg settingsFile}
|
||||||
|
mkdir -p "$(dirname "$settingsFile")"
|
||||||
|
|
||||||
|
if [ -f "$settingsFile" ]; then
|
||||||
|
${lib.getExe pkgs.jq} \
|
||||||
|
'.settings.bindings.transcribe.current_binding = ""
|
||||||
|
| .settings.bindings.transcribe_with_post_process.current_binding = ""' \
|
||||||
|
"$settingsFile" > "$settingsFile.tmp"
|
||||||
|
else
|
||||||
|
${lib.getExe pkgs.jq} -n '
|
||||||
|
{
|
||||||
|
settings: {
|
||||||
|
bindings: {
|
||||||
|
transcribe: {
|
||||||
|
id: "transcribe",
|
||||||
|
name: "Transcribe",
|
||||||
|
description: "Converts your speech into text.",
|
||||||
|
default_binding: "ctrl+space",
|
||||||
|
current_binding: ""
|
||||||
|
},
|
||||||
|
transcribe_with_post_process: {
|
||||||
|
id: "transcribe_with_post_process",
|
||||||
|
name: "Transcribe with Post-Processing",
|
||||||
|
description: "Converts your speech into text and applies AI post-processing.",
|
||||||
|
default_binding: "ctrl+shift+space",
|
||||||
|
current_binding: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' > "$settingsFile.tmp"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv "$settingsFile.tmp" "$settingsFile"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.user.services.handy = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Handy speech-to-text";
|
||||||
|
After = [ "graphical-session.target" ];
|
||||||
|
PartOf = [ "graphical-session.target" ];
|
||||||
|
};
|
||||||
|
Service = {
|
||||||
|
ExecStart = "${lib.getExe handy} --start-hidden";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 5;
|
||||||
|
};
|
||||||
|
Install.WantedBy = [ "graphical-session.target" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
description = "Handy offline speech-to-text";
|
||||||
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
home.packages = [ pkgs.htop ];
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
home.packages = [ pkgs.python314Packages.huggingface-hub ];
|
|
||||||
}
|
|
||||||
@@ -102,6 +102,8 @@ in
|
|||||||
(action "W-q" "Close")
|
(action "W-q" "Close")
|
||||||
(action "W-f" "ToggleMaximize")
|
(action "W-f" "ToggleMaximize")
|
||||||
(action "W-c" "Iconify")
|
(action "W-c" "Iconify")
|
||||||
|
(action "W-Tab" "NextWindow")
|
||||||
|
(action "W-S-Tab" "PreviousWindow")
|
||||||
(action "W-Up" "Lower")
|
(action "W-Up" "Lower")
|
||||||
(action "W-Down" "Raise")
|
(action "W-Down" "Raise")
|
||||||
(action "W-Left" "NextWindow")
|
(action "W-Left" "NextWindow")
|
||||||
@@ -121,12 +123,14 @@ in
|
|||||||
(execute "W-s" "noctalia msg panel-toggle launcher")
|
(execute "W-s" "noctalia msg panel-toggle launcher")
|
||||||
(execute "W-e" "nautilus --new-window")
|
(execute "W-e" "nautilus --new-window")
|
||||||
(execute "W-l" "loginctl lock-session")
|
(execute "W-l" "loginctl lock-session")
|
||||||
(execute "W-v" "vicinae vicinae://launch/clipboard/history")
|
(execute "W-v" "vicinae vicinae://launch/clipboard/history?toggle=true")
|
||||||
(execute "W-j" "nani-translate-primary")
|
(execute "W-j" "nani-translate-primary")
|
||||||
(execute "W-S-j" "nani-translate-ocr")
|
(execute "W-S-j" "normcap-translate")
|
||||||
(execute "W-C-j" "${lib.getExe' pkgs.xdg-utils "xdg-open"} naniapp://translate")
|
(execute "W-C-j" "${lib.getExe' pkgs.xdg-utils "xdg-open"} naniapp://translate")
|
||||||
(execute "W-space" "ghostty +toggle-quick-terminal")
|
(execute "W-space" "ghostty +toggle-quick-terminal")
|
||||||
(execute "W-p" "wdisplays")
|
(execute "W-p" "wdisplays")
|
||||||
|
(execute "W-z" "wl-find-cursor -c 0xCCFF453A -s 160 -d 1200")
|
||||||
|
(execute "C-space" "handy --toggle-transcription")
|
||||||
|
|
||||||
# Function keys (sync with niri modules/applications/niri/home.nix)
|
# Function keys (sync with niri modules/applications/niri/home.nix)
|
||||||
(execute "XF86AudioRaiseVolume" "noctalia msg volume-up")
|
(execute "XF86AudioRaiseVolume" "noctalia msg volume-up")
|
||||||
|
|||||||
@@ -4,5 +4,6 @@
|
|||||||
includes = [
|
includes = [
|
||||||
"systems.wayland"
|
"systems.wayland"
|
||||||
"applications.screenshot"
|
"applications.screenshot"
|
||||||
|
"applications.wl-find-cursor"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,16 @@
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
unstable = inputs.nixpkgs-unstable.legacyPackages.${pkgs.stdenv.hostPlatform.system};
|
unstable = inputs.nixpkgs-unstable.legacyPackages.${pkgs.stdenv.hostPlatform.system};
|
||||||
|
labwc = unstable.labwc.overrideAttrs (oldAttrs: {
|
||||||
|
patches = (oldAttrs.patches or [ ]) ++ [
|
||||||
|
./patches/remove-ext-workspace-output-on-destroy.patch
|
||||||
|
];
|
||||||
|
});
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
programs.labwc = {
|
programs.labwc = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = unstable.labwc;
|
package = labwc;
|
||||||
};
|
};
|
||||||
|
|
||||||
xdg.portal.config.labwc.default = [
|
xdg.portal.config.labwc.default = [
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
From: Codex <[email protected]>
|
||||||
|
Subject: [PATCH] output: remove destroyed output from ext-workspace group
|
||||||
|
|
||||||
|
The DRM backend destroys and recreates outputs when a session is paused and
|
||||||
|
resumed. Remove the output from the ext-workspace group before wlroots
|
||||||
|
finishes it, otherwise the group's output_bind listener remains attached and
|
||||||
|
wlr_output_finish() aborts.
|
||||||
|
|
||||||
|
---
|
||||||
|
src/output.c | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/output.c b/src/output.c
|
||||||
|
index 2eab8ec..f19c3ff 100644
|
||||||
|
--- a/src/output.c
|
||||||
|
+++ b/src/output.c
|
||||||
|
@@ -277,6 +277,9 @@ handle_output_destroy(struct wl_listener *listener, void *data)
|
||||||
|
struct seat *seat = &server.seat;
|
||||||
|
regions_evacuate_output(output);
|
||||||
|
regions_destroy(seat, &output->regions);
|
||||||
|
+ wlr_ext_workspace_group_handle_v1_output_leave(
|
||||||
|
+ server.workspaces.ext_group, output->wlr_output);
|
||||||
|
+
|
||||||
|
if (seat->overlay.active.output == output) {
|
||||||
|
overlay_finish(seat);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
set -o errexit -o nounset -o pipefail
|
||||||
|
|
||||||
|
playlist_file="$1"
|
||||||
|
default_id="$2"
|
||||||
|
configuration_id="$3"
|
||||||
|
shift 3
|
||||||
|
|
||||||
|
state_dir="${XDG_RUNTIME_DIR:?}/linux-wallpaperengine"
|
||||||
|
state_file="$state_dir/current"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
printf '%s\n' \
|
||||||
|
'Usage: wallpaperengine-wallpaper COMMAND [ID]' \
|
||||||
|
'' \
|
||||||
|
'Commands:' \
|
||||||
|
' select ID Select a declaratively configured ID for this session' \
|
||||||
|
' next Select the next configured ID' \
|
||||||
|
' previous Select the previous configured ID' \
|
||||||
|
' list List configured IDs and mark the selected one' \
|
||||||
|
' current Print the selected ID' \
|
||||||
|
' restart Restart the selected wallpaper' \
|
||||||
|
' stop Stop Wallpaper Engine for this session'
|
||||||
|
}
|
||||||
|
|
||||||
|
load_playlist() {
|
||||||
|
mapfile -t wallpaper_ids < <(awk '/^[0-9]+$/ && !seen[$0]++' "$playlist_file")
|
||||||
|
if [ "${#wallpaper_ids[@]}" -eq 0 ]; then
|
||||||
|
echo "wallpaperengine-wallpaper: no wallpaper IDs are configured in settings.nix" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
contains_id() {
|
||||||
|
local candidate="$1"
|
||||||
|
local id
|
||||||
|
|
||||||
|
for id in "${wallpaper_ids[@]}"; do
|
||||||
|
[ "$id" = "$candidate" ] && return 0
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
current_id() {
|
||||||
|
local saved_configuration=""
|
||||||
|
local saved_id=""
|
||||||
|
local -a saved_state=()
|
||||||
|
|
||||||
|
if [ -s "$state_file" ]; then
|
||||||
|
mapfile -t saved_state <"$state_file"
|
||||||
|
saved_configuration="${saved_state[0]:-}"
|
||||||
|
saved_id="${saved_state[1]:-}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$saved_configuration" = "$configuration_id" ] && contains_id "$saved_id"; then
|
||||||
|
printf '%s\n' "$saved_id"
|
||||||
|
else
|
||||||
|
printf '%s\n' "$default_id"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
select_id() {
|
||||||
|
local id="$1"
|
||||||
|
|
||||||
|
if ! contains_id "$id"; then
|
||||||
|
echo "wallpaperengine-wallpaper: ID is not declared in settings.nix: $id" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$state_dir"
|
||||||
|
printf '%s\n%s\n' "$configuration_id" "$id" >"$state_file"
|
||||||
|
systemctl --user restart linux-wallpaperengine.service
|
||||||
|
}
|
||||||
|
|
||||||
|
cycle() {
|
||||||
|
local step="$1"
|
||||||
|
local current
|
||||||
|
local index=0
|
||||||
|
local next_index
|
||||||
|
|
||||||
|
current=$(current_id)
|
||||||
|
for i in "${!wallpaper_ids[@]}"; do
|
||||||
|
if [ "${wallpaper_ids[$i]}" = "$current" ]; then
|
||||||
|
index="$i"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
next_index=$(((index + step + ${#wallpaper_ids[@]}) % ${#wallpaper_ids[@]}))
|
||||||
|
select_id "${wallpaper_ids[$next_index]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
load_playlist
|
||||||
|
|
||||||
|
command="${1:-}"
|
||||||
|
if [ -z "$command" ]; then
|
||||||
|
usage
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
|
||||||
|
case "$command" in
|
||||||
|
select)
|
||||||
|
[ "$#" -eq 1 ] || {
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
select_id "$1"
|
||||||
|
;;
|
||||||
|
next)
|
||||||
|
[ "$#" -eq 0 ] || {
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
cycle 1
|
||||||
|
;;
|
||||||
|
previous)
|
||||||
|
[ "$#" -eq 0 ] || {
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
cycle -1
|
||||||
|
;;
|
||||||
|
list)
|
||||||
|
[ "$#" -eq 0 ] || {
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
current=$(current_id)
|
||||||
|
for id in "${wallpaper_ids[@]}"; do
|
||||||
|
if [ "$id" = "$current" ]; then
|
||||||
|
printf '* %s\n' "$id"
|
||||||
|
else
|
||||||
|
printf ' %s\n' "$id"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
current)
|
||||||
|
[ "$#" -eq 0 ] || {
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
current_id
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
[ "$#" -eq 0 ] || {
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
systemctl --user restart linux-wallpaperengine.service
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
[ "$#" -eq 0 ] || {
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
systemctl --user stop linux-wallpaperengine.service
|
||||||
|
;;
|
||||||
|
help | -h | --help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
set -o errexit -o nounset -o pipefail
|
||||||
|
|
||||||
|
playlist_file="$1"
|
||||||
|
default_id="$2"
|
||||||
|
configuration_id="$3"
|
||||||
|
assets_dir="$4"
|
||||||
|
workshop_dir="$5"
|
||||||
|
scaling="$6"
|
||||||
|
shift 6
|
||||||
|
|
||||||
|
state_file="${XDG_RUNTIME_DIR:?}/linux-wallpaperengine/current"
|
||||||
|
wallpaper_id="$default_id"
|
||||||
|
saved_configuration=""
|
||||||
|
saved_id=""
|
||||||
|
saved_state=()
|
||||||
|
outputs=()
|
||||||
|
|
||||||
|
if [ -s "$state_file" ]; then
|
||||||
|
mapfile -t saved_state <"$state_file"
|
||||||
|
saved_configuration="${saved_state[0]:-}"
|
||||||
|
saved_id="${saved_state[1]:-}"
|
||||||
|
|
||||||
|
if [ "$saved_configuration" = "$configuration_id" ] &&
|
||||||
|
awk -v id="$saved_id" '$0 == id { found = 1 } END { exit !found }' "$playlist_file"; then
|
||||||
|
wallpaper_id="$saved_id"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
wallpaper_path="$workshop_dir/$wallpaper_id"
|
||||||
|
if [ ! -d "$wallpaper_path" ]; then
|
||||||
|
echo "linux-wallpaperengine: missing declared wallpaper: $wallpaper_path" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$assets_dir" ]; then
|
||||||
|
echo "linux-wallpaperengine: missing Wallpaper Engine assets: $assets_dir" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mapfile -t outputs < <(wlr-randr --json | jq -r '.[] | select(.enabled == true) | .name')
|
||||||
|
if [ "${#outputs[@]}" -eq 0 ]; then
|
||||||
|
echo "linux-wallpaperengine: no enabled Wayland outputs were detected" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
engine_args=("$@" --assets-dir "$assets_dir")
|
||||||
|
for output in "${outputs[@]}"; do
|
||||||
|
engine_args+=(
|
||||||
|
--screen-root "$output"
|
||||||
|
--bg "$wallpaper_path"
|
||||||
|
--scaling "$scaling"
|
||||||
|
)
|
||||||
|
done
|
||||||
|
|
||||||
|
exec linux-wallpaperengine "${engine_args[@]}"
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
settings = import ../settings.nix;
|
||||||
|
inherit (settings)
|
||||||
|
assetsDirectory
|
||||||
|
fps
|
||||||
|
mute
|
||||||
|
scaling
|
||||||
|
selectedWallpaperId
|
||||||
|
switchIntervalSeconds
|
||||||
|
wallpaperIds
|
||||||
|
workshopDirectory
|
||||||
|
;
|
||||||
|
|
||||||
|
resolveHomePath =
|
||||||
|
path:
|
||||||
|
if lib.hasPrefix "~/" path then
|
||||||
|
"${config.home.homeDirectory}/${lib.removePrefix "~/" path}"
|
||||||
|
else if lib.hasPrefix "/" path then
|
||||||
|
path
|
||||||
|
else
|
||||||
|
"${config.home.homeDirectory}/${path}";
|
||||||
|
|
||||||
|
hasWallpapers = wallpaperIds != [ ];
|
||||||
|
defaultWallpaperId =
|
||||||
|
if selectedWallpaperId != null then
|
||||||
|
selectedWallpaperId
|
||||||
|
else if hasWallpapers then
|
||||||
|
lib.head wallpaperIds
|
||||||
|
else
|
||||||
|
"";
|
||||||
|
configurationId = builtins.hashString "sha256" (builtins.toJSON settings);
|
||||||
|
resolvedAssetsDirectory = resolveHomePath assetsDirectory;
|
||||||
|
resolvedWorkshopDirectory = resolveHomePath workshopDirectory;
|
||||||
|
playlist = pkgs.writeText "linux-wallpaperengine-playlist" (
|
||||||
|
lib.concatMapStringsSep "\n" (id: id) wallpaperIds + "\n"
|
||||||
|
);
|
||||||
|
engineArguments = lib.optional mute "--silent" ++ [
|
||||||
|
"--fps"
|
||||||
|
(toString fps)
|
||||||
|
];
|
||||||
|
|
||||||
|
controller = pkgs.writeShellApplication {
|
||||||
|
name = "wallpaperengine-wallpaper";
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.gawk
|
||||||
|
pkgs.systemd
|
||||||
|
];
|
||||||
|
text = ''
|
||||||
|
exec ${lib.getExe pkgs.bash} ${./controller.sh} \
|
||||||
|
${lib.escapeShellArg playlist} \
|
||||||
|
${lib.escapeShellArg defaultWallpaperId} \
|
||||||
|
${lib.escapeShellArg configurationId} \
|
||||||
|
"$@"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
launcher = pkgs.writeShellApplication {
|
||||||
|
name = "linux-wallpaperengine-launcher";
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.gawk
|
||||||
|
pkgs.jq
|
||||||
|
pkgs.linux-wallpaperengine
|
||||||
|
pkgs.wlr-randr
|
||||||
|
];
|
||||||
|
text = ''
|
||||||
|
exec ${lib.getExe pkgs.bash} ${./launcher.sh} \
|
||||||
|
${lib.escapeShellArg playlist} \
|
||||||
|
${lib.escapeShellArg defaultWallpaperId} \
|
||||||
|
${lib.escapeShellArg configurationId} \
|
||||||
|
${lib.escapeShellArg resolvedAssetsDirectory} \
|
||||||
|
${lib.escapeShellArg resolvedWorkshopDirectory} \
|
||||||
|
${lib.escapeShellArg scaling} \
|
||||||
|
${lib.escapeShellArgs engineArguments}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in
|
||||||
|
assert lib.assertMsg (lib.all (
|
||||||
|
id: builtins.isString id && builtins.match "[0-9]+" id != null
|
||||||
|
) wallpaperIds) "linux-wallpaperengine: wallpaperIds must contain only numeric strings";
|
||||||
|
assert lib.assertMsg (
|
||||||
|
lib.unique wallpaperIds == wallpaperIds
|
||||||
|
) "linux-wallpaperengine: wallpaperIds must not contain duplicates";
|
||||||
|
assert lib.assertMsg (
|
||||||
|
selectedWallpaperId == null || builtins.elem selectedWallpaperId wallpaperIds
|
||||||
|
) "linux-wallpaperengine: selectedWallpaperId must be null or a member of wallpaperIds";
|
||||||
|
assert lib.assertMsg (
|
||||||
|
switchIntervalSeconds == null || (builtins.isInt switchIntervalSeconds && switchIntervalSeconds > 0)
|
||||||
|
) "linux-wallpaperengine: switchIntervalSeconds must be null or a positive integer";
|
||||||
|
assert lib.assertMsg (
|
||||||
|
builtins.isInt fps && fps > 0
|
||||||
|
) "linux-wallpaperengine: fps must be a positive integer";
|
||||||
|
assert lib.assertMsg (
|
||||||
|
builtins.isString assetsDirectory && assetsDirectory != ""
|
||||||
|
) "linux-wallpaperengine: assetsDirectory must be a non-empty string";
|
||||||
|
assert lib.assertMsg (
|
||||||
|
builtins.isString workshopDirectory && workshopDirectory != ""
|
||||||
|
) "linux-wallpaperengine: workshopDirectory must be a non-empty string";
|
||||||
|
assert lib.assertMsg (builtins.elem scaling [
|
||||||
|
"default"
|
||||||
|
"fill"
|
||||||
|
"fit"
|
||||||
|
"stretch"
|
||||||
|
]) "linux-wallpaperengine: scaling must be default, fill, fit, or stretch";
|
||||||
|
{
|
||||||
|
home.packages = [
|
||||||
|
controller
|
||||||
|
pkgs.linux-wallpaperengine
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd.user.services = lib.optionalAttrs hasWallpapers {
|
||||||
|
linux-wallpaperengine = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Linux Wallpaper Engine";
|
||||||
|
After = [ "graphical-session.target" ];
|
||||||
|
PartOf = [ "graphical-session.target" ];
|
||||||
|
};
|
||||||
|
Service = {
|
||||||
|
ExecStart = lib.getExe launcher;
|
||||||
|
Restart = "on-abnormal";
|
||||||
|
};
|
||||||
|
Install.WantedBy = [ "graphical-session.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
linux-wallpaperengine-switch = {
|
||||||
|
Unit.Description = "Switch Linux Wallpaper Engine wallpaper";
|
||||||
|
Service = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "${lib.getExe controller} next";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.user.timers =
|
||||||
|
lib.optionalAttrs
|
||||||
|
(hasWallpapers && builtins.length wallpaperIds > 1 && switchIntervalSeconds != null)
|
||||||
|
{
|
||||||
|
linux-wallpaperengine-switch = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Periodically switch Linux Wallpaper Engine wallpaper";
|
||||||
|
PartOf = [ "graphical-session.target" ];
|
||||||
|
};
|
||||||
|
Timer = {
|
||||||
|
OnActiveSec = "${toString switchIntervalSeconds}s";
|
||||||
|
OnUnitActiveSec = "${toString switchIntervalSeconds}s";
|
||||||
|
Unit = "linux-wallpaperengine-switch.service";
|
||||||
|
};
|
||||||
|
Install.WantedBy = [ "graphical-session.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
description = "Wallpaper Engine backgrounds for Linux";
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
assetsDirectory = "~/.local/share/Steam/steamapps/common/wallpaper_engine/assets";
|
||||||
|
workshopDirectory = "~/.local/share/Steam/steamapps/workshop/content/431960";
|
||||||
|
|
||||||
|
wallpaperIds = [
|
||||||
|
"2833810156"
|
||||||
|
"2834355367"
|
||||||
|
"2836628501"
|
||||||
|
"2845095254"
|
||||||
|
"2859848175"
|
||||||
|
"2861661119"
|
||||||
|
"2982896307"
|
||||||
|
];
|
||||||
|
|
||||||
|
# null selects the first ID above.
|
||||||
|
selectedWallpaperId = null;
|
||||||
|
# Set a number such as 300 to rotate through multiple IDs.
|
||||||
|
switchIntervalSeconds = 300;
|
||||||
|
|
||||||
|
fps = 30;
|
||||||
|
mute = true;
|
||||||
|
scaling = "fill";
|
||||||
|
}
|
||||||
@@ -1,78 +1,5 @@
|
|||||||
{ pkgs, ... }:
|
_: {
|
||||||
let
|
|
||||||
tessdataBest = pkgs.runCommand "tessdata-best-jpn-eng-chi-sim" { } ''
|
|
||||||
mkdir -p "$out"
|
|
||||||
ln -s ${
|
|
||||||
pkgs.fetchurl {
|
|
||||||
url = "https://github.com/tesseract-ocr/tessdata_best/raw/main/jpn.traineddata";
|
|
||||||
hash = "sha256-Nr35rII/WRHmJMMNBVPokLirx8MaZbPvFNqUNljEC3k=";
|
|
||||||
}
|
|
||||||
} "$out/jpn.traineddata"
|
|
||||||
ln -s ${
|
|
||||||
pkgs.fetchurl {
|
|
||||||
url = "https://github.com/tesseract-ocr/tessdata_best/raw/main/eng.traineddata";
|
|
||||||
hash = "sha256-goCu0Hgv4nJXpo6hD+fvMkyg+Nhb0v0UXRwrVgvLZro=";
|
|
||||||
}
|
|
||||||
} "$out/eng.traineddata"
|
|
||||||
ln -s ${
|
|
||||||
pkgs.fetchurl {
|
|
||||||
url = "https://github.com/tesseract-ocr/tessdata_best/raw/main/chi_sim.traineddata";
|
|
||||||
hash = "sha256-T+8tEwbI6HYW1NPkxsZ/r11EvjNCKQz48vD246p+c1s=";
|
|
||||||
}
|
|
||||||
} "$out/chi_sim.traineddata"
|
|
||||||
'';
|
|
||||||
|
|
||||||
tesseract = pkgs.tesseract5.override {
|
|
||||||
tessdata = tessdataBest;
|
|
||||||
};
|
|
||||||
|
|
||||||
naniTranslatePrimary = pkgs.writeShellApplication {
|
|
||||||
name = "nani-translate-primary";
|
|
||||||
|
|
||||||
runtimeInputs = with pkgs; [
|
|
||||||
jq
|
|
||||||
wl-clipboard
|
|
||||||
xdg-utils
|
|
||||||
];
|
|
||||||
|
|
||||||
text = ''
|
|
||||||
selected_text="$(wl-paste --primary --no-newline)" || exit 0
|
|
||||||
[ -n "$selected_text" ] || exit 0
|
|
||||||
encoded_text="$(printf '%s' "$selected_text" | jq -sRr @uri)"
|
|
||||||
exec xdg-open "naniapp://translate?source=$encoded_text"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
naniTranslateOcr = pkgs.writeShellApplication {
|
|
||||||
name = "nani-translate-ocr";
|
|
||||||
|
|
||||||
runtimeInputs = with pkgs; [
|
|
||||||
grim
|
|
||||||
jq
|
|
||||||
slurp
|
|
||||||
tesseract
|
|
||||||
xdg-utils
|
|
||||||
];
|
|
||||||
|
|
||||||
text = ''
|
|
||||||
geometry="$(slurp)" || exit 0
|
|
||||||
captured_text="$(
|
|
||||||
grim -g "$geometry" - \
|
|
||||||
| tesseract stdin stdout -l jpn+eng+chi_sim --oem 1 --psm 6
|
|
||||||
)"
|
|
||||||
[ -n "$captured_text" ] || exit 0
|
|
||||||
encoded_text="$(printf '%s' "$captured_text" | jq -sRr @uri)"
|
|
||||||
exec xdg-open "naniapp://translate?source=$encoded_text"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
programs.naniTranslateLinux.enable = true;
|
programs.naniTranslateLinux.enable = true;
|
||||||
|
|
||||||
xdg.mimeApps.defaultApplications."x-scheme-handler/naniapp" = "nani.desktop";
|
xdg.mimeApps.defaultApplications."x-scheme-handler/naniapp" = "nani.desktop";
|
||||||
|
|
||||||
home.packages = [
|
|
||||||
naniTranslatePrimary
|
|
||||||
naniTranslateOcr
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
home.packages = [ pkgs.nano ];
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
description = "Sipeed NanoKVM-USB desktop client";
|
|
||||||
|
|
||||||
includes = [ "services.nanokvm-usb" ];
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
let
|
|
||||||
pname = "nanokvm-usb";
|
|
||||||
version = "1.1.4";
|
|
||||||
|
|
||||||
src = pkgs.fetchurl {
|
|
||||||
url = "https://github.com/sipeed/NanoKVM-USB/releases/download/v${version}/NanoKVM-USB-${version}-linux-x86_64.AppImage";
|
|
||||||
hash = "sha256-00MT4U2afv0qt3xFVhLr0SSmS2cLrKBlmfzqYEFuaVc=";
|
|
||||||
};
|
|
||||||
|
|
||||||
appimageContents = pkgs.appimageTools.extractType2 {
|
|
||||||
inherit pname src version;
|
|
||||||
};
|
|
||||||
|
|
||||||
nanokvm-usb = pkgs.appimageTools.wrapType2 {
|
|
||||||
inherit pname src version;
|
|
||||||
|
|
||||||
meta = {
|
|
||||||
description = "Sipeed NanoKVM-USB desktop client";
|
|
||||||
homepage = "https://github.com/sipeed/NanoKVM-USB";
|
|
||||||
license = pkgs.lib.licenses.gpl3Only;
|
|
||||||
platforms = [ "x86_64-linux" ];
|
|
||||||
mainProgram = "nanokvm-usb";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
desktopItem = pkgs.makeDesktopItem {
|
|
||||||
name = pname;
|
|
||||||
desktopName = "NanoKVM-USB";
|
|
||||||
comment = "NanoKVM-USB Desktop";
|
|
||||||
exec = "nanokvm-usb --no-sandbox %U";
|
|
||||||
icon = "${appimageContents}/nanokvm-usb.png";
|
|
||||||
categories = [ "Utility" ];
|
|
||||||
startupWMClass = "NanoKVM-USB";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
environment.systemPackages = [
|
|
||||||
nanokvm-usb
|
|
||||||
desktopItem
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -162,6 +162,14 @@ in
|
|||||||
"file://${config.home.homeDirectory}/Desktop Desktop"
|
"file://${config.home.homeDirectory}/Desktop Desktop"
|
||||||
"file://${config.home.homeDirectory}/Pictures Pictures"
|
"file://${config.home.homeDirectory}/Pictures Pictures"
|
||||||
"file://${config.home.homeDirectory}/Downloads Downloads"
|
"file://${config.home.homeDirectory}/Downloads Downloads"
|
||||||
"file://${config.home.homeDirectory}/Projects Projects"
|
"file://${config.home.homeDirectory}/projects projects"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
home.activation.createProjectsDirectory = {
|
||||||
|
after = [ "writeBoundary" ];
|
||||||
|
before = [ ];
|
||||||
|
data = ''
|
||||||
|
$DRY_RUN_CMD mkdir -p "$HOME/projects"
|
||||||
|
'';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,28 @@
|
|||||||
{ lib, pkgs, ... }:
|
{ lib, pkgs, ... }:
|
||||||
let
|
let
|
||||||
keybindings = import ./keybindings.nix;
|
keybindings = import ./keybindings.nix;
|
||||||
|
naniTranslatePrimary = pkgs.writeShellApplication {
|
||||||
|
name = "nani-translate-primary";
|
||||||
|
runtimeInputs = with pkgs; [
|
||||||
|
jq
|
||||||
|
wl-clipboard
|
||||||
|
xdg-utils
|
||||||
|
];
|
||||||
|
text = ''
|
||||||
|
selected_text="$(wl-paste --primary --no-newline)" || exit 0
|
||||||
|
[ -n "$selected_text" ] || exit 0
|
||||||
|
encoded_text="$(printf '%s' "$selected_text" | jq -sRr @uri)"
|
||||||
|
exec xdg-open "naniapp://translate?source=$encoded_text"
|
||||||
|
'';
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
home.packages = [ naniTranslatePrimary ];
|
||||||
|
|
||||||
programs.niri.settings = {
|
programs.niri.settings = {
|
||||||
|
|
||||||
binds = keybindings // {
|
binds = keybindings // {
|
||||||
# niri window or focus move
|
# niri window or focus move
|
||||||
"Mod+MouseMiddle".action.toggle-window-floating = [ ];
|
|
||||||
|
|
||||||
"Mod+Shift+Left" = {
|
"Mod+Shift+Left" = {
|
||||||
action.focus-monitor-left = [ ];
|
action.focus-monitor-left = [ ];
|
||||||
hotkey-overlay.title = "Focus Monitor Left";
|
hotkey-overlay.title = "Focus Monitor Left";
|
||||||
@@ -26,18 +40,6 @@ in
|
|||||||
hotkey-overlay.title = "Focus Monitor Down";
|
hotkey-overlay.title = "Focus Monitor Down";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Use the modifier combinations in the opposite direction from Niri's defaults.
|
|
||||||
"Mod+WheelScrollDown".action.focus-column-right = [ ];
|
|
||||||
"Mod+WheelScrollUp".action.focus-column-left = [ ];
|
|
||||||
"Mod+Shift+WheelScrollDown" = {
|
|
||||||
cooldown-ms = 150;
|
|
||||||
action.focus-workspace-down = [ ];
|
|
||||||
};
|
|
||||||
"Mod+Shift+WheelScrollUp" = {
|
|
||||||
cooldown-ms = 150;
|
|
||||||
action.focus-workspace-up = [ ];
|
|
||||||
};
|
|
||||||
|
|
||||||
"Mod+Shift+Ctrl+Left" = {
|
"Mod+Shift+Ctrl+Left" = {
|
||||||
action.move-window-to-monitor-left = [ ];
|
action.move-window-to-monitor-left = [ ];
|
||||||
hotkey-overlay.title = "Move Window to Monitor Left";
|
hotkey-overlay.title = "Move Window to Monitor Left";
|
||||||
@@ -106,7 +108,7 @@ in
|
|||||||
"Mod+V" = {
|
"Mod+V" = {
|
||||||
action.spawn = [
|
action.spawn = [
|
||||||
"vicinae"
|
"vicinae"
|
||||||
"vicinae://launch/clipboard/history"
|
"vicinae://launch/clipboard/history?toggle=true"
|
||||||
];
|
];
|
||||||
hotkey-overlay.title = "Clipboard History";
|
hotkey-overlay.title = "Clipboard History";
|
||||||
};
|
};
|
||||||
@@ -117,7 +119,7 @@ in
|
|||||||
};
|
};
|
||||||
"Mod+Shift+J" = {
|
"Mod+Shift+J" = {
|
||||||
repeat = false;
|
repeat = false;
|
||||||
action.spawn = [ "nani-translate-ocr" ];
|
action.spawn = [ "normcap-translate" ];
|
||||||
hotkey-overlay.title = "OCR and Translate with Nani";
|
hotkey-overlay.title = "OCR and Translate with Nani";
|
||||||
};
|
};
|
||||||
"Mod+Ctrl+J" = {
|
"Mod+Ctrl+J" = {
|
||||||
@@ -139,6 +141,26 @@ in
|
|||||||
action.spawn = "wdisplays";
|
action.spawn = "wdisplays";
|
||||||
hotkey-overlay.title = "Display Settings: wdisplays";
|
hotkey-overlay.title = "Display Settings: wdisplays";
|
||||||
};
|
};
|
||||||
|
"Mod+Z" = {
|
||||||
|
action.spawn = [
|
||||||
|
"wl-find-cursor"
|
||||||
|
"-c"
|
||||||
|
"0xCCFF453A"
|
||||||
|
"-s"
|
||||||
|
"160"
|
||||||
|
"-d"
|
||||||
|
"1200"
|
||||||
|
];
|
||||||
|
hotkey-overlay.title = "Find Cursor";
|
||||||
|
};
|
||||||
|
"Ctrl+Space" = {
|
||||||
|
action.spawn = [
|
||||||
|
"handy"
|
||||||
|
"--toggle-transcription"
|
||||||
|
];
|
||||||
|
hotkey-overlay.title = "Toggle Handy Transcription";
|
||||||
|
};
|
||||||
|
|
||||||
# Function keys (sync with labwc modules/applications/labwc/home.nix)
|
# Function keys (sync with labwc modules/applications/labwc/home.nix)
|
||||||
"XF86AudioRaiseVolume".action.spawn = [
|
"XF86AudioRaiseVolume".action.spawn = [
|
||||||
"noctalia"
|
"noctalia"
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
includes = [
|
includes = [
|
||||||
"systems.wayland"
|
"systems.wayland"
|
||||||
"applications.screenshot"
|
"applications.screenshot"
|
||||||
|
"applications.wl-find-cursor"
|
||||||
];
|
];
|
||||||
|
|
||||||
imports = {
|
imports = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{ lib, pkgs }:
|
{ lib, pkgs }:
|
||||||
let
|
let
|
||||||
version = "0.56.0";
|
version = "0.46.0";
|
||||||
architecture =
|
architecture =
|
||||||
if pkgs.stdenv.hostPlatform.isx86_64 then
|
if pkgs.stdenv.hostPlatform.isx86_64 then
|
||||||
"x86_64"
|
"x86_64"
|
||||||
@@ -10,8 +10,8 @@ let
|
|||||||
throw "CodexBar CLI is only packaged for x86_64-linux and aarch64-linux";
|
throw "CodexBar CLI is only packaged for x86_64-linux and aarch64-linux";
|
||||||
hash =
|
hash =
|
||||||
{
|
{
|
||||||
x86_64 = "sha256-hzCnAyiizm8ZDfE1ONEP6S2Pdnskclm+XdDBBhEYVqE=";
|
x86_64 = "sha256-yMrOpu1WIv2sGVgvY9qf2XCoX2AXMSqR2b8bQDRU6os=";
|
||||||
aarch64 = "sha256-vfcgDEFpORPymcRYmlqvsjhV4pU7lNC8Vd9FDPI9UjM=";
|
aarch64 = "sha256-pCp3NOlxFN6zeH67W04WGSPbUae+ktzR5vEunWqu00g=";
|
||||||
}
|
}
|
||||||
.${architecture};
|
.${architecture};
|
||||||
in
|
in
|
||||||
|
|||||||
@@ -13,6 +13,14 @@ let
|
|||||||
--replace-fail "@codexbarPath@" "${lib.getExe codexbar}"
|
--replace-fail "@codexbarPath@" "${lib.getExe codexbar}"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
noctaliaPatched =
|
||||||
|
inputs.noctalia.packages.${pkgs.stdenv.hostPlatform.system}.default.overrideAttrs
|
||||||
|
(oldAttrs: {
|
||||||
|
patches = (oldAttrs.patches or [ ]) ++ [
|
||||||
|
./patches/window-switcher-labwc.patch
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
wallpapers = pkgs.fetchFromGitHub {
|
wallpapers = pkgs.fetchFromGitHub {
|
||||||
owner = "moons-14";
|
owner = "moons-14";
|
||||||
repo = "wallpapers";
|
repo = "wallpapers";
|
||||||
@@ -42,7 +50,7 @@ in
|
|||||||
programs.noctalia = {
|
programs.noctalia = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
package = inputs.noctalia.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
package = noctaliaPatched;
|
||||||
|
|
||||||
systemd.enable = true;
|
systemd.enable = true;
|
||||||
|
|
||||||
@@ -157,7 +165,7 @@ in
|
|||||||
network-connection = {
|
network-connection = {
|
||||||
type = "custom_button";
|
type = "custom_button";
|
||||||
glyph = "access-point";
|
glyph = "access-point";
|
||||||
actions.left = "exec nm-connection-editor";
|
actions.left = "nm-connection-editor";
|
||||||
};
|
};
|
||||||
tray = {
|
tray = {
|
||||||
type = "tray";
|
type = "tray";
|
||||||
@@ -178,7 +186,7 @@ in
|
|||||||
"google-chrome"
|
"google-chrome"
|
||||||
"code"
|
"code"
|
||||||
"dev.zed.Zed"
|
"dev.zed.Zed"
|
||||||
"chatgpt"
|
"codex-desktop"
|
||||||
"vesktop"
|
"vesktop"
|
||||||
];
|
];
|
||||||
show_all_outputs = true;
|
show_all_outputs = true;
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
diff --git a/src/shell/bar/widgets/taskbar_widget.cpp b/src/shell/bar/widgets/taskbar_widget.cpp
|
||||||
|
--- a/src/shell/bar/widgets/taskbar_widget.cpp
|
||||||
|
+++ b/src/shell/bar/widgets/taskbar_widget.cpp
|
||||||
|
@@ -5,6 +5,7 @@
|
||||||
|
#include "compositors/workspace_backend.h"
|
||||||
|
#include "config/config_service.h"
|
||||||
|
#include "core/deferred_call.h"
|
||||||
|
+#include "core/process/process.h"
|
||||||
|
#include "i18n/i18n.h"
|
||||||
|
#include "render/core/color.h"
|
||||||
|
#include "render/core/renderer.h"
|
||||||
|
@@ -36,6 +37,18 @@
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
+ [[nodiscard]] bool launchTaskbarOverview(const std::string& appId) {
|
||||||
|
+ constexpr const char* command = "noctalia-taskbar-overview";
|
||||||
|
+ if (appId.empty() || !process::commandExists(command)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ return process::runAsync({
|
||||||
|
+ command,
|
||||||
|
+ "--app-id",
|
||||||
|
+ appId.c_str(),
|
||||||
|
+ });
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// Integer centering; optional odd spare pixel on the end side (right/bottom).
|
||||||
|
[[nodiscard]] float centeredOffset(float extent, float content, float inset = 0.0F, bool oddSpareOnEnd = true) {
|
||||||
|
const float inner = std::max(0.0F, extent - inset * 2.0F);
|
||||||
|
@@ -373,6 +386,12 @@ void TaskbarWidget::activateOrLaunchPinned(const TaskModel& task) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ const std::string overviewAppId =
|
||||||
|
+ !task.appId.empty() ? task.appId : (!task.desktopEntryId.empty() ? task.desktopEntryId : task.idLower);
|
||||||
|
+ if (launchTaskbarOverview(overviewAppId)) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
const std::string cycleKey = !task.desktopEntryId.empty() ? task.desktopEntryId : task.idLower;
|
||||||
|
std::size_t& cursor = m_groupedAppCycleCursor[cycleKey];
|
||||||
|
if (cursor >= windows.size()) {
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
diff --git a/src/shell/switcher/window_switcher.cpp b/src/shell/switcher/window_switcher.cpp
|
||||||
|
--- a/src/shell/switcher/window_switcher.cpp
|
||||||
|
+++ b/src/shell/switcher/window_switcher.cpp
|
||||||
|
@@ -286,12 +286,19 @@ indexLiveToplevelsByWindowId(const CompositorPlatform& platform, std::unordered_
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- const auto mappedId = platform.compositorWindowIdForToplevelInfo(info);
|
||||||
|
- if (!mappedId.has_value() || mappedId->empty()) {
|
||||||
|
- continue;
|
||||||
|
+ std::string key;
|
||||||
|
+ if (const auto mappedId = platform.compositorWindowIdForToplevelInfo(info);
|
||||||
|
+ mappedId.has_value() && !mappedId->empty()) {
|
||||||
|
+ key = canonicalWindowId(*mappedId);
|
||||||
|
}
|
||||||
|
- const std::string key = canonicalWindowId(*mappedId);
|
||||||
|
+
|
||||||
|
+ // Generic wlroots compositors such as labwc do not provide a
|
||||||
|
+ // compositor-specific window ID. The wlr toplevel handle is stable
|
||||||
|
+ // for the lifetime of the window and is sufficient for switcher identity.
|
||||||
|
+ if (key.empty() && wlrHandle != 0) {
|
||||||
|
+ key = "toplevel:" + std::to_string(wlrHandle);
|
||||||
|
+ }
|
||||||
|
if (key.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
normcap = pkgs.normcap.override {
|
||||||
|
tesseract4 = pkgs.tesseract4.override {
|
||||||
|
enableLanguages = [
|
||||||
|
"chi_sim"
|
||||||
|
"jpn"
|
||||||
|
"eng"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
normcapTranslate = pkgs.writeShellApplication {
|
||||||
|
name = "normcap-translate";
|
||||||
|
|
||||||
|
runtimeInputs = [
|
||||||
|
normcap
|
||||||
|
pkgs.jq
|
||||||
|
pkgs.xdg-utils
|
||||||
|
];
|
||||||
|
|
||||||
|
text = ''
|
||||||
|
captured_text="$(
|
||||||
|
normcap \
|
||||||
|
--cli-mode \
|
||||||
|
--screenshot-handler grim \
|
||||||
|
--show-introduction False \
|
||||||
|
--update False \
|
||||||
|
--detect-codes False \
|
||||||
|
--notification False \
|
||||||
|
-l jpn eng chi_sim
|
||||||
|
)" || exit 0
|
||||||
|
[ -n "$captured_text" ] || exit 0
|
||||||
|
encoded_text="$(printf '%s' "$captured_text" | jq -sRr @uri)"
|
||||||
|
exec xdg-open "naniapp://translate?source=$encoded_text"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.packages = [
|
||||||
|
normcap
|
||||||
|
normcapTranslate
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
description = "NormCap OCR screen capture";
|
||||||
|
|
||||||
|
includes = [
|
||||||
|
"applications.nani"
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -2,19 +2,5 @@
|
|||||||
{
|
{
|
||||||
home.packages = [
|
home.packages = [
|
||||||
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.opencode
|
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.opencode
|
||||||
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.oh-my-opencode
|
|
||||||
];
|
];
|
||||||
|
|
||||||
home.file.".omo/omo.jsonc".text = builtins.toJSON {
|
|
||||||
agents = {
|
|
||||||
sisyphus.model = "openai/gpt-5.6-sol";
|
|
||||||
hephaestus.model = "openai/gpt-5.6-terra";
|
|
||||||
prometheus.model = "openai/gpt-5.6-terra";
|
|
||||||
oracle.model = "openai/gpt-5.6-terra";
|
|
||||||
momus.model = "openai/gpt-5.6-terra";
|
|
||||||
librarian.model = "openai/gpt-5.6-luna";
|
|
||||||
explore.model = "openai/gpt-5.6-luna";
|
|
||||||
atlas.model = "openai/gpt-5.6-luna";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ lib.mkMerge [
|
|||||||
User = "git";
|
User = "git";
|
||||||
AddKeysToAgent = "no";
|
AddKeysToAgent = "no";
|
||||||
};
|
};
|
||||||
|
"*.sfc.wide.ad.jp" = {
|
||||||
|
identityFile = "~/.ssh/id_ed25519_sk_rk";
|
||||||
|
identitiesOnly = true;
|
||||||
|
};
|
||||||
"*" = {
|
"*" = {
|
||||||
AddKeysToAgent = "no";
|
AddKeysToAgent = "no";
|
||||||
SetEnv.TERM = "xterm-256color";
|
SetEnv.TERM = "xterm-256color";
|
||||||
@@ -20,27 +24,9 @@ lib.mkMerge [
|
|||||||
};
|
};
|
||||||
|
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
Match exec "test -n \"$SSH_AUTH_SOCK\" && test -S \"$SSH_AUTH_SOCK\""
|
|
||||||
IdentityAgent $SSH_AUTH_SOCK
|
|
||||||
|
|
||||||
Match exec "test -S %d/.1password/agent.sock"
|
Match exec "test -S %d/.1password/agent.sock"
|
||||||
IdentityAgent %d/.1password/agent.sock
|
IdentityAgent %d/.1password/agent.sock
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
home.activation.generateSshKey = {
|
|
||||||
after = [ "writeBoundary" ];
|
|
||||||
before = [ ];
|
|
||||||
data = ''
|
|
||||||
key="$HOME/.ssh/id_ed25519"
|
|
||||||
if [ ! -f "$key" ]; then
|
|
||||||
umask 077
|
|
||||||
mkdir -p "$HOME/.ssh"
|
|
||||||
${pkgs.openssh}/bin/ssh-keygen -t ed25519 -N "" -f "$key" \
|
|
||||||
-C "moons@$(${pkgs.hostname}/bin/hostname || echo host)"
|
|
||||||
echo "Generated SSH key at $key"
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ in
|
|||||||
programs.vicinae = {
|
programs.vicinae = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
enableChromeIntegration = false;
|
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
font.size = 11;
|
font.size = 11;
|
||||||
close_on_focus_loss = true;
|
close_on_focus_loss = true;
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
programs.vicinae = {
|
programs.vicinae = {
|
||||||
|
|
||||||
|
package = pkgs.vicinae;
|
||||||
|
|
||||||
systemd = {
|
systemd = {
|
||||||
enable = true;
|
enable = true;
|
||||||
autoStart = true;
|
autoStart = true;
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{ inputs, pkgs, ... }:
|
||||||
|
let
|
||||||
|
unstable = inputs.nixpkgs-unstable.legacyPackages.${pkgs.stdenv.hostPlatform.system};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.packages = [ unstable.wl-find-cursor ];
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
description = "Wayland cursor locator";
|
||||||
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
homebrew = {
|
|
||||||
enable = true;
|
|
||||||
masApps = {
|
|
||||||
Xcode = 497799835;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
home.packages = [ pkgs.yt-dlp ];
|
|
||||||
}
|
|
||||||
@@ -4,12 +4,8 @@
|
|||||||
extensions = [
|
extensions = [
|
||||||
"catppuccin"
|
"catppuccin"
|
||||||
"nix"
|
"nix"
|
||||||
"dockerfile"
|
|
||||||
"terraform"
|
|
||||||
];
|
];
|
||||||
mutableUserSettings = false;
|
mutableUserSettings = false;
|
||||||
mutableUserKeymaps = false;
|
|
||||||
userKeymaps = import ./keymaps.nix;
|
|
||||||
|
|
||||||
userSettings = {
|
userSettings = {
|
||||||
agent = {
|
agent = {
|
||||||
@@ -40,9 +36,6 @@
|
|||||||
light = "Catppuccin Latte";
|
light = "Catppuccin Latte";
|
||||||
dark = "Catppuccin Mocha";
|
dark = "Catppuccin Mocha";
|
||||||
};
|
};
|
||||||
edit_predictions = {
|
|
||||||
provider = "copilot";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
context = "Editor && vim_mode == normal";
|
|
||||||
bindings = {
|
|
||||||
# This selected native-equivalent subset preserves Zed's Vim defaults for
|
|
||||||
# K, gd, grr, gri, gra, gO, ]d, [d, zM, zR, [b, and ]b.
|
|
||||||
"g r t" = "editor::GoToTypeDefinition";
|
|
||||||
"space space" = "pane::AlternateFile";
|
|
||||||
"space r n" = "editor::Rename";
|
|
||||||
"space c a" = "editor::ToggleCodeActions";
|
|
||||||
"space c f" = "editor::Format";
|
|
||||||
"space d l" = "editor::Hover";
|
|
||||||
"space e" = "project_panel::Toggle";
|
|
||||||
"space t t" = "terminal_panel::Toggle";
|
|
||||||
"space b c" = "pane::CloseActiveItem";
|
|
||||||
"space f f" = "file_finder::Toggle";
|
|
||||||
"space f g" = "pane::DeploySearch";
|
|
||||||
"space f b" = "tab_switcher::ToggleAll";
|
|
||||||
"space f s" = "outline::Toggle";
|
|
||||||
"space f shift-s" = "project_symbols::Toggle";
|
|
||||||
"space x x" = "diagnostics::Deploy";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# Keep normal-mode editor navigation out of terminals and other panels.
|
|
||||||
context = "Editor && vim_mode == normal && !menu";
|
|
||||||
bindings = {
|
|
||||||
"ctrl-h" = "workspace::ActivatePaneLeft";
|
|
||||||
"ctrl-j" = "workspace::ActivatePaneDown";
|
|
||||||
"ctrl-k" = "workspace::ActivatePaneUp";
|
|
||||||
"ctrl-l" = "workspace::ActivatePaneRight";
|
|
||||||
"ctrl-left" = "workspace::ActivatePaneLeft";
|
|
||||||
"ctrl-down" = "workspace::ActivatePaneDown";
|
|
||||||
"ctrl-up" = "workspace::ActivatePaneUp";
|
|
||||||
"ctrl-right" = "workspace::ActivatePaneRight";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -5,7 +5,10 @@
|
|||||||
modesetting.enable = true;
|
modesetting.enable = true;
|
||||||
open = true;
|
open = true;
|
||||||
|
|
||||||
powerManagement.enable = true;
|
powerManagement = {
|
||||||
|
enable = true;
|
||||||
|
kernelSuspendNotifier = true;
|
||||||
|
};
|
||||||
|
|
||||||
moduleParams.nvidia.NVreg_TemporaryFilePath = "/var/tmp";
|
moduleParams.nvidia.NVreg_TemporaryFilePath = "/var/tmp";
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ required on every supported host.
|
|||||||
| Profile | Supported host class |
|
| Profile | Supported host class |
|
||||||
| ------------------------------------ | --------------------------------------------- |
|
| ------------------------------------ | --------------------------------------------- |
|
||||||
| `base` | NixOS, macOS |
|
| `base` | NixOS, macOS |
|
||||||
| `interface.minimal` | NixOS, macOS with Home Manager |
|
|
||||||
| `interface.cli` | NixOS, macOS with Home Manager |
|
| `interface.cli` | NixOS, macOS with Home Manager |
|
||||||
| `interface.gui` | NixOS, macOS with Home Manager |
|
| `interface.gui` | NixOS, macOS with Home Manager |
|
||||||
| `interface.macos` | macOS |
|
| `interface.macos` | macOS |
|
||||||
@@ -37,15 +36,10 @@ required on every supported host.
|
|||||||
| `platform.laptop` | Physical NixOS laptop |
|
| `platform.laptop` | Physical NixOS laptop |
|
||||||
| `platform.thinkpad-x1` | Intel ThinkPad X1 running NixOS |
|
| `platform.thinkpad-x1` | Intel ThinkPad X1 running NixOS |
|
||||||
| `platform.vm` | UEFI QEMU NixOS guest with NFS client support |
|
| `platform.vm` | UEFI QEMU NixOS guest with NFS client support |
|
||||||
| `workload.deploy-rs-target` | NixOS |
|
|
||||||
| `workload.development` | NixOS, macOS with Home Manager |
|
| `workload.development` | NixOS, macOS with Home Manager |
|
||||||
| `workload.game` | NixOS, macOS |
|
| `workload.game` | NixOS, macOS |
|
||||||
| `workload.machine-learning` | NixOS with Home Manager |
|
|
||||||
| `workload.network-lab` | NixOS |
|
|
||||||
| `workload.personal` | NixOS, macOS with Home Manager |
|
| `workload.personal` | NixOS, macOS with Home Manager |
|
||||||
| `workload.photography` | NixOS with Home Manager |
|
|
||||||
| `workload.remote-access` | NixOS, macOS |
|
| `workload.remote-access` | NixOS, macOS |
|
||||||
| `workload.camera` | NixOS |
|
|
||||||
| `workload.server` | NixOS, macOS with Home Manager |
|
| `workload.server` | NixOS, macOS with Home Manager |
|
||||||
| `networking.tailscale-client` | NixOS, macOS |
|
| `networking.tailscale-client` | NixOS, macOS |
|
||||||
| `networking.tailscale-subnet-router` | NixOS |
|
| `networking.tailscale-subnet-router` | NixOS |
|
||||||
@@ -64,36 +58,18 @@ selects labwc. A daily-use macOS development machine can combine
|
|||||||
`interface.macos`, `workload.development`, and `workload.personal`. Hardware
|
`interface.macos`, `workload.development`, and `workload.personal`. Hardware
|
||||||
support does not implicitly select an interface or workload.
|
support does not implicitly select an interface or workload.
|
||||||
|
|
||||||
`platform.nixos` selects the shared network foundation and the clatd service.
|
|
||||||
VM, laptop, and desktop platform profiles inherit both.
|
|
||||||
|
|
||||||
`interface.minimal` provides SSH client access and key generation, Nano, htop,
|
|
||||||
btop, fastfetch, unzip, wget, Direnv, Git, GnuPG, nh, Zellij, and Zsh for remote
|
|
||||||
administration. `interface.cli` includes that baseline and adds the configured
|
|
||||||
Neovim, Yazi, and the remaining interactive command-line tools.
|
|
||||||
|
|
||||||
`workload.machine-learning` provides the Hugging Face Hub CLI for hosts used
|
|
||||||
to download and publish machine learning models and datasets.
|
|
||||||
|
|
||||||
`workload.network-lab` provides containerlab using its upstream NixOS module,
|
|
||||||
the Docker service, and the NanoKVM-USB desktop client with serial-port access.
|
|
||||||
It is selected by galleria and x1g13.
|
|
||||||
|
|
||||||
`workload.photography` provides darktable with AI support from the locked
|
|
||||||
unstable package set. Its ONNX Runtime uses CUDA when the NVIDIA hardware unit
|
|
||||||
is enabled, and CPU inference otherwise. Keep the default CUDA capabilities
|
|
||||||
and forward compatibility to reuse the CUDA binary cache; these targets include
|
|
||||||
galleria's RTX 3060 Ti. OpenCL drivers remain owned by hardware units.
|
|
||||||
|
|
||||||
`workload.deploy-rs-target` enables OpenSSH and provisions the `nixdeploy`
|
|
||||||
service account with the narrowly scoped passwordless commands required for
|
|
||||||
deploy-rs activation and rollback confirmation.
|
|
||||||
|
|
||||||
`workload.personal` provides Pear Desktop on both NixOS and macOS. Home Manager
|
`workload.personal` provides Pear Desktop on both NixOS and macOS. Home Manager
|
||||||
enables performance improvements, synced lyrics, tracker blocking, the album
|
enables performance improvements, synced lyrics, tracker blocking, the album
|
||||||
color theme, and custom output-device selection while preserving user-owned
|
color theme, and custom output-device selection while preserving user-owned
|
||||||
settings such as the selected device.
|
settings such as the selected device.
|
||||||
|
|
||||||
|
`workload.personal` also provides Handy for offline speech-to-text. It starts
|
||||||
|
hidden when the graphical session begins. On niri and labwc, `Ctrl+Space` is
|
||||||
|
owned by the compositor and invokes Handy's `--toggle-transcription` command;
|
||||||
|
Handy's own shortcut bindings are disabled on NixOS so it does not monitor
|
||||||
|
keyboard events under Wayland. Handy uses the Homebrew cask and starts at login
|
||||||
|
on macOS.
|
||||||
|
|
||||||
`workload.personal` provides ActivityWatch for local activity tracking. On
|
`workload.personal` provides ActivityWatch for local activity tracking. On
|
||||||
NixOS, its server and Wayland-compatible watcher run as Home Manager user
|
NixOS, its server and Wayland-compatible watcher run as Home Manager user
|
||||||
services. On macOS, the Homebrew cask starts at login.
|
services. On macOS, the Homebrew cask starts at login.
|
||||||
|
|||||||
@@ -8,21 +8,36 @@
|
|||||||
dust
|
dust
|
||||||
eza
|
eza
|
||||||
fd
|
fd
|
||||||
|
fastfetch
|
||||||
fzf
|
fzf
|
||||||
|
htop
|
||||||
jq
|
jq
|
||||||
lsof
|
lsof
|
||||||
nurl
|
nurl
|
||||||
ripgrep
|
ripgrep
|
||||||
tio
|
tio
|
||||||
unrar
|
unrar
|
||||||
traceroute
|
unzip
|
||||||
tcpdump
|
wget
|
||||||
iw
|
|
||||||
nmap
|
|
||||||
]
|
]
|
||||||
++ lib.optionals stdenv.isLinux [
|
++ lib.optionals stdenv.isLinux [
|
||||||
lm_sensors
|
lm_sensors
|
||||||
psmisc
|
psmisc
|
||||||
strace
|
strace
|
||||||
];
|
];
|
||||||
|
|
||||||
|
home.activation.generateSshKey = {
|
||||||
|
after = [ "writeBoundary" ];
|
||||||
|
before = [ ];
|
||||||
|
data = ''
|
||||||
|
key="$HOME/.ssh/id_ed25519"
|
||||||
|
if [ ! -f "$key" ]; then
|
||||||
|
umask 077
|
||||||
|
mkdir -p "$HOME/.ssh"
|
||||||
|
${pkgs.openssh}/bin/ssh-keygen -t ed25519 -N "" -f "$key" \
|
||||||
|
-C "moons@$(${pkgs.hostname}/bin/hostname || echo host)"
|
||||||
|
echo "Generated SSH key at $key"
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,17 @@
|
|||||||
description = "Cross-platform interactive command-line environment";
|
description = "Cross-platform interactive command-line environment";
|
||||||
|
|
||||||
includes = [
|
includes = [
|
||||||
"profiles.interface.minimal"
|
"applications.btop"
|
||||||
|
"applications.direnv"
|
||||||
|
"applications.git"
|
||||||
|
"applications.gnupg"
|
||||||
|
"applications.nh"
|
||||||
"applications.nix-index"
|
"applications.nix-index"
|
||||||
|
"applications.ssh"
|
||||||
"applications.vim"
|
"applications.vim"
|
||||||
"applications.yazi"
|
"applications.yazi"
|
||||||
|
"applications.zellij"
|
||||||
"applications.zoxide"
|
"applications.zoxide"
|
||||||
|
"applications.zsh"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
pkgs.playerctl
|
pkgs.playerctl
|
||||||
];
|
];
|
||||||
|
|
||||||
|
programs.noctalia.settings.wallpaper.enabled = false;
|
||||||
|
|
||||||
xdg.userDirs = {
|
xdg.userDirs = {
|
||||||
enable = true;
|
enable = true;
|
||||||
createDirectories = true;
|
createDirectories = true;
|
||||||
@@ -15,6 +17,5 @@
|
|||||||
publicShare = "$HOME/Public";
|
publicShare = "$HOME/Public";
|
||||||
templates = "$HOME/Templates";
|
templates = "$HOME/Templates";
|
||||||
videos = "$HOME/Videos";
|
videos = "$HOME/Videos";
|
||||||
projects = "$HOME/Projects";
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,15 +11,15 @@
|
|||||||
"applications.ghostty"
|
"applications.ghostty"
|
||||||
"applications.gtk"
|
"applications.gtk"
|
||||||
"applications.loupe"
|
"applications.loupe"
|
||||||
|
"applications.linux-wallpaperengine"
|
||||||
"applications.nautilus"
|
"applications.nautilus"
|
||||||
"applications.nani"
|
"applications.normcap"
|
||||||
"applications.papers"
|
"applications.papers"
|
||||||
"applications.qalculate-gtk"
|
"applications.qalculate-gtk"
|
||||||
"applications.resources"
|
"applications.resources"
|
||||||
"applications.vlc"
|
"applications.vlc"
|
||||||
"hardwares.graphics"
|
"hardwares.graphics"
|
||||||
"services.gvfs"
|
"services.gvfs"
|
||||||
"services.evremap"
|
|
||||||
"services.polkit-gnome"
|
"services.polkit-gnome"
|
||||||
"systems.audio"
|
"systems.audio"
|
||||||
"systems.fonts"
|
"systems.fonts"
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
home.packages = with pkgs; [
|
|
||||||
fastfetch
|
|
||||||
unzip
|
|
||||||
wget
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
description = "Minimal cross-platform command-line environment for remote administration";
|
|
||||||
|
|
||||||
includes = [
|
|
||||||
"applications.btop"
|
|
||||||
"applications.direnv"
|
|
||||||
"applications.git"
|
|
||||||
"applications.gnupg"
|
|
||||||
"applications.htop"
|
|
||||||
"applications.nano"
|
|
||||||
"applications.nh"
|
|
||||||
"applications.ssh"
|
|
||||||
"applications.zellij"
|
|
||||||
"applications.zsh"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
# every system sleep path; screen blanking while locked is handled by
|
# every system sleep path; screen blanking while locked is handled by
|
||||||
# services.swayidle in the graphical session.
|
# services.swayidle in the graphical session.
|
||||||
systemd.sleep.settings.Sleep = {
|
systemd.sleep.settings.Sleep = {
|
||||||
AllowSuspend = true;
|
|
||||||
AllowHibernation = false;
|
AllowHibernation = false;
|
||||||
AllowHybridSleep = false;
|
AllowHybridSleep = false;
|
||||||
AllowSuspendThenHibernate = false;
|
AllowSuspendThenHibernate = false;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
description = "Foundation shared by all NixOS platforms";
|
description = "Foundation shared by all NixOS platforms";
|
||||||
|
|
||||||
includes = [
|
includes = [
|
||||||
"services.clatd"
|
|
||||||
"services.kmscon"
|
"services.kmscon"
|
||||||
"systems.disko"
|
"systems.disko"
|
||||||
"systems.boot.base"
|
"systems.boot.base"
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
description = "Camera capture and virtual camera tools";
|
|
||||||
|
|
||||||
includes = [ "systems.boot.v4l2loopback" ];
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
gphoto2
|
|
||||||
ffmpeg
|
|
||||||
v4l-utils
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
description = "NixOS deploy-rs deployment target";
|
|
||||||
|
|
||||||
includes = [
|
|
||||||
"services.openssh"
|
|
||||||
"users.nixdeploy"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
bind
|
bind
|
||||||
bun
|
bun
|
||||||
nil
|
nil
|
||||||
python314
|
python312
|
||||||
uv
|
uv
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
"applications.claude"
|
"applications.claude"
|
||||||
"applications.codex"
|
"applications.codex"
|
||||||
"applications.codex-desktop"
|
"applications.codex-desktop"
|
||||||
"applications.codex-session-usage"
|
|
||||||
"applications.docker"
|
"applications.docker"
|
||||||
"applications.drawio"
|
"applications.drawio"
|
||||||
"applications.ghostty"
|
"applications.ghostty"
|
||||||
@@ -14,7 +13,6 @@
|
|||||||
"applications.java"
|
"applications.java"
|
||||||
"applications.opencode"
|
"applications.opencode"
|
||||||
"applications.vscode"
|
"applications.vscode"
|
||||||
"applications.xcode"
|
|
||||||
"applications.zed"
|
"applications.zed"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
description = "Machine learning tools";
|
|
||||||
|
|
||||||
includes = [ "applications.huggingface-cli" ];
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
description = "Network lab and hardware console environment";
|
|
||||||
|
|
||||||
includes = [
|
|
||||||
"applications.containerlab"
|
|
||||||
"applications.nanokvm-usb"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -6,8 +6,8 @@
|
|||||||
"applications.activitywatch"
|
"applications.activitywatch"
|
||||||
"applications.chrome"
|
"applications.chrome"
|
||||||
"applications.discord"
|
"applications.discord"
|
||||||
"applications.ffmpeg"
|
|
||||||
"applications.gnome-text-editor"
|
"applications.gnome-text-editor"
|
||||||
|
"applications.handy"
|
||||||
"applications.kde"
|
"applications.kde"
|
||||||
"applications.moonlight"
|
"applications.moonlight"
|
||||||
"applications.slack"
|
"applications.slack"
|
||||||
@@ -15,6 +15,5 @@
|
|||||||
"applications.obs"
|
"applications.obs"
|
||||||
"applications.nani"
|
"applications.nani"
|
||||||
"applications.thunderbird"
|
"applications.thunderbird"
|
||||||
"applications.yt-dlp"
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
description = "RAW photo development and editing";
|
|
||||||
|
|
||||||
includes = [ "applications.darktable" ];
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
_: {
|
|
||||||
services.clatd.enable = true;
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
{ config, primaryUser, ... }:
|
{ primaryUser, ... }:
|
||||||
{
|
{
|
||||||
hardware.nvidia-container-toolkit.enable = config.my.hardwares.nvidia.enable;
|
|
||||||
|
|
||||||
virtualisation.docker = {
|
virtualisation.docker = {
|
||||||
enable = true;
|
enable = true;
|
||||||
autoPrune = {
|
autoPrune = {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user