Compare commits

...

91 Commits

Author SHA1 Message Date
1ac96316ea feat: re-enable affine service
All checks were successful
Flake checker / Build Nix targets (pull_request) Successful in 9m32s
2026-02-23 17:05:03 +05:30
8d636ce194 refactor(matrix): simplify LiveKit configuration to use services.livekit and services.lk-jwt-service 2026-02-23 16:32:14 +05:30
bbeed99f43 refactor(affine): use Docker network option instead of --network flag 2026-02-23 16:05:09 +05:30
7e6ece1b0d feat(matrix): add LiveKit support with firewall and systemd services 2026-02-23 15:49:50 +05:30
60952a0e7f feat(programs): add yq package to home programs 2026-02-23 14:43:49 +05:30
738013df66 refactor: update mbsync settings for Fastmail and Neomutt 2026-02-22 15:32:38 +05:30
34160d0de4 feat: Updated notifications
All checks were successful
Flake checker / Build Nix targets (push) Successful in 9m27s
2026-02-22 15:16:10 +05:30
02b8a16f41 feat(cargo): add pkgs metadata alias
All checks were successful
Flake checker / Build Nix targets (push) Successful in 9m33s
2026-02-20 03:42:46 +05:30
684f6fdea5 fix(apps): make playerctl conditional to ryu device only 2026-02-20 03:42:44 +05:30
7ef1785a0f feat: Added caldav 2026-02-20 03:08:24 +05:30
49c0c607d8 feat: Added stuff 2026-02-20 02:01:24 +05:30
ab52b423ee feat: Move stuff into programs / apps in ryu 2026-02-19 23:03:52 +05:30
f852a73d47 feat: Updated to latest nixpkgs-unstable 2026-02-19 21:16:08 +05:30
998ebc1164 feat(programs): add jujutsu(jj) package
All checks were successful
Flake checker / Build Nix targets (push) Successful in 9m41s
2026-02-19 13:51:12 +05:30
9acb378e5f feat: disable some services and disable root login from ssh altogether 2026-02-19 13:41:40 +05:30
dca434c0ba Enable Audacity and add local Ollama provider configuration
- Remove comment from audacity.nix to enable Audacity application
- Add Ollama provider configuration for local LLM access
- Configure glm-4.7-flash model with custom base URL
2026-02-19 00:19:08 +05:30
c22ff38874 feat: Added affine 2026-02-18 18:03:06 +05:30
0591868be3 feat: Added affine server 2026-02-18 17:23:05 +05:30
e249f13313 feat: Vertical to horizontal secondary monitor 3
All checks were successful
Flake checker / Build Nix targets (push) Successful in 9m37s
2026-02-16 03:17:34 +05:30
4ecf045deb feat: Added ip target for ignore ip 2026-02-16 02:48:03 +05:30
05d1890b01 feat: Added steamdeck deploy target
All checks were successful
Flake checker / Build Nix targets (push) Successful in 9m35s
2026-02-16 02:21:06 +05:30
2babff5576 feat: Added cloudflare cli to add / remove dns entries from cli 2026-02-12 19:04:13 +05:30
aa7c26516c feat: Added gitea runner
All checks were successful
Flake checker / Build Nix targets (push) Successful in 9m33s
2026-02-12 16:21:36 +05:30
a1369cbb41 feat(attic): Use env variable for attic login
All checks were successful
Flake checker / Build Nix targets (push) Successful in 29m34s
2026-02-11 19:53:05 +05:30
54c5cf932d feat: Added attic-client 2026-02-11 17:53:27 +05:30
bb68711814 fix: use tcp instead of unix sockets for attic
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-11 17:07:40 +05:30
6b31922615 feat: Added attic ATTIC_SERVER_TOKEN_RS256_SECRET_BASE64
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-11 16:56:23 +05:30
21e779c304 fix: Macos fixes
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-11 16:30:38 +05:30
e718da413b feat: Replace deprecated options from navidrome
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-11 04:48:39 +05:30
98989afdec feat: upgrade to excalidraw-full 2026-02-11 04:27:14 +05:30
3a97de6af2 fix: Matrix server fix
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-11 03:55:29 +05:30
66b7a31943 feat: Update to latest nix 2026-02-10 23:14:12 +05:30
ddb53d879e feat: Added matrix 2026-02-10 22:25:37 +05:30
e403e47c28 feat: Added tuwunel 2026-02-10 14:24:39 +05:30
d8b3d6fb09 chore: Update flake.nix
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-07 02:42:39 +05:30
91d6863d60 feat: Change wallpapers
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-06 12:46:33 +05:30
618e5593e7 feat: Update hyprland.conf 2026-02-06 10:46:10 +05:30
e1c9a27ca3 feat: added libnotify
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-05 13:56:34 +05:30
7a58571c03 feat: disable default.clock.rate use allowed-rates 2026-02-05 12:48:21 +05:30
768caf9882 feat: Unify all of the nixos substituters
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-04 23:33:40 +05:30
e07d6a44a3 feat: Update to latest nixos 2026-02-04 23:21:42 +05:30
97d8c17436 feat: auto generate remmina desktop entries 2026-02-04 22:37:11 +05:30
89fd861c20 feat: Re-enable retroarch
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-04 02:51:32 +05:30
cf30dc9f6c feat: Remove pipewire from configuration 2026-02-03 23:40:24 +05:30
b88704bf1f feat: Update AGENTS.md
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-03 22:15:52 +05:30
eb63ef2585 feat: Use lower latency for pipewire 64 48000
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-03 22:05:20 +05:30
d688fc0eef feat: Added audio stuff
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-03 21:10:47 +05:30
63a4fba675 feat: added stuff 2026-02-03 21:10:47 +05:30
8fedc57570 feat(opencode): add support for kuro device
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-03 13:24:11 +05:30
dd322cb71c docs: add example of how to add secrets
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-02 04:42:32 +05:30
23b5917620 refactor: update monitoring target labels and jellyfin caddy config 2026-02-02 02:34:28 +05:30
5cecce74e8 chore(config): reduce ironbar favorites, disable cadvisor, update pihole hostname for the extractor
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-02 01:07:00 +05:30
15853f918a chore(services): delete command-runner.nix and its entry in default.nix
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-01 22:01:37 +05:30
22d619b3ce refactor(monitoring): dashboard provisioning, sops secret, exportarr off 2026-02-01 21:09:52 +05:30
d5396917c3 chore: fmt 2026-02-01 19:52:48 +05:30
a7d4a88741 feat: Update ironbar 2026-02-01 19:52:06 +05:30
2f901052f1 feat: Added grafana 2026-02-01 19:51:51 +05:30
56f1ba896c feat: Added opencode.nvim 2026-02-01 18:59:00 +05:30
9607e8f3a4 feat: Added agents.md
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-01 18:30:57 +05:30
41f5da953a feat: Disable terraria 2026-02-01 18:07:19 +05:30
a444694054 fix: Don't remove resolved.enable = false else it'll fuck up ssh into tsuba
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
This is a dns issue where if we dont explicitly disable it then it
conflicts with the 53 port from the pihole container and we can't ssh
into the device anymore
2026-02-01 02:53:38 +05:30
62dd4d3713 feat: comment out resolved for tsuba
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-02-01 02:22:23 +05:30
da8f61ca5d feat: Disable ssh enableDefaultConfig 2026-02-01 02:17:24 +05:30
1bb14d4c62 feat: Update resolved configuration 2026-02-01 02:12:30 +05:30
d25ad73b3b feat: Added blobdrop
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-29 20:21:18 +05:30
2913f0c8e1 fix(scripts): correct aichat role syntax
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-28 14:34:31 +05:30
fb7c219cf2 feat: Disable mpv on macos
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-28 13:49:31 +05:30
581fa74f19 feat: Add embedding model and extraPackages to aichat
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-27 16:37:57 +05:30
3f1f23391a feat: Disable nixvim grammarPackages for now because of is-not treesitter
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-26 23:54:38 +05:30
ddb0345587 feat: Update use local model
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-26 20:59:27 +05:30
99494b8777 feat: Remove command runner 2026-01-26 20:55:15 +05:30
4c385b2653 feat: Update to latest flake.lock
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-26 01:06:30 +05:30
f32d7d3643 feat: Added hytale
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-25 15:30:45 +05:30
ab4c22592a feat(games): add Hytale game module and Flatpak support
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-24 23:50:55 +05:30
869778df2a feat(nix): integrate cratesNix across Darwin and home modules
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-23 16:27:52 +05:30
0a2ad32dfb feat: Use different partition for swapfile
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-23 12:59:50 +05:30
230547eb92 feat: extend ghostty shader, add shadps4 builds, update nix, homepage
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-21 20:21:25 +05:30
3beb85c474 chore(flake): update flake.lock 2026-01-21 10:41:33 +05:30
101331cbc9 refactor: switch ping to siteMonitor and enable GLSL analyzer 2026-01-21 02:09:15 +05:30
d803dd9dc8 refactor(nixos): add ping to homepage 2026-01-20 17:00:57 +05:30
509a9b49ed feat(nixos): enable immich ml; bind localhost; add ollama env 2026-01-18 21:35:15 +05:30
a97ff2c46d chore(flake): update flake.lock
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-15 02:16:54 +05:30
6453bb62a1 feat(kellnr): add sops config and docs flag, dynamic domain vhost
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-14 12:08:19 +05:30
67305549bc feat: Added kellnr
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-14 11:45:10 +05:30
6ff14a1aa4 feat(vicinae): Adde pactl for sound plugin
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-13 17:14:45 +05:30
9a6d19b101 feat(atuin): add macOS launchd daemon agent
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-13 16:23:45 +05:30
2494e8ce83 feat(yazi): add config arg and preview cache_dir
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-13 16:01:52 +05:30
f90f84b3f7 feat(overlays): override libfprint to CS9711 fork with deps
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-13 15:36:16 +05:30
3db69c9e41 chore(darwin): prune kuro packages, update shiro casks, add 1password
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-13 15:23:12 +05:30
ac55fa4426 refactor: update aichat model; add atuin daemon; cleanup gui
Some checks failed
Flake checker / Build Nix targets (push) Has been cancelled
2026-01-13 15:20:13 +05:30
5a195af336 feat(home): added binwalk 2026-01-13 14:46:19 +05:30
127 changed files with 3799 additions and 5264 deletions

1
.ignore Normal file
View File

@@ -0,0 +1 @@
*.lock

198
AGENTS.md Normal file
View File

@@ -0,0 +1,198 @@
# Agent Guidelines for NixOS/nix-darwin Dotfiles
This repository contains NixOS, nix-darwin, and Home Manager configurations in Nix. You are a sysadmin managing server configurations and deployments.
## Build, Test, and Deployment Commands
### Build and Apply Configurations
**Linux (NixOS):**
```bash
just build # Build configuration
just install cores='32' # Apply with 32 cores
sudo nixos-rebuild test --fast --flake . # Test without activation
sudo nixos-rebuild switch --rollback --flake . # Rollback
```
**macOS (nix-darwin):**
```bash
just build # Build configuration
just install # Apply configuration
```
**Home Manager:**
```bash
just home
```
### Deploy to Remote Machines (deploy-rs)
```bash
deploy -s .#ryu # Desktop (x86_64-linux)
deploy -s .#tako # Server (x86_64-linux)
deploy -s .#tsuba # Raspberry Pi (aarch64-linux)
deploy -s .#kuro # MacBook M4 Pro (aarch64-darwin)
deploy -s .#shiro # Mac Mini M4 (aarch64-darwin)
```
### Validation and Formatting
```bash
nix flake check --show-trace # Check flake for errors
alejandra fmt . # Format all files
alejandra fmt <file>.nix # Format single file
```
## Directory Structure
- `flake.nix` - Main entry point, device definitions
- `nixos/` - NixOS machine configs (ryu, tako, tsuba)
- `darwin/` - macOS machine configs (kuro, shiro)
- `home/` - Home Manager modules (programs/, services/, apps/)
- `modules/` - Custom modules (nixos/, darwin/, home/)
- `secrets/` - SOPS encrypted secrets
- `overlays.nix`, `deploy.nix`, `sops.nix`, `stylix.nix` - Config files
## Code Style Guidelines
### Nix Language Conventions
**File Structure:**
```nix
{inputs, config, pkgs, lib, device, ...}: {
# Configuration here
}
```
**Imports:**
- Order: `inputs`, `config`, `pkgs`, `lib`, `device`, custom params, `...`
- Use set destructuring for clarity
**Formatting:**
- Use `alejandra` formatter (run before committing)
- 2-space indentation
- Trailing commas in lists and attribute sets
**Naming Conventions:**
- Files: lowercase-with-hyphens (e.g., `my-module.nix`)
- Attributes: camelCase (e.g., `enableMyFeature`)
- Functions: camelCase (e.g., `mkDevice`)
- Constants: UPPER_SNAKE_CASE (e.g., `API_KEY`)
- Device names: lowercase (e.g., `ryu`, `tako`)
**Let Expressions:**
```nix
with lib; let
cfg = config.programs.myProgram;
in {
options = { ... };
config = mkIf cfg.enable { ... };
}
```
**Conditionals:**
- Use `mkIf` for config options
- Use `lib.optionalAttrs` for attribute sets
- Use `lib.optionals` for lists
### Module Patterns
**Simple Package Module:**
```nix
{pkgs, ...}: {
home.packages = [pkgs.myPackage];
}
```
**Program Configuration Module:**
```nix
{config, pkgs, lib, ...}:
with lib; let
cfg = config.programs.myProgram;
in {
options.programs.myProgram = {
enable = mkEnableOption "myProgram";
};
config = mkIf cfg.enable {
home.packages = [pkgs.myProgram];
};
}
```
**Device-Specific Logic:**
```nix
home.packages = lib.optionals device.isLinux [pkgs.linuxPackage]
++ lib.optionals device.isDarwin [pkgs.macPackage];
sessionVariables.BROWSER = if device.isDarwin then "open" else "xdg-open";
```
## Important Rules
1. **NEVER create markdown files** unless explicitly requested
2. **DO NOT add shell scripts** - use Nix expressions
3. **All configurations must use Nix expressions** when possible
4. **Follow existing naming conventions** and directory structure
5. Create custom application entries in `~/.local/share/applications/{appname}.desktop`
## Secrets Management
- Secrets are managed with SOPS in `secrets/` directory
- Encrypted secrets in `secrets/` directory
- Configuration in `.sops.yaml`
- Access via `config.sops.secrets."secret/value".path`
```yaml
foo:
bar: somesecret
```
The path is the file that contains `somesecret`
- Add new secrets using `sops set`
Example
```bash
openssl rand -hex 32 | tr -d '\n' | jq -sR | sops set --value-stdin secrets/secrets.yaml '["foo"]["bar"]'
```
This will add a randomly generated secret to the sops file
## Common Patterns
### Adding a New Program
```bash
just add program myprogram # Creates home/programs/myprogram.nix and adds import
```
### Adding a new dns entry
```bash
cfcli add --type A foobar.bazbar.biz 192.168.0.1
```
### Creating a Module
1. Determine location: `modules/nixos/`, `modules/darwin/`, or `modules/home/`
2. Create file with proper structure
3. Add to `modules/default.nix` imports
### Device Configuration
Devices are defined in `flake.nix` using `mkDevice`. Properties available:
- `device.isLinux`, `device.isDarwin`, `device.isArm`
- `device.isServer`, `device.hasGui`, `device.isDesktopLinux`
- `device.name`, `device.user`, `device.home`
## Error Handling
- Use `mkIf` to conditionally enable configurations
- Handle both Linux and macOS cases when adding cross-platform features
## Testing Changes
1. Build first: `just build` or `nixos-rebuild build --flake .`
2. Check for errors with `--show-trace` flag
## Version Information
- Nix Version: 2.32+
- Flakes: Enabled (required)
- Formatter: alejandra
- State Version: (varies by machine & never change this)

View File

@@ -1,6 +1,6 @@
# Machines # Machines
1. Ryu Dektop (Intel i9-14900KS / Nvidia 5090 / DDR5 64GB CL36@6000MTs) 1. Ryu Dektop (Intel i9-14900KS / Nvidia RTX 5090 / DDR5 64GB CL36@6000MTs)
``` ```
deploy -s .#ryu deploy -s .#ryu
``` ```

View File

@@ -1,7 +0,0 @@
# {
# hostName = "mirai.darksailor.dev";
# sshUser = "remotebuilder";
# systems = ["x86_64-linux" "aarch64-linux"];
# protocol = "ssh-ng";
# supportedFeatures = ["nixos-test" "benchmark" "big-parallel" "kvm"];
# }

View File

