mirror of
https://github.com/moons-14/dotfiles.git
synced 2026-10-06 05:48:12 +09:00
Compare commits
74
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec3770502d | ||
|
|
fda29cd08d | ||
|
|
db0a440da4 | ||
|
|
76f5dce9c0 | ||
|
|
3b61457718 | ||
|
|
c9f1584797 | ||
|
|
d51948c307 | ||
|
|
9a38e9f614 | ||
|
|
2cb7e76ca1 | ||
|
|
749410e032 | ||
|
|
d43f19c20a | ||
|
|
32a3067cb0 | ||
|
|
6e60bd8886 | ||
|
|
bcf7ef56cf | ||
|
|
63e2008423 | ||
|
|
3b8147ff46 | ||
|
|
c84f257149 | ||
|
|
6347292c1d | ||
|
|
2a82433754 | ||
|
|
847ee17b29 | ||
|
|
95f74aabcd | ||
|
|
717572ae24 | ||
|
|
8086c9a7f3 | ||
|
|
eba23455d4 | ||
|
|
b3b1031364 | ||
|
|
366ff54403 | ||
|
|
456e9946f4 | ||
|
|
c104404e5b | ||
|
|
cb41932fec | ||
|
|
fa4b7ca404 | ||
|
|
847d33e83b | ||
|
|
b2c700e1e4 | ||
|
|
c1540d8764 | ||
|
|
5b8c3b1415 | ||
|
|
6743569789 | ||
|
|
70253fc451 | ||
|
|
5107b80173 | ||
|
|
2bdea522cb | ||
|
|
c113d0d46d | ||
|
|
fa50be8feb | ||
|
|
33ebef4a1e | ||
|
|
94048ef8d5 | ||
|
|
c7627fa1b0 | ||
|
|
d68da620ac | ||
|
|
5f0df47775 | ||
|
|
119342e564 | ||
|
|
1f066e8937 | ||
|
|
0a440e3da8 | ||
|
|
bdf93ac6bb | ||
|
|
9ae5da4d30 | ||
|
|
872436b170 | ||
|
|
c14325e29c | ||
|
|
45bc66e25f | ||
|
|
78ee2d41ec | ||
|
|
0b1ae13048 | ||
|
|
458b0a2cdb | ||
|
|
01179f3dc6 | ||
|
|
42949fc06c | ||
|
|
a7f514c0f9 | ||
|
|
9bed1c3e25 | ||
|
|
791b6baa83 | ||
|
|
349f49e496 | ||
|
|
3166c12448 | ||
|
|
4c459e4aa7 | ||
|
|
9b9141dd84 | ||
|
|
16e3fda275 | ||
|
|
ca36b07839 | ||
|
|
5ebcbb4abf | ||
|
|
f8fd8a3d99 | ||
|
|
16742d2fd7 | ||
|
|
15da7affaa | ||
|
|
548647fec7 | ||
|
|
bcbd08c225 | ||
|
|
a0ae83d24e |
@@ -357,6 +357,7 @@ modules/profiles/
|
|||||||
│ ├── labwc/
|
│ ├── labwc/
|
||||||
│ └── niri/
|
│ └── niri/
|
||||||
├── networking/
|
├── networking/
|
||||||
|
│ ├── homelab-cache-client/
|
||||||
│ ├── tailscale-client/
|
│ ├── tailscale-client/
|
||||||
│ └── tailscale-subnet-router/
|
│ └── tailscale-subnet-router/
|
||||||
├── platform/
|
├── platform/
|
||||||
@@ -367,7 +368,11 @@ modules/profiles/
|
|||||||
│ ├── desktop/
|
│ ├── desktop/
|
||||||
│ └── vm/
|
│ └── vm/
|
||||||
├── workload/
|
├── workload/
|
||||||
|
│ ├── camera/
|
||||||
│ ├── development/
|
│ ├── development/
|
||||||
|
│ ├── game/
|
||||||
|
│ ├── machine-learning/
|
||||||
|
│ ├── nix-builder/
|
||||||
│ ├── personal/
|
│ ├── personal/
|
||||||
│ ├── server/
|
│ ├── server/
|
||||||
│ └── remote-access/
|
│ └── remote-access/
|
||||||
@@ -602,6 +607,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.personal"
|
"workload.personal"
|
||||||
];
|
];
|
||||||
@@ -624,6 +630,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.personal"
|
"workload.personal"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
# 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
|
||||||
|
```
|
||||||
Generated
+737
-380
File diff suppressed because it is too large
Load Diff
@@ -38,12 +38,6 @@
|
|||||||
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";
|
||||||
|
|
||||||
@@ -66,6 +60,11 @@
|
|||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
deploy-rs = {
|
||||||
|
url = "github:serokell/deploy-rs";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
# Disk management
|
# Disk management
|
||||||
disko = {
|
disko = {
|
||||||
url = "github:nix-community/disko";
|
url = "github:nix-community/disko";
|
||||||
@@ -97,6 +96,13 @@
|
|||||||
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";
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
./deploy.nix
|
||||||
./formatter.nix
|
./formatter.nix
|
||||||
./git-hooks.nix
|
./git-hooks.nix
|
||||||
./registry.nix
|
./registry.nix
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
inputs,
|
||||||
|
self,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
flake.deploy = {
|
||||||
|
nodes.nix-builder = {
|
||||||
|
hostname = "nix-builder";
|
||||||
|
sshUser = "moons";
|
||||||
|
user = "root";
|
||||||
|
|
||||||
|
interactiveSudo = true;
|
||||||
|
remoteBuild = true;
|
||||||
|
autoRollback = true;
|
||||||
|
magicRollback = true;
|
||||||
|
|
||||||
|
profiles.system.path = inputs.deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.nix-builder;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
perSystem =
|
||||||
|
{ system, ... }:
|
||||||
|
{
|
||||||
|
apps.deploy = inputs.deploy-rs.apps.${system}.default;
|
||||||
|
checks = inputs.deploy-rs.lib.${system}.deployChecks self.deploy;
|
||||||
|
};
|
||||||
|
}
|
||||||
+8
-31
@@ -1,47 +1,20 @@
|
|||||||
{
|
{
|
||||||
nix-example = {
|
nix-builder = {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
stateVersion = "26.05";
|
stateVersion = "26.05";
|
||||||
user = "moons";
|
user = "moons";
|
||||||
path = ./nix-example;
|
path = ./nix-builder;
|
||||||
|
|
||||||
profiles = [
|
profiles = [
|
||||||
"base"
|
"base"
|
||||||
"interface.cli"
|
"interface.cli"
|
||||||
|
"networking.tailscale-client"
|
||||||
"platform.vm"
|
"platform.vm"
|
||||||
"workload.development"
|
"workload.nix-builder"
|
||||||
"workload.remote-access"
|
"workload.remote-access"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
ops = {
|
|
||||||
system = "x86_64-linux";
|
|
||||||
stateVersion = "26.05";
|
|
||||||
user = "moons";
|
|
||||||
path = ./ops;
|
|
||||||
|
|
||||||
profiles = [
|
|
||||||
"base"
|
|
||||||
"interface.cli"
|
|
||||||
"platform.vm"
|
|
||||||
"workload.remote-access"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
internal-app-01 = {
|
|
||||||
system = "x86_64-linux";
|
|
||||||
stateVersion = "26.05";
|
|
||||||
user = "moons";
|
|
||||||
path = ./internal-app-01;
|
|
||||||
|
|
||||||
profiles = [
|
|
||||||
"base"
|
|
||||||
"interface.cli"
|
|
||||||
"platform.vm"
|
|
||||||
"workload.server"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
installer = {
|
installer = {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
stateVersion = "26.05";
|
stateVersion = "26.05";
|
||||||
@@ -91,6 +64,7 @@
|
|||||||
"workload.game"
|
"workload.game"
|
||||||
"workload.personal"
|
"workload.personal"
|
||||||
];
|
];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
galleria = {
|
galleria = {
|
||||||
@@ -104,6 +78,7 @@
|
|||||||
"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"
|
||||||
@@ -111,7 +86,9 @@
|
|||||||
"security.fingerprint"
|
"security.fingerprint"
|
||||||
"workload.development"
|
"workload.development"
|
||||||
"workload.game"
|
"workload.game"
|
||||||
|
"workload.machine-learning"
|
||||||
"workload.personal"
|
"workload.personal"
|
||||||
|
"workload.camera"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,11 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
|
# 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,6 +8,13 @@
|
|||||||
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
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
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; [
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
imports = [ ./hardware-configuration.nix ];
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
# nix-builder bootstrap
|
||||||
|
|
||||||
|
The host configuration can be built before its cache signing secret exists.
|
||||||
|
Harmonia's socket remains stopped until SOPS installs the signing key at
|
||||||
|
`/run/secrets/harmonia/signing-key`.
|
||||||
|
|
||||||
|
## Proxmox storage layout
|
||||||
|
|
||||||
|
The host configuration expects three filesystems. Keep the build scratch space
|
||||||
|
separate from the store so a large build cannot fill the root filesystem.
|
||||||
|
|
||||||
|
| Mount point | Suggested size | Contents |
|
||||||
|
| -------------------- | -------------- | ------------------------------- |
|
||||||
|
| `/` | 48 GiB | NixOS and mutable system state |
|
||||||
|
| `/var/lib/nix-build` | 192 GiB | Disposable build scratch space |
|
||||||
|
| `/nix/store` | 1 TiB | Fleet closures and binary cache |
|
||||||
|
|
||||||
|
The build-server policy starts emergency store GC below 64 GiB free and aims
|
||||||
|
for 128 GiB free. Persistent roots under `/var/lib/nix-fleet/roots` protect the
|
||||||
|
latest fleet builds from that GC. It also limits Nix to two concurrent
|
||||||
|
derivations while allowing each derivation to use every vCPU assigned to the
|
||||||
|
VM.
|
||||||
|
|
||||||
|
For the two dedicated ext4 data filesystems, remove the default root-reserved
|
||||||
|
blocks once after formatting; keep the root filesystem's reserve intact:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo tune2fs -m 0 /dev/disk/by-label/nix-build
|
||||||
|
sudo tune2fs -m 0 /dev/disk/by-label/nix-store
|
||||||
|
```
|
||||||
|
|
||||||
|
## Initial deployment
|
||||||
|
|
||||||
|
Once the VM is reachable as `moons@nix-builder`, deploy it from the repository:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix run .#deploy -- .#nix-builder
|
||||||
|
```
|
||||||
|
|
||||||
|
deploy-rs uses the target's `ssh-ng` store, so the system closure is built on
|
||||||
|
the builder rather than copied from the laptop. Automatic and magic rollback
|
||||||
|
remain enabled.
|
||||||
|
|
||||||
|
## Add the host SOPS recipient
|
||||||
|
|
||||||
|
After the VM has a stable SSH host key, derive its age recipient:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh-keyscan -t ed25519 nix-builder 2>/dev/null | ssh-to-age
|
||||||
|
```
|
||||||
|
|
||||||
|
Add the recipient to `.sops.yaml` and add a creation rule for
|
||||||
|
`secrets/hosts/nix-builder/*.yaml`. The admin YubiKey recipient should remain in
|
||||||
|
the same key group for recovery.
|
||||||
|
|
||||||
|
## Generate the cache signing key
|
||||||
|
|
||||||
|
Run this on a trusted Nix machine, preferably with the temporary files on a
|
||||||
|
tmpfs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix-store --generate-binary-cache-key \
|
||||||
|
cache.app.homelabs.run-1 \
|
||||||
|
harmonia.private \
|
||||||
|
harmonia.public
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `secrets/hosts/nix-builder/system.yaml` with SOPS and store the complete
|
||||||
|
contents of `harmonia.private` at `harmonia.signing-key`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
harmonia:
|
||||||
|
signing-key: cache.app.homelabs.run-1:REDACTED
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy the complete contents of `harmonia.public` to
|
||||||
|
`modules/systems/nix/homelab-cache/public-key`. The private plaintext file must
|
||||||
|
not be committed or retained.
|
||||||
|
|
||||||
|
After committing both encrypted/public files, select
|
||||||
|
`networking.homelab-cache-client` on each client host.
|
||||||
|
|
||||||
|
Redeploy the builder and verify the cache after installing the secret:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix run .#deploy -- .#nix-builder
|
||||||
|
curl --fail http://nix-builder:5000/nix-cache-info
|
||||||
|
```
|
||||||
|
|
||||||
|
## Normal operation
|
||||||
|
|
||||||
|
Run `fleet-build` on the builder to build and root every NixOS host, or pass a
|
||||||
|
list of host names to build only those hosts. Run `fleet-deploy` with the normal
|
||||||
|
deploy-rs target syntax when additional fleet nodes have been added to
|
||||||
|
`flake/deploy.nix`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fleet-build
|
||||||
|
fleet-build x1g13 galleria
|
||||||
|
fleet-deploy .#nix-builder
|
||||||
|
```
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
fileSystems."/nix/store" = {
|
||||||
|
device = "/dev/disk/by-label/nix-store";
|
||||||
|
fsType = "ext4";
|
||||||
|
|
||||||
|
options = [
|
||||||
|
"noatime"
|
||||||
|
];
|
||||||
|
|
||||||
|
neededForBoot = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
fileSystems."/var/lib/nix-build" = {
|
||||||
|
device = "/dev/disk/by-label/nix-build";
|
||||||
|
fsType = "ext4";
|
||||||
|
|
||||||
|
options = [
|
||||||
|
"noatime"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
nix.settings.build-dir = "/var/lib/nix-build";
|
||||||
|
|
||||||
|
services.fstrim.enable = true;
|
||||||
|
}
|
||||||
+9
-5
@@ -1,8 +1,12 @@
|
|||||||
# Do not modify this file! It was generated by `nixos-generate-config` and may
|
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||||
# be overwritten by future invocations.
|
# and may be overwritten by future invocations. Please make changes
|
||||||
|
# to /etc/nixos/configuration.nix instead.
|
||||||
{ lib, modulesPath, ... }:
|
{ lib, modulesPath, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
|
imports = [
|
||||||
|
(modulesPath + "/profiles/qemu-guest.nix")
|
||||||
|
];
|
||||||
|
|
||||||
boot.initrd.availableKernelModules = [
|
boot.initrd.availableKernelModules = [
|
||||||
"ata_piix"
|
"ata_piix"
|
||||||
@@ -17,12 +21,12 @@
|
|||||||
boot.extraModulePackages = [ ];
|
boot.extraModulePackages = [ ];
|
||||||
|
|
||||||
fileSystems."/" = {
|
fileSystems."/" = {
|
||||||
device = "/dev/disk/by-uuid/1b12ab98-2537-4207-a3f4-bb8ba7b53b00";
|
device = "/dev/disk/by-uuid/49fc2e1c-7909-41cc-ac78-55b4d9a01e62";
|
||||||
fsType = "ext4";
|
fsType = "ext4";
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/boot" = {
|
fileSystems."/boot" = {
|
||||||
device = "/dev/disk/by-uuid/8365-C778";
|
device = "/dev/disk/by-uuid/40D4-ABBE";
|
||||||
fsType = "vfat";
|
fsType = "vfat";
|
||||||
options = [
|
options = [
|
||||||
"fmask=0077"
|
"fmask=0077"
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{ lib, ... }:
|
||||||
|
let
|
||||||
|
hostSecrets = ../../secrets/hosts/nix-builder/system.yaml;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./filesystem.nix
|
||||||
|
./hardware-configuration.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
sops.secrets = lib.mkIf (builtins.pathExists hostSecrets) {
|
||||||
|
"harmonia/signing-key" = {
|
||||||
|
sopsFile = hostSecrets;
|
||||||
|
restartUnits = [ "harmonia.service" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.interfaces."tailscale0".allowedTCPPorts = [ 5000 ];
|
||||||
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# 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/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";
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
{
|
|
||||||
imports = [ ./hardware-configuration.nix ];
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
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,9 +1,37 @@
|
|||||||
_: {
|
{
|
||||||
|
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=MiddleClickAutoscroll"
|
"--enable-features=${lib.concatStringsSep "," features}"
|
||||||
|
"--use-gl=angle"
|
||||||
|
"--use-angle=gl"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
{ 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,15 +4,7 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
programs.codexDesktopLinux = {
|
environment.systemPackages = [
|
||||||
enable = true;
|
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.chatgpt
|
||||||
cliPackage = inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.codex;
|
|
||||||
remoteControl.enable = true;
|
|
||||||
remoteMobileControl.enable = true;
|
|
||||||
computerUseUi.enable = false;
|
|
||||||
linuxFeatures = [
|
|
||||||
"appshots"
|
|
||||||
"open-target-discovery"
|
|
||||||
];
|
];
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
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
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
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,6 +1,36 @@
|
|||||||
{ inputs, pkgs, ... }:
|
|
||||||
{
|
{
|
||||||
home.packages = [
|
config,
|
||||||
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.codex
|
inputs,
|
||||||
];
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
configDirectory =
|
||||||
|
if config.home.preferXdgDirectories then
|
||||||
|
"${config.xdg.configHome}/codex"
|
||||||
|
else
|
||||||
|
"${config.home.homeDirectory}/.codex";
|
||||||
|
configFile = "${configDirectory}/config.toml";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
programs.codex = {
|
||||||
|
enable = true;
|
||||||
|
package = inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.codex;
|
||||||
|
|
||||||
|
skills = {
|
||||||
|
grilling = inputs.skills + "/skills/productivity/grilling";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Keep the repository copy as an initial value. Codex may mutate the live
|
||||||
|
# file between activations; each Home Manager switch resets it from here.
|
||||||
|
home.activation.resetCodexConfig = {
|
||||||
|
after = [ "writeBoundary" ];
|
||||||
|
before = [ ];
|
||||||
|
data = ''
|
||||||
|
${pkgs.coreutils}/bin/mkdir -p ${lib.escapeShellArg configDirectory}
|
||||||
|
${pkgs.coreutils}/bin/install -m 0600 ${./config.toml} ${lib.escapeShellArg configFile}
|
||||||
|
'';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
_: {
|
{
|
||||||
|
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";
|
||||||
@@ -16,6 +25,10 @@ _: {
|
|||||||
|
|
||||||
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"
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
home.packages = [ pkgs.ffmpeg ];
|
||||||
|
}
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
{ inputs, system, ... }: {
|
{ inputs, system, ... }: {
|
||||||
programs.ghostty = {
|
programs.ghostty = {
|
||||||
systemd.enable = true;
|
# Labwc's Close action correctly targets one xdg-toplevel, but Ghostty's
|
||||||
|
# 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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
homebrew.casks = [ "handy" ];
|
|
||||||
|
|
||||||
launchd.agents.handy = {
|
|
||||||
command = "/usr/bin/open -gja Handy --args --start-hidden";
|
|
||||||
serviceConfig.RunAtLoad = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
{
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
description = "Handy offline speech-to-text";
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
home.packages = [ pkgs.python314Packages.huggingface-hub ];
|
||||||
|
}
|
||||||
@@ -102,8 +102,6 @@ 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")
|
||||||
@@ -123,14 +121,13 @@ 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?toggle=true")
|
(execute "W-v" "vicinae vicinae://launch/clipboard/history")
|
||||||
(execute "W-j" "nani-translate-primary")
|
(execute "W-j" "nani-translate-primary")
|
||||||
(execute "W-S-j" "normcap-translate")
|
(execute "W-S-j" "nani-translate-ocr")
|
||||||
(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 "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")
|
||||||
|
|||||||
@@ -6,16 +6,11 @@
|
|||||||
}:
|
}:
|
||||||
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 = labwc;
|
package = unstable.labwc;
|
||||||
};
|
};
|
||||||
|
|
||||||
xdg.portal.config.labwc.default = [
|
xdg.portal.config.labwc.default = [
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
# 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[@]}"
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
{
|
|
||||||
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" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
description = "Wallpaper Engine backgrounds for Linux";
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
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,5 +1,78 @@
|
|||||||
_: {
|
{ 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
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,14 +162,6 @@ 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,28 +1,14 @@
|
|||||||
{ 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";
|
||||||
@@ -40,6 +26,18 @@ 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";
|
||||||
@@ -108,7 +106,7 @@ in
|
|||||||
"Mod+V" = {
|
"Mod+V" = {
|
||||||
action.spawn = [
|
action.spawn = [
|
||||||
"vicinae"
|
"vicinae"
|
||||||
"vicinae://launch/clipboard/history?toggle=true"
|
"vicinae://launch/clipboard/history"
|
||||||
];
|
];
|
||||||
hotkey-overlay.title = "Clipboard History";
|
hotkey-overlay.title = "Clipboard History";
|
||||||
};
|
};
|
||||||
@@ -119,7 +117,7 @@ in
|
|||||||
};
|
};
|
||||||
"Mod+Shift+J" = {
|
"Mod+Shift+J" = {
|
||||||
repeat = false;
|
repeat = false;
|
||||||
action.spawn = [ "normcap-translate" ];
|
action.spawn = [ "nani-translate-ocr" ];
|
||||||
hotkey-overlay.title = "OCR and Translate with Nani";
|
hotkey-overlay.title = "OCR and Translate with Nani";
|
||||||
};
|
};
|
||||||
"Mod+Ctrl+J" = {
|
"Mod+Ctrl+J" = {
|
||||||
@@ -153,13 +151,6 @@ in
|
|||||||
];
|
];
|
||||||
hotkey-overlay.title = "Find Cursor";
|
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 = [
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
description = "Fleet build and deploy command-line tools";
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
inputs,
|
||||||
|
pkgs,
|
||||||
|
primaryUser,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
system = pkgs.stdenv.hostPlatform.system;
|
||||||
|
deployRs = inputs.deploy-rs.packages.${system}.default;
|
||||||
|
|
||||||
|
fleetBuild = pkgs.writeShellApplication {
|
||||||
|
name = "fleet-build";
|
||||||
|
runtimeInputs = [
|
||||||
|
pkgs.jq
|
||||||
|
pkgs.nix
|
||||||
|
];
|
||||||
|
text = ''
|
||||||
|
flake_ref="''${FLAKE:-/home/${primaryUser}/dotfiles}"
|
||||||
|
|
||||||
|
if (( $# == 0 )); then
|
||||||
|
# Keep this pipeline inside command substitution so pipefail and
|
||||||
|
# writeShellApplication's errexit propagate evaluation failures.
|
||||||
|
host_lines="$(
|
||||||
|
nix eval --json "$flake_ref#nixosConfigurations" \
|
||||||
|
--apply 'configs: builtins.attrNames configs' |
|
||||||
|
jq -r '.[] | select(. != "installer")'
|
||||||
|
)"
|
||||||
|
if [[ -z "$host_lines" ]]; then
|
||||||
|
echo "No deployable NixOS hosts found in $flake_ref" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mapfile -t hosts <<< "$host_lines"
|
||||||
|
else
|
||||||
|
hosts=("$@")
|
||||||
|
fi
|
||||||
|
|
||||||
|
for host in "''${hosts[@]}"; do
|
||||||
|
nix build \
|
||||||
|
--out-link "/var/lib/nix-fleet/roots/build/$host" \
|
||||||
|
"$flake_ref#nixosConfigurations.$host.config.system.build.toplevel"
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
fleetDeploy = pkgs.writeShellApplication {
|
||||||
|
name = "fleet-deploy";
|
||||||
|
runtimeInputs = [ deployRs ];
|
||||||
|
text = ''
|
||||||
|
cd "''${FLAKE:-/home/${primaryUser}/dotfiles}" || exit 1
|
||||||
|
|
||||||
|
exec deploy \
|
||||||
|
--keep-result \
|
||||||
|
--result-path /var/lib/nix-fleet/roots/deploy \
|
||||||
|
"$@"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
environment.systemPackages = [
|
||||||
|
fleetBuild
|
||||||
|
fleetDeploy
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{ lib, pkgs }:
|
{ lib, pkgs }:
|
||||||
let
|
let
|
||||||
version = "0.46.0";
|
version = "0.56.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-yMrOpu1WIv2sGVgvY9qf2XCoX2AXMSqR2b8bQDRU6os=";
|
x86_64 = "sha256-hzCnAyiizm8ZDfE1ONEP6S2Pdnskclm+XdDBBhEYVqE=";
|
||||||
aarch64 = "sha256-pCp3NOlxFN6zeH67W04WGSPbUae+ktzR5vEunWqu00g=";
|
aarch64 = "sha256-vfcgDEFpORPymcRYmlqvsjhV4pU7lNC8Vd9FDPI9UjM=";
|
||||||
}
|
}
|
||||||
.${architecture};
|
.${architecture};
|
||||||
in
|
in
|
||||||
|
|||||||
@@ -13,14 +13,6 @@ 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";
|
||||||
@@ -50,7 +42,7 @@ in
|
|||||||
programs.noctalia = {
|
programs.noctalia = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
package = noctaliaPatched;
|
package = inputs.noctalia.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||||
|
|
||||||
systemd.enable = true;
|
systemd.enable = true;
|
||||||
|
|
||||||
@@ -165,7 +157,7 @@ in
|
|||||||
network-connection = {
|
network-connection = {
|
||||||
type = "custom_button";
|
type = "custom_button";
|
||||||
glyph = "access-point";
|
glyph = "access-point";
|
||||||
actions.left = "nm-connection-editor";
|
actions.left = "exec nm-connection-editor";
|
||||||
};
|
};
|
||||||
tray = {
|
tray = {
|
||||||
type = "tray";
|
type = "tray";
|
||||||
@@ -186,7 +178,7 @@ in
|
|||||||
"google-chrome"
|
"google-chrome"
|
||||||
"code"
|
"code"
|
||||||
"dev.zed.Zed"
|
"dev.zed.Zed"
|
||||||
"codex-desktop"
|
"chatgpt"
|
||||||
"vesktop"
|
"vesktop"
|
||||||
];
|
];
|
||||||
show_all_outputs = true;
|
show_all_outputs = true;
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
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()) {
|
|
||||||
@@ -792,6 +811,9 @@ void TaskbarWidget::create() {
|
|
||||||
}
|
|
||||||
if (data.button == BTN_LEFT) {
|
|
||||||
if (!cycleCandidates.empty()) {
|
|
||||||
+ if (cycleCandidates.size() > 1 && launchTaskbarOverview(current->appId)) {
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
std::size_t& cursor = m_groupedAppCycleCursor[cycleKey];
|
|
||||||
if (cursor >= cycleCandidates.size()) {
|
|
||||||
cursor = 0;
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
{ 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
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
description = "NormCap OCR screen capture";
|
|
||||||
|
|
||||||
includes = [
|
|
||||||
"applications.nani"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
@@ -2,5 +2,19 @@
|
|||||||
{
|
{
|
||||||
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";
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +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
|
||||||
'';
|
'';
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ 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,9 +8,6 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
programs.vicinae = {
|
programs.vicinae = {
|
||||||
|
|
||||||
package = pkgs.vicinae;
|
|
||||||
|
|
||||||
systemd = {
|
systemd = {
|
||||||
enable = true;
|
enable = true;
|
||||||
autoStart = true;
|
autoStart = true;
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
homebrew = {
|
||||||
|
enable = true;
|
||||||
|
masApps = {
|
||||||
|
Xcode = 497799835;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
home.packages = [ pkgs.yt-dlp ];
|
||||||
|
}
|
||||||
@@ -4,8 +4,11 @@
|
|||||||
extensions = [
|
extensions = [
|
||||||
"catppuccin"
|
"catppuccin"
|
||||||
"nix"
|
"nix"
|
||||||
|
"dockerfile"
|
||||||
];
|
];
|
||||||
mutableUserSettings = false;
|
mutableUserSettings = false;
|
||||||
|
mutableUserKeymaps = false;
|
||||||
|
userKeymaps = import ./keymaps.nix;
|
||||||
|
|
||||||
userSettings = {
|
userSettings = {
|
||||||
agent = {
|
agent = {
|
||||||
@@ -36,6 +39,9 @@
|
|||||||
light = "Catppuccin Latte";
|
light = "Catppuccin Latte";
|
||||||
dark = "Catppuccin Mocha";
|
dark = "Catppuccin Mocha";
|
||||||
};
|
};
|
||||||
|
edit_predictions = {
|
||||||
|
provider = "copilot";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
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,10 +5,7 @@
|
|||||||
modesetting.enable = true;
|
modesetting.enable = true;
|
||||||
open = true;
|
open = true;
|
||||||
|
|
||||||
powerManagement = {
|
powerManagement.enable = true;
|
||||||
enable = true;
|
|
||||||
kernelSuspendNotifier = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
moduleParams.nvidia.NVreg_TemporaryFilePath = "/var/tmp";
|
moduleParams.nvidia.NVreg_TemporaryFilePath = "/var/tmp";
|
||||||
|
|
||||||
|
|||||||
@@ -38,9 +38,13 @@ required on every supported host.
|
|||||||
| `platform.vm` | UEFI QEMU NixOS guest with NFS client support |
|
| `platform.vm` | UEFI QEMU NixOS guest with NFS client support |
|
||||||
| `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.nix-builder` | NixOS central build and binary-cache VM |
|
||||||
| `workload.personal` | NixOS, macOS with Home Manager |
|
| `workload.personal` | NixOS, macOS 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.homelab-cache-client` | NixOS, macOS with access to nix-builder |
|
||||||
| `networking.tailscale-client` | NixOS, macOS |
|
| `networking.tailscale-client` | NixOS, macOS |
|
||||||
| `networking.tailscale-subnet-router` | NixOS |
|
| `networking.tailscale-subnet-router` | NixOS |
|
||||||
| `security.fingerprint` | NixOS, macOS |
|
| `security.fingerprint` | NixOS, macOS |
|
||||||
@@ -58,18 +62,22 @@ 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.
|
||||||
|
|
||||||
|
`workload.machine-learning` provides the Hugging Face Hub CLI for hosts used
|
||||||
|
to download and publish machine learning models and datasets.
|
||||||
|
|
||||||
|
`workload.nix-builder` provides the central build policy, persistent fleet GC
|
||||||
|
roots, deploy-rs tooling, SOPS integration, and Harmonia binary cache. Network
|
||||||
|
reachability and remote shell access remain independent host selections.
|
||||||
|
|
||||||
|
`networking.homelab-cache-client` adds the internal Harmonia substituter and
|
||||||
|
its trusted public key. It requires the public key generated during
|
||||||
|
`hosts/nix-builder/README.md` bootstrap.
|
||||||
|
|
||||||
`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.
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
pkgs.playerctl
|
pkgs.playerctl
|
||||||
];
|
];
|
||||||
|
|
||||||
programs.noctalia.settings.wallpaper.enabled = false;
|
|
||||||
|
|
||||||
xdg.userDirs = {
|
xdg.userDirs = {
|
||||||
enable = true;
|
enable = true;
|
||||||
createDirectories = true;
|
createDirectories = true;
|
||||||
@@ -17,5 +15,6 @@
|
|||||||
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.normcap"
|
"applications.nani"
|
||||||
"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"
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
description = "Use the homelab Harmonia binary cache";
|
||||||
|
|
||||||
|
includes = [ "systems.nix.homelab-cache" ];
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
# 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;
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
sops.secrets."users/moons/hashedPassword" = {
|
||||||
|
sopsFile = ../../../secrets/common/system.yaml;
|
||||||
|
neededForUsers = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
description = "Camera capture and virtual camera tools";
|
||||||
|
|
||||||
|
includes = [ "systems.boot.v4l2loopback" ];
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
gphoto2
|
||||||
|
ffmpeg
|
||||||
|
v4l-utils
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
bind
|
bind
|
||||||
bun
|
bun
|
||||||
nil
|
nil
|
||||||
python312
|
python314
|
||||||
uv
|
uv
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
"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"
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
"applications.java"
|
"applications.java"
|
||||||
"applications.opencode"
|
"applications.opencode"
|
||||||
"applications.vscode"
|
"applications.vscode"
|
||||||
|
"applications.xcode"
|
||||||
"applications.zed"
|
"applications.zed"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
description = "Machine learning tools";
|
||||||
|
|
||||||
|
includes = [ "applications.huggingface-cli" ];
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
description = "Central Nix builder, deploy controller, and binary cache";
|
||||||
|
|
||||||
|
includes = [
|
||||||
|
"applications.nix-fleet"
|
||||||
|
"services.harmonia"
|
||||||
|
"systems.nix.build-server"
|
||||||
|
"systems.sops"
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -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,5 +15,6 @@
|
|||||||
"applications.obs"
|
"applications.obs"
|
||||||
"applications.nani"
|
"applications.nani"
|
||||||
"applications.thunderbird"
|
"applications.thunderbird"
|
||||||
|
"applications.yt-dlp"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
services.evremap = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
device_name = "VXE VXE Mouse 1K Dongle Mouse";
|
||||||
|
|
||||||
|
remap = [
|
||||||
|
{
|
||||||
|
input = [ "BTN_SIDE" ];
|
||||||
|
output = [ "KEY_LEFTMETA" ];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
input = [ "BTN_EXTRA" ];
|
||||||
|
output = [ "BTN_SIDE" ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
description = "Harmonia binary cache backed by the local Nix store";
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
let
|
||||||
|
signingKeyPath = "/run/secrets/harmonia/signing-key";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.harmonia.cache = {
|
||||||
|
enable = true;
|
||||||
|
signKeyPaths = [ signingKeyPath ];
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
bind = "0.0.0.0:5000";
|
||||||
|
priority = 30;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Keep activation usable while the host-specific SOPS secret is bootstrapped.
|
||||||
|
# Once the secret exists, starting the socket also starts Harmonia on demand.
|
||||||
|
systemd.sockets.harmonia.unitConfig.ConditionPathExists = signingKeyPath;
|
||||||
|
systemd.services.harmonia.unitConfig.ConditionPathExists = signingKeyPath;
|
||||||
|
}
|
||||||
@@ -10,6 +10,8 @@ let
|
|||||||
brightnessState = "$XDG_RUNTIME_DIR/swayidle-brightness";
|
brightnessState = "$XDG_RUNTIME_DIR/swayidle-brightness";
|
||||||
|
|
||||||
onBattery = pkgs.writeShellScript "swayidle-on-battery" ''
|
onBattery = pkgs.writeShellScript "swayidle-on-battery" ''
|
||||||
|
[ "''${SWAYIDLE_ASSUME_AC:-0}" = 1 ] && exit 1
|
||||||
|
|
||||||
for supply in /sys/class/power_supply/*; do
|
for supply in /sys/class/power_supply/*; do
|
||||||
[ -f "$supply/type" ] || continue
|
[ -f "$supply/type" ] || continue
|
||||||
[ "$(< "$supply/type")" = "Battery" ] || continue
|
[ "$(< "$supply/type")" = "Battery" ] || continue
|
||||||
|
|||||||
@@ -21,29 +21,5 @@ in
|
|||||||
pulse.enable = true;
|
pulse.enable = true;
|
||||||
jack.enable = true;
|
jack.enable = true;
|
||||||
wireplumber.enable = true;
|
wireplumber.enable = true;
|
||||||
|
|
||||||
extraConfig.pipewire."90-echo-cancel.conf" = {
|
|
||||||
"context.modules" = [
|
|
||||||
{
|
|
||||||
name = "libpipewire-module-echo-cancel";
|
|
||||||
|
|
||||||
args = {
|
|
||||||
"library.name" = "aec/libspa-aec-webrtc";
|
|
||||||
|
|
||||||
"monitor.mode" = true;
|
|
||||||
|
|
||||||
"capture.props" = {
|
|
||||||
"node.name" = "echo_cancel_capture";
|
|
||||||
"node.description" = "Echo Cancel Capture";
|
|
||||||
};
|
|
||||||
|
|
||||||
"source.props" = {
|
|
||||||
"node.name" = "echo_cancel_source";
|
|
||||||
"node.description" = "Echo Cancelled Microphone";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{ pkgs, lib, ... }:
|
{ pkgs, lib, ... }:
|
||||||
{
|
{
|
||||||
boot.loader.systemd-boot.configurationLimit = lib.mkDefault 8;
|
boot.loader.systemd-boot.configurationLimit = lib.mkDefault 8;
|
||||||
boot.kernelPackages = pkgs.linuxPackages_latest;
|
boot.kernelPackages = pkgs.linuxPackages;
|
||||||
programs.nix-ld.enable = true;
|
programs.nix-ld.enable = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
|
boot = {
|
||||||
|
extraModulePackages = [ config.boot.kernelPackages.v4l2loopback ];
|
||||||
|
kernelModules = [ "v4l2loopback" ];
|
||||||
|
extraModprobeConfig = ''
|
||||||
|
options v4l2loopback devices=1 video_nr=42 card_label="LUMIX S9" exclusive_caps=1
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
description = "Central Nix build server policy and persistent fleet roots";
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
{ primaryUser, ... }:
|
||||||
|
let
|
||||||
|
GiB = 1024 * 1024 * 1024;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
nix = {
|
||||||
|
nrBuildUsers = 64;
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
# Limit concurrent derivations so build scratch and memory usage remain
|
||||||
|
# bounded. Each derivation may still use every vCPU exposed to the VM.
|
||||||
|
max-jobs = 2;
|
||||||
|
cores = 0;
|
||||||
|
|
||||||
|
# Keep enough room for large desktop, browser, and CUDA closures.
|
||||||
|
min-free = 64 * GiB;
|
||||||
|
max-free = 128 * GiB;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.nix-daemon.serviceConfig = {
|
||||||
|
MemoryAccounting = true;
|
||||||
|
MemoryMax = "90%";
|
||||||
|
OOMScoreAdjust = 500;
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d /var/lib/nix-fleet 0750 ${primaryUser} users - -"
|
||||||
|
"d /var/lib/nix-fleet/roots 0750 ${primaryUser} users - -"
|
||||||
|
"d /var/lib/nix-fleet/roots/build 0750 ${primaryUser} users - -"
|
||||||
|
"d /var/lib/nix-fleet/roots/deploy 0750 ${primaryUser} users - -"
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -7,14 +7,18 @@
|
|||||||
"flakes"
|
"flakes"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
connect-timeout = 10;
|
||||||
|
|
||||||
extra-substituters = [
|
extra-substituters = [
|
||||||
"https://cache.nixos.org"
|
"https://cache.nixos.org"
|
||||||
"https://nix-community.cachix.org"
|
"https://nix-community.cachix.org"
|
||||||
"https://moons-dotfiles.cachix.org"
|
"https://moons-dotfiles.cachix.org"
|
||||||
"https://noctalia.cachix.org"
|
"https://noctalia.cachix.org"
|
||||||
"https://vicinae.cachix.org"
|
"https://vicinae.cachix.org"
|
||||||
|
"https://ghostty.cachix.org"
|
||||||
"https://cache.numtide.com"
|
"https://cache.numtide.com"
|
||||||
"https://codex-desktop-linux.cachix.org"
|
"https://codex-desktop-linux.cachix.org"
|
||||||
|
"https://cuda-maintainers.cachix.org"
|
||||||
];
|
];
|
||||||
|
|
||||||
extra-trusted-public-keys = [
|
extra-trusted-public-keys = [
|
||||||
@@ -23,8 +27,10 @@
|
|||||||
"moons-dotfiles.cachix.org-1:WHoroKiNScG2/dpxHHL1I0qVmvuQhJbEAP+DS2j9Rr0="
|
"moons-dotfiles.cachix.org-1:WHoroKiNScG2/dpxHHL1I0qVmvuQhJbEAP+DS2j9Rr0="
|
||||||
"noctalia.cachix.org-1:pCOR47nnMEo5thcxNDtzWpOxNFQsBRglJzxWPp3dkU4="
|
"noctalia.cachix.org-1:pCOR47nnMEo5thcxNDtzWpOxNFQsBRglJzxWPp3dkU4="
|
||||||
"vicinae.cachix.org-1:1kDrfienkGHPYbkpNj1mWTr7Fm1+zcenzgTizIcI3oc="
|
"vicinae.cachix.org-1:1kDrfienkGHPYbkpNj1mWTr7Fm1+zcenzgTizIcI3oc="
|
||||||
|
"ghostty.cachix.org-1:QB389yTa6gTyneehvqG58y0WnHjQOqgnA+wBnpWWxns="
|
||||||
"niks3.numtide.com-1:DTx8wZduET09hRmMtKdQDxNNthLQETkc/yaX7M4qK0g="
|
"niks3.numtide.com-1:DTx8wZduET09hRmMtKdQDxNNthLQETkc/yaX7M4qK0g="
|
||||||
"codex-desktop-linux.cachix.org-1:nX/xy6AdK9hQE24A8ALGjkCKj2ObFmcnemiL5Cid4nk="
|
"codex-desktop-linux.cachix.org-1:nX/xy6AdK9hQE24A8ALGjkCKj2ObFmcnemiL5Cid4nk="
|
||||||
|
"cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E="
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{ lib, ... }:
|
||||||
|
let
|
||||||
|
publicKeyFile = ./public-key;
|
||||||
|
hasPublicKey = builtins.pathExists publicKeyFile;
|
||||||
|
publicKey = if hasPublicKey then lib.removeSuffix "\n" (builtins.readFile publicKeyFile) else "";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = hasPublicKey;
|
||||||
|
message = ''
|
||||||
|
systems.nix.homelab-cache requires
|
||||||
|
modules/systems/nix/homelab-cache/public-key
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
nix.settings = lib.mkIf hasPublicKey {
|
||||||
|
extra-substituters = [ "http://nix-builder:5000" ];
|
||||||
|
extra-trusted-public-keys = [ publicKey ];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
description = "Homelab Harmonia binary-cache client settings";
|
||||||
|
}
|
||||||
@@ -1,8 +1,3 @@
|
|||||||
{
|
{
|
||||||
services.pcscd.enable = true;
|
services.pcscd.enable = true;
|
||||||
|
|
||||||
sops.secrets."users/moons/hashedPassword" = {
|
|
||||||
sopsFile = ../../../secrets/common/system.yaml;
|
|
||||||
neededForUsers = true;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
imports = [
|
imports = [
|
||||||
./dotnix.nix
|
./dotnix.nix
|
||||||
./android.nix
|
./android.nix
|
||||||
|
./ios.nix
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
_: {
|
||||||
|
perSystem =
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
installIosSimulator = pkgs.writeShellApplication {
|
||||||
|
name = "ios-simulator-install";
|
||||||
|
text = ''
|
||||||
|
if [[ "$(/usr/bin/uname -s)" != "Darwin" ]]; then
|
||||||
|
echo "ios-simulator-install is only supported on macOS." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
xcode_app="/Applications/Xcode.app"
|
||||||
|
developer_dir="$xcode_app/Contents/Developer"
|
||||||
|
|
||||||
|
if [[ ! -d "$developer_dir" ]]; then
|
||||||
|
echo "Xcode is not installed at $xcode_app." >&2
|
||||||
|
echo "Apply the m2 nix-darwin configuration first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
current_developer_dir="$(/usr/bin/xcode-select -p 2>/dev/null || true)"
|
||||||
|
if [[ "$current_developer_dir" != "$developer_dir" ]]; then
|
||||||
|
echo "Selecting stable Xcode..."
|
||||||
|
/usr/bin/sudo /usr/bin/xcode-select --switch "$developer_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Installing Xcode first-launch components..."
|
||||||
|
/usr/bin/sudo /usr/bin/xcodebuild -runFirstLaunch
|
||||||
|
|
||||||
|
echo "Checking for newer hardware support..."
|
||||||
|
/usr/bin/xcodebuild -runFirstLaunch -checkForNewerComponents
|
||||||
|
|
||||||
|
echo "Downloading and installing the latest iOS Simulator runtime..."
|
||||||
|
/usr/bin/xcodebuild -downloadPlatform iOS
|
||||||
|
|
||||||
|
echo
|
||||||
|
/usr/bin/xcodebuild -version
|
||||||
|
/usr/bin/xcrun simctl list runtimes
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells.ios = pkgs.mkShell {
|
||||||
|
packages = [ installIosSimulator ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user