40 Commits

Author SHA1 Message Date
chexit 6755d28c8f migrate from github to gitea
Check NixOS Config / build (push) Failing after 21s
2026-05-21 11:48:53 +03:00
chexit 0db7fd1251 remove mounting of wd blue 2026-05-19 10:02:52 +03:00
chexit 6467343c6b add rustrover 2026-05-18 20:59:05 +03:00
chexit b4d47ee6b8 feat: add zed-editor and gpu-screen-recorder-gtk to packages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 15:56:00 +03:00
chexit c6b8d087ac feat: extract gaming config into dedicated gaming.nix module
Moves steam, gamemode, DualSense udev rules, and gaming packages
(lutris, winetricks, wine, dxvk, vkd3d-proton, mangohud, dualsensectl,
protonup-qt, prismlauncher) into gaming.nix. Also adds bluetooth/blueman
config to configuration.nix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 15:55:58 +03:00
chexit 8e1a3352d6 feat: install codex-cli globally via systemPackages
https://claude.ai/code/session_01WbhyZRRuzioZn7F3NTuntf
2026-04-28 01:00:01 +03:00
chexit fb40a985d8 flake.lock 2026-04-28 00:57:45 +03:00
chexit f52f0e545f add gitignore 2026-04-28 00:56:54 +03:00
Claude 3fffe5c8c3 fix: merge codex-cli-nix into single valid flake
Two separate flake expressions were concatenated with a comma, causing
a syntax error. Merged them into one: added codex-cli-nix as an input
and devShells output alongside the existing nixosConfigurations.

https://claude.ai/code/session_01WbhyZRRuzioZn7F3NTuntf
2026-04-27 21:33:25 +00:00
chexit 59c86f5b21 Merge branch 'master' of https://github.com/Chexit/nix-config 2026-04-28 00:31:38 +03:00
Claude a3b35e3a12 Merge branch 'claude/add-niri-config-XJjm4'
Add niri compositor with full desktop stack (bar, launcher, notifications, configs).

https://claude.ai/code/session_01WbhyZRRuzioZn7F3NTuntf
2026-04-27 21:29:29 +00:00
Claude e2049748bb feat: add helium browser via schembriaiden/helium-browser-nix-flake
https://claude.ai/code/session_01WbhyZRRuzioZn7F3NTuntf
2026-04-27 21:28:00 +00:00
chexit b5247c7dc4 add codex 2026-04-23 22:41:00 +03:00
Claude 3f736a9ac3 niri: add full desktop stack (bar, launcher, notifications, configs)
Moves programs.niri into a dedicated niri.nix module and installs the
usual Wayland userland — alacritty, fuzzel, waybar, mako, swaybg,
grim/slurp/wl-clipboard, swaylock/swayidle/wlogout, xwayland-satellite,
plus nm-applet/pavucontrol/playerctl/brightnessctl.

Ships starter configs for niri (keybinds mirroring sway/KDE habits,
screenshots to ~/Pictures/Screenshots, media keys, workspace switching,
auto-lock via swayidle), waybar with a Catppuccin-ish style, mako, and
fuzzel — all wired up through home-manager's xdg.configFile.

https://claude.ai/code/session_01NrGdGEBRbDbWvHUb3Lho44
2026-04-23 14:57:14 +00:00
Claude 4a6258f8f9 desktop: enable niri compositor
Adds niri as an available Wayland session alongside Plasma6, selectable
from SDDM.

https://claude.ai/code/session_01NrGdGEBRbDbWvHUb3Lho44
2026-04-23 14:50:24 +00:00
chexit 5a5822b27e add openvpn 2026-04-23 17:46:22 +03:00
chexit 5afd18dc12 add thunderbird 2026-04-19 23:33:20 +03:00
chexit cb0bcc0cf8 add spotify 2026-04-19 19:25:32 +03:00
Vladimir be12ef4465 Merge pull request #8 from Chexit/claude/add-yami-dev-stack-zHOMn
feat(yami): add dataDir option for separate-disk state
2026-04-19 19:05:04 +03:00
chexit 6775a88ca8 feat(yami): add dataDir option for storing stack state on separate disk
- Bind-mounts /var/lib/{gitea,postgresql} under configurable dataDir
- gitea-runner intentionally excluded: its DynamicUser + StateDirectory
  conflicts with pre-existing mount points ("File exists")
- Runner token moved to /var/lib/gitea-runner-secret/ to avoid the same
  symlink/StateDirectory conflict inside /var/lib/gitea-runner