@@ -3,6 +3,7 @@
inputs, inputs,
nix-darwin, nix-darwin,
overlays, overlays,
nixpkgs,
... ...
}: (builtins.mapAttrs ( }: (builtins.mapAttrs (
name: device: name: device:
@@ -11,6 +12,7 @@
specialArgs = { specialArgs = {
inherit device inputs; inherit device inputs;
stablePkgs = inputs.nixpkgs-stable.legacyPackages.${device.system}; stablePkgs = inputs.nixpkgs-stable.legacyPackages.${device.system};
cratesNix = inputs.crates-nix.mkLib {pkgs = nixpkgs.legacyPackages.${device.system};};
}; };
modules = [ modules = [
inputs.home-manager.darwinModules.home-manager inputs.home-manager.darwinModules.home-manager

View File

@@ -28,7 +28,7 @@
extra-nix-path = nixpkgs=flake:nixpkgs extra-nix-path = nixpkgs=flake:nixpkgs
builders-use-substitutes = true builders-use-substitutes = true
''; '';
package = pkgs.nixVersions.latest; package = pkgs.nixVersions.nix_2_32;
buildMachines = [ buildMachines = [
../../builders/tako.nix ../../builders/tako.nix
../../builders/shiro.nix ../../builders/shiro.nix

View File

@@ -8,11 +8,8 @@
"lunar" "lunar"
"orcaslicer" "orcaslicer"
"raycast" "raycast"
"shapr3d"
"vlc"
"zed" "zed"
"zen" "zen"
"lm-studio"
]; ];
}; };
} }

View File

@@ -1,6 +1,5 @@
{stablePkgs, ...}: { {...}: {
services.tailscale = { services.tailscale = {
enable = true; enable = true;
# package = stablePkgs.tailscale;
}; };
} }

View File

@@ -5,12 +5,10 @@
"docker-compose" "docker-compose"
]; ];
casks = [ casks = [
"1password"
"docker" "docker"
"raycast" "raycast"
"lunar" "lunar"
"virtual-desktop-streamer"
"kicad"
"shapr3d"
"orcaslicer" "orcaslicer"
"zed" "zed"
"zen" "zen"

View File

@@ -55,13 +55,13 @@
user = "root"; user = "root";
}; };
}; };
# deck = { deck = {
# hostname = "steamdeck"; hostname = "sdeck";
# profiles.system = { profiles.system = {
# sshUser = "deck"; sshUser = "deck";
# path = deploy-rs.lib.x86_64-linux.activate.home-manager self.homeConfigurations.deck; path = deploy-rs.lib.x86_64-linux.activate.home-manager self.homeConfigurations.deck;
# user = "deck"; user = "deck";
# }; };
# }; };
}; };
} }

1072
flake.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -155,9 +155,9 @@
}; };
zen-browser = { zen-browser = {
url = "github:0xc000022070/zen-browser-flake"; url = "github:0xc000022070/zen-browser-flake";
# IMPORTANT: we're using "libgbm" and is only available in unstable so ensure # IMPORTANT: To ensure compatibility with the latest Firefox version, use nixpkgs-unstable.
# to have it up-to-date or simply don't specify the nixpkgs input
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
inputs.home-manager.follows = "home-manager";
}; };
anyrun = { anyrun = {
@@ -189,11 +189,6 @@
url = "github:uttarayan21/ddcbacklight"; url = "github:uttarayan21/ddcbacklight";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
command-runner = {
url = "github:uttarayan21/command-runner";
# url = "path:/home/servius/Projects/command-runner";
inputs.nixpkgs.follows = "nixpkgs";
};
hyprmonitors = { hyprmonitors = {
url = "git+https://git.darksailor.dev/servius/hyprmonitors"; url = "git+https://git.darksailor.dev/servius/hyprmonitors";
# url = "path:/home/servius/Projects/hyprmonitors"; # url = "path:/home/servius/Projects/hyprmonitors";
@@ -230,7 +225,14 @@
url = "github:xatuke/handoff"; url = "github:xatuke/handoff";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
crates-nix.url = "github:uttarayan21/crates.nix"; crates-io-index = {
url = "git+https://github.com/rust-lang/crates.io-index?shallow=1";
flake = false;
};
crates-nix = {
url = "github:uttarayan21/crates.nix";
inputs.crates-io-index.follows = "crates-io-index";
};
headplane = { headplane = {
url = "github:tale/headplane"; url = "github:tale/headplane";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
@@ -247,6 +249,9 @@
url = "github:christo-auer/eilmeldung"; url = "github:christo-auer/eilmeldung";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
hytale-launcher = {
url = "github:JPyke3/hytale-launcher-nix";
};
}; };
outputs = { outputs = {

View File

@@ -5,8 +5,10 @@
}: { }: {
sops = { sops = {
secrets."accounts/mail/fastmail" = {}; secrets."accounts/mail/fastmail" = {};
secrets."accounts/calendar/fastmail" = {};
}; };
accounts.email = { accounts = {
email = {
maildirBasePath = "Mail"; maildirBasePath = "Mail";
accounts = { accounts = {
fastmail = rec { fastmail = rec {
@@ -29,9 +31,6 @@
port = 465; port = 465;
tls.enable = true; tls.enable = true;
}; };
imapnotify = {
enable = true;
};
passwordCommand = ["cat" "${config.sops.secrets."accounts/mail/fastmail".path}"]; passwordCommand = ["cat" "${config.sops.secrets."accounts/mail/fastmail".path}"];
mbsync = { mbsync = {
enable = true; enable = true;
@@ -40,8 +39,27 @@
}; };
}; };
}; };
programs.mbsync.enable = true; calendar = {
services.mbsync.enable = pkgs.stdenv.isLinux; basePath = "Calendar";
accounts = {
fastmail = {
remote = {
url = "https://caldav.fastmail.com/dav/calendars/user/email@uttarayan.me";
userName = "email@uttarayan.me";
passwordCommand = ["cat" "${config.sops.secrets."accounts/calendar/fastmail".path}"];
type = "caldav";
};
khal = {
enable = true;
addresses = ["email@uttarayan.me"];
};
vdirsyncer = {
enable = true;
};
};
};
};
};
# accounts.email.accounts.<name>.mbsync.create # accounts.email.accounts.<name>.mbsync.create
# services.mbsync.enable = true; # services.mbsync.enable = true;
} }

9
home/apps/affine.nix Normal file
View File

@@ -0,0 +1,9 @@
{
pkgs,
lib,
...
}: {
home.packages = lib.optionals pkgs.stdenv.isLinux [
pkgs.affine
];
}

View File

@@ -6,38 +6,41 @@
lib.optionalAttrs device.hasGui { lib.optionalAttrs device.hasGui {
imports = [ imports = [
# ./audacity.nix # ./audacity.nix
# ./blueman.nix
# ./bottles.nix # ./bottles.nix
./chromium.nix
# ./cursor.nix # ./cursor.nix
./discord.nix
./firefox.nix
./ghostty.nix
# ./gimp.nix # ./gimp.nix
# ./guitarix.nix # ./guitarix.nix
./hyprpicker.nix
# ./ida.nix # ./ida.nix
# ./jellyflix.nix # ./jellyflix.nix
# ./kicad.nix # ./kicad.nix
./kitty.nix # ./lmstudio.nix
./lmstudio.nix
./mpv.nix
# ./neovide.nix # ./neovide.nix
./nextcloud.nix
./obs-studio.nix
# ./openscad.nix # ./openscad.nix
./orcaslicer.nix # ./orcaslicer.nix
# ./pcsx2.nix # ./pcsx2.nix
./prismlauncher.nix # ./prismlauncher.nix
# ./rpcs3.nix # ./rpcs3.nix
./shadps4.nix # ./shadps4.nix
./slack.nix
# ./thunderbird.nix # ./thunderbird.nix
# ./tsukimi.nix # ./tsukimi.nix
# ./vial.nix # ./vial.nix
./vicinae.nix # ./vlc.nix
./vlc.nix
# ./vscode.nix # ./vscode.nix
./affine.nix
./blueman.nix
./chromium.nix
./discord.nix
./firefox.nix
./ghostty.nix
./hyprpicker.nix
./kitty.nix
./matrix.nix
./mpv.nix
./nextcloud.nix
./obs-studio.nix
./slack.nix
./vicinae.nix
./wezterm.nix ./wezterm.nix
./zathura.nix ./zathura.nix
./zed.nix ./zed.nix

View File

@@ -12,10 +12,63 @@
"Hasklug Nerd Font Mono" "Hasklug Nerd Font Mono"
]; ];
window-decoration = false; window-decoration = false;
title = ""; title = "ghostty";
command = "fish"; command = "fish";
background-opacity = 0.8; background-opacity = 0.8;
theme = "catppuccin-mocha"; theme = "catppuccin-mocha";
custom-shader = "~/.config/ghostty/shader.glsl";
# custom-shader = toString (pkgs.writeText "shader.glsl"
# /*
# glsl
# */
# ''
# const float CURSOR_ANIMATION_SPEED = 150.0; // ms
# const float TRAILING_CURSORS = 3.0;
# bool at_pos(vec2 fragCoord, vec2 pos, vec2 size) {
# return (pos.x <= fragCoord.x && fragCoord.x <= pos.x + size.x &&
# pos.y - size.y <= fragCoord.y && fragCoord.y <= pos.y);
# }
# void mainImage(out vec4 fragColor, in vec2 fragCoord) {
# // Normalized pixel coordinates (from 0 to 1)
# vec2 uv = fragCoord / iResolution.xy;
# vec2 current_cursor = iCurrentCursor.xy;
# vec2 previous_cursor = iPreviousCursor.xy;
# float time_passed = (iTime - iTimeCursorChange) * 1000.0; // in ms
#
# if (time_passed > CURSOR_ANIMATION_SPEED) {
# // No animation, just render normally
# fragColor = texture(iChannel0, uv);
# return;
# }
# // Animate cursor meovement
# vec4 col = texture(iChannel0, uv);
# // linear interpolation between current and previous cursor position based on time passed
# vec2 animated_cursor_pos = mix(previous_cursor, current_cursor, time_passed / CURSOR_ANIMATION_SPEED);
# // make 3 trailing cursors for smoother animation
# for (int i = 1; i <= int(TRAILING_CURSORS); i++) {
# float t = float(i) / TRAILING_CURSORS;
# vec2 trail_pos = mix(previous_cursor, current_cursor, (time_passed / CURSOR_ANIMATION_SPEED) * t);
# if (at_pos(fragCoord, trail_pos, iCurrentCursor.zw)) {
# col = mix(col, iCurrentCursorColor, t);
# }
# }
#
# // vec4 cursor_color = mix(iPreviousCursorColor, iCurrentCursorColor, time_passed / CURSOR_ANIMATION_SPEED);
# vec4 cursor_color = iCurrentCursorColor; // no color animation for now
# vec2 cursor_size = iCurrentCursor.zw;
# // check if fragCoord is within the animated cursor rectangle
# // y is in the negative direction
# // if (animated_cursor_pos.x <= fragCoord.x && fragCoord.x <= animated_cursor_pos.x + cursor_size.x &&
# // animated_cursor_pos.y - cursor_size.y <= fragCoord.y && fragCoord.y <= animated_cursor_pos.y) {
# // col = cursor_color;
# // }
# if (at_pos(fragCoord, animated_cursor_pos, cursor_size)) {
# col = cursor_color;
# }
#
# fragColor = col;
# }
# '');
}; };
systemd.enable = true; systemd.enable = true;
themes = { themes = {

12
home/apps/matrix.nix Normal file
View File

@@ -0,0 +1,12 @@
{
pkgs,
lib,
device,
...
}: {
home.packages = lib.optionals (device.is "ryu") [
pkgs.fluffychat
pkgs.fractal
# pkgs.quaternion
];
}

View File

@@ -1,6 +1,6 @@
{...}: { {pkgs, ...}: {
programs.mpv = { programs.mpv = {
enable = true; enable = pkgs.stdenv.isLinux;
config = { config = {
vo = "gpu-next"; vo = "gpu-next";
gpu-api = "vulkan"; gpu-api = "vulkan";
@@ -8,20 +8,20 @@
loop-playlist = "inf"; loop-playlist = "inf";
}; };
profiles = { profiles = {
hdr = { # hdr = {
vo = "gpu-next"; # vo = "gpu-next";
gpu-api = "vulkan"; # gpu-api = "vulkan";
hdr-compute-peak = "yes"; # hdr-compute-peak = "yes";
hdr-peak-detect = "yes"; # hdr-peak-detect = "yes";
target-peak = 400; # target-peak = 400;
target-prim = "bt.2020"; # target-prim = "bt.2020";
target-trc = "pq"; # target-trc = "pq";
inverse-tone-mapping = "yes"; # inverse-tone-mapping = "yes";
tone-mapping = "spline"; # tone-mapping = "spline";
tone-mapping-mode = "auto"; # tone-mapping-mode = "auto";
target-colorspace-hint = "auto"; # target-colorspace-hint = "auto";
gamut-mapping = "desaturate"; # gamut-mapping = "desaturate";
}; # };
}; };
}; };
} }

View File

@@ -2,12 +2,122 @@
pkgs, pkgs,
lib, lib,
... ...
}: { }: let
shadps4_qtlauncher = pkgs.fetchFromGitHub {
owner = "shadps4-emu";
repo = "shadps4-qtlauncher";
rev = "1f4e59f6110d5f991cead5a3e9f72671fced2c70";
sha256 = "sha256-AAxj3Eqp7iGJgRgJki/93fln5Z6ae8AydJLGZ6Dbb00=";
fetchSubmodules = true;
};
# diegolixShadps4 = pkgs.fetchFromGitHub {
# owner = "diegolix";
# repo = "shadps4-qtlauncher";
# rev = "a1b2c3d4e5f67890123456789abcdef01234567";
# sha256 = "sha256-PLACEHOLDERFORHASHVALUE1234567890ABCDEFGH=";
# fetchSubmodules = true;
# };
bblauncher = pkgs.fetchFromGitHub {
owner = "rainmakerv3";
repo = "BB_Launcher";
rev = "2280c90974d2d741ce927dfc88f0ecf98c8bd2df";
sha256 = "sha256-jPcIQp2EBAEiaTLvC/OBH0BgcfYv3zo2H7akHJSlPaI=";
fetchSubmodules = true;
};
in {
home.packages = lib.optionals pkgs.stdenv.isLinux [ home.packages = lib.optionals pkgs.stdenv.isLinux [
(pkgs.shadps4.overrideAttrs (pkgs.shadps4.overrideAttrs
(oldAttrs: { (oldAttrs: {
nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [pkgs.cudatoolkit]; nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [pkgs.cudatoolkit];
buildInputs = oldAttrs.buildInputs ++ [pkgs.cudatoolkit]; buildInputs = oldAttrs.buildInputs ++ [pkgs.cudatoolkit];
})) }))
(pkgs.stdenv.mkDerivation {
pname = "shadps4-qt";
version = "1.0.0";
src = shadps4_qtlauncher;
nativeBuildInputs = [
pkgs.cmake
pkgs.pkg-config
pkgs.qt6.wrapQtAppsHook
];
buildInputs = [
pkgs.alsa-lib
pkgs.ffmpeg
pkgs.fmt
pkgs.glslang
pkgs.jack2
pkgs.libedit
pkgs.libevdev
pkgs.libpng
pkgs.libpulseaudio
pkgs.libxkbcommon
pkgs.openal
pkgs.openssl
pkgs.qt6.qtbase
pkgs.qt6.qtmultimedia
pkgs.qt6.qttools
pkgs.qt6.qtwayland
pkgs.SDL2
pkgs.sdl3
pkgs.sndio
pkgs.stb
pkgs.udev
pkgs.vulkan-headers
pkgs.vulkan-tools
pkgs.vulkan-utility-libraries
pkgs.wayland
pkgs.wayland-protocols
pkgs.xorg.libxcb
pkgs.xorg.xcbutil
pkgs.xorg.xcbutilkeysyms
pkgs.xorg.xcbutilwm
pkgs.zlib
];
})
(pkgs.stdenv.mkDerivation {
pname = "BBLauncher";
version = "1.0.0";
src = bblauncher;
nativeBuildInputs = [
pkgs.cmake
pkgs.pkg-config
pkgs.qt6.wrapQtAppsHook
];
buildInputs = [
pkgs.alsa-lib
pkgs.ffmpeg
pkgs.fmt
pkgs.glslang
pkgs.jack2
pkgs.libedit
pkgs.libevdev
pkgs.libpng
pkgs.libpulseaudio
pkgs.libxkbcommon
pkgs.openal
pkgs.openssl
pkgs.qt6.qtbase
pkgs.qt6.qtmultimedia
pkgs.qt6.qttools
pkgs.qt6.qtwayland
pkgs.qt6.qtwebview
pkgs.SDL2
pkgs.sdl3
pkgs.sndio
pkgs.stb
pkgs.udev
pkgs.vulkan-headers
pkgs.vulkan-tools
pkgs.vulkan-utility-libraries
pkgs.wayland
pkgs.wayland-protocols
pkgs.xorg.libxcb
pkgs.xorg.xcbutil
pkgs.xorg.xcbutilkeysyms
pkgs.xorg.xcbutilwm
pkgs.zlib
];
})
]; ];
} }

View File

@@ -12,4 +12,9 @@
autoStart = true; autoStart = true;
}; };
}; };
home.packages = with pkgs;
lib.optionals (device.is "ryu") [
# pulseaudio
playerctl
];
} }

View File

