instances.nix-container-builder becomes nix_container_builder so the service unit is gitea-runner-nix_container_builder.service instead of gitea-runner-nix\x2dcontainer\x2dbuilder.service. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
424 lines
11 KiB
Nix
424 lines
11 KiB
Nix
{ config, pkgs, lib, ... }:
|
|
|
|
let
|
|
# Libraries needed by mise-compiled runtimes (python-build, etc.)
|
|
buildDeps = with pkgs; [ zlib readline bzip2 xz libffi ncurses sqlite openssl ];
|
|
in
|
|
{
|
|
# Allow unfree packages (NVIDIA drivers, Steam)
|
|
nixpkgs.config.allowUnfree = true;
|
|
|
|
# Bootloader
|
|
boot.loader.systemd-boot.enable = true;
|
|
boot.loader.efi.canTouchEfiVariables = true;
|
|
|
|
# No TPM module on this board
|
|
systemd.tpm2.enable = false;
|
|
|
|
# Networking
|
|
networking.hostName = "ringtail";
|
|
networking.networkmanager.enable = true;
|
|
|
|
# Time zone
|
|
time.timeZone = "America/Los_Angeles";
|
|
|
|
# Locale
|
|
i18n.defaultLocale = "en_US.UTF-8";
|
|
|
|
# NVIDIA proprietary drivers
|
|
hardware.graphics.enable = true;
|
|
services.xserver.videoDrivers = [ "nvidia" ];
|
|
hardware.nvidia = {
|
|
modesetting.enable = true;
|
|
open = false; # Use proprietary driver for RTX 4080
|
|
nvidiaSettings = true;
|
|
package = config.boot.kernelPackages.nvidiaPackages.stable;
|
|
};
|
|
|
|
# Wayland / Sway
|
|
programs.sway = {
|
|
enable = true;
|
|
wrapperFeatures.gtk = true;
|
|
extraSessionCommands = ''
|
|
export WLR_NO_HARDWARE_CURSORS=1
|
|
'';
|
|
extraPackages = with pkgs; [
|
|
swaylock
|
|
swayidle
|
|
wezterm # terminal
|
|
wmenu # app launcher
|
|
mako # notifications
|
|
grim # screenshots
|
|
slurp # region selection
|
|
];
|
|
};
|
|
security.polkit.enable = true;
|
|
security.sudo.wheelNeedsPassword = false;
|
|
|
|
# Enable greetd as display manager for sway
|
|
services.greetd = {
|
|
enable = true;
|
|
settings = {
|
|
default_session = {
|
|
command = "${pkgs.tuigreet}/bin/tuigreet --time --cmd 'sway --unsupported-gpu'";
|
|
user = "greeter";
|
|
};
|
|
};
|
|
};
|
|
|
|
# PipeWire for audio
|
|
services.pipewire = {
|
|
enable = true;
|
|
alsa.enable = true;
|
|
pulse.enable = true;
|
|
};
|
|
|
|
# Bluetooth
|
|
hardware.bluetooth = {
|
|
enable = true;
|
|
powerOnBoot = true;
|
|
};
|
|
services.blueman.enable = true;
|
|
|
|
# Fish shell
|
|
programs.fish.enable = true;
|
|
|
|
# 1Password (modules handle CLI group/setgid and polkit for GUI integration)
|
|
programs._1password.enable = true;
|
|
programs._1password-gui = {
|
|
enable = true;
|
|
polkitPolicyOwners = [ "eblume" ];
|
|
};
|
|
|
|
# Steam
|
|
programs.steam = {
|
|
enable = true;
|
|
dedicatedServer.openFirewall = true;
|
|
};
|
|
|
|
# K3s single-node cluster
|
|
services.k3s = {
|
|
enable = true;
|
|
role = "server";
|
|
tokenFile = "/etc/k3s/token";
|
|
extraFlags = toString [
|
|
"--disable=traefik"
|
|
"--disable=servicelb"
|
|
"--disable=metrics-server"
|
|
"--write-kubeconfig-mode=644"
|
|
"--tls-san=ringtail.tail8d86e.ts.net"
|
|
];
|
|
};
|
|
|
|
# K3s containerd registry mirrors (pull through Zot on indri)
|
|
environment.etc."rancher/k3s/registries.yaml".source = ./k3s-registries.yaml;
|
|
|
|
# Tailscale
|
|
services.tailscale = {
|
|
enable = true;
|
|
extraUpFlags = [ "--accept-routes" "--ssh" ];
|
|
};
|
|
|
|
# Trust Tailscale interface (ArgoCD on indri connects via tailnet)
|
|
networking.firewall.trustedInterfaces = [ "tailscale0" ];
|
|
|
|
# SSH
|
|
services.openssh = {
|
|
enable = true;
|
|
settings = {
|
|
PasswordAuthentication = false;
|
|
PermitRootLogin = "no";
|
|
};
|
|
};
|
|
|
|
# User account
|
|
users.users.eblume = {
|
|
isNormalUser = true;
|
|
shell = pkgs.fish;
|
|
extraGroups = [ "wheel" "networkmanager" "video" ];
|
|
openssh.authorizedKeys.keys = [
|
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILmh1SSCdDAyu3vkSQH7kAXEPDi8APyjo9JXDTjtha2j"
|
|
];
|
|
};
|
|
|
|
# System packages
|
|
environment.systemPackages = with pkgs; [
|
|
git
|
|
kubectl
|
|
python3 # required for Ansible
|
|
vim
|
|
htop
|
|
curl
|
|
wget
|
|
chezmoi
|
|
neovim
|
|
eza
|
|
fd
|
|
fzf
|
|
zoxide
|
|
starship
|
|
atuin
|
|
bat
|
|
ripgrep
|
|
mise
|
|
gcc
|
|
gnumake
|
|
pkg-config
|
|
openssl
|
|
gnupg
|
|
unzip
|
|
fuzzel
|
|
pulseaudio
|
|
librewolf
|
|
];
|
|
|
|
# Allow running dynamically linked binaries (mise-installed runtimes, etc.)
|
|
programs.nix-ld.enable = true;
|
|
programs.nix-ld.libraries = buildDeps ++ [ pkgs.icu ];
|
|
|
|
# Compile-time flags for mise python-build and similar source builds
|
|
environment.sessionVariables = {
|
|
PKG_CONFIG_PATH = lib.makeSearchPath "lib/pkgconfig" (map lib.getDev buildDeps);
|
|
CFLAGS = lib.concatMapStringsSep " " (p: "-I${lib.getDev p}/include") buildDeps;
|
|
LDFLAGS = lib.concatMapStringsSep " " (p: "-L${lib.getLib p}/lib") buildDeps;
|
|
};
|
|
|
|
# Fonts
|
|
fonts.packages = with pkgs; [
|
|
nerd-fonts.victor-mono
|
|
];
|
|
|
|
# Home Manager (minimal — chezmoi owns dotfiles, this is ringtail-specific)
|
|
home-manager.useGlobalPkgs = true;
|
|
home-manager.useUserPackages = true;
|
|
home-manager.users.eblume = {
|
|
home.stateVersion = "25.11";
|
|
|
|
wayland.windowManager.sway = {
|
|
enable = true;
|
|
checkConfig = false;
|
|
config = {
|
|
terminal = "wezterm";
|
|
modifier = "Mod4";
|
|
fonts = {
|
|
names = [ "VictorMono Nerd Font" ];
|
|
size = 10.0;
|
|
};
|
|
bars = [{ command = "waybar"; }];
|
|
gaps = {
|
|
inner = 8;
|
|
outer = 4;
|
|
};
|
|
window = {
|
|
border = 2;
|
|
titlebar = false;
|
|
};
|
|
colors = {
|
|
focused = {
|
|
border = "#8aadf4";
|
|
background = "#24273a";
|
|
text = "#cad3f5";
|
|
indicator = "#c6a0f6";
|
|
childBorder = "#8aadf4";
|
|
};
|
|
focusedInactive = {
|
|
border = "#494d64";
|
|
background = "#1e2030";
|
|
text = "#a5adcb";
|
|
indicator = "#494d64";
|
|
childBorder = "#494d64";
|
|
};
|
|
unfocused = {
|
|
border = "#363a4f";
|
|
background = "#1e2030";
|
|
text = "#6e738d";
|
|
indicator = "#363a4f";
|
|
childBorder = "#363a4f";
|
|
};
|
|
urgent = {
|
|
border = "#ed8796";
|
|
background = "#24273a";
|
|
text = "#cad3f5";
|
|
indicator = "#ed8796";
|
|
childBorder = "#ed8796";
|
|
};
|
|
};
|
|
input = {
|
|
"*" = {
|
|
xkb_options = "ctrl:nocaps";
|
|
};
|
|
};
|
|
output = {
|
|
"DP-1" = {
|
|
mode = "2560x1440@165Hz";
|
|
adaptive_sync = "on";
|
|
bg = "~/.config/sway/wallpaper.jpg fill";
|
|
};
|
|
};
|
|
keybindings = let mod = "Mod4"; in {
|
|
"${mod}+Return" = "exec wezterm";
|
|
"${mod}+Shift+q" = "kill";
|
|
"${mod}+d" = "exec wmenu-run";
|
|
"${mod}+space" = "exec fuzzel";
|
|
"${mod}+Shift+c" = "reload";
|
|
"--locked XF86AudioMute" = "exec pactl set-sink-mute @DEFAULT_SINK@ toggle";
|
|
"--locked XF86AudioLowerVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ -5%";
|
|
"--locked XF86AudioRaiseVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ +5%";
|
|
"--locked XF86AudioMicMute" = "exec pactl set-source-mute @DEFAULT_SOURCE@ toggle";
|
|
};
|
|
startup = [
|
|
{ command = "1password"; }
|
|
{ command = "steam"; }
|
|
];
|
|
};
|
|
};
|
|
|
|
programs.fuzzel = {
|
|
enable = true;
|
|
settings = {
|
|
main = {
|
|
font = "VictorMono Nerd Font:size=14";
|
|
terminal = "wezterm";
|
|
width = 40;
|
|
horizontal-pad = 16;
|
|
vertical-pad = 8;
|
|
border-radius = 8;
|
|
border-width = 2;
|
|
};
|
|
colors = {
|
|
background = "24273add";
|
|
text = "cad3f5ff";
|
|
match = "8aadf4ff";
|
|
selection = "363a4fff";
|
|
selection-text = "cad3f5ff";
|
|
selection-match = "8aadf4ff";
|
|
border = "8aadf4ff";
|
|
};
|
|
};
|
|
};
|
|
|
|
programs.waybar = {
|
|
enable = true;
|
|
settings = [{
|
|
layer = "top";
|
|
position = "top";
|
|
height = 30;
|
|
modules-left = [ "sway/workspaces" "sway/mode" ];
|
|
modules-center = [ "sway/window" ];
|
|
modules-right = [ "pulseaudio" "bluetooth" "network" "clock" "tray" ];
|
|
tray = { spacing = 8; };
|
|
clock = { format = "{:%a %b %d %H:%M}"; };
|
|
network = {
|
|
interval = 2;
|
|
format-ethernet = "{bandwidthDownBits} down {bandwidthUpBits} up";
|
|
format-wifi = "{essid} {bandwidthDownBits} down {bandwidthUpBits} up";
|
|
format-disconnected = "disconnected";
|
|
};
|
|
pulseaudio = {
|
|
format = "{icon} {volume}%";
|
|
format-muted = " muted";
|
|
format-icons = {
|
|
headphone = "";
|
|
default = [ "" "" "" ];
|
|
};
|
|
};
|
|
}];
|
|
style = ''
|
|
* {
|
|
font-family: "VictorMono Nerd Font";
|
|
font-size: 13px;
|
|
border: none;
|
|
border-radius: 0;
|
|
min-height: 0;
|
|
}
|
|
window#waybar {
|
|
background-color: rgba(30, 32, 48, 0.9);
|
|
color: #cad3f5;
|
|
margin: 4px 4px 0 4px;
|
|
}
|
|
#workspaces button {
|
|
padding: 0 8px;
|
|
margin: 0 2px;
|
|
color: #6e738d;
|
|
background: transparent;
|
|
border-radius: 4px;
|
|
}
|
|
#workspaces button.focused {
|
|
color: #8aadf4;
|
|
background: #363a4f;
|
|
border-bottom: 2px solid #8aadf4;
|
|
}
|
|
#workspaces button.urgent {
|
|
color: #ed8796;
|
|
}
|
|
#window {
|
|
color: #a5adcb;
|
|
}
|
|
#bluetooth {
|
|
color: #8aadf4;
|
|
}
|
|
#bluetooth.off, #bluetooth.disabled {
|
|
color: #6e738d;
|
|
}
|
|
#clock, #network, #pulseaudio, #bluetooth, #tray {
|
|
padding: 0 12px;
|
|
margin: 4px 2px;
|
|
color: #cad3f5;
|
|
background: #363a4f;
|
|
border-radius: 4px;
|
|
}
|
|
#clock {
|
|
color: #8aadf4;
|
|
}
|
|
#pulseaudio {
|
|
color: #f5a97f;
|
|
}
|
|
#network {
|
|
color: #a6da95;
|
|
}
|
|
#network.disconnected {
|
|
color: #ed8796;
|
|
}
|
|
'';
|
|
};
|
|
};
|
|
|
|
# Ensure mounted drives are owned by eblume
|
|
systemd.tmpfiles.rules = [
|
|
"d /mnt/games 0755 eblume users -"
|
|
"d /mnt/storage1 0755 eblume users -"
|
|
"d /mnt/storage2 0755 eblume users -"
|
|
];
|
|
|
|
# Forgejo Actions runner (nix container builder)
|
|
services.gitea-actions-runner = {
|
|
package = pkgs.forgejo-runner;
|
|
instances.nix_container_builder = {
|
|
enable = true;
|
|
name = "ringtail-nix-builder";
|
|
url = "https://forge.ops.eblu.me";
|
|
tokenFile = "/etc/forgejo-runner/token.env";
|
|
labels = [ "nix-container-builder:host" ];
|
|
hostPackages = with pkgs; [
|
|
bash coreutils curl gawk gitMinimal gnused nodejs wget
|
|
nix skopeo
|
|
];
|
|
settings = {
|
|
log.level = "info";
|
|
runner = {
|
|
capacity = 1;
|
|
timeout = "3h";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
# Enable nix flakes
|
|
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
|
|
|
# Allow the runner's dynamic user to access the nix daemon
|
|
nix.settings.trusted-users = [ "gitea-runner" ];
|
|
|
|
# NixOS release
|
|
system.stateVersion = "25.11";
|
|
}
|