- Enable the stack on this host with dataDir = /mnt/ssd_110/yami
2026-04-19 18:54:28 +03:00
Vladimir 61b1cf5097 Merge pull request #4 from Chexit/claude/switch-to-fish-shell-LDSqe
Switch default shell from Zsh to Fish with Starship prompt
2026-04-19 18:29:56 +03:00
Vladimir da4ad4b025 Merge pull request #7 from Chexit/claude/add-yami-dev-stack-zHOMn
docs(yami): note that runner tokenFile must be env-file format (TOKEN…
2026-04-19 18:24:38 +03:00
chexit a83500e382 docs(yami): note that runner tokenFile must be env-file format (TOKEN=...) 2026-04-19 18:23:56 +03:00
Vladimir 7bf3369d53 Merge pull request #6 from Chexit/claude/add-yami-dev-stack-zHOMn
fix(yami): tmpfiles for runner token must use root (DynamicUser has n…
2026-04-19 18:18:11 +03:00
chexit ecf8b5974a fix(yami): tmpfiles for runner token must use root (DynamicUser has no static user) 2026-04-19 18:17:24 +03:00
Vladimir fac913504f Merge pull request #5 from Chexit/claude/add-yami-dev-stack-zHOMn
fix(yami): use services.gitea.lfs.enable instead of raw LFS_START_SERVER
2026-04-19 18:02:39 +03:00
chexit 6a2fb0970c fix(yami): use services.gitea.lfs.enable instead of raw LFS_START_SERVER
Raw LFS_START_SERVER made gitea try to generate and persist LFS_JWT_SECRET
into app.ini, which NixOS intentionally keeps read-only. The lfs.enable
helper lets the module own the secret and wire it in correctly.
2026-04-19 18:00:03 +03:00
Claude 11f8ed08e9 Add 1Password GUI and CLI via NixOS programs module
Enables programs._1password (CLI) and programs._1password-gui with
polkit authorization for user chexit. allowUnfree is already set,
so packages install without additional config.

https://claude.ai/code/session_01NS2hpapno51a1Ng7hWaQKy
2026-04-19 11:24:46 +00:00
Claude 393c2e72bd Switch default shell from zsh to fish with starship prompt
Replace programs.zsh (powerlevel10k theme) with programs.fish and
starship prompt integration. Fish provides autosuggestions and syntax
highlighting out of the box, eliminating the need for separate plugins.

https://claude.ai/code/session_01NS2hpapno51a1Ng7hWaQKy
2026-04-19 11:17:14 +00:00
Vladimir e0f403143e Merge pull request #3 from Chexit/claude/add-yami-dev-stack-zHOMn
feat: add Yami dev stack module (on-demand gitea+postgres+docker+runner)
2026-04-19 02:58:52 +03:00
Claude 27cb88d8a0 feat: add Yami dev stack module (on-demand gitea+postgres+docker+runner)
https://claude.ai/code/session_017dm8ypaaWNeA27ctmwq5dn
2026-04-18 23:00:41 +00:00
Claude 18480df83b Merge remote-tracking branch 'origin/feature/small-fixes' 2026-04-17 19:51:08 +00:00
Claude 1a1df93285 Merge branch 'feature/home-manager-flakes-gaming' 2026-04-17 19:46:56 +00:00
chexit a1f5215275 typo 2026-04-17 22:37:38 +03:00
chexit e38c6d0f1c add alias and flake.lock 2026-04-17 22:37:03 +03:00
chexit d02310b8fb add throne to packages and typos 2026-04-17 22:31:00 +03:00
Vladimir 2e4775d99f Merge pull request #1 from Chexit/feature/home-manager-flakes-gaming
feat: Home Manager (NixOS module), Flakes, gaming packages
2026-04-17 22:29:02 +03:00
Claude 23375d10b1 ci: free disk space before Nix build to prevent ENOSPC on NVIDIA/CUDA packages
GitHub Actions free runners have ~14 GB total; removing unused toolchains
(dotnet, android, CodeQL, boost) reclaims ~8-10 GB needed for the full
NixOS system build.

https://claude.ai/code/session_01JwjdjwvgMGW4TcpYi4MZ6n
2026-04-17 18:53:08 +00:00
chexit 7a1d4cddd0 fix 2026-04-17 21:35:05 +03:00
chexit 68d5d45d65 add github action for checking 2026-04-17 21:29:03 +03:00
16 changed files with 997 additions and 41 deletions
+46
View File
@@ -0,0 +1,46 @@
name: Check NixOS Config
on:
pull_request:
push:
branches: [master]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Free disk space
run: |
sudo rm -rf /usr/share/dotnet /usr/share/swift /usr/local/lib/android \
/opt/ghc /opt/hostedtoolcache/CodeQL /usr/local/share/boost \
"$AGENT_TOOLSDIRECTORY"
sudo docker image prune --all --force || true
df -h
- name: Install Nix
uses: cachix/install-nix-action@v27
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: |
experimental-features = nix-command flakes
accept-flake-config = true
- name: Setup Cachix
uses: cachix/cachix-action@v15
with:
name: chexit
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Check flake syntax
run: nix flake check --no-build
- name: Build system config
run: |
nix build .#nixosConfigurations.chexit.config.system.build.toplevel \
--no-link \
--print-build-logs
+1
View File
@@ -0,0 +1 @@
flake.lock
+29 -14
View File
@@ -5,8 +5,11 @@
./hardware-configuration.nix ./hardware-configuration.nix
./packages.nix ./packages.nix
./desktop.nix ./desktop.nix
./niri.nix
./nvidia.nix ./nvidia.nix
./shell.nix ./shell.nix
./yami-dev-stack.nix
./gaming.nix
]; ];
nix = { nix = {
@@ -44,11 +47,11 @@
fsType = "ext4"; fsType = "ext4";
options = [ "nosuid" "nodev" "nofail" ]; options = [ "nosuid" "nodev" "nofail" ];
}; };
"/mnt/wd_blue" = { #"/mnt/wd_blue" = {
device = "/dev/disk/by-uuid/91feabaf-ea5f-490e-9925-56f7c05e7110"; # device = "/dev/disk/by-uuid/91feabaf-ea5f-490e-9925-56f7c05e7110";
fsType = "ext4"; # fsType = "ext4";
options = [ "nosuid" "nodev" "nofail" ]; # options = [ "nosuid" "nodev" "nofail" ];
}; #};
}; };
networking = { networking = {
@@ -56,6 +59,12 @@
networkmanager.enable = true; networkmanager.enable = true;
}; };
hardware.bluetooth = {
enable = true;
powerOnBoot = true;
};
services.blueman.enable = true;
time.timeZone = "Europe/Moscow"; time.timeZone = "Europe/Moscow";
i18n = { i18n = {
@@ -76,25 +85,31 @@
users.users.chexit = { users.users.chexit = {
isNormalUser = true; isNormalUser = true;
description = "chexit"; description = "chexit";
shell = pkgs.zsh; shell = pkgs.fish;
extraGroups = [ "networkmanager" "wheel" "docker" ]; extraGroups = [ "networkmanager" "wheel" "docker" ];
}; };
programs._1password.enable = true;
programs._1password-gui = {
enable = true;
polkitPolicyOwners = [ "chexit" ];
};
programs.throne = { programs.throne = {
enable = true; enable = true;
tunMode.enable = true; tunMode.enable = true;
}; };
programs.steam = {
enable = true;
remotePlay.openFirewall = true;
dedicatedServer.openFirewall = true;
};
programs.gamemode.enable = true;
services.tailscale.enable = true; services.tailscale.enable = true;
virtualisation.docker.enable = true; # Docker is now managed by yami-dev-stack.nix when that module is enabled.
# services.yami-dev-stack = { enable = true; user = "chexit"; };
services.yami-dev-stack = {
enable = true;
user = "chexit";
dataDir = "/mnt/ssd_110/yami";
};
system.stateVersion = "25.11"; system.stateVersion = "25.11";
} }
Generated
+172
View File
@@ -0,0 +1,172 @@
{
"nodes": {
"codex-cli-nix": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1777054843,
"narHash": "sha256-aiuiKK6xJu5inj/RTmSl9S3jDC6RzNsKfNJ700MRPNY=",
"owner": "sadjow",
"repo": "codex-cli-nix",
"rev": "fc382bef14dcb9873769bdcb4d3b943ef2606489",
"type": "github"
},
"original": {
"owner": "sadjow",
"repo": "codex-cli-nix",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"helium-browser": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"utils": "utils"
},
"locked": {
"lastModified": 1777187169,
"narHash": "sha256-D5su73XFSyZgrYjLwTFYUpLWJhAxi0M/k/7nPABCa4g=",
"owner": "schembriaiden",
"repo": "helium-browser-nix-flake",
"rev": "c786dc23029c5a6651b9131f8d6548fd31d6b99f",
"type": "github"
},
"original": {
"owner": "schembriaiden",
"repo": "helium-browser-nix-flake",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1776454077,
"narHash": "sha256-7zSUFWsU0+jlD7WB3YAxQ84Z/iJurA5hKPm8EfEyGJk=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "565e5349208fe7d0831ef959103c9bafbeac0681",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1776949667,
"narHash": "sha256-GMSVw35Q+294GlrTUKlx087E31z7KurReQ1YHSKp5iw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "01fbdeef22b76df85ea168fbfe1bfd9e63681b30",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1776169885,
"narHash": "sha256-l/iNYDZ4bGOAFQY2q8y5OAfBBtrDAaPuRQqWaFHVRXM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4bd9165a9165d7b5e33ae57f3eecbcb28fb231c9",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"codex-cli-nix": "codex-cli-nix",
"helium-browser": "helium-browser",
"home-manager": "home-manager",
"nixpkgs": "nixpkgs_2"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"utils": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
}
},
"root": "root",
"version": 7
}
+33 -13
View File
@@ -7,21 +7,41 @@
url = "github:nix-community/home-manager"; url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
helium-browser = {
url = "github:schembriaiden/helium-browser-nix-flake";
inputs.nixpkgs.follows = "nixpkgs";
};
codex-cli-nix.url = "github:sadjow/codex-cli-nix";
}; };
outputs = { nixpkgs, home-manager, ... }: { outputs = { nixpkgs, home-manager, helium-browser, codex-cli-nix, ... }:
nixosConfigurations.chexit = nixpkgs.lib.nixosSystem { let
system = "x86_64-linux"; system = "x86_64-linux";
modules = [ pkgs = nixpkgs.legacyPackages.${system};
./configuration.nix in
home-manager.nixosModules.home-manager {
{ nixosConfigurations.chexit = nixpkgs.lib.nixosSystem {
home-manager.useGlobalPkgs = true; inherit system;
home-manager.useUserPackages = true; specialArgs = {
home-manager.backupFileExtension = "hm-bak"; helium = helium-browser.packages.${system}.helium;
home-manager.users.chexit = import ./home.nix; codex = codex-cli-nix.packages.${system}.default;
} };
]; modules = [
./configuration.nix
home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.backupFileExtension = "hm-bak";
home-manager.users.chexit = import ./home.nix;
}
];
};
devShells.${system}.default = pkgs.mkShell {
buildInputs = [
codex-cli-nix.packages.${system}.default
];
};
}; };
};
} }
+32
View File
@@ -0,0 +1,32 @@
{ pkgs, ... }:
{
programs.steam = {
enable = true;
remotePlay.openFirewall = true;
dedicatedServer.openFirewall = true;
};
programs.gamemode.enable = true;
services.udev.extraRules = ''
# DualSense: тачпад не должен работать как мышь рабочего стола.
# Steam Input/SDL читают геймпад (включая тачпад) через hidraw,
# так что в играх он останется доступен как тачпад контроллера.
SUBSYSTEM=="input", ATTRS{name}=="Sony Interactive Entertainment DualSense Wireless Controller Touchpad", ENV{LIBINPUT_IGNORE_DEVICE}="1", ENV{ID_INPUT_MOUSE}="0", ENV{ID_INPUT_TOUCHPAD}="0"
SUBSYSTEM=="input", ATTRS{name}=="DualSense Wireless Controller Touchpad", ENV{LIBINPUT_IGNORE_DEVICE}="1", ENV{ID_INPUT_MOUSE}="0", ENV{ID_INPUT_TOUCHPAD}="0"
'';
environment.systemPackages = with pkgs; [
dualsensectl
protonup-qt
prismlauncher
lutris
winetricks
wineWow64Packages.stagingFull
dxvk
vkd3d-proton
mangohud
gamemode
];
}
+36 -8
View File
@@ -1,18 +1,46 @@
{ pkgs, ... }: { ... }:
{ {
home.username = "chexit"; home.username = "chexit";
home.homeDirectory = "/home/chexit"; home.homeDirectory = "/home/chexit";
home.stateVersion = "25.11"; home.stateVersion = "25.11";
programs.zsh = { programs.fish = {
enable = true; enable = true;
enableCompletion = true; shellAliases = {
autosuggestion.enable = true; rebuild = "sudo nixos-rebuild switch --flake ~/nixos-config#chexit";
syntaxHighlighting.enable = true; };
initContent = '' };
source ${pkgs.zsh-powerlevel10k}/share/zsh-powerlevel10k/powerlevel10k.zsh-theme
''; programs.starship = {
enable = true;
enableFishIntegration = true;
};
programs.alacritty = {
enable = true;
settings = {
window = {
padding = { x = 10; y = 10; };
opacity = 0.95;
decorations = "None";
};
font = {
normal = { family = "JetBrainsMono Nerd Font"; style = "Regular"; };
size = 11;
};
colors = {
primary = { background = "#1e1e2e"; foreground = "#cdd6f4"; };
};
};
};
xdg.configFile = {
"niri/config.kdl".source = ./niri/config.kdl;
"waybar/config.jsonc".source = ./niri/waybar/config.jsonc;
"waybar/style.css".source = ./niri/waybar/style.css;
"mako/config".source = ./niri/mako/config;
"fuzzel/fuzzel.ini".source = ./niri/fuzzel/fuzzel.ini;
}; };
programs.home-manager.enable = true; programs.home-manager.enable = true;
+43
View File
@@ -0,0 +1,43 @@
{ pkgs, ... }:
{
programs.niri.enable = true;
environment.systemPackages = with pkgs; [
# terminal + launcher
alacritty
fuzzel
# bar, notifications, wallpaper
waybar
mako
swaybg
# screenshots + clipboard
grim
slurp
swappy
wl-clipboard
# lock + idle
swaylock-effects
swayidle
wlogout
# XWayland shim for niri
xwayland-satellite
# tray + system utilities
networkmanagerapplet
pavucontrol
playerctl
brightnessctl
libnotify
xdg-utils
];
environment.sessionVariables = {
XDG_CURRENT_DESKTOP = "niri";
XDG_SESSION_DESKTOP = "niri";
};
}
+201
View File
@@ -0,0 +1,201 @@
// niri configuration
// docs: https://github.com/YaLTeR/niri/wiki/Configuration:-Overview
input {
keyboard {
xkb {
layout "us"
}
repeat-delay 300
repeat-rate 40
}
touchpad {
tap
dwt
natural-scroll
accel-speed 0.2
}
mouse {
accel-speed 0.0
}
warp-mouse-to-focus
}
output "*" {
// let niri autodetect; override here per-monitor if needed
}
layout {
gaps 12
center-focused-column "never"
preset-column-widths {
proportion 0.33333
proportion 0.5
proportion 0.66667
}
default-column-width { proportion 0.5; }
focus-ring {
width 2
active-color "#7fc8ff"
inactive-color "#3a3a3a"
}
border {
off
}
struts {
left 8
right 8
top 4
bottom 4
}
}
cursor {
xcursor-theme "Adwaita"
xcursor-size 24
}
prefer-no-csd
screenshot-path "~/Pictures/Screenshots/Screenshot-%Y-%m-%d-%H%M%S.png"
hotkey-overlay {
skip-at-startup
}
environment {
DISPLAY ":0"
QT_QPA_PLATFORM "wayland;xcb"
GDK_BACKEND "wayland,x11"
MOZ_ENABLE_WAYLAND "1"
_JAVA_AWT_WM_NONREPARENTING "1"
}
spawn-at-startup "xwayland-satellite"
spawn-at-startup "waybar"
spawn-at-startup "mako"
spawn-at-startup "swaybg" "-c" "#1e1e2e"
spawn-at-startup "nm-applet" "--indicator"
spawn-at-startup "swayidle" "-w" \
"timeout" "600" "swaylock -f" \
"timeout" "900" "niri msg action power-off-monitors" \
"before-sleep" "swaylock -f"
window-rule {
geometry-corner-radius 8
clip-to-geometry true
}
window-rule {
match app-id="^org\\.keepassxc\\.KeePassXC$"
match app-id="^1Password$"
block-out-from "screen-capture"
}
binds {
Mod+Shift+Slash { show-hotkey-overlay; }
// launchers
Mod+Return { spawn "alacritty"; }
Mod+D { spawn "fuzzel"; }
Mod+E { spawn "dolphin"; }
Mod+B { spawn "firefox"; }
Mod+Ctrl+L { spawn "swaylock" "-f"; }
Mod+Shift+Escape { spawn "wlogout"; }
// media keys
XF86AudioRaiseVolume allow-when-locked=true { spawn "wpctl" "set-volume" "-l" "1.0" "@DEFAULT_AUDIO_SINK@" "5%+"; }
XF86AudioLowerVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "5%-"; }
XF86AudioMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; }
XF86AudioMicMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"; }
XF86AudioPlay { spawn "playerctl" "play-pause"; }
XF86AudioPause { spawn "playerctl" "play-pause"; }
XF86AudioNext { spawn "playerctl" "next"; }
XF86AudioPrev { spawn "playerctl" "previous"; }
XF86MonBrightnessUp { spawn "brightnessctl" "set" "5%+"; }
XF86MonBrightnessDown { spawn "brightnessctl" "set" "5%-"; }
// window management
Mod+Q { close-window; }
Mod+Left { focus-column-left; }
Mod+Right { focus-column-right; }
Mod+Up { focus-window-up; }
Mod+Down { focus-window-down; }
Mod+H { focus-column-left; }
Mod+L { focus-column-right; }
Mod+K { focus-window-up; }
Mod+J { focus-window-down; }
Mod+Ctrl+Left { move-column-left; }
Mod+Ctrl+Right { move-column-right; }
Mod+Ctrl+Up { move-window-up; }
Mod+Ctrl+Down { move-window-down; }
Mod+Ctrl+H { move-column-left; }
Mod+Ctrl+L { move-column-right; }
Mod+Ctrl+K { move-window-up; }
Mod+Ctrl+J { move-window-down; }
Mod+Home { focus-column-first; }
Mod+End { focus-column-last; }
Mod+Page_Down { focus-workspace-down; }
Mod+Page_Up { focus-workspace-up; }
Mod+U { focus-workspace-down; }
Mod+I { focus-workspace-up; }
Mod+Shift+Page_Down { move-column-to-workspace-down; }
Mod+Shift+Page_Up { move-column-to-workspace-up; }
Mod+Shift+U { move-column-to-workspace-down; }
Mod+Shift+I { move-column-to-workspace-up; }
Mod+1 { focus-workspace 1; }
Mod+2 { focus-workspace 2; }
Mod+3 { focus-workspace 3; }
Mod+4 { focus-workspace 4; }
Mod+5 { focus-workspace 5; }
Mod+6 { focus-workspace 6; }
Mod+7 { focus-workspace 7; }
Mod+8 { focus-workspace 8; }
Mod+9 { focus-workspace 9; }
Mod+Shift+1 { move-column-to-workspace 1; }
Mod+Shift+2 { move-column-to-workspace 2; }
Mod+Shift+3 { move-column-to-workspace 3; }
Mod+Shift+4 { move-column-to-workspace 4; }
Mod+Shift+5 { move-column-to-workspace 5; }
Mod+Shift+6 { move-column-to-workspace 6; }
Mod+Shift+7 { move-column-to-workspace 7; }
Mod+Shift+8 { move-column-to-workspace 8; }
Mod+Shift+9 { move-column-to-workspace 9; }
Mod+Comma { consume-window-into-column; }
Mod+Period { expel-window-from-column; }
Mod+R { switch-preset-column-width; }
Mod+F { maximize-column; }
Mod+Shift+F { fullscreen-window; }
Mod+C { center-column; }
Mod+Minus { set-column-width "-10%"; }
Mod+Equal { set-column-width "+10%"; }
Mod+Shift+Minus { set-window-height "-10%"; }
Mod+Shift+Equal { set-window-height "+10%"; }
// screenshots
Print { screenshot; }
Ctrl+Print { screenshot-screen; }
Alt+Print { screenshot-window; }
// session
Mod+Shift+E { quit; }
Mod+Shift+P { power-off-monitors; }
}
+23
View File
@@ -0,0 +1,23 @@
font=JetBrainsMono Nerd Font:size=12
dpi-aware=yes
terminal=alacritty
prompt=" "
icon-theme=Adwaita
width=40
lines=12
horizontal-pad=20
vertical-pad=14
inner-pad=10
[colors]
background=1e1e2eee
text=cdd6f4ff
match=f9e2afff
selection=89b4faff
selection-text=1e1e2eff
selection-match=1e1e2eff
border=89b4faff
[border]
width=2
radius=10
+20
View File
@@ -0,0 +1,20 @@
font=JetBrainsMono Nerd Font 10
background-color=#1e1e2eee
text-color=#cdd6f4
border-color=#89b4fa
border-size=2
border-radius=8
padding=12
margin=8
default-timeout=5000
ignore-timeout=1
max-visible=5
layer=overlay
anchor=top-right
[urgency=low]
border-color=#6c7086
[urgency=high]
border-color=#f38ba8
default-timeout=0
+77
View File
@@ -0,0 +1,77 @@
{
"layer": "top",
"position": "top",
"height": 30,
"spacing": 6,
"margin-top": 4,
"margin-left": 8,
"margin-right": 8,
"modules-left": ["niri/workspaces", "niri/window"],
"modules-center": ["clock"],
"modules-right": [
"tray",
"network",
"pulseaudio",
"cpu",
"memory",
"custom/power"
],
"niri/workspaces": {
"format": "{icon}",
"format-icons": {
"default": "",
"active": "",
"urgent": ""
}
},
"niri/window": {
"format": "{title}",
"max-length": 80,
"separate-outputs": true
},
"clock": {
"format": "{:%a %d %b %H:%M}",
"tooltip-format": "<tt><small>{calendar}</small></tt>"
},
"cpu": {
"format": " {usage}%",
"interval": 2
},
"memory": {
"format": " {used:0.1f}G",
"interval": 5
},
"network": {
"format-wifi": " {essid}",
"format-ethernet": " {ifname}",
"format-disconnected": "⚠ offline",
"tooltip-format": "{ifname} · {ipaddr}"
},
"pulseaudio": {
"format": "{icon} {volume}%",
"format-muted": " muted",
"format-icons": {
"default": ["", "", ""]
},
"on-click": "pavucontrol"
},
"tray": {
"icon-size": 16,
"spacing": 8
},
"custom/power": {
"format": "⏻",
"tooltip": false,
"on-click": "wlogout"
}
}
+62
View File
@@ -0,0 +1,62 @@
* {
font-family: "JetBrainsMono Nerd Font", "Geist", sans-serif;
font-size: 13px;
border: none;
border-radius: 0;
min-height: 0;
}
window#waybar {
background: rgba(30, 30, 46, 0.85);
color: #cdd6f4;
border-radius: 10px;
}
#workspaces button {
padding: 0 8px;
color: #9399b2;
background: transparent;
border-radius: 6px;
}
#workspaces button.active {
color: #1e1e2e;
background: #89b4fa;
}
#workspaces button.urgent {
background: #f38ba8;
color: #1e1e2e;
}
#window,
#clock,
#cpu,
#memory,
#network,
#pulseaudio,
#tray,
#custom-power {
padding: 0 10px;
margin: 4px 2px;
border-radius: 6px;
background: rgba(49, 50, 68, 0.6);
}
#clock {
color: #f9e2af;
font-weight: 600;
}
#custom-power {
color: #f38ba8;
padding: 0 12px;
}
#network.disconnected {
color: #f38ba8;
}
#pulseaudio.muted {
color: #6c7086;
}
+13 -5
View File
@@ -1,10 +1,10 @@
{ pkgs, ... }: { pkgs, helium, codex, ... }:
{ {
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
# системное # system
wget wget
git git
htop htop
@@ -14,20 +14,28 @@
kdePackages.qtstyleplugin-kvantum kdePackages.qtstyleplugin-kvantum
kdePackages.kate kdePackages.kate
# софт # soft
helium
firefox firefox
vesktop vesktop
materialgram materialgram
termius termius
throne
spotify
thunderbird
openvpn
# dev # dev
vscode vscode
zed-editor
docker-compose docker-compose
codex
jetbrains.rust-rover
# gaming / media # media / gpu utils
gpu-screen-recorder-gtk
libva-utils libva-utils
vdpauinfo vdpauinfo
lazydocker lazydocker
mangohud
]; ];
} }
+1 -1
View File
@@ -1,5 +1,5 @@
{ ... }: { ... }:
{ {
programs.zsh.enable = true; programs.fish.enable = true;
} }
+208
View File
@@ -0,0 +1,208 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.yami-dev-stack;
in
{
options.services.yami-dev-stack = {
enable = mkEnableOption "Yami development stack (gitea, postgres, docker, runner)";
user = mkOption {
type = types.str;
description = "User that will own runner token and be added to docker group";
};
dataDir = mkOption {
type = types.nullOr types.path;
default = null;
example = "/mnt/ssd_110/yami";
description = ''
If set, bind-mounts /var/lib/{gitea,postgresql,gitea-runner} under this
path so all stack data lives on a separate disk. Directories are created
automatically; existing data must be rsync'd manually before enabling.
'';
};
};
config = mkIf cfg.enable (mkMerge [ {
# ── Systemd target ─────────────────────────────────────────────────────────
# Manual-only: nothing in wantedBy, so it never starts on boot.
systemd.targets.yami-dev = {
description = "Yami development stack (gitea, postgres, docker, runner)";
wantedBy = [ ];
};
# ── PostgreSQL 16 ──────────────────────────────────────────────────────────
services.postgresql = {
enable = true;
package = pkgs.postgresql_16;
ensureDatabases = [ "gitea" ];
ensureUsers = [
{
name = "gitea";
ensureDBOwnership = true;
}
];
};
# Pull postgres under yami-dev.target; stop it when target stops.
systemd.services.postgresql = {
wantedBy = mkForce [ "yami-dev.target" ];
partOf = [ "yami-dev.target" ];
};
# ── Gitea ──────────────────────────────────────────────────────────────────
services.gitea = {
enable = true;
appName = "Yami Git";
# LFS enabled via the NixOS helper so the module manages LFS_JWT_SECRET
# (writing it to app.ini, which is read-only by design).
lfs.enable = true;
database = {
type = "postgres";
socket = "/run/postgresql";
name = "gitea";
user = "gitea";
};
settings = {
server = {
DOMAIN = "localhost";
ROOT_URL = "http://localhost:3000/";
HTTP_ADDR = "0.0.0.0";
HTTP_PORT = 3000;
SSH_PORT = 2222;
START_SSH_SERVER = true;
};
service = {
DISABLE_REGISTRATION = true;
DEFAULT_KEEP_EMAIL_PRIVATE = true;
};
repository = {
DEFAULT_BRANCH = "main";
ENABLE_PUSH_CREATE_USER = true;
ENABLE_PUSH_CREATE_ORG = true;
};
actions = {
ENABLED = true;
DEFAULT_ACTIONS_URL = "github";
LOG_RETENTION_DAYS = 14;
ARTIFACT_RETENTION_DAYS = 30;
};
packages = {
ENABLED = true;
};
session = {
COOKIE_SECURE = false;
};
"cron.git_gc_repos" = {
ENABLED = true;
SCHEDULE = "@every 72h";
ARGS = "--aggressive --prune=now";
};
};
};
systemd.services.gitea = {
wantedBy = mkForce [ "yami-dev.target" ];
partOf = [ "yami-dev.target" ];
after = [ "postgresql.service" ];
requires = [ "postgresql.service" ];
};
# ── Docker ─────────────────────────────────────────────────────────────────
virtualisation.docker = {
enable = true;
enableOnBoot = false;
};
systemd.services.docker = {
wantedBy = mkForce [ "yami-dev.target" ];
partOf = [ "yami-dev.target" ];
};
users.users.${cfg.user}.extraGroups = [ "docker" ];
# ── Gitea Actions Runner ───────────────────────────────────────────────────
services.gitea-actions-runner.instances.default = {
enable = true;
name = "home-runner";
url = "http://localhost:3000";
# NOT under /var/lib/gitea-runner — that path is systemd-managed for the
# service (DynamicUser + StateDirectory means it becomes a symlink to
# /var/lib/private/gitea-runner). Pre-creating it ourselves breaks the
# service with "Failed to set up special execution directory: File exists".
tokenFile = "/var/lib/gitea-runner-secret/token";
labels = [
"ubuntu-latest:docker://node:20"
"native:host"
];
};
systemd.services."gitea-runner-default" = {
wantedBy = mkForce [ "yami-dev.target" ];
partOf = [ "yami-dev.target" ];
after = [ "gitea.service" "docker.service" ];
requires = [ "gitea.service" "docker.service" ];
};
# Runner uses DynamicUser, so there's no static gitea-runner user/group.
# Token lives in a sibling dir (not /var/lib/gitea-runner — that's systemd's
# StateDirectory and pre-creating it breaks DynamicUser bind setup).
# The file MUST be in env-file format, not a raw token:
# TOKEN=<paste-registration-token-from-gitea-ui>
# Get the token from Site Administration → Actions → Runners → Create new Runner.
systemd.tmpfiles.rules = [
"d /var/lib/gitea-runner-secret 0700 root root -"
];
# ── Shell aliases ──────────────────────────────────────────────────────────
environment.shellAliases = {
yami-up = "sudo systemctl start yami-dev.target && echo 'Gitea http://localhost:3000'";
yami-down = "sudo systemctl stop yami-dev.target && echo 'Yami dev stack stopped'";
yami-status = "systemctl status yami-dev.target gitea postgresql docker gitea-runner-default --no-pager";
yami-logs = "journalctl -u gitea -u gitea-runner-default -f";
};
# ── Firewall ───────────────────────────────────────────────────────────────
# Merged with existing rules (Steam etc.); does not overwrite them.
networking.firewall.allowedTCPPorts = [ 3000 2222 ];
}
# ── Optional: move all stack data to a separate disk via bind-mounts ─────────
(mkIf (cfg.dataDir != null) (
let
# gitea-runner intentionally NOT bind-mounted: its service uses
# DynamicUser + StateDirectory, which refuses to adopt an existing
# mount point ("Failed to set up special execution directory: File exists").
# Its data is tiny (token + .runner state) so it stays on the system disk.
subs = [ "gitea" "postgresql" ];
mkBind = name: {
name = "/var/lib/${name}";
value = {
device = "${cfg.dataDir}/${name}";
fsType = "none";
options = [ "bind" ];
};
};
in {
# Ensure target dirs exist on the data disk before mounts happen.
systemd.tmpfiles.rules = map (n: "d ${cfg.dataDir}/${n} 0755 root root -") subs
++ [ "d ${cfg.dataDir} 0755 root root -" ];
fileSystems = listToAttrs (map mkBind subs);
}
))
]);
}