@@ -2,6 +2,7 @@
pkgs, pkgs,
inputs, inputs,
device, device,
config,
... ...
}: { }: {
imports = [ imports = [
@@ -10,6 +11,47 @@
programs.zen-browser = { programs.zen-browser = {
enable = device.isLinux; enable = device.isLinux;
profiles.default = { profiles.default = {
containersForce = true;
containers = {
Personal = {
color = "purple";
icon = "fingerprint";
id = 1;
};
Work = {
color = "blue";
icon = "briefcase";
id = 2;
};
Shopping = {
color = "yellow";
icon = "dollar";
id = 3;
};
};
spacesForce = true;
spaces = let
containers = config.programs.zen-browser.profiles."default".containers;
in {
"Personal" = {
id = "";
icon = "👤";
container = containers."Personal".id;
position = 1000;
};
"Work" = {
id = "00bdd434-e31b-4e2b-b8f5-fa7055631a64";
icon = "💼";
container = containers."Work".id;
position = 2000;
};
"Shopping" = {
id = "77452260-56e6-4c9e-8d5f-417958bc4fa4";
icon = "💸";
container = containers."Shopping".id;
position = 3000;
};
};
extensions.packages = with pkgs.nur.repos.rycee.firefox-addons; [ extensions.packages = with pkgs.nur.repos.rycee.firefox-addons; [
privacy-badger privacy-badger
violentmonkey violentmonkey
@@ -42,5 +84,6 @@
Fingerprinting = true; Fingerprinting = true;
}; };
}; };
suppressXdgMigrationWarning = true;
}; };
} }

View File

@@ -27,6 +27,7 @@
home-manager = { home-manager = {
enable = true; enable = true;
}; };
man.generateCaches = true;
}; };
fonts.fontconfig.enable = true; fonts.fontconfig.enable = true;
@@ -35,26 +36,6 @@
username = device.user; username = device.user;
homeDirectory = lib.mkForce device.home; homeDirectory = lib.mkForce device.home;
file = {
".config/fish/themes".source = pkgs.catppuccinThemes.fish + "/themes";
".cargo/config.toml".text =
# toml
''
[alias]
lldb = ["with", "rust-lldb", "--"]
t = ["nextest", "run"]
[net]
git-fetch-with-cli = true
[registries.catscii]
index = "https://git.shipyard.rs/catscii/crate-index.git"
[http]
user-agent = "shipyard J0/QFq2Sa5y6nTxJQAb8t+e/3qLSub1/sa3zn0leZv6LKG/zmQcoikT9U3xPwbzp8hQ="
'';
};
sessionVariables = { sessionVariables = {
EDITOR = "nvim"; EDITOR = "nvim";
SHELL = "${pkgs.bash}/bin/bash"; SHELL = "${pkgs.bash}/bin/bash";

View File

@@ -1,6 +1,7 @@
{ {
device, device,
inputs, inputs,
pkgs,
... ...
}: { }: {
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;
@@ -12,6 +13,7 @@
inherit inputs; inherit inputs;
inherit device; inherit device;
stablePkgs = inputs.nixpkgs-stable.legacyPackages.${device.system}; stablePkgs = inputs.nixpkgs-stable.legacyPackages.${device.system};
cratesNix = inputs.crates-nix.mkLib {inherit pkgs;};
}; };
users.${device.user}.imports = [ users.${device.user}.imports = [
inputs.nixvim.homeModules.nixvim inputs.nixvim.homeModules.nixvim

View File

@@ -1,4 +1,8 @@
{config, ...}: { {
pkgs,
config,
...
}: {
sops = { sops = {
secrets."llama/api_key" = {}; secrets."llama/api_key" = {};
secrets."openai/api_key" = {}; secrets."openai/api_key" = {};
@@ -17,7 +21,7 @@
settings = { settings = {
save_session = true; save_session = true;
model = "ryu:qwen3:30b-a3b"; model = "ryu:qwen3:30b-a3b";
rag_embedding_model = "ollama:RobinBially/nomic-embed-text-8k"; rag_embedding_model = "ryu:RobinBially/nomic-embed-text-8k";
clients = [ clients = [
{ {
type = "openai-compatible"; type = "openai-compatible";
@@ -29,15 +33,27 @@
name = "gpt-oss:20b"; name = "gpt-oss:20b";
type = "chat"; type = "chat";
} }
# {
# name = "gpt-oss:20b-instruct";
# type = "chat";
# real_name = "gpt-oss:20b";
# patch = {
# body = {
# think = "low";
# };
# };
# }
{ {
name = "qwen3:30b-a3b"; name = "qwen3:30b-a3b";
type = "chat"; type = "chat";
} }
# { {
# name = "RobinBially/nomic-embed-text-8k"; name = "RobinBially/nomic-embed-text-8k";
# type = "embedding"; type = "embedding";
# default_chunk_size = 8000; default_chunk_size = 1000;
# } max_tokens_per_chunk = 8192;
max_batch_size = 100;
}
# { # {
# name = "deepseek-r1:14b"; # name = "deepseek-r1:14b";
# type = "chat"; # type = "chat";
@@ -133,9 +149,16 @@
}; };
} }
]; ];
document_loaders = {
git =
/*
sh
*/
''sh -c "yek $1 --json | jq '[.[] | { path: .filename, contents: .content }]'"'';
};
}; };
roles = { roles = {
"%git-commit%" = "git-commit" =
/* /*
md md
*/ */
@@ -146,5 +169,9 @@
Your task is to generate a concise and informative commit message based on the provided diff. Use the conventional commit format, which includes a type (feat, fix, chore, docs, style, refactor, perf, test) and an optional scope. The message should be in the imperative mood and should not exceed 72 characters in the subject line. Do not under any circumstance include any additional text or explanations, just add the commit message. Your task is to generate a concise and informative commit message based on the provided diff. Use the conventional commit format, which includes a type (feat, fix, chore, docs, style, refactor, perf, test) and an optional scope. The message should be in the imperative mood and should not exceed 72 characters in the subject line. Do not under any circumstance include any additional text or explanations, just add the commit message.
''; '';
}; };
extraPackages = with pkgs; [
jq
yek
];
}; };
} }

35
home/programs/attic.nix Normal file
View File

@@ -0,0 +1,35 @@
{
pkgs,
lib,
config,
...
}: let
attic-unwrapped = pkgs.attic-client.overrideAttrs (oldAttrs: {
patches =
(oldAttrs.patches or [])
++ [
# PR #309: Add environment variable support for login
# https://github.com/zhaofengli/attic/pull/309
(pkgs.fetchpatch {
url = "https://github.com/zhaofengli/attic/pull/309.patch";
hash = "sha256-mDoxA+e2bBZDvERp03SyYvkEdtH/bfWtZqKZv0uCS0M=";
})
];
});
in {
sops.secrets."attic/token" = {};
home.packages = [
(pkgs.stdenv.mkDerivation {
pname = "attic-client";
version = "0.1.0";
src = attic-unwrapped;
buildInputs = [];
nativeBuildInputs = [pkgs.makeWrapper];
installPhase = ''
install -Dm755 $src/bin/attic $out/bin/attic
wrapProgram $out/bin/attic \
--run "export ATTIC_LOGIN_TOKEN=\`cat -v ${config.sops.secrets."attic/token".path}\`"
'';
})
];
}

View File

@@ -9,9 +9,49 @@
auto_sync = true; auto_sync = true;
sync_frequency = "1m"; sync_frequency = "1m";
sync_address = "https://atuin.darksailor.dev"; sync_address = "https://atuin.darksailor.dev";
sync = {
records = true;
};
daemon = {
enabled = true;
};
}; };
enable = true; enable = true;
enableFishIntegration = true; enableFishIntegration = true;
enableNushellIntegration = true; enableNushellIntegration = true;
}; };
systemd.user.services.atuin-daemon = {
Unit = {
Description = "Atuin Daemon";
After = ["network.target"];
};
Install = {
WantedBy = ["default.target"];
};
Service = {
ExecStart = "${pkgs.atuin}/bin/atuin daemon";
Restart = "on-failure";
RestartSec = "10s";
# Environment = lib.mkForce "ATUIN_DATA_DIR=${device.home}/.local/share/atuin";
};
};
launchd.agents.atuin-daemon = {
enable = true;
config = {
# A label for the service
Label = "dev.darksailor.atuin-daemon";
# The command to run
ProgramArguments = [
"${pkgs.atuin}/bin/atuin"
"daemon"
];
# Run the service when you log in
RunAtLoad = true;
# Keep the process alive, or restart if it dies
KeepAlive = true;
# Log files
StandardOutPath = "${device.home}/Library/Logs/atuin-daemon.log";
StandardErrorPath = "${device.home}/Library/Logs/atuin-daemon.error.log";
};
};
} }

View File

@@ -0,0 +1 @@
{pkgs, ...}: {home.packages = [pkgs.binwalk];}

View File

@@ -0,0 +1,8 @@
{
pkgs,
device,
lib,
...
}: {
home.packages = lib.optionals (device.name == "ryu") [pkgs.blobdrop];
}

View File

@@ -0,0 +1,6 @@
{pkgs, ...}: {
programs.khal.enable = true;
programs.qcal.enable = true;
programs.vdirsyncer.enable = true;
accounts.calendar.accounts.fastmail.qcal.enable = true;
}

View File

@@ -1,13 +1,8 @@
{ {...}: {
pkgs,
lib,
device,
...
}: {
programs. programs.
carapace = { carapace = {
enable = false; enable = false;
enableFishIntegration = true; enableFishIntegration = false;
enableNushellIntegration = true; enableNushellIntegration = true;
}; };
} }

30
home/programs/cargo.nix Normal file
View File

@@ -0,0 +1,30 @@
{
lib,
device,
cratesNix,
...
}: let
cargo-credential-1password = cratesNix.buildCrate "cargo-credential-1password" {};
in
lib.mkIf (!device.isServer) {
home.file.".cargo/config.toml".text =
# toml
''
[alias]
lldb = ["with", "rust-lldb", "--"]
t = ["nextest", "run"]
pkgs = ["metadata", "--no-deps", "--format-version", "1"]
[net]
git-fetch-with-cli = true
[registries.kellnr]
index = "sparse+https://crates.darksailor.dev/api/v1/crates/"
[registry]
global-credential-providers = ["cargo:token", "${lib.getExe cargo-credential-1password} --account my.1password.com"]
'';
home.packages = [
cargo-credential-1password
];
}

27
home/programs/cfcli.nix Normal file
View File

@@ -0,0 +1,27 @@
{
pkgs,
lib,
config,
...
}: {
sops.secrets."cloudflare/darksailor_dev_api_key" = {};
home.packages = [
# (pkgs.stdenv.mkDerivation {
# pname = "cfcli";
# version = "0.1.0";
# buildInputs = [pkgs.cloudflare-cli];
# nativeBuildInputs = [pkgs.makeWrapper];
# installPhase = ''
# $out/bin/cfcli \
# --run "export CF_API_KEY=\`cat -v ${config.sops.secrets."cloudflare/darksailor_dev_api_key".path}\`"
# '';
# })
(pkgs.writeShellScriptBin
"cfcli"
''
#!/bin/sh
export CF_API_KEY="$(cat -v ${config.sops.secrets."cloudflare/darksailor_dev_api_key".path})"
exec ${pkgs.cloudflare-cli}/bin/cfcli "$@"
'')
];
}

View File

@@ -4,22 +4,47 @@
... ...
}: { }: {
imports = [ imports = [
# ./bluetui.nix
# ./goread.nix
# ./helix.nix
# ./magika.nix
# ./mpd.nix
# ./mpris-scrobbler.nix
# ./ncmpcpp.nix
# ./newsboat.nix
# ./nh.nix
# ./ryujinx.nix
# ./sxiv.nix
# ./tea.nix
# ./template.nix
# ./tuifeed.nix
# ./xh.nix
# ./zellij.nix
../../modules ../../modules
./1password-cli.nix ./1password-cli.nix
./aichat.nix ./aichat.nix
./alejandra.nix ./alejandra.nix
./aria2.nix ./aria2.nix
./ast-grep.nix ./ast-grep.nix
./attic.nix
./atuin.nix ./atuin.nix
./bat.nix ./bat.nix
./binwalk.nix
./blobdrop.nix
./bottom.nix ./bottom.nix
./btop.nix ./btop.nix
./cachix.nix ./cachix.nix
./calendar.nix
./carapace.nix ./carapace.nix
./cargo.nix
./cfcli.nix
./ddcbacklight.nix ./ddcbacklight.nix
./deploy-rs.nix ./deploy-rs.nix
./direnv.nix ./direnv.nix
./dust.nix ./dust.nix
./dysk.nix
./eilmeldung.nix ./eilmeldung.nix
./eza.nix ./eza.nix
./fastfetch.nix ./fastfetch.nix
@@ -33,15 +58,18 @@
./himalaya.nix ./himalaya.nix
./hyprshade.nix ./hyprshade.nix
./jq.nix ./jq.nix
./jujutsu.nix
./just.nix ./just.nix
./ncpamixer.nix ./ncpamixer.nix
./neomutt.nix ./neomutt.nix
./neovim.nix ./neovim.nix
./nix-index.nix ./nix-index.nix
./nushell.nix ./nushell.nix
./omnix.nix
./opencode.nix ./opencode.nix
./p7zip.nix ./p7zip.nix
./pkg-config.nix ./pkg-config.nix
./retroarch.nix
./ripgrep.nix ./ripgrep.nix
./rustup.nix ./rustup.nix
./sd.nix ./sd.nix
@@ -54,29 +82,6 @@
./yazi.nix ./yazi.nix
./yt-dlp.nix ./yt-dlp.nix
./zoxide.nix ./zoxide.nix
# ./bluetui.nix ./yq.nix
# ./goread.nix
# ./helix.nix
# ./magika.nix
# ./mpd.nix
# ./mpris-scrobbler.nix
# ./ncmpcpp.nix
# ./newsboat.nix
# ./nh.nix
# ./omnix.nix
# ./retroarch.nix
# ./ryujinx.nix
# ./sxiv.nix
# ./tea.nix
# ./template.nix
# ./tuifeed.nix
# ./xh.nix
# ./zellij.nix
./dysk.nix
]; ];
# home.packages = with pkgs;
# []
# ++ lib.optionals (!device.isServer) []
# ++ lib.optionals device.isLinux []
# ++ lib.optionals device.isDarwin [];
} }

View File

@@ -6,6 +6,9 @@
... ...
}: }:
{ {
home.file = {
".config/fish/themes".source = pkgs.catppuccinThemes.fish + "/themes";
};
programs.fish = { programs.fish = {
enable = true; enable = true;
shellAbbrs = { shellAbbrs = {
@@ -40,6 +43,7 @@
''} ''}
''; '';
}; };
home.shell.enableFishIntegration = true;
} }
// lib.optionalAttrs (!(device.is "tsuba")) { // lib.optionalAttrs (!(device.is "tsuba")) {
stylix.targets.fish.enable = false; stylix.targets.fish.enable = false;

View File

@@ -0,0 +1 @@
{pkgs, ...}: {home.packages = [pkgs.jujutsu];}

View File

@@ -1,4 +1,9 @@
{pkgs, ...}: { {pkgs, ...}: let
theme = builtins.fetchurl {
url = "https://raw.githubusercontent.com/catppuccin/neomutt/refs/heads/main/neomuttrc";
sha256 = "sha256:1q086p5maqwxa4gh6z8g7h3nfavdmkbql025ibdhglpz46hsq0hs";
};
in {
programs.neomutt = { programs.neomutt = {
enable = true; enable = true;
vimKeys = true; vimKeys = true;
@@ -6,6 +11,9 @@
sidebar = { sidebar = {
enable = true; enable = true;
}; };
extraConfig = ''
source ${theme}
'';
}; };
programs.notmuch = { programs.notmuch = {
enable = true; enable = true;
@@ -17,4 +25,38 @@
enable = true; enable = true;
neomutt.enable = true; neomutt.enable = true;
}; };
services.imapnotify = {
enable = true;
path = [pkgs.coreutils pkgs.isync pkgs.libnotify];
};
accounts.email.accounts.fastmail.imapnotify = {
enable = true;
boxes = ["Inbox"];
onNotify = "${pkgs.writeShellScript "mbsync-notify" ''
${pkgs.isync}/bin/mbsync $1
${pkgs.libnotify}/bin/notify-send "New Mail" "New email in $1"
''} %s";
};
programs.mbsync.enable = true;
services.mbsync.enable = pkgs.stdenv.isLinux;
# launchd.agents.mbsync = {
# enable = true;
# config = {
# # A label for the service
# Label = "dev.darksailor.atuin-daemon";
# # The command to run
# ProgramArguments = [
# "${pkgs.atuin}/bin/atuin"
# "daemon"
# ];
# # Run the service when you log in
# RunAtLoad = true;
# # Keep the process alive, or restart if it dies
# KeepAlive = true;
# # Log files
# StandardOutPath = "${device.home}/Library/Logs/atuin-daemon.log";
# StandardErrorPath = "${device.home}/Library/Logs/atuin-daemon.error.log";
# };
# };
} }

View File

@@ -26,4 +26,5 @@
} }
''; '';
}; };
home.shell.enableNushellIntegration = true;
} }

