chore: update

This commit is contained in:
kp2pml30 2026-04-12 22:38:09 +09:00
parent eaccf45596
commit d3790a167b
No known key found for this signature in database
GPG key ID: 1739F9D8BA250D04
27 changed files with 715 additions and 229 deletions

29
nix/claude-vm/default.nix Normal file
View file

@ -0,0 +1,29 @@
{ pkgs, lib, ... }:
{
users.mutableUsers = false;
users.users.claude = {
isNormalUser = true;
extraGroups = [ "wheel" ];
shell = pkgs.fish;
hashedPassword = "";
};
users.users.root.hashedPassword = "";
security.sudo.wheelNeedsPassword = false;
programs.fish.enable = true;
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "yes";
PermitEmptyPasswords = "yes";
};
};
networking.firewall.allowedTCPPorts = [ 22 ];
nix.settings.trusted-users = [ "root" "claude" ];
}

View file

@ -0,0 +1,64 @@
{ pkgs, lib, rootPath, modulesPath, ... }:
let
install-claude-vm = pkgs.writeShellScriptBin "install-claude-vm" ''
set -euo pipefail
DISK="/dev/vda"
echo "=== claude-vm installer ==="
echo "Target disk: $DISK"
# Partition: MBR with single root partition
echo "Partitioning..."
parted -s "$DISK" -- \
mklabel msdos \
mkpart primary ext4 1MiB 100%
# Format with label
echo "Formatting..."
mkfs.ext4 -L nixos "''${DISK}1"
# Mount
echo "Mounting..."
mount "''${DISK}1" /mnt
# Copy flake source
echo "Copying flake to /mnt/dotfiles..."
mkdir -p /mnt/dotfiles
cp -a /etc/dotfiles-src/. /mnt/dotfiles/
# Install
echo "Running nixos-install..."
nixos-install --flake /mnt/dotfiles#claude-vm --no-root-passwd --show-trace
echo "=== Installation complete! Shutting down... ==="
${pkgs.systemd}/bin/systemctl poweroff
'';
in
{
imports = [
"${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix"
];
# Serial console for -nographic QEMU
boot.kernelParams = [ "console=ttyS0,115200n8" ];
boot.loader.timeout = lib.mkForce 5;
environment.etc."dotfiles-src".source = rootPath;
environment.systemPackages = [ install-claude-vm ];
# Auto-run installer on boot
systemd.services.auto-install = {
description = "Automatic claude-vm installation";
after = [ "multi-user.target" ];
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ nix nixos-install-tools util-linux coreutils git curl wget binutils e2fsprogs dosfstools parted ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${install-claude-vm}/bin/install-claude-vm";
StandardOutput = "journal+console";
StandardError = "journal+console";
};
};
}

View file

@ -1,113 +0,0 @@
{ pkgs, lib, rootPath }:
let
user = "devuser";
uid = "1000";
gid = "1000";
baseVim = rootPath + "/home/.config/nvim/base.vim";
fromGitHub = rev: repo: pkgs.vimUtils.buildVimPlugin {
pname = "${lib.strings.sanitizeDerivationName repo}";
version = rev;
src = builtins.fetchGit {
url = "https://github.com/${repo}.git";
inherit rev;
};
};
customNeovim = pkgs.neovim.override {
configure = {
customRC = builtins.readFile baseVim;
packages.myPlugins = with pkgs.vimPlugins; {
start = [
nvim-treesitter.withAllGrammars
nvim-autopairs
nerdtree
tokyonight-nvim
barbar-nvim
((fromGitHub "3587f57480b88e8009df7b36dc84e9c7ff8f2c49" "famiu/feline.nvim").overrideAttrs (old: {
doCheck = false;
}))
(fromGitHub "d63c811337b2f75de52f16efee176695f31e7fbc" "timakro/vim-yadi")
(fromGitHub "aafa5c187a15701a7299a392b907ec15d9a7075f" "nvim-tree/nvim-web-devicons")
];
};
};
};
# Create passwd/group/shadow as a package
userSetup = pkgs.runCommand "user-setup" {} ''
mkdir -p $out/etc
echo "root:x:0:0:root:/root:/bin/bash" > $out/etc/passwd
echo "${user}:x:${uid}:${gid}:${user}:/home/${user}:${pkgs.bash}/bin/bash" >> $out/etc/passwd
echo "root:x:0:" > $out/etc/group
echo "${user}:x:${gid}:" >> $out/etc/group
echo "root:!:1::::::" > $out/etc/shadow
echo "${user}:!:1::::::" >> $out/etc/shadow
mkdir -p $out/etc/nix
cat > $out/etc/nix/nix.conf <<EOF
experimental-features = nix-command flakes
EOF
mkdir -p $out/etc/sudoers.d
echo "${user} ALL=(ALL) NOPASSWD: ALL" > $out/etc/sudoers.d/${user}
chmod 440 $out/etc/sudoers.d/${user}
mkdir -p $out/tmp
chmod 1777 $out/tmp
'';
entrypoint = pkgs.writeShellScriptBin "entrypoint" ''
if ! command -v claude &> /dev/null; then
echo "Installing claude-code..."
npm install -g @anthropic-ai/claude-code
fi
exec "$@"
'';
in
pkgs.dockerTools.buildLayeredImage {
name = "nix-node";
tag = "latest";
contents = with pkgs; [
nix
nodejs
bash
coreutils
cacert
git
fish
curl
wget
htop
sudo
customNeovim
userSetup
entrypoint
];
fakeRootCommands = ''
mkdir -p ./home/${user}/.npm-global
chown -R ${uid}:${gid} ./home/${user}
mkdir -p ./usr/bin
ln -s ${pkgs.coreutils}/bin/env ./usr/bin/env
'';
enableFakechroot = true;
config = {
Entrypoint = [ "${entrypoint}/bin/entrypoint" ];
Cmd = [ "${pkgs.bash}/bin/bash" ];
User = "${user}";
WorkingDir = "/home/${user}";
Env = [
"HOME=/home/${user}"
"USER=${user}"
"NIX_PAGER=cat"
"SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
"NIX_CONF_DIR=/etc/nix"
"NPM_CONFIG_PREFIX=/home/${user}/.npm-global"
"PATH=/home/${user}/.npm-global/bin:/usr/bin:/bin"
];
};
}