View File

@@ -3,8 +3,23 @@
lib, lib,
... ...
}: }:
lib.optionalAttrs (device.is "ryu") { lib.optionalAttrs (device.is "ryu" || device.is "kuro") {
programs.opencode = { programs.opencode = {
enable = true; enable = true;
settings.provider = {
ollama = {
models = {
"glm-4.7-flash" = {
# "_launch" = true;
name = "glm-4.7-flash";
};
};
name = "Ollama (local)";
npm = "@ai-sdk/openai-compatible";
options = {
baseURL = "https://ollama.darksailor.dev/v1";
};
};
};
}; };
} }

View File

@@ -12,4 +12,12 @@
defaultSopsFormat = "yaml"; defaultSopsFormat = "yaml";
age.keyFile = "${config.home.homeDirectory}/.config/sops/age/keys.txt"; age.keyFile = "${config.home.homeDirectory}/.config/sops/age/keys.txt";
}; };
launchd.agents.sops-nix = pkgs.lib.mkIf pkgs.stdenv.isDarwin {
enable = true;
config = {
EnvironmentVariables = {
PATH = pkgs.lib.mkForce "/usr/bin:/bin:/usr/sbin:/sbin";
};
};
};
} }

View File

@@ -6,6 +6,7 @@
}: { }: {
programs.ssh = { programs.ssh = {
enable = true; enable = true;
enableDefaultConfig = false;
matchBlocks = { matchBlocks = {
tsuba = { tsuba = {
user = "servius"; user = "servius";
@@ -45,13 +46,13 @@
hostname = "steamdeck"; hostname = "steamdeck";
forwardAgent = true; forwardAgent = true;
}; };
# "*" = { "*" = {
# forwardAgent = false; forwardAgent = false;
# addKeysToAgent = "no"; addKeysToAgent = "no";
# # compression = true; # compression = true;
# # HashKnownHosts = "no"; # HashKnownHosts = "no";
# serverAliveInterval = 60; serverAliveInterval = 60;
# }; };
}; };
extraConfig = extraConfig =
lib.strings.optionalString (pkgs.stdenv.isDarwin && !device.isServer) lib.strings.optionalString (pkgs.stdenv.isDarwin && !device.isServer)

View File

@@ -1,4 +1,4 @@
{...}: { {config, ...}: {
programs. yazi = { programs. yazi = {
enable = true; enable = true;
enableFishIntegration = true; enableFishIntegration = true;
@@ -13,6 +13,10 @@
} }
]; ];
}; };
preview = {
cache_dir = config.home.homeDirectory + "/.cache/yazi/previews";
}; };
}; };
shellWrapperName = "yy";
};
} }

1
home/programs/yq.nix Normal file
View File

@@ -0,0 +1 @@
{pkgs, ...}: {home.packages = [pkgs.yq];}

View File

@@ -1,31 +0,0 @@
{
config,
lib,
pkgs,
inputs,
...
}: {
imports = [
inputs.command-runner.homeManagerModules.command-runner
];
services.command-runner = {
enable = true;
port = 5599;
database.path = "${config.home.homeDirectory}/.local/share/command-runner.db";
commands = let
hyprctl = "${pkgs.hyprland}/bin/hyprctl";
in
{
"display_on" = [hyprctl "-i" "{instance}" "dispatch" "dpms" "on"];
"display_off" = [hyprctl "-i" "{instance}" "dispatch" "dpms" "off"];
"display_toggle" = [hyprctl "-i" "{instance}" "dispatch" "dpms" "toggle"];
"display_status" = [hyprctl "-i" "{instance}" "-j" "monitors"];
"hyprland_instance" = [hyprctl "-j" "instances"];
}
// (builtins.foldl' (acc: elem: acc // elem) {} (lib.map (name: {
"display_on_${name}" = [hyprctl "-i" "{instance}" "dispatch" "dpms" "on" name];
"display_off_${name}" = [hyprctl "-i" "{instance}" "dispatch" "dpms" "off" name];
"display_toggle_${name}" = [hyprctl "-i" "{instance}" "dispatch" "dpms" "toggle" name];
}) ["HDMI-A-1" "DP-3" "DP-1"]));
};
}

View File