View file

@ -0,0 +1,41 @@
{ lib, ... }:
{
imports = [
./common.nix
];
boot.initrd.availableKernelModules = [
"virtio_pci"
"virtio_blk"
"virtio_net"
"virtio_balloon"
"virtio_scsi"
"xhci_pci"
"ahci"
"usbhid"
];
boot.kernelParams = [ "console=ttyS0,115200n8" ];
boot.loader.efi.canTouchEfiVariables = lib.mkForce false;
boot.loader.grub = {
enable = true;
device = "/dev/vda";
extraConfig = ''
serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1
terminal_input serial console
terminal_output serial console
'';
};
fileSystems."/" = {
device = "/dev/disk/by-label/nixos";
fsType = "ext4";
};
services.qemuGuest.enable = true;
networking = {
hostName = "claude-vm";
useDHCP = true;
};
}

View file

@ -21,15 +21,24 @@
options = [ "fmask=0077" "dmask=0077" ];
};
# fileSystems."/mnt/d" = {
# device = "/dev/sda1";
# fsType = "exfat";
# options = [
# "users"
# "exec"
# "nofail"
# ];
# };
fileSystems."/mnt/d" = {
device = "/dev/sda1";
fsType = "exfat";
options = [
"users"
"exec"
"nofail"
];
};
fileSystems."/mnt/d/SteamLibrary/steamapps/compatdata" = {
device = "/home/kp2pml30/.local/share/Steam/steamapps/compatdata-d";
fsType = "none";
options = [
"bind"
"nofail"
];
};
swapDevices = [ { device = "/dev/disk/by-uuid/c68daa9f-f165-4e23-8710-2aab0ad8d282"; } ];
@ -44,8 +53,8 @@
programs.nix-ld.enable = true;
home-manager.users.${config.kp2pml30.username}.programs.git.extraConfig = {
user.signingkey = "0xCD6528BAC23E3E34!";
home-manager.users.${config.kp2pml30.username}.programs.git.settings = {
user.signingkey = "0x1739F9D8BA250D04!";
commit.gpgsign = true;
tag.gpgSign = true;
};

View file

@ -13,4 +13,6 @@
open = true;
nvidiaSettings = true;
};
hardware.nvidia-container-toolkit.enable = true;
}

View file

@ -6,6 +6,8 @@
}@args:
let
cfg = config.kp2pml30;
startsWith = prefix: str:
builtins.substring 0 (builtins.stringLength prefix) str == prefix;
in {
options.kp2pml30 = {
username = lib.mkOption {
@ -65,22 +67,17 @@ in {
fish
fishPlugins.grc
fishPlugins.bass
nushell
carapace
python312 # needed for bass
grc
];
nixpkgs.config.allowUnfreePredicate = pkg:
builtins.any (x: startsWith x (pkgs.lib.getName pkg)) [ "vscode" "steam" "nvidia" ] ||
builtins.elem (pkgs.lib.getName pkg) [
"anytype-heart"
"vscode"
"steam"
"steam-run"
"steam-original"
"steam-unwrapped"
"nvidia-x11"
"nvidia-settings"
"nvidia-persistenced"
"opera"
"discord"
"slack"

View file

@ -17,37 +17,49 @@ in {
./messengers-work.nix
];
xdg.portal = {
enable = true;
extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
config = {
assertions = [
{ assertion = cfg.kitty -> cfg.xserver; message = "kp2pml30.kitty requires kp2pml30.xserver"; }
{ assertion = cfg.vscode -> cfg.xserver; message = "kp2pml30.vscode requires kp2pml30.xserver"; }
{ assertion = cfg.opera -> cfg.xserver; message = "kp2pml30.opera requires kp2pml30.xserver"; }
{ assertion = cfg.steam -> cfg.xserver; message = "kp2pml30.steam requires kp2pml30.xserver"; }
{ assertion = cfg.messengers.personal -> cfg.xserver; message = "kp2pml30.messengers.personal requires kp2pml30.xserver"; }
{ assertion = cfg.messengers.work -> cfg.xserver; message = "kp2pml30.messengers.work requires kp2pml30.xserver"; }
];
} // lib.mkIf cfg.xserver {
xdg.portal = {
enable = true;
extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
config.common.default = "*";
};
services.flatpak.enable = true;
systemd.services.flatpak-repo = {
wantedBy = [ "multi-user.target" ];
path = [ pkgs.flatpak ];
script = ''
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
'';
};
environment.systemPackages = with pkgs; [
#anytype
flatpak
gnome-software
firefox
feh
vlc
];
fonts.enableDefaultPackages = true;
fonts.packages = with pkgs; [
noto-fonts
noto-fonts-cjk-sans
noto-fonts-cjk-sans
fira-code
fira-code-symbols
nerd-fonts.fira-code
];
};
services.flatpak.enable = true;
systemd.services.flatpak-repo = {
wantedBy = [ "multi-user.target" ];
path = [ pkgs.flatpak ];
script = ''
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
'';
};
environment.systemPackages = with pkgs; [
anytype
flatpak
gnome-software
nodePackages.npm
nodejs
];
fonts.enableDefaultPackages = true;
fonts.packages = with pkgs; [
noto-fonts
noto-fonts-cjk-sans
noto-fonts-cjk-sans
fira-code
fira-code-symbols
nerd-fonts.fira-code
];
}

View file

@ -9,9 +9,9 @@ let
in lib.mkIf cfg.steam {
programs.steam = {
enable = true;
remotePlay.openFirewall = false;
remotePlay.openFirewall = true;
dedicatedServer.openFirewall = false;
localNetworkGameTransfers.openFirewall = false;
localNetworkGameTransfers.openFirewall = true;
};
hardware.steam-hardware.enable = true;

View file

@ -10,15 +10,16 @@ in lib.mkIf cfg.vscode {
home-manager.users.${cfg.username} = {
programs.vscode = {
enable = true;
package = (pkgs.vscode.overrideAttrs (oldAttrs: rec {
src = (builtins.fetchTarball {
url = "https://update.code.visualstudio.com/1.104.1/linux-x64/stable";
sha256 = "sha256:109mdk1v323dyhzrq0444gjjhfpjxbllkqkhsapfj44ypjzdjcy8";
});
version = "1.102.2";
}));
package = pkgs.vscode.overrideAttrs (oldAttrs: {
buildInputs = (oldAttrs.buildInputs or []) ++ [
pkgs.curl
pkgs.openssl
pkgs.webkitgtk_4_1
pkgs.libsoup_3
];
});
mutableExtensionsDir = false;
userSettings = lib.importJSON("${rootPath}/vscode/settings.json");
profiles.default.userSettings = lib.importJSON("${rootPath}/vscode/settings.json");
# extensions = with pkgs; [
# vscode-extensions.eamodio.gitlens
# vscode-extensions.editorconfig.editorconfig

View file

@ -18,7 +18,7 @@ in {
home-manager.users.${cfg.username} = { lib, ... }: {
home = {
stateVersion = "24.05";
stateVersion = "25.11";
username = cfg.username;
homeDirectory = "/home/${cfg.username}";
packages = with pkgs; [
@ -41,16 +41,16 @@ in {
nix.gc = {
automatic = true;
frequency = "weekly";
dates = "weekly";
};
programs = {
git = {
enable = true;
userName = cfg.username;
userEmail = "kp2pml30@gmail.com";
lfs.enable = true;
extraConfig = {
settings = {
user.name = cfg.username;
user.email = "kp2pml30@gmail.com";
init.defaultBranch = "main";
};
};
@ -60,6 +60,12 @@ in {
shellInitLast = builtins.readFile (rootPath + "/home/.config/fish/config.fish");
};
nushell = {
enable = true;
extraEnv = builtins.readFile (rootPath + "/home/.config/nushell/env.nu");
extraConfig = builtins.readFile (rootPath + "/home/.config/nushell/config.nu");
};
starship = {
enable = true;
settings = {
@ -80,7 +86,50 @@ in {
};
};
dconf.settings = {
xdg.desktopEntries = lib.mkIf config.kp2pml30.xserver {
yazi = {
name = "Yazi";
comment = "Terminal file manager";
exec = "kitty -- yazi %u";
terminal = false;
mimeType = [ "inode/directory" ];
categories = [ "System" "FileManager" ];
};
nvim = {
name = "Neovim";
comment = "Terminal text editor";
exec = "kitty -- nvim %F";
terminal = false;
mimeType = [ "text/plain" ];
categories = [ "Utility" "TextEditor" ];
};
};
xdg.mimeApps = lib.mkIf config.kp2pml30.xserver (let
mimeMap = desktop: types:
builtins.listToAttrs (map (t: { name = t; value = [ desktop ]; }) types);
in {
enable = true;
defaultApplications =
{ "inode/directory" = [ "yazi.desktop" ]; }
// mimeMap "nvim.desktop" [
"text/plain" "text/html" "text/css" "text/xml" "text/markdown"
"text/x-csrc" "text/x-chdr" "text/x-c++src" "text/x-c++hdr"
"text/x-python" "text/x-shellscript" "text/x-makefile"
"application/json" "application/xml" "application/x-yaml"
"application/toml" "application/javascript" "application/x-shellscript"
"application/x-nix"
]
// mimeMap "feh.desktop" [
"image/png" "image/jpeg" "image/gif" "image/webp" "image/bmp" "image/svg+xml"
]
// mimeMap "vlc.desktop" [
"video/mp4" "video/x-matroska" "video/webm" "video/x-msvideo"
"video/quicktime" "video/x-flv"
];
});
dconf.settings = lib.mkIf config.kp2pml30.xserver {
"org/gnome/desktop/interface" = {
color-scheme = "prefer-dark";
};

View file

@ -8,6 +8,7 @@ let
cfg = config.kp2pml30;
in {
config = {
nixpkgs.overlays = [ inputs.claude-code.overlays.default ];
programs = {
tmux.enable = true;
yazi.enable = true;
@ -18,6 +19,8 @@ in {
ncdu
timewarrior
p7zip
claude-code
lazydocker
];
};

21
nix/qemu.nix Normal file
View file

@ -0,0 +1,21 @@
{ config
, pkgs
, lib
, ...
}:
let
cfg = config.kp2pml30;
in {
options.kp2pml30.qemu = lib.mkEnableOption "";
config = lib.mkIf cfg.qemu {
environment.systemPackages = with pkgs; [
qemu
OVMF
];
virtualisation.libvirtd.enable = true;
users.users.${cfg.username}.extraGroups = [ "libvirtd" ];
};
}

View file

@ -124,6 +124,16 @@ in lib.mkIf cfg.nginx {
root = cfg.sitePath;
tryFiles = "$uri $uri/ /index.html";
};
locations."/fs/" = {
root = cfg.sitePath;
tryFiles = "$uri $uri/ /fs/index.html";
};
locations."/view/" = {
root = cfg.sitePath;
tryFiles = "$uri $uri/ /view/index.html";
};
};
} // (if cfg.xray then {
# Xray fallback proxy servers

View file

@ -23,7 +23,7 @@ let
fi
# Decrypt and parse XRAY_UIDS
${pkgs.openssl}/bin/openssl enc -aes-256-cbc -pbkdf2 -iter 1000000 -base64 -d -k "$KP2_DOTFILES_SECRET_KEY" -in "${./secrets.yaml}" | ${pkgs.yq}/bin/yq '.XRAY_UIDS[]' -r
${pkgs.openssl}/bin/openssl enc -aes-256-cbc -pbkdf2 -iter 1000000 -base64 -d -k "$KP2_DOTFILES_SECRET_KEY" -in "${./secrets.yaml}" | ${pkgs.yq}/bin/yq '.XRAY_UIDS[].uid' -r
'';
xray-config-base = builtins.toFile "xray.json" (builtins.toJSON (

View file

@ -1,4 +1,6 @@
U2FsdGVkX18N4BW9sin9kPVNkpbtVNoDqBAm+080vcYSS7qySHVOCfe94a7S8mh4
G5tbvoRrOFxJ+RW/WYNMsEZ7wgsJM8b9AiKPaT30BMHXriTdtai80i6xKqv9zdCb
moGUlBSgMtqEhvAnvpYBxHQ+NtDhxw7K9UjaO7eodNp+l9PR6z+IeL29rC2DMxQc
jXAjbfPa3aeSikXF0g118HbUwVJQwlXq99n/fjkJ8XOhBo/S4tWbt0U8O97VKlA6
U2FsdGVkX18Z/nFLuSfx9e8XYdUPqLO0NOAdKcPf+WkKg7exhD+p6p+pDzaHhdHP
0JzWp5p8yz/sehmSoqrXJtS7G9Y5f9gj2dLwfxLobzx4TTR/s8Hz2qVyNKu+D8hP
vBkNQaMJQNjPgJHsmKDnqT0zFGr0nz5GfchMbxepherBdysuwZKk7j7X0TKcgA0R
c4v+QWYZH669dWij2Oq9P6IFE/aM420cmSXh2Ilr/MMirk/rZ3dr3Kx0JdVHaeFT
VAHU243eV0++OpvL9td7r8L9BWBS2p/5nowN5mVcUmBBBF7FrYeDaYjkoi3IXLTb
1EfrTOpIQfgm7qOqsfy1lClfrHaKPadqyIYxkuY+i/k=

View file

@ -13,9 +13,9 @@ in lib.mkIf cfg.xray {
};
# Ensure xray can read the certificates
users.users.xray.extraGroups = [ "nginx" ];
users.users.xray.extraGroups = [ "certreaders" ];
# Ensure the xray service starts after ACME certificates are available
systemd.services.xray.after = [ "acme-${cfg.hostname}.service" ];
systemd.services.xray.wants = [ "acme-${cfg.hostname}.service" ];
}
}

70
nix/xray.nix Normal file
View file

@ -0,0 +1,70 @@
{ config
, pkgs
, lib
, ...
}:
let
cfg = config.kp2pml30;
xray-config-base = builtins.toFile "xray-client.json" (builtins.toJSON
(builtins.fromJSON (builtins.readFile ./server/xray-client.json))
);
decryptSecrets = pkgs.writeShellScript "decrypt-secrets" ''
set -euo pipefail
source /var/lib/secrets/.env
if [ -z "''${KP2_DOTFILES_SECRET_KEY:-}" ]; then
echo "Error: KP2_DOTFILES_SECRET_KEY environment variable not set" >&2
exit 1
fi
${pkgs.openssl}/bin/openssl enc -aes-256-cbc -pbkdf2 -iter 1000000 -base64 -d -k "$KP2_DOTFILES_SECRET_KEY" -in "${./server/secrets.yaml}" | ${pkgs.yq}/bin/yq --arg id "${cfg.xray-client-id}" '.XRAY_UIDS[] | select(.id == $id) | .uid' -r
'';
generateXrayConfig = pkgs.writeShellScript "generate-xray-client-config" ''
set -euo pipefail
UUID=$(${decryptSecrets})
cat "${xray-config-base}" | \
${pkgs.jq}/bin/jq --arg uuid "$UUID" '.outbounds[0].settings.vnext[0].users[0].id = $uuid'
'';
in {
options.kp2pml30.xray-client = lib.mkEnableOption "";
options.kp2pml30.xray-client-id = lib.mkOption {
type = lib.types.str;
description = "ID to select the correct UUID from secrets";
};
config = lib.mkIf cfg.xray-client {
services.xray = {
enable = true;
settingsFile = "/run/secrets/xray-client-config.json";
};
systemd.services.xray-client-secrets = {
description = "Generate Xray client configuration";
wantedBy = [ "xray.service" ];
before = [ "xray.service" ];
serviceConfig = {
Type = "oneshot";
User = "root";
EnvironmentFile = "/var/lib/secrets/.env";
};
script = ''
mkdir -p /run/secrets
${generateXrayConfig} > /run/secrets/xray-client-config.json
chmod 444 /run/secrets/xray-client-config.json
'';
};
systemd.tmpfiles.rules = [
"d /var/lib/secrets 0750 root root -"
"d /run/secrets 0755 root root -"
];
};
}