@@ -2,24 +2,8 @@
pkgs, pkgs,
device, device,
lib, lib,
inputs,
... ...
}: { }: {
systemd.user.services.onepassword-gui = lib.optionalAttrs (device.is "ryu") {
Unit = {
Description = "1Password GUI";
BindsTo = ["graphical-session.target"];
After = ["graphical-session-pre.target"];
};
Service = {
ExecStart = "${pkgs._1password-gui}/bin/1password";
Restart = "always";
};
Install = {
WantedBy = ["graphical-session.target"];
};
};
home.packages = with pkgs; home.packages = with pkgs;
lib.optionals (device.is "ryu") [ lib.optionals (device.is "ryu") [
nautilus nautilus

View File

@@ -61,9 +61,9 @@
{ {
output = device.monitors.secondary; output = device.monitors.secondary;
mode = "2560x1440@170"; mode = "2560x1440@170";
position = "-1440x-1120"; position = "-2560x0";
scale = 1; scale = 1;
transform = 1; transform = 0;
} }
{ {
output = device.monitors.tertiary; output = device.monitors.tertiary;
@@ -156,21 +156,20 @@
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ # windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more # See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
windowrulev2 = [ windowrule = [
# "float, title:^(Steam)$" # "match:title ^(Steam)$ float"
"float, title:^(Archetype.*)$" "match:title ^(Archetype.*)$ float"
"float, class:(.*nextcloud.*)" "match:class (.*nextcloud.*) float"
"float, class:org.kde.kdeconnect.app" "match:class org.kde.kdeconnect.app float"
]; ];
# "misc:vfr" = true;
env = [ env = [
"XCURSOR_SIZE,24" "XCURSOR_SIZE,24"
"XDG_SESSION_TYPE,wayland" "XDG_SESSION_TYPE,wayland"
"MOZ_ENABLE_WAYLAND,1" "MOZ_ENABLE_WAYLAND,1"
"QT_QPA_PLATFORM,wayland" "QT_QPA_PLATFORM,wayland"
]; ];
exec-once = [ exec-once = [
# "${pkgs.polkit-kde-agent}/libexec/polkit-kde-authentication-agent-1" # "${pkgs.polkit-kde-agent}/libexec/polkit-kde-authentication-agent-1"
"${pkgs.mate.mate-polkit}/libexec/polkit-mate-authentication-agent-1" "${pkgs.mate.mate-polkit}/libexec/polkit-mate-authentication-agent-1"
@@ -190,8 +189,8 @@
]; ];
bind = [ bind = [
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more # Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
"$mainMod, Return, exec, ${lib.getExe pkgs.wezterm}" "$mainMod, Return, exec, ${lib.getExe pkgs.kitty}"
"$mainModShift, Return, exec, ${lib.getExe pkgs.kitty}" "$mainModShift, Return, exec, ${lib.getExe pkgs.ghostty}"
# "$mainModShift, Return, exec, ${pkgs.foot}/bin/foot" # "$mainModShift, Return, exec, ${pkgs.foot}/bin/foot"
"$mainModShift, Q, killactive," "$mainModShift, Q, killactive,"
"$mainModShift, s, exec, ${lib.getExe pkgs.hyprshot} -m region -o ~/Pictures/Screenshots/" "$mainModShift, s, exec, ${lib.getExe pkgs.hyprshot} -m region -o ~/Pictures/Screenshots/"

View File

@@ -7,11 +7,13 @@
services.hyprpaper = let services.hyprpaper = let
wallpapers = import ../../utils/wallhaven.nix {inherit pkgs;}; wallpapers = import ../../utils/wallhaven.nix {inherit pkgs;};
nextcloudWallpapers = name: config.home.homeDirectory + "/Nextcloud/Wallpapers/" + name; nextcloudWallpapers = name: config.home.homeDirectory + "/Nextcloud/Wallpapers/" + name;
silksongFleas = nextcloudWallpapers "silksong-fleas.jpg"; # silksongFleas = nextcloudWallpapers "silksong-fleas.jpg";
bocchiVertical = nextcloudWallpapers "bocchi-vertical.jpg";
silksongShadeLord = nextcloudWallpapers "silksong-shadelord.jpg"; silksongShadeLord = nextcloudWallpapers "silksong-shadelord.jpg";
in { in {
enable = device.is "ryu"; enable = device.is "ryu";
settings = { settings = {
splash = false;
wallpaper = [ wallpaper = [
{ {
monitor = device.monitors.primary; monitor = device.monitors.primary;
@@ -25,7 +27,7 @@
} }
{ {
monitor = device.monitors.tertiary; monitor = device.monitors.tertiary;
path = silksongFleas; path = bocchiVertical;
fit_mode = "cover"; fit_mode = "cover";
} }
]; ];

View File

@@ -13,13 +13,14 @@
"${device.monitors.secondary}" = { "${device.monitors.secondary}" = {
position = "bottom"; position = "bottom";
start = [ start = [
{ {type = "tray";}
type = "launcher"; # {
favourites = ["firefox" "discord"]; # type = "launcher";
show_names = false; # favourites = ["firefox" "discord"];
show_icons = true; # show_names = false;
} # show_icons = true;
{type = "focused";} # }
# {type = "focused";}
]; ];
end = [ end = [
{ {
@@ -35,46 +36,45 @@
{type = "clock";} {type = "clock";}
]; ];
}; };
"${device.monitors.primary}" = { # "${device.monitors.primary}" = {
position = "bottom"; # position = "bottom";
icon_theme = "Papirus-Dark"; # icon_theme = "Papirus-Dark";
end = [ # end = [
{ # {
type = "sys_info"; # type = "sys_info";
format = [ # format = [
" CPU {cpu_percent}% | {temp_c:coretemp-Package-id-0}°C" # " CPU {cpu_percent}% | {temp_c:coretemp-Package-id-0}°C"
" RAM {memory_used}GB/{memory_total}GB" # " RAM {memory_used}GB/{memory_total}GB"
]; # ];
interval = { # interval = {
cpu = 1; # cpu = 1;
temps = 5; # temps = 5;
memory = 30; # memory = 30;
# disks= 300; # # disks= 300;
# networks= 3; # # networks= 3;
}; # };
} # }
{type = "tray";} # ];
]; # start = [
start = [ # {
{ # type = "workspaces";
type = "workspaces"; # name_map = {
name_map = { # "1" = "icon:kitty";
"1" = "icon:foot"; # "2" = "icon:code";
"2" = "icon:code"; # "3" = "icon:firefox";
"3" = "icon:firefox"; # "4" = "icon:slack";
"4" = "icon:slack"; # # "5" = "icon:steam";
"5" = "icon:steam"; # # "6" = "icon:foot";
"6" = "icon:foot"; # # "7" = "icon:foot";
"7" = "icon:foot"; # # "8" = "icon:firefox";
"8" = "icon:firefox"; # # "9" = "icon:discord";
"9" = "icon:discord"; # # "10" = "icon:spotify";
"10" = "icon:spotify"; # };
}; # favorites = ["1" "2" "3" "4"];
favorites = ["1" "2" "3" "4" "5" "6" "7" "8" "9" "10"]; # all_monitors = false;
all_monitors = true; # }
} # ];
]; # };
};
"${device.monitors.tertiary}" = { "${device.monitors.tertiary}" = {
position = "bottom"; position = "bottom";
icon_theme = "Papirus-Dark"; icon_theme = "Papirus-Dark";

View File

@@ -1,7 +1,68 @@
{device, ...}: { {
device,
pkgs,
lib,
config,
...
}:
with lib; let
remminaDir = "${config.home.homeDirectory}/.local/share/remmina";
applicationsDir = "${config.home.homeDirectory}/.local/share/applications";
# Script to generate desktop entries for Remmina connections
generateRemminaDesktopEntries = pkgs.writeShellScript "generate-remmina-desktop-entries" ''
REMMINA_DIR="${remminaDir}"
APPS_DIR="${applicationsDir}"
# Create applications directory if it doesn't exist
mkdir -p "$APPS_DIR"
# Remove old remmina desktop entries
rm -f "$APPS_DIR"/remmina-*.desktop
# Exit if remmina directory doesn't exist
[[ ! -d "$REMMINA_DIR" ]] && exit 0
# Generate desktop entries for each .remmina file
find "$REMMINA_DIR" -name "*.remmina" -type f | while read -r file; do
# Extract connection details
name=$(${pkgs.gnugrep}/bin/grep "^name=" "$file" | ${pkgs.coreutils}/bin/cut -d'=' -f2-)
server=$(${pkgs.gnugrep}/bin/grep "^server=" "$file" | ${pkgs.coreutils}/bin/cut -d'=' -f2-)
protocol=$(${pkgs.gnugrep}/bin/grep "^protocol=" "$file" | ${pkgs.coreutils}/bin/cut -d'=' -f2-)
# Use filename as fallback if name is empty
[[ -z "$name" ]] && name=$(${pkgs.coreutils}/bin/basename "$file" .remmina)
[[ -z "$protocol" ]] && protocol="Unknown"
# Generate desktop entry filename
desktop_name=$(${pkgs.coreutils}/bin/basename "$file" .remmina | ${pkgs.gnused}/bin/sed 's/[^a-zA-Z0-9_-]/-/g')
desktop_file="$APPS_DIR/remmina-$desktop_name.desktop"
# Create desktop entry
cat > "$desktop_file" <<EOF
[Desktop Entry]
Type=Application
Name=Remmina - $name
GenericName=$protocol Connection to $server
Comment=Connect to $server via $protocol
Exec=${pkgs.remmina}/bin/remmina -c "$file"
Icon=org.remmina.Remmina
Terminal=false
Categories=Network;RemoteAccess;
EOF
done
'';
in {
services.remmina = { services.remmina = {
enable = device.is "ryu"; enable = device.is "ryu";
systemdService.enable = true; systemdService.enable = true;
addRdpMimeTypeAssoc = true; addRdpMimeTypeAssoc = true;
}; };
# Activation script to generate desktop entries
home.activation.generateRemminaDesktopEntries = mkIf (device.is "ryu") (
lib.hm.dag.entryAfter ["writeBoundary"] ''
run ${generateRemminaDesktopEntries}
''
);
} }

View File

@@ -5,28 +5,28 @@
... ...
}: }:
lib.mkIf (device.is "ryu") { lib.mkIf (device.is "ryu") {
# systemd.user.services.wallpaperengine = { systemd.user.services.wallpaperengine = {
# Unit = { Unit = {
# Description = "Linux Wallpaper Engine"; Description = "Linux Wallpaper Engine";
# After = ["hyprland-session.target"]; After = ["hyprland-session.target"];
# Wants = ["hyprland-session.target"]; Wants = ["hyprland-session.target"];
# PartOf = ["hyprland-session.target"]; PartOf = ["hyprland-session.target"];
# }; };
#
# Service = { Service = {
# Environment = [ Environment = [
# "XDG_SESSION_TYPE=wayland" "XDG_SESSION_TYPE=wayland"
# ]; ];
# Type = "simple"; Type = "simple";
# ExecStartPre = "${pkgs.coreutils}/bin/sleep 3"; ExecStartPre = "${pkgs.coreutils}/bin/sleep 3";
# ExecStart = "${pkgs.linux-wallpaperengine}/bin/linux-wallpaperengine --silent --no-audio-processing -f 15 --scaling fill --screen-root HDMI-A-1 --bg 2780316434"; ExecStart = "${pkgs.linux-wallpaperengine}/bin/linux-wallpaperengine --silent --no-audio-processing -f 15 --scaling fill --screen-root HDMI-A-1 --bg 2780316434";
# Restart = "on-failure"; Restart = "on-failure";
# RestartSec = 5; RestartSec = 5;
# TimeoutStartSec = 30; TimeoutStartSec = 30;
# }; };
#
# Install = { Install = {
# WantedBy = ["hyprland-session.target"]; WantedBy = ["hyprland-session.target"];
# }; };
# }; };
} }

View File

@@ -3,12 +3,11 @@
lib, lib,
device, device,
... ...
}: }: {
lib.optionalAttrs (device.is "ryu") {
xdg.portal = { xdg.portal = {
enable = pkgs.stdenv.isLinux; enable = device.is "ryu";
config = { config = {
hyprland.default = ["kde" "hyprland"]; hyprland.default = ["hyprland"];
common.default = ["*" "hyprland"]; common.default = ["*" "hyprland"];
}; };
extraPortals = with pkgs; [ extraPortals = with pkgs; [

View File

@@ -41,3 +41,5 @@ add program:
alejandra fmt home/programs/{{program}}.nix home/programs/default.nix alejandra fmt home/programs/{{program}}.nix home/programs/default.nix
git add home/programs/{{program}}.nix git add home/programs/{{program}}.nix
# add-secret secret:
# openssl rand -hex 32 | tr -d '\n' | jq -sR | sops set --value-stdin secrets/secrets.yaml {{secret}}

View File

@@ -81,6 +81,14 @@ in {
type = lib.types.attrsOf lib.types.str; type = lib.types.attrsOf lib.types.str;
description = "Roles for the AI chat clients"; description = "Roles for the AI chat clients";
}; };
extraPackages = mkOption {
type = lib.types.listOf lib.types.package;
default = [];
example = literalExpression "with pkgs; [ jq yek ];";
description = ''
Additional packages to install.
'';
};
}; };
}; };
@@ -99,7 +107,7 @@ in {
''; '';
}; };
in { in {
home.packages = mkIf cfg.enable [aichat-wrapped]; home.packages = mkIf cfg.enable ([aichat-wrapped] ++ cfg.extraPackages);
programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration fishIntegration; programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration fishIntegration;
programs.bash.initExtra = mkIf cfg.enableBashIntegration bashIntegration; programs.bash.initExtra = mkIf cfg.enableBashIntegration bashIntegration;

162
modules/nixos/affine.nix Normal file
View File

@@ -0,0 +1,162 @@
{
config,
lib,
...
}:
with lib; let
cfg = config.services.affine;
dbName = "affine";
dbUser = "affine";
in {
options.services.affine = {
enable = mkEnableOption "AFFiNE self-hosted workspace";
port = mkOption {
type = types.port;
default = 3010;
description = "Port for the AFFiNE server to listen on";
};
domain = mkOption {
type = types.str;
description = "Public domain for AFFiNE (e.g. notes.darksailor.dev)";
};
imageTag = mkOption {
type = types.str;
default = "stable";
description = "Docker image tag for AFFiNE (stable, beta, canary)";
};
dataDir = mkOption {
type = types.str;
default = "/var/lib/affine";
description = "Base data directory for AFFiNE storage";
};
environmentFiles = mkOption {
type = types.listOf types.path;
default = [];
description = "Environment files containing secrets (DB password, etc.)";
};
};
config = mkIf cfg.enable {
# Create data directories
systemd.tmpfiles.rules = [
"d ${cfg.dataDir} 0755 root root -"
"d ${cfg.dataDir}/storage 0755 root root -"
"d ${cfg.dataDir}/config 0755 root root -"
"d ${cfg.dataDir}/postgres 0700 root root -"
"d ${cfg.dataDir}/redis 0755 root root -"
];
virtualisation.oci-containers = {
backend = "docker";
containers = {
affine-postgres = {
image = "pgvector/pgvector:pg16";
volumes = [
"${cfg.dataDir}/postgres:/var/lib/postgresql/data"
];
environment = {
POSTGRES_USER = dbUser;
POSTGRES_DB = dbName;
POSTGRES_INITDB_ARGS = "--data-checksums";
POSTGRES_HOST_AUTH_METHOD = "trust";
};
environmentFiles = cfg.environmentFiles;
extraOptions = [
"--health-cmd=pg_isready -U ${dbUser} -d ${dbName}"
"--health-interval=10s"
"--health-timeout=5s"
"--health-retries=5"
];
networks = ["affine-net"];
};
affine-redis = {
image = "redis:7";
volumes = [
"${cfg.dataDir}/redis:/data"
];
networks = ["affine-net"];
extraOptions = [
"--health-cmd=redis-cli --raw incr ping"
"--health-interval=10s"
"--health-timeout=5s"
"--health-retries=5"
];
};
affine = {
image = "ghcr.io/toeverything/affine:${cfg.imageTag}";
ports = ["127.0.0.1:${toString cfg.port}:3010"];
dependsOn = [
"affine-postgres"
"affine-redis"
"affine-migration"
];
volumes = [
"${cfg.dataDir}/storage:/root/.affine/storage"
"${cfg.dataDir}/config:/root/.affine/config"
];
environment = {
AFFINE_SERVER_PORT = "3010";
AFFINE_SERVER_HOST = cfg.domain;
AFFINE_SERVER_HTTPS = "true";
AFFINE_SERVER_EXTERNAL_URL = "https://${cfg.domain}";
REDIS_SERVER_HOST = "affine-redis";
DATABASE_URL = "postgresql://${dbUser}:$${AFFINE_DB_PASSWORD:-affine}@affine-postgres:5432/${dbName}";
AFFINE_INDEXER_ENABLED = "false";
};
environmentFiles = cfg.environmentFiles;
networks = ["affine-net"];
};
affine-migration = {
image = "ghcr.io/toeverything/affine:${cfg.imageTag}";
dependsOn = [
"affine-postgres"
"affine-redis"
];
volumes = [
"${cfg.dataDir}/storage:/root/.affine/storage"
"${cfg.dataDir}/config:/root/.affine/config"
];
cmd = ["sh" "-c" "node ./scripts/self-host-predeploy.js"];
environment = {
REDIS_SERVER_HOST = "affine-redis";
DATABASE_URL = "postgresql://${dbUser}:$${AFFINE_DB_PASSWORD:-affine}@affine-postgres:5432/${dbName}";
AFFINE_INDEXER_ENABLED = "false";
};
environmentFiles = cfg.environmentFiles;
networks = ["affine-net"];
};
};
};
# Create the Docker network
# systemd.services.affine-network = {
# description = "Create AFFiNE Docker network";
# after = ["docker.service"];
# wantedBy = ["multi-user.target"];
# serviceConfig = {
# Type = "oneshot";
# RemainAfterExit = true;
# # ExecStart = "${config.virtualisation.docker.package}/bin/docker network create affine-net";
# # ExecStop = "${config.virtualisation.docker.package}/bin/docker network remove affine-net";
# };
# };
#
# Ensure containers start after the network is created
# systemd.services.docker-affine.after = ["affine-network.service"];
# systemd.services.docker-affine.requires = ["affine-network.service"];
# systemd.services.docker-affine-postgres.after = ["affine-network.service"];
# systemd.services.docker-affine-postgres.requires = ["affine-network.service"];
# systemd.services.docker-affine-redis.after = ["affine-network.service"];
# systemd.services.docker-affine-redis.requires = ["affine-network.service"];
# systemd.services.docker-affine-migration.after = ["affine-network.service"];
# systemd.services.docker-affine-migration.requires = ["affine-network.service"];
};
}

View File

@@ -1,480 +0,0 @@
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.services.caddy;
certs = config.security.acme.certs;
virtualHosts = attrValues cfg.virtualHosts;
acmeEnabledVhosts = filter (hostOpts: hostOpts.useACMEHost != null) virtualHosts;
vhostCertNames = unique (map (hostOpts: hostOpts.useACMEHost) acmeEnabledVhosts);
dependentCertNames = filter (cert: certs.${cert}.dnsProvider == null) vhostCertNames; # those that might depend on the HTTP server
independentCertNames = filter (cert: certs.${cert}.dnsProvider != null) vhostCertNames; # those that don't depend on the HTTP server
mkVHostConf = hostOpts: let
sslCertDir = config.security.acme.certs.${hostOpts.useACMEHost}.directory;
in ''
${hostOpts.hostName} ${concatStringsSep " " hostOpts.serverAliases} {
${optionalString (
hostOpts.listenAddresses != []
) "bind ${concatStringsSep " " hostOpts.listenAddresses}"}
${optionalString (
hostOpts.useACMEHost != null
) "tls ${sslCertDir}/cert.pem ${sslCertDir}/key.pem"}
log {
${hostOpts.logFormat}
}
${hostOpts.extraConfig}
}
'';
settingsFormat = pkgs.formats.json {};
configFile =
if cfg.settings != {}
then settingsFormat.generate "caddy.json" cfg.settings
else let
Caddyfile = pkgs.writeTextDir "Caddyfile" ''
{
${cfg.globalConfig}
}
${cfg.extraConfig}
${concatMapStringsSep "\n" mkVHostConf virtualHosts}
'';
Caddyfile-formatted = pkgs.runCommand "Caddyfile-formatted" {} ''
mkdir -p $out
cp --no-preserve=mode ${Caddyfile}/Caddyfile $out/Caddyfile
${lib.getExe cfg.package} fmt --overwrite $out/Caddyfile
'';
in "${
if pkgs.stdenv.buildPlatform == pkgs.stdenv.hostPlatform
then Caddyfile-formatted
else Caddyfile
}/Caddyfile";
etcConfigFile = "caddy/caddy_config";
configPath = "/etc/${etcConfigFile}";
mkCertOwnershipAssertion = import ../../../security/acme/mk-cert-ownership-assertion.nix lib;
in {
imports = [
(mkRemovedOptionModule [
"services"
"caddy"
"agree"
] "this option is no longer necessary for Caddy 2")
(mkRenamedOptionModule ["services" "caddy" "ca"] ["services" "caddy" "acmeCA"])
(mkRenamedOptionModule ["services" "caddy" "config"] ["services" "caddy" "extraConfig"])
];
# interface
options.services.caddy = {
enable = mkEnableOption "Caddy web server";
user = mkOption {
default = "caddy";
type = types.str;
description = ''
User account under which caddy runs.
::: {.note}
If left as the default value this user will automatically be created
on system activation, otherwise you are responsible for
ensuring the user exists before the Caddy service starts.
:::
'';
};
group = mkOption {
default = "caddy";
type = types.str;
description = ''
Group under which caddy runs.
::: {.note}
If left as the default value this group will automatically be created
on system activation, otherwise you are responsible for
ensuring the group exists before the Caddy service starts.
:::
'';
};
package = mkPackageOption pkgs "caddy" {};
dataDir = mkOption {
type = types.path;
default = "/var/lib/caddy";
description = ''
The data directory for caddy.
::: {.note}
If left as the default value this directory will automatically be created
before the Caddy server starts, otherwise you are responsible for ensuring
the directory exists with appropriate ownership and permissions.
Caddy v2 replaced `CADDYPATH` with XDG directories.
See <https://caddyserver.com/docs/conventions#file-locations>.
:::
'';
};
logDir = mkOption {
type = types.path;
default = "/var/log/caddy";
description = ''
Directory for storing Caddy access logs.
::: {.note}
If left as the default value this directory will automatically be created
before the Caddy server starts, otherwise the sysadmin is responsible for
ensuring the directory exists with appropriate ownership and permissions.
:::
'';
};
logFormat = mkOption {
type = types.lines;
default = ''
level ERROR
'';
example = literalExpression ''
mkForce "level INFO";
'';
description = ''
Configuration for the default logger. See
<https://caddyserver.com/docs/caddyfile/options#log>
for details.
'';
};
configFile = mkOption {
type = types.path;
default = configFile;
defaultText = "A Caddyfile automatically generated by values from services.caddy.*";
example = literalExpression ''
pkgs.writeText "Caddyfile" '''
example.com
root * /var/www/wordpress
php_fastcgi unix//run/php/php-version-fpm.sock
file_server
''';
'';
description = ''
Override the configuration file used by Caddy. By default,
NixOS generates one automatically.
The configuration file is exposed at {file}`${configPath}`.
'';
};
adapter = mkOption {
default =
if ((cfg.configFile != configFile) || (builtins.baseNameOf cfg.configFile) == "Caddyfile")
then "caddyfile"
else null;
defaultText = literalExpression ''
if ((cfg.configFile != configFile) || (builtins.baseNameOf cfg.configFile) == "Caddyfile") then "caddyfile" else null
'';
example = literalExpression "nginx";
type = with types; nullOr str;
description = ''
Name of the config adapter to use.
See <https://caddyserver.com/docs/config-adapters>
for the full list.
If `null` is specified, the `--adapter` argument is omitted when
starting or restarting Caddy. Notably, this allows specification of a
configuration file in Caddy's native JSON format, as long as the
filename does not start with `Caddyfile` (in which case the `caddyfile`
adapter is implicitly enabled). See
<https://caddyserver.com/docs/command-line#caddy-run> for details.
::: {.note}
Any value other than `null` or `caddyfile` is only valid when providing
your own `configFile`.
:::
'';
};
resume = mkOption {
default = false;
type = types.bool;
description = ''
Use saved config, if any (and prefer over any specified configuration passed with `--config`).
'';
};
globalConfig = mkOption {
type = types.lines;
default = "";
example = ''
debug
servers {
protocol {
experimental_http3
}
}
'';
description = ''
Additional lines of configuration appended to the global config section
of the `Caddyfile`.
Refer to <https://caddyserver.com/docs/caddyfile/options#global-options>
for details on supported values.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
example = ''
example.com {
encode gzip
log
root /srv/http
}
'';
description = ''
Additional lines of configuration appended to the automatically
generated `Caddyfile`.
'';
};
virtualHosts = mkOption {
type = with types; attrsOf (submodule (import ./vhost-options.nix {inherit cfg;}));
default = {};
example = literalExpression ''
{
"hydra.example.com" = {
serverAliases = [ "www.hydra.example.com" ];
extraConfig = '''
encode gzip
root * /srv/http
''';
};
};
'';
description = ''
Declarative specification of virtual hosts served by Caddy.
'';
};
acmeCA = mkOption {
default = null;
example = "https://acme-v02.api.letsencrypt.org/directory";
type = with types; nullOr str;
description = ''
::: {.note}
Sets the [`acme_ca` option](https://caddyserver.com/docs/caddyfile/options#acme-ca)
in the global options block of the resulting Caddyfile.
:::
The URL to the ACME CA's directory. It is strongly recommended to set
this to `https://acme-staging-v02.api.letsencrypt.org/directory` for
Let's Encrypt's [staging endpoint](https://letsencrypt.org/docs/staging-environment/)
while testing or in development.
Value `null` should be prefered for production setups,
as it omits the `acme_ca` option to enable
[automatic issuer fallback](https://caddyserver.com/docs/automatic-https#issuer-fallback).
'';
};
email = mkOption {
default = null;
type = with types; nullOr str;
description = ''
Your email address. Mainly used when creating an ACME account with your
CA, and is highly recommended in case there are problems with your
certificates.
'';
};
enableReload = mkOption {
default = true;
type = types.bool;
description = ''
Reload Caddy instead of restarting it when configuration file changes.
Note that enabling this option requires the [admin API](https://caddyserver.com/docs/caddyfile/options#admin)
to not be turned off.
If you enable this option, consider setting [`grace_period`](https://caddyserver.com/docs/caddyfile/options#grace-period)
to a non-infinite value in {option}`services.caddy.globalConfig`
to prevent Caddy waiting for active connections to finish,
which could delay the reload essentially indefinitely.
'';
};
settings = mkOption {
type = settingsFormat.type;
default = {};
description = ''
Structured configuration for Caddy to generate a Caddy JSON configuration file.
See <https://caddyserver.com/docs/json/> for available options.
::: {.warning}
Using a [Caddyfile](https://caddyserver.com/docs/caddyfile) instead of a JSON config is highly recommended by upstream.
There are only very few exception to this.
Please use a Caddyfile via {option}`services.caddy.configFile`, {option}`services.caddy.virtualHosts` or
{option}`services.caddy.extraConfig` with {option}`services.caddy.globalConfig` instead.
:::
::: {.note}
Takes presence over most `services.caddy.*` options, such as {option}`services.caddy.configFile` and {option}`services.caddy.virtualHosts`, if specified.
:::
'';
};
environmentFile = mkOption {
type = with types; nullOr path;
default = null;
example = "/run/secrets/caddy.env";
description = ''
Environment file as defined in {manpage}`systemd.exec(5)`.
You can use environment variables to pass secrets to the service without adding
them to the world-redable nix store.
```
# in configuration.nix
services.caddy.environmentFile = "/run/secrets/caddy.env";
services.caddy.globalConfig = '''
{
acme_ca https://acme.zerossl.com/v2/DV90
acme_eab {
key_id {$EAB_KEY_ID}
mac_key {$EAB_MAC_KEY}
}
}
''';
```
```
# in /run/secrets/caddy.env
EAB_KEY_ID=secret
EAB_MAC_KEY=secret
```
Find more examples
[here](https://caddyserver.com/docs/caddyfile/concepts#environment-variables)
'';
};
};
# implementation
config = mkIf cfg.enable {
assertions =
[
{
assertion = cfg.configFile == configFile -> cfg.adapter == "caddyfile" || cfg.adapter == null;
message = "To specify an adapter other than 'caddyfile' please provide your own configuration via `services.caddy.configFile`";
}
]
++ map (
name:
mkCertOwnershipAssertion {
cert = config.security.acme.certs.${name};
groups = config.users.groups;
services = [config.systemd.services.caddy];
}
)
vhostCertNames;
services.caddy.globalConfig = ''
${optionalString (cfg.email != null) "email ${cfg.email}"}
${optionalString (cfg.acmeCA != null) "acme_ca ${cfg.acmeCA}"}
log {
${cfg.logFormat}
}
'';
# https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes
boot.kernel.sysctl."net.core.rmem_max" = mkDefault 2500000;
boot.kernel.sysctl."net.core.wmem_max" = mkDefault 2500000;
systemd.packages = [cfg.package];
systemd.services.caddy = {
wants = map (certName: "acme-finished-${certName}.target") vhostCertNames;
after =
map (certName: "acme-selfsigned-${certName}.service") vhostCertNames
++ map (certName: "acme-${certName}.service") independentCertNames; # avoid loading self-signed key w/ real cert, or vice-versa
before = map (certName: "acme-${certName}.service") dependentCertNames;
wantedBy = ["multi-user.target"];
startLimitIntervalSec = 14400;
startLimitBurst = 10;
reloadTriggers = optional cfg.enableReload cfg.configFile;
restartTriggers = optional (!cfg.enableReload) cfg.configFile;
serviceConfig = let
runOptions = ''--config ${configPath} ${
optionalString (cfg.adapter != null) "--adapter ${cfg.adapter}"
}'';
in {
# Override the `ExecStart` line from upstream's systemd unit file by our own:
# https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=
# If the empty string is assigned to this option, the list of commands to start is reset, prior assignments of this option will have no effect.
ExecStart = [
""
''${lib.getExe cfg.package} run ${runOptions} ${optionalString cfg.resume "--resume"}''
];
# Validating the configuration before applying it ensures well get a proper error that will be reported when switching to the configuration
ExecReload =
[
""
]
++ lib.optional cfg.enableReload "${lib.getExe cfg.package} reload ${runOptions} --force";
User = cfg.user;
Group = cfg.group;
ReadWritePaths = [cfg.dataDir];
StateDirectory = mkIf (cfg.dataDir == "/var/lib/caddy") ["caddy"];
LogsDirectory = mkIf (cfg.logDir == "/var/log/caddy") ["caddy"];
Restart = "on-failure";
RestartPreventExitStatus = 1;
RestartSec = "5s";
EnvironmentFile = optional (cfg.environmentFile != null) cfg.environmentFile;
# TODO: attempt to upstream these options
NoNewPrivileges = true;
PrivateDevices = true;
ProtectHome = true;
};
};
users.users = optionalAttrs (cfg.user == "caddy") {
caddy = {
group = cfg.group;
uid = config.ids.uids.caddy;
home = cfg.dataDir;
};
};
users.groups = optionalAttrs (cfg.group == "caddy") {
caddy.gid = config.ids.gids.caddy;
};
security.acme.certs = let
certCfg =
map (
certName:
nameValuePair certName {
group = mkDefault cfg.group;
reloadServices = ["caddy.service"];
}
)
vhostCertNames;
in
listToAttrs certCfg;
environment.etc.${etcConfigFile}.source = cfg.configFile;
};
}

View File

@@ -1,83 +0,0 @@
{cfg}: {
config,
lib,
name,
...
}: let
inherit (lib) literalExpression mkOption types;
in {
options = {
hostName = mkOption {
type = types.str;
default = name;
description = "Canonical hostname for the server.";
};
serverAliases = mkOption {
type = with types; listOf str;
default = [];
example = [
"www.example.org"
"example.org"
];
description = ''
Additional names of virtual hosts served by this virtual host configuration.
'';
};
listenAddresses = mkOption {
type = with types; listOf str;
description = ''
A list of host interfaces to bind to for this virtual host.
'';
default = [];
example = [
"127.0.0.1"
"::1"
];
};
useACMEHost = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
A host of an existing Let's Encrypt certificate to use.
This is mostly useful if you use DNS challenges but Caddy does not
currently support your provider.
*Note that this option does not create any certificates, nor
does it add subdomains to existing ones you will need to create them
manually using [](#opt-security.acme.certs).*
'';
};
logFormat = mkOption {
type = types.lines;
default = ''
output file ${cfg.logDir}/access-${lib.replaceStrings ["/" " "] ["_" "_"] config.hostName}.log
'';
defaultText = ''
output file ''${config.services.caddy.logDir}/access-''${hostName}.log
'';
example = literalExpression ''
mkForce '''
output discard
''';
'';
description = ''
Configuration for HTTP request logging (also known as access logs). See
<https://caddyserver.com/docs/caddyfile/directives/log#log>
for details.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Additional lines of configuration appended to this virtual host in the
automatically generated `Caddyfile`.
'';
};
};
}

View File

@@ -0,0 +1,50 @@
{
config,
lib,
...
}:
with lib; let
cfg = config.nix.substituters;
in {
options.nix.substituters = {
enableCuda = mkOption {
type = types.bool;
default = false;
description = "Enable NixOS CUDA cache";
};
enableLlamaCpp = mkOption {
type = types.bool;
default = false;
description = "Enable llama-cpp cache";
};
};
config = {
nix.settings = {
trusted-substituters =
[
"https://nix-community.cachix.org"
"https://nixos-raspberrypi.cachix.org"
]
++ optionals cfg.enableLlamaCpp [
"https://llama-cpp.cachix.org"
]
++ optionals cfg.enableCuda [
"https://cache.nixos-cuda.org"
];
trusted-public-keys =
[
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI="
]
++ optionals cfg.enableLlamaCpp [
"llama-cpp.cachix.org-1:H75X+w83wUKTIPSO1KWy9ADUrzThyGs8P5tmAbkWhQc="
]
++ optionals cfg.enableCuda [
"cache.nixos-cuda.org:74DUi4Ye579gUqzH4ziL9IyiJBlDpMRn9MBN8oNan9M="
];
};
};
}

View File

@@ -20,6 +20,7 @@
}; };
in { in {
opts = { opts = {
autoread = true;
completeopt = "menu,menuone,popup,noselect"; completeopt = "menu,menuone,popup,noselect";
expandtab = true; expandtab = true;
foldenable = true; foldenable = true;
@@ -106,7 +107,7 @@ in {
"<C-q>x" = "[[<cmd>tabclose<cr>]]"; "<C-q>x" = "[[<cmd>tabclose<cr>]]";
"<C-q>n" = "[[<cmd>tabnext<cr>]]"; "<C-q>n" = "[[<cmd>tabnext<cr>]]";
"<C-q>p" = "[[<cmd>tabprevious<cr>]]"; "<C-q>p" = "[[<cmd>tabprevious<cr>]]";
"<c-.>" = "require('sidekick.cli').toggle"; "<C-.>" = "require('opencode').toggle";
}; };
terminal = { terminal = {
"<C-\\>" = "require('FTerm').toggle"; "<C-\\>" = "require('FTerm').toggle";
@@ -177,16 +178,19 @@ in {
trouble.enable = true; trouble.enable = true;
ts-context-commentstring.enable = true; ts-context-commentstring.enable = true;
which-key.enable = true; which-key.enable = true;
opencode = {
sidekick = {
enable = true; enable = true;
settings = {
nes = {
enabled = false;
};
};
}; };
# sidekick = {
# enable = true;
# settings = {
# nes = {
# enabled = false;
# };
# };
# };
conform-nvim = { conform-nvim = {
enable = true; enable = true;
settings = { settings = {
@@ -358,17 +362,17 @@ in {
}; };
}; };
folding.enable = true; folding.enable = true;
grammarPackages = # grammarPackages =
(with pkgs.tree-sitter-grammars; [ # (with pkgs.tree-sitter-grammars; [
tree-sitter-norg # tree-sitter-norg
tree-sitter-norg-meta # tree-sitter-norg-meta
tree-sitter-just # tree-sitter-just
tree-sitter-nu # tree-sitter-nu
tree-sitter-pest # tree-sitter-pest
tree-sitter-slint # tree-sitter-slint
]) # ])
++ pkgs.vimPlugins.nvim-treesitter.allGrammars; # ++ pkgs.vimPlugins.nvim-treesitter.allGrammars;
nixGrammars = true; # nixGrammars = true;
}; };
telescope = { telescope = {
@@ -548,6 +552,7 @@ in {
pyright.enable = true; pyright.enable = true;
slint_lsp.enable = true; slint_lsp.enable = true;
wgsl_analyzer.enable = true; wgsl_analyzer.enable = true;
glsl_analyzer.enable = true;
# sourcekit.enable = true; # sourcekit.enable = true;
openscad_lsp.enable = true; openscad_lsp.enable = true;
tinymist.enable = true; tinymist.enable = true;
@@ -615,6 +620,21 @@ in {
}; };
sources = { sources = {
cmdline = []; cmdline = [];
# default =
# rawLua
# /*
# lua
# */
# ''
# function(ctx)
# local success, node = pcall(vim.treesitter.get_node)
# if success and node and vim.tbl_contains({ 'comment', 'line_comment', 'block_comment' }, node:type()) then
# return { 'buffer' }
# else
# return { 'git', 'lsp', 'path', 'snippets', 'buffer', 'dictionary', 'ripgrep', 'tmux' }
# end
# end
# '';
default = [ default = [
"git" "git"
"lsp" "lsp"
@@ -623,6 +643,7 @@ in {
"path" "path"
"buffer" "buffer"
"ripgrep" "ripgrep"
# "tmux"
]; ];
providers = { providers = {
buffer = { buffer = {
@@ -634,23 +655,30 @@ in {
path = {}; path = {};
dictionary = { dictionary = {
module = "blink-cmp-dictionary"; module = "blink-cmp-dictionary";
name = "Dict"; name = "dict";
min_keyword_length = 3; min_keyword_length = 3;
opts = { opts = {
}; };
}; };
git = { git = {
module = "blink-cmp-git"; module = "blink-cmp-git";
name = "Git"; name = "git";
opts = { opts = {
# -- options for the blink-cmp-git # -- options for the blink-cmp-git
}; };
}; };
ripgrep = { ripgrep = {
module = "blink-ripgrep"; module = "blink-ripgrep";
name = "Ripgrep"; name = "ripgrep";
opts = {}; opts = {};
}; };
# tmux = {
# module = "blink-cmp-tmux";
# name = "tmux";
# opts = {
# triggered_only = false;
# };
# };
}; };
}; };
}; };
@@ -660,6 +688,7 @@ in {
blink-cmp-dictionary.enable = true; blink-cmp-dictionary.enable = true;
blink-cmp-copilot.enable = true; blink-cmp-copilot.enable = true;
blink-cmp-spell.enable = true; blink-cmp-spell.enable = true;
blink-cmp-tmux.enable = true;
blink-compat = { blink-compat = {
enable = true; enable = true;
settings.impersonate_nvim_cmp = true; settings.impersonate_nvim_cmp = true;
@@ -856,5 +885,6 @@ in {
pkgs.lua pkgs.lua
pkgs.ripgrep pkgs.ripgrep
pkgs.nodejs-slim pkgs.nodejs-slim
pkgs.lsof
]; ];
} }

View File

@@ -4,4 +4,5 @@
documentation.dev.enable = true; documentation.dev.enable = true;
documentation.doc.enable = true; documentation.doc.enable = true;
documentation.nixos.enable = true; documentation.nixos.enable = true;
documentation.man.generateCaches = true;
} }

View File

@@ -7,5 +7,11 @@
# ./alvr.nix # ./alvr.nix
./easyeffects.nix ./easyeffects.nix
./vr.nix ./vr.nix
./helvum.nix
# ./wine.nix
# ./virt.nix
./gparted.nix
./nvtop.nix
# ./qpwgraph.nix
]; ];
} }

View File

@@ -0,0 +1,3 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [gparted];
}

View File

@@ -0,0 +1,3 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [helvum];
}

3
nixos/ryu/apps/nvtop.nix Normal file
View File

@@ -0,0 +1,3 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [nvtopPackages.nvidia];
}

View File

@@ -0,0 +1,3 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [qpwgraph];
}

6
nixos/ryu/apps/virt.nix Normal file
View File

@@ -0,0 +1,6 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
virt-manager
quickemu
];
}

View File

@@ -1,7 +1,8 @@
{pkgs, ...}: { {pkgs, ...}: {
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
wlx-overlay-s wayvr
wayvr-dashboard # wlx-overlay-s
# wayvr-dashboard
# bs-manager # bs-manager
monado-vulkan-layers monado-vulkan-layers
# envision # envision

7
nixos/ryu/apps/wine.nix Normal file
View File

@@ -0,0 +1,7 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
wine-wayland
winetricks
wineWowPackages.waylandFull
];
}

View File

@@ -2,6 +2,7 @@
pkgs, pkgs,
lib, lib,
device, device,
config,
... ...
}: { }: {
imports = [ imports = [
@@ -11,6 +12,8 @@
./containers ./containers
./apps ./apps
./vms ./vms
./games
../../modules/nixos/substituters.nix
]; ];
security.tpm2 = { security.tpm2 = {
@@ -25,6 +28,7 @@
withUWSM = true; withUWSM = true;
xwayland.enable = true; xwayland.enable = true;
}; };
uwsm.enable = true;
}; };
systemd.services.NetworkManager-wait-online.enable = lib.mkForce false; systemd.services.NetworkManager-wait-online.enable = lib.mkForce false;
@@ -44,18 +48,7 @@
auto-optimise-store = true; auto-optimise-store = true;
extra-experimental-features = "nix-command flakes auto-allocate-uids"; extra-experimental-features = "nix-command flakes auto-allocate-uids";
trusted-users = [device.user]; trusted-users = [device.user];
trusted-substituters = [ extra-sandbox-paths = [config.programs.ccache.cacheDir];
"https://nix-community.cachix.org"
"https://nixos-raspberrypi.cachix.org"
"https://llama-cpp.cachix.org"
"https://cuda-maintainers.cachix.org"
];
trusted-public-keys = [
"cuda-maintainers.cachix.org-1:0dq3bujKpuEPMCX6U4WylrUDZ9JyUG0VpVZa7CNfq5E="
"llama-cpp.cachix.org-1:H75X+w83wUKTIPSO1KWy9ADUrzThyGs8P5tmAbkWhQc="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI="
];
}; };
extraOptions = '' extraOptions = ''
build-users-group = nixbld build-users-group = nixbld
@@ -67,19 +60,24 @@
dates = "daily"; dates = "daily";
options = "--delete-older-than +5"; options = "--delete-older-than +5";
}; };
package = pkgs.nixVersions.latest; # deploy-rs doesn't work with nix >= 2.32 package = pkgs.nixVersions.nix_2_32; # deploy-rs doesn't work with nix >= 2.33
buildMachines = [ buildMachines = [
../../builders/tako.nix ../../builders/tako.nix
../../builders/shiro.nix ../../builders/shiro.nix
# ../../builders/tsuba.nix # ../../builders/tsuba.nix
]; ];
distributedBuilds = true; distributedBuilds = true;
# Enable CUDA and llama-cpp caches
substituters = {
enableCuda = true;
enableLlamaCpp = true;
};
}; };
users.users.${device.user} = { users.users.${device.user} = {
uid = device.uid; uid = device.uid;
isNormalUser = true; isNormalUser = true;
extraGroups = ["wheel" "audio" "i2c" "media" "video" "tss"]; extraGroups = ["wheel" "audio" "i2c" "media" "video" "tss" "plugdev"];
openssh.authorizedKeys.keyFiles = [ openssh.authorizedKeys.keyFiles = [
../../secrets/id_ed25519.pub ../../secrets/id_ed25519.pub
../../secrets/id_ios.pub ../../secrets/id_ios.pub
@@ -109,12 +107,6 @@
}; };
displayManager.gdm.enable = true; displayManager.gdm.enable = true;
# desktopManager.gnome.enable = true; # desktopManager.gnome.enable = true;
pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
};
}; };
boot = { boot = {
@@ -167,12 +159,31 @@
Name = "Ryu"; Name = "Ryu";
Enable = "Source,Sink,Media,Socket"; Enable = "Source,Sink,Media,Socket";
ControllerMode = "dual"; ControllerMode = "dual";
FactConnectable = "true"; FactConnectable = true;
Experimental = "true"; Experimental = true;
}; };
}; };
}; };
}; };
boot.extraModprobeConfig = ''
# Keep Bluetooth coexistence disabled for better BT audio stability
options iwlwifi bt_coex_active=0
# Enable software crypto (helps BT coexistence sometimes)
options iwlwifi swcrypto=1
# Disable power saving on Wi-Fi module to reduce radio state changes that might disrupt BT
options iwlwifi power_save=0
# Disable Unscheduled Automatic Power Save Delivery (U-APSD) to improve BT audio stability
options iwlwifi uapsd_disable=1
# Disable D0i3 power state to avoid problematic power transitions
options iwlwifi d0i3_disable=1
# Set power scheme for performance (iwlmvm)
options iwlmvm power_scheme=1
'';
networking = { networking = {
interfaces.eno1.wakeOnLan = { interfaces.eno1.wakeOnLan = {
@@ -282,41 +293,6 @@
fonts.fontconfig.enable = true; fonts.fontconfig.enable = true;
fonts.fontDir.enable = true; fonts.fontDir.enable = true;
environment = { environment = {
# List packages installed in system profile. To search, run:
# $ nix search wget
systemPackages = with pkgs; [
v4l-utils
polychromatic
openrazer-daemon
cudatoolkit
# Wine
wine-wayland
winetricks
wineWowPackages.waylandFull
virt-manager
gparted
nvtopPackages.nvidia
quickemu
# (nixvim.makeNixvim (import ../../neovim))
qpwgraph
hyprland
xorg.xhost
foot
git
fish
nushell
# (pkgs.wrapFirefox
# (pkgs.firefox-unwrapped.override {pipewireSupport = true;})
# {})
gnumake
python3
nerd-fonts.fira-code
nerd-fonts.hasklug
nerd-fonts.symbols-only
monaspace
ddcutil
];
sessionVariables = { sessionVariables = {
WLR_NO_HARDWARE_CURSORS = "1"; WLR_NO_HARDWARE_CURSORS = "1";
NIXOS_OZONE_WL = "1"; NIXOS_OZONE_WL = "1";

View File

@@ -2,12 +2,11 @@
port = 3003; port = 3003;
in { in {
virtualisation.oci-containers = { virtualisation.oci-containers = {
backend = "docker";
containers = { containers = {
immich-machine-learning = { immich-machine-learning = {
image = "ghcr.io/immich-app/immich-machine-learning:v${pkgs.immich.version}-cuda"; image = "ghcr.io/immich-app/immich-machine-learning:v${pkgs.immich.version}-cuda";
ports = [ ports = [
"0.0.0.0:${toString port}:3003" "127.0.0.1:${toString port}:3003"
]; ];
volumes = [ volumes = [
"model-cache:/cache" "model-cache:/cache"
@@ -20,7 +19,4 @@ in {
nvidia-docker nvidia-docker
nvidia-container-toolkit nvidia-container-toolkit
]; ];
# services.caddy.virtualHosts."ml.ryu.darksailor.dev".extraConfig = ''
# reverse_proxy localhost:${toString port}
# '';
} }

View File

@@ -0,0 +1,5 @@
{...}: {
imports = [
# ./hytale.nix
];
}

499
nixos/ryu/games/hytale.nix Normal file
View File

@@ -0,0 +1,499 @@
# {pkgs, ...}: let
# version = "2026.01.21-11273a4";
# hytale-launcher = pkgs.fetchzip {
# url = "https://launcher.hytale.com/builds/release/linux/amd64/hytale-launcher-${version}.zip";
# sha256 = "sha256-PPdYmLxAVyqSkhulZXLcaEuhofCHZ4JcDJXIQ+lBhFg=";
# };
# in {
# environment.systemPackages = with pkgs; [
# # (pkgs.buildFHSEnv {
# # pname = "hytale";
# # inherit version;
# # targetPkgs = p:
# # with p; [
# # # Launcher
# # libsoup_3
# # gdk-pixbuf
# # glib
# # gtk3
# # webkitgtk_4_1
# #
# # # Game
# # alsa-lib
# # icu
# # libGL
# # openssl
# # udev
# # xorg.libX11
# # xorg.libXcursor
# # xorg.libXrandr
# # xorg.libXi
# # ];
# # runScript = "${hytale-launcher}/hytale-launcher";
# # })
# hytale-launcher
# ];
# }
#
# { pkgs }:
#
# let
# # === AUTO-UPDATE MARKERS - DO NOT MODIFY FORMAT ===
# version = "2026.01.24-997c2cb";
# sha256 = "sha256-G+FFMOtLVPH2zaWQ87jymf6+JUAVFEKA4SMyuYE9MZ0=";
# # === END AUTO-UPDATE MARKERS ===
#
# pname = "hytale-launcher";
# downloadUrl = "https://launcher.hytale.com/builds/release/linux/amd64/hytale-launcher-${version}.zip";
#
# # Unwrapped derivation - extracts and patches the binary
# hytale-launcher-unwrapped = pkgs.stdenv.mkDerivation {
# pname = "${pname}-unwrapped";
# inherit version;
#
# src = pkgs.fetchurl {
# url = downloadUrl;
# inherit sha256;
# };
#
# nativeBuildInputs = with pkgs; [
# autoPatchelfHook
# unzip
# ];
#
# unpackPhase = ''
# runHook preUnpack
# unzip $src -d .
# runHook postUnpack
# '';
#
# buildInputs = with pkgs; [
# webkitgtk_4_1
# gtk3
# glib
# gdk-pixbuf
# libsoup_3
# cairo
# pango
# at-spi2-atk
# harfbuzz
# glibc
# ];
#
# runtimeDependencies = with pkgs; [
# libGL
# libxkbcommon
# xorg.libX11
# xorg.libXcomposite
# xorg.libXdamage
# xorg.libXext
# xorg.libXfixes
# xorg.libXrandr
# ];
#
# # No build phase needed - just unpack and install
# dontBuild = true;
#
# installPhase = ''
# runHook preInstall
#
# mkdir -p $out/lib/hytale-launcher
# install -m755 hytale-launcher $out/lib/hytale-launcher/
#
# runHook postInstall
# '';
#
# meta = with pkgs.lib; {
# description = "Official launcher for Hytale game (unwrapped)";
# homepage = "https://hytale.com";
# license = licenses.unfree;
# sourceProvenance = with sourceTypes; [ binaryNativeCode ];
# maintainers = [{
# name = "Jacob Pyke";
# email = "github@pyk.ee";
# github = "JPyke3";
# githubId = 13283054;
# }];
# platforms = [ "x86_64-linux" ];
# };
# };
#
# # FHS-wrapped derivation - allows self-updates to work
# hytale-launcher = pkgs.buildFHSEnv {
# name = "hytale-launcher";
# inherit version;
#
# targetPkgs = pkgs: with pkgs; [
# # Core dependencies
# hytale-launcher-unwrapped
#
# # WebKit/GTK stack (for launcher UI)
# webkitgtk_4_1
# gtk3
# glib
# gdk-pixbuf
# libsoup_3
# cairo
# pango
# at-spi2-atk
# harfbuzz
#
# # Graphics - OpenGL/Vulkan/EGL (for game client via SDL3)
# libGL
# libGLU
# libglvnd
# mesa
# vulkan-loader
# egl-wayland
#
# # X11 (SDL3 dlopens these)
# xorg.libX11
# xorg.libXcomposite
# xorg.libXdamage
# xorg.libXext
# xorg.libXfixes
# xorg.libXrandr
# xorg.libXcursor
# xorg.libXi
# xorg.libxcb
# xorg.libXScrnSaver
# xorg.libXinerama
# xorg.libXxf86vm
#
# # Wayland (SDL3 can use Wayland backend)
# wayland
# libxkbcommon
#
# # Audio (for game client via bundled OpenAL)
# alsa-lib
# pipewire
# pulseaudio
#
# # System libraries
# dbus
# fontconfig
# freetype
# glibc
# nspr
# nss
# systemd
# zlib
#
# # C++ runtime (needed by libNoesis.so, libopenal.so in game client)
# stdenv.cc.cc.lib
#
# # .NET runtime dependencies (HytaleClient is a .NET application)
# icu
# openssl
# krb5
#
# # TLS/SSL support for GLib networking (launcher)
# glib-networking
# cacert
# ];
#
# runScript = pkgs.writeShellScript "hytale-launcher-wrapper" ''
# # Hytale data directory
# LAUNCHER_DIR="''${XDG_DATA_HOME:-$HOME/.local/share}/Hytale"
# LAUNCHER_BIN="$LAUNCHER_DIR/hytale-launcher"
# BUNDLED_HASH_FILE="$LAUNCHER_DIR/.bundled_hash"
# BUNDLED_BIN="${hytale-launcher-unwrapped}/lib/hytale-launcher/hytale-launcher"
#
# mkdir -p "$LAUNCHER_DIR"
#
# # Compute hash of bundled binary to detect Nix package updates
# BUNDLED_HASH=$(sha256sum "$BUNDLED_BIN" | cut -d" " -f1)
#
# # Copy bundled binary if needed (new install or Nix package update)
# if [ ! -x "$LAUNCHER_BIN" ] || [ ! -f "$BUNDLED_HASH_FILE" ] || [ "$(cat "$BUNDLED_HASH_FILE")" != "$BUNDLED_HASH" ]; then
# install -m755 "$BUNDLED_BIN" "$LAUNCHER_BIN"
# echo "$BUNDLED_HASH" > "$BUNDLED_HASH_FILE"
# fi
#
# # Required environment variable from Flatpak metadata
# export WEBKIT_DISABLE_COMPOSITING_MODE=1
#
# # Enable GLib TLS backend (glib-networking)
# export GIO_MODULE_DIR=/usr/lib/gio/modules
#
# # SSL certificates
# export SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt
#
# exec "$LAUNCHER_BIN" "$@"
# '';
#
# extraInstallCommands = ''
# # Install desktop file
# mkdir -p $out/share/applications
# cat > $out/share/applications/hytale-launcher.desktop << EOF
# [Desktop Entry]
# Name=Hytale Launcher
# Comment=Official launcher for Hytale
# Exec=$out/bin/hytale-launcher
# Icon=hytale-launcher
# Terminal=false
# Type=Application
# Categories=Game;
# Keywords=hytale;game;launcher;hypixel;
# StartupWMClass=com.hypixel.HytaleLauncher
# EOF
#
# '';
#
# meta = with pkgs.lib; {
# description = "Official launcher for Hytale game";
# longDescription = ''
# The official launcher for Hytale, developed by Hypixel Studios.
# This package wraps the launcher from the official distribution,
# providing FHS compatibility for self-updates.
# '';
# homepage = "https://hytale.com";
# license = licenses.unfree;
# sourceProvenance = with sourceTypes; [ binaryNativeCode ];
# maintainers = [{
# name = "Jacob Pyke";
# email = "github@pyk.ee";
# github = "JPyke3";
# githubId = 13283054;
# }];
# platforms = [ "x86_64-linux" ];
# mainProgram = "hytale-launcher";
# };
# };
#
# in {
# inherit hytale-launcher hytale-launcher-unwrapped;
# }
{pkgs, ...}: let
# === AUTO-UPDATE MARKERS - DO NOT MODIFY FORMAT ===
version = "2026.01.24-997c2cb";
sha256 = "sha256-G+FFMOtLVPH2zaWQ87jymf6+JUAVFEKA4SMyuYE9MZ0=";
# === END AUTO-UPDATE MARKERS ===
pname = "hytale-launcher";
downloadUrl = "https://launcher.hytale.com/builds/release/linux/amd64/hytale-launcher-${version}.zip";
# Unwrapped derivation - extracts and patches the binary
hytale-launcher-unwrapped = pkgs.stdenv.mkDerivation {
pname = "${pname}-unwrapped";
inherit version;
src = pkgs.fetchurl {
url = downloadUrl;
inherit sha256;
};
nativeBuildInputs = with pkgs; [
autoPatchelfHook
unzip
];
unpackPhase = ''
runHook preUnpack
unzip $src -d .
runHook postUnpack
'';
buildInputs = with pkgs; [
webkitgtk_4_1
gtk3
glib
gdk-pixbuf
libsoup_3
cairo
pango
at-spi2-atk
harfbuzz
glibc
];
runtimeDependencies = with pkgs; [
libGL
libxkbcommon
# xorg.libX11
# xorg.libXcomposite
# xorg.libXdamage
# xorg.libXext
# xorg.libXfixes
# xorg.libXrandr
];
# No build phase needed - just unpack and install
dontBuild = true;
installPhase = ''
runHook preInstall
mkdir -p $out/lib/hytale-launcher
install -m755 hytale-launcher $out/lib/hytale-launcher/
runHook postInstall
'';
meta = with pkgs.lib; {
description = "Official launcher for Hytale game (unwrapped)";
homepage = "https://hytale.com";
license = licenses.unfree;
sourceProvenance = with sourceTypes; [binaryNativeCode];
maintainers = [
{
name = "Jacob Pyke";
email = "github@pyk.ee";
github = "JPyke3";
githubId = 13283054;
}
];
platforms = ["x86_64-linux"];
};
};
# FHS-wrapped derivation - allows self-updates to work
hytale-launcher = pkgs.buildFHSEnv {
name = "hytale-launcher";
inherit version;
targetPkgs = pkgs:
with pkgs; [
# Core dependencies
hytale-launcher-unwrapped
# WebKit/GTK stack (for launcher UI)
webkitgtk_4_1
gtk3
glib
gdk-pixbuf
libsoup_3
cairo
pango
at-spi2-atk
harfbuzz
# Graphics - OpenGL/Vulkan/EGL (for game client via SDL3)
libGL
libGLU
libglvnd
mesa
vulkan-loader
egl-wayland
# X11 (SDL3 dlopens these)
# xorg.libX11
# xorg.libXcomposite
# xorg.libXdamage
# xorg.libXext
# xorg.libXfixes
# xorg.libXrandr
# xorg.libXcursor
# xorg.libXi
# xorg.libxcb
# xorg.libXScrnSaver
# xorg.libXinerama
# xorg.libXxf86vm
# Wayland (SDL3 can use Wayland backend)
wayland
libxkbcommon
# Audio (for game client via bundled OpenAL)
alsa-lib
pipewire
pulseaudio
# System libraries
dbus
fontconfig
freetype
glibc
nspr
nss
systemd
zlib
# C++ runtime (needed by libNoesis.so, libopenal.so in game client)
stdenv.cc.cc.lib
# .NET runtime dependencies (HytaleClient is a .NET application)
icu
openssl
krb5
# TLS/SSL support for GLib networking (launcher)
glib-networking
cacert
];
runScript = pkgs.writeShellScript "hytale-launcher-wrapper" ''
# Hytale data directory
LAUNCHER_DIR="''${XDG_DATA_HOME:-$HOME/.local/share}/Hytale"
LAUNCHER_BIN="$LAUNCHER_DIR/hytale-launcher"
BUNDLED_HASH_FILE="$LAUNCHER_DIR/.bundled_hash"
BUNDLED_BIN="${hytale-launcher-unwrapped}/lib/hytale-launcher/hytale-launcher"
mkdir -p "$LAUNCHER_DIR"
# Compute hash of bundled binary to detect Nix package updates
BUNDLED_HASH=$(sha256sum "$BUNDLED_BIN" | cut -d" " -f1)
# Copy bundled binary if needed (new install or Nix package update)
if [ ! -x "$LAUNCHER_BIN" ] || [ ! -f "$BUNDLED_HASH_FILE" ] || [ "$(cat "$BUNDLED_HASH_FILE")" != "$BUNDLED_HASH" ]; then
install -m755 "$BUNDLED_BIN" "$LAUNCHER_BIN"
echo "$BUNDLED_HASH" > "$BUNDLED_HASH_FILE"
fi
# Required environment variable from Flatpak metadata
export WEBKIT_DISABLE_COMPOSITING_MODE=1
# Enable GLib TLS backend (glib-networking)
export GIO_MODULE_DIR=/usr/lib/gio/modules
# SSL certificates
export SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt
exec "$LAUNCHER_BIN" "$@"
'';
extraInstallCommands = ''
# Install desktop file
mkdir -p $out/share/applications
cat > $out/share/applications/hytale-launcher.desktop << EOF
[Desktop Entry]
Name=Hytale Launcher
Comment=Official launcher for Hytale
Exec=$out/bin/hytale-launcher
Icon=hytale-launcher
Terminal=false
Type=Application
Categories=Game;
Keywords=hytale;game;launcher;hypixel;
StartupWMClass=com.hypixel.HytaleLauncher
EOF
'';
meta = with pkgs.lib; {
description = "Official launcher for Hytale game";
longDescription = ''
The official launcher for Hytale, developed by Hypixel Studios.
This package wraps the launcher from the official distribution,
providing FHS compatibility for self-updates.
'';
homepage = "https://hytale.com";
license = licenses.unfree;
sourceProvenance = with sourceTypes; [binaryNativeCode];
maintainers = [
{
name = "Jacob Pyke";
email = "github@pyk.ee";
github = "JPyke3";
githubId = 13283054;
}
];
platforms = ["x86_64-linux"];
mainProgram = "hytale-launcher";
};
};
in {
environment.systemPackages = with pkgs; [
hytale-launcher
];
}

View File

View File

@@ -0,0 +1,6 @@
{...}: {
programs.ccache = {
enable = true;
packageNames = ["ollama" "orca-slicer" "opencv" "onnxruntime" "obs-studio" "llama-cpp"];
};
}

View File

@@ -0,0 +1,3 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [cudatoolkit];
}

View File

@@ -0,0 +1,3 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [ddcutil];
}

View File

@@ -4,12 +4,23 @@
./steam.nix ./steam.nix
./1password.nix ./1password.nix
./localsend.nix ./localsend.nix
./appimage.nix # ./appimage.nix
./obs-studio.nix ./obs-studio.nix
./gnome-disks.nix ./gnome-disks.nix
./nix-ld.nix ./nix-ld.nix
./gamemode.nix ./gamemode.nix
./droidcam.nix ./droidcam.nix
./wireshark.nix ./wireshark.nix
./flatpak.nix
./v4l-utils.nix
./razer.nix
./cuda.nix
./fonts.nix
./dev.nix
./shells.nix
./hyprland.nix
./foot.nix
./ddcutil.nix
./libnotify.nix
]; ];
} }

View File

@@ -0,0 +1,7 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
git
gnumake
python3
];
}

View File

@@ -0,0 +1,5 @@
{...}: {
services.flatpak = {
enable = true;
};
}

View File

@@ -0,0 +1,8 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
nerd-fonts.fira-code
nerd-fonts.hasklug
nerd-fonts.symbols-only
monaspace
];
}

View File

@@ -0,0 +1,3 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [foot];
}

View File

@@ -0,0 +1,6 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
hyprland
xorg.xhost
];
}

View File

@@ -0,0 +1,3 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [libnotify];
}

View File

@@ -0,0 +1,6 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
polychromatic
openrazer-daemon
];
}

View File

@@ -0,0 +1,6 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
fish
nushell
];
}

View File

@@ -0,0 +1,3 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [v4l-utils];
}

View File

@@ -138,7 +138,7 @@
swapDevices = [ swapDevices = [
{ {
device = "/var/lib/swapfile"; device = "/home/swapfile";
size = 64 * 1024; size = 64 * 1024;
} }
]; ];

View File

@@ -14,6 +14,11 @@
services = { services = {
caddy = { caddy = {
enable = true; enable = true;
globalConfig = ''
servers {
metrics
}
'';
extraConfig = '' extraConfig = ''
(cloudflare) { (cloudflare) {
tls { tls {

View File

@@ -1,27 +0,0 @@
{
config,
lib,
pkgs,
...
}: {
# services.command-runner = {
# enable = false;
# port = 5599;
# user = "servius";
# commands = let
# hyprctl = "${pkgs.hyprland}/bin/hyprctl";
# in
# {
# "display_on" = [hyprctl "-i" "{instance}" "dispatch" "dpms" "on"];
# "display_off" = [hyprctl "-i" "{instance}" "dispatch" "dpms" "off"];
# "display_toggle" = [hyprctl "-i" "{instance}" "dispatch" "dpms" "toggle"];
# "display_status" = [hyprctl "-i" "{instance}" "-j" "monitors"];
# "hyprland_instance" = [hyprctl "-j" "instances"];
# }
# // (builtins.foldl' (acc: elem: acc // elem) {} (lib.map (name: {
# "display_on_${name}" = [hyprctl "-i" "{instance}" "dispatch" "dpms" "on" name];
# "display_off_${name}" = [hyprctl "-i" "{instance}" "dispatch" "dpms" "off" name];
# "display_toggle_${name}" = [hyprctl "-i" "{instance}" "dispatch" "dpms" "toggle" name];
# }) ["HDMI-A-1" "DP-3" "DP-1"]));
# };
}

View File

@@ -1,26 +1,26 @@
{...}: { {...}: {
imports = [ imports = [
# ./rsyncd.nix # ./rsyncd.nix
# ./sunshine.nix
# ./zerotier.nix # ./zerotier.nix
# ./dnscrypt.nix # ./dnscrypt.nix
./ollama.nix
./tailscale.nix
./samba.nix
./mullvad.nix
./openrgb.nix
./command-runner.nix
./resolved.nix
./minecraft.nix
./fwupd.nix
./caddy.nix ./caddy.nix
./monitoring.nix
./wivrn.nix
./sshd.nix
./fprintd.nix
./handoff.nix
./gstreamer.nix
./dualsense.nix ./dualsense.nix
./fprintd.nix
./fwupd.nix
./gstreamer.nix
./handoff.nix
./minecraft.nix
./monitoring.nix
./mullvad.nix
./ollama.nix
./openrgb.nix
./openssh.nix ./openssh.nix
./resolved.nix
./samba.nix
./sshd.nix
# ./sunshine.nix
./tailscale.nix
./wivrn.nix
./pipewire.nix
]; ];
} }

View File

@@ -1,11 +1,28 @@
{...}: { {pkgs, ...}: let
# Port configurations
ports = {
# System exporters
node = 9100;
systemd = 9558;
process = 9256;
nvidiagpu = 9835;
# Infrastructure exporters
cadvisor = 8080;
caddy = 2019;
};
in {
services = { services = {
prometheus = { prometheus = {
exporters = { exporters = {
systemd = { systemd = {
enable = true; enable = true;
port = ports.systemd;
};
nvidia-gpu = {
enable = true;
port = ports.nvidiagpu;
}; };
nvidia-gpu.enable = true;
node = { node = {
enable = true; enable = true;
enabledCollectors = [ enabledCollectors = [
@@ -19,7 +36,10 @@
"time" "time"
"uname" "uname"
"vmstat" "vmstat"
"diskstats"
"cpu"
]; ];
port = ports.node;
}; };
process = { process = {
enable = true; enable = true;
@@ -33,4 +53,34 @@
}; };
}; };
}; };
# Docker cAdvisor for container metrics
# virtualisation.oci-containers.containers.cadvisor = {
# image = "gcr.io/cadvisor/cadvisor:v0.49.1";
# ports = ["${toString ports.cadvisor}:8080"];
# volumes = [
# "/:/rootfs:ro"
# "/var/run:/var/run:ro"
# "/sys:/sys:ro"
# "/var/lib/docker/:/var/lib/docker:ro"
# "/dev/disk/:/dev/disk:ro"
# ];
# extraOptions = [
# "--privileged"
# "--device=/dev/kmsg"
# ];
# };
# Open firewall ports for Prometheus exporters
networking.firewall = {
# Allow from Tailscale network
interfaces."tailscale0".allowedTCPPorts = [
ports.node
ports.systemd
ports.process
ports.nvidiagpu
ports.cadvisor
ports.caddy
];
};
} }

View File

@@ -25,6 +25,8 @@
OLLAMA_LLM_LIBRARY = "cuda"; OLLAMA_LLM_LIBRARY = "cuda";
LD_LIBRARY_PATH = "run/opengl-driver/lib"; LD_LIBRARY_PATH = "run/opengl-driver/lib";
HTTP_PROXY = "https://ollama.darksailor.dev"; HTTP_PROXY = "https://ollama.darksailor.dev";
OLLAMA_CONTEXT_LENGTH = "32000";
OLLAMA_KEEP_ALIVE = "30m";
}; };
package = pkgs.ollama-cuda; package = pkgs.ollama-cuda;
}; };

View File

@@ -0,0 +1,19 @@
{...}: {
services.pipewire = {
enable = true;
audio.enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
extraConfig = {
pipewire = {
"10-clock-rate" = {
"context.properties" = {
"default.clock.quantum" = 32;
"default.clock.allowed-rates" = [44100 48000 88200 96000];
};
};
};
};
};
}

View File

@@ -2,10 +2,14 @@
# Disable all the dns stuff in favour of tailscale's DNS # Disable all the dns stuff in favour of tailscale's DNS
services.resolved = { services.resolved = {
enable = true; enable = true;
dnssec = "true"; settings = {
dnsovertls = "true"; Resolve = {
domains = ["lemur-newton.ts.net"]; DNSSEC = "true";
fallbackDns = []; DNSoverTLS = "true";
Domains = ["lemur-newton.ts.net"];
FallbackDNS = [];
};
};
}; };
networking.nameservers = []; networking.nameservers = [];
} }

View File

@@ -9,6 +9,7 @@
./services ./services
./tako.nix ./tako.nix
# ./docker.nix # ./docker.nix
../../modules/nixos/substituters.nix
]; ];
virtualisation.docker.enable = true; virtualisation.docker.enable = true;
@@ -35,7 +36,6 @@
# Use the systemd-boot EFI boot loader. # Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true; boot.loader.efi.canTouchEfiVariables = true;
nix = { nix = {
settings = { settings = {
max-jobs = 1; max-jobs = 1;
@@ -43,16 +43,6 @@
auto-optimise-store = true; auto-optimise-store = true;
extra-experimental-features = "nix-command flakes auto-allocate-uids"; extra-experimental-features = "nix-command flakes auto-allocate-uids";
trusted-users = [device.user "remotebuilder"]; trusted-users = [device.user "remotebuilder"];
trusted-substituters = [
"https://nix-community.cachix.org"
"https://nixos-raspberrypi.cachix.org"
# "https://sh.darksailor.dev"
];
trusted-public-keys = [
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI="
# "tako:bcVPoFGBZ0i7JAKMXIqLj2GY3CulLC4kP7rQyqes1RM="
];
}; };
extraOptions = '' extraOptions = ''
build-users-group = nixbld build-users-group = nixbld
@@ -65,8 +55,11 @@
dates = "daily"; dates = "daily";
options = "--delete-older-than 5d"; options = "--delete-older-than 5d";
}; };
package = pkgs.nixVersions.latest; # deploy-rs doesn't work with nix >= 2.32 package = pkgs.nixVersions.nix_2_32; # deploy-rs doesn't work with nix >= 2.32
distributedBuilds = true; distributedBuilds = true;
substituters = {
enableCuda = true;
};
}; };
users.users.${device.user} = { users.users.${device.user} = {

View File

@@ -0,0 +1,89 @@
{config, ...}: let
domain = "notes.darksailor.dev";
in {
imports = [
../../../modules/nixos/affine.nix
];
# SOPS secrets
sops = {
secrets = {
"affine/db_password" = {};
"authelia/oidc/affine/client_id" = {
owner = config.systemd.services.authelia-darksailor.serviceConfig.User;
mode = "0440";
restartUnits = ["authelia-darksailor.service"];
};
"authelia/oidc/affine/client_secret" = {
owner = config.systemd.services.authelia-darksailor.serviceConfig.User;
mode = "0440";
restartUnits = ["authelia-darksailor.service"];
};
};
templates."affine.env".content = ''
AFFINE_DB_PASSWORD=${config.sops.placeholder."affine/db_password"}
POSTGRES_PASSWORD=${config.sops.placeholder."affine/db_password"}
AFFINE_SERVER_EXTERNAL_URL=https://${domain}
'';
};
# Enable AFFiNE service
services.affine = {
enable = true;
inherit domain;
environmentFiles = [
config.sops.templates."affine.env".path
];
};
# Caddy reverse proxy with SSO forward auth
services.caddy.virtualHosts."${domain}".extraConfig = ''
reverse_proxy localhost:${toString config.services.affine.port}
'';
# Authelia access control rules
services.authelia.instances.darksailor.settings = {
access_control.rules = [
{
inherit domain;
policy = "bypass";
resources = [
"^/api/(sync|awareness)([/?].*)?$"
"^/socket\\.io([/?].*)?$"
];
}
{
inherit domain;
policy = "one_factor";
}
];
# OIDC client for AFFiNE
identity_providers.oidc.clients = [
{
client_name = "AFFiNE: Darksailor";
client_id = ''{{ secret "${config.sops.secrets."authelia/oidc/affine/client_id".path}" }}'';
client_secret = ''{{ secret "${config.sops.secrets."authelia/oidc/affine/client_secret".path}" }}'';
public = false;
authorization_policy = "one_factor";
require_pkce = false;
redirect_uris = [
"https://${domain}/oauth/callback"
];
scopes = [
"openid"
"email"
"profile"
];
response_types = ["code"];
grant_types = ["authorization_code"];
userinfo_signed_response_alg = "none";
token_endpoint_auth_method = "client_secret_post";
}
];
};
# Ensure containers start after secrets are available
systemd.services.docker-affine.after = ["sops-install-secrets.service"];
systemd.services.docker-affine-migration.after = ["sops-install-secrets.service"];
systemd.services.docker-affine-postgres.after = ["sops-install-secrets.service"];
}

View File

@@ -1,16 +1,21 @@
{...}: { {config, ...}: let
address = "127.0.0.1:8052";
in {
sops = {
secrets."attic/jwt_secret" = {};
templates."attic.env".content = ''
ATTIC_SERVER_TOKEN_RS256_SECRET_BASE64=${config.sops.placeholder."attic/jwt_secret"}
'';
};
services = { services = {
atticd = { atticd = {
enable = false; enable = true;
listen = "/run/attic.sock"; settings.listen = address;
environmentFile = config.sops.templates."attic.env".path;
}; };
caddy = { caddy = {
virtualHosts."cache.darksailor.dev".extraConfig = '' virtualHosts."cache.darksailor.dev".extraConfig = ''
reverse_proxy /run/attic.sock { reverse_proxy ${address}
transport http {
protocol = "fd"
}
}
''; '';
}; };
}; };

View File

@@ -0,0 +1,19 @@
{
device,
config,
...
}: {
services = {
blocky = {
enable = true;
settings = {
ports.dns = 53;
ports.http = 83838;
ports.dohPath = "/dns-query";
};
};
caddy.virtualHosts."blocky.${device.domain}".extraConfig = ''
reverse_proxy localhost:83838
'';
};
}

View File

@@ -2,6 +2,11 @@
services = { services = {
caddy = { caddy = {
enable = true; enable = true;
globalConfig = ''
servers {
metrics
}
'';
extraConfig = '' extraConfig = ''
(auth) { (auth) {
forward_auth localhost:5555 { forward_auth localhost:5555 {

View File

@@ -1,28 +1,33 @@
{...}: { {...}: {
imports = [ imports = [
./games
# ./headscale.nix
./llms.nix
# ./monitoring.nix
# ./paperless.nix
./navidrome.nix
./shitpost.nix
./atuin.nix ./atuin.nix
./authelia.nix ./authelia.nix
./caddy.nix ./caddy.nix
./excalidraw.nix
./fail2ban.nix ./fail2ban.nix
./flaresolverr.nix
./gitea.nix
./homepage.nix ./homepage.nix
./immich.nix
./lldap.nix ./lldap.nix
./navidrome.nix
./nextcloud.nix ./nextcloud.nix
./openssh.nix ./openssh.nix
./prowlarr.nix
./resolved.nix ./resolved.nix
./searxng.nix
./tailscale.nix ./tailscale.nix
./gitea.nix
./affine.nix
./attic.nix
./excalidraw.nix
./flaresolverr.nix
# ./games
# ./headscale.nix
./immich.nix
./kellnr.nix
# ./llms.nix
./matrix
# ./monitoring.nix
# ./paperless.nix
./prowlarr.nix
# ./searxng.nix
# ./shitpost.nix
]; ];
services = { services = {
nix-serve = { nix-serve = {

View File

@@ -1,30 +1,91 @@
{...}: { {config, ...}: let
dataDir = "/var/lib/excalidraw";
base_domain = "darksailor.dev";
in {
# SOPS secrets and templates
sops = {
secrets = {
"excalidraw/jwt_secret" = {};
"authelia/oidc/excalidraw/client_id" = {
owner = config.systemd.services.authelia-darksailor.serviceConfig.User;
mode = "0440";
restartUnits = ["authelia-darksailor.service"];
};
"authelia/oidc/excalidraw/client_secret" = {
owner = config.systemd.services.authelia-darksailor.serviceConfig.User;
mode = "0440";
restartUnits = ["authelia-darksailor.service"];
};
};
templates."excalidraw.env".content = ''
OIDC_ISSUER_URL=https://auth.${base_domain}
OIDC_CLIENT_ID=${config.sops.placeholder."authelia/oidc/excalidraw/client_id"}
OIDC_CLIENT_SECRET=${config.sops.placeholder."authelia/oidc/excalidraw/client_secret"}
OIDC_REDIRECT_URL=https://draw.${base_domain}/auth/callback
JWT_SECRET=${config.sops.placeholder."excalidraw/jwt_secret"}
STORAGE_TYPE=sqlite
DATA_SOURCE_NAME=excalidraw.db
LOCAL_STORAGE_PATH=/root/data
'';
};
# Create data directory and initialize SQLite DB
systemd.tmpfiles.rules = [
"d ${dataDir} 0755 root root -"
"d ${dataDir}/data 0755 root root -"
"f ${dataDir}/excalidraw.db 0644 root root -"
];
virtualisation.oci-containers = { virtualisation.oci-containers = {
backend = "docker"; backend = "docker";
containers = { containers = {
# Excalidraw Full backend
excalidraw = { excalidraw = {
image = "excalidraw/excalidraw:latest"; image = "ghcr.io/betterandbetterii/excalidraw-full:latest";
ports = ["127.0.0.1:5959:80"]; ports = ["127.0.0.1:3002:3002"];
volumes = []; environmentFiles = [
config.sops.templates."excalidraw.env".path
];
volumes = [
"${dataDir}/data:/root/data"
"${dataDir}/excalidraw.db:/root/excalidraw.db"
];
}; };
}; };
}; };
services.caddy.virtualHosts."draw.darksailor.dev".extraConfig = ''
import auth # Caddy reverse proxy
reverse_proxy localhost:5959 services.caddy.virtualHosts."draw.${base_domain}".extraConfig = ''
reverse_proxy localhost:3002
''; '';
services.authelia = {
instances.darksailor = { # Configure Authelia OIDC for Excalidraw
settings = { services.authelia.instances.darksailor.settings = {
access_control = { identity_providers = {
rules = [ oidc = {
clients = [
{ {
domain = "draw.darksailor.dev"; client_name = "Excalidraw: Darksailor";
policy = "one_factor"; client_id = ''{{ secret "${config.sops.secrets."authelia/oidc/excalidraw/client_id".path}" }}'';
client_secret = ''{{ secret "${config.sops.secrets."authelia/oidc/excalidraw/client_secret".path}" }}'';
public = false;
authorization_policy = "one_factor";
require_pkce = false;
redirect_uris = [
"https://draw.${base_domain}/auth/callback"
];
scopes = [
"openid"
"email"
"profile"
];
response_types = ["code"];
grant_types = ["authorization_code"];
userinfo_signed_response_alg = "none";
token_endpoint_auth_method = "client_secret_post";
} }
]; ];
}; };
}; };
}; };
};
} }

View File

@@ -16,6 +16,7 @@
ignoreIP = [ ignoreIP = [
"106.219.121.52" "106.219.121.52"
"106.219.122.125" "106.219.122.125"
"106.219.122.221"
]; ];
}; };
}; };

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