init: Add crossbox's configurations

This commit is contained in:
Matthew Binning 2026-01-10 10:55:18 -08:00
parent 9339a28783
commit cbac6cd532
8 changed files with 632 additions and 0 deletions

265
configuration.nix Normal file
View file

@ -0,0 +1,265 @@
{ config, pkgs, ... }:
let
hostConfigs = {
crossbox = [ ./sdr.nix ./syncthing.nix ./forgejo.nix ./radicale.nix ./ollama.nix ./docuseal.nix ./nginx.nix ];
anvil = [ ./sdr.nix ./syncthing.nix ];
};
in
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
] ++ hostConfigs.crossbox;
nix.settings.experimental-features = [ "nix-command" "flakes" ];
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
# List packages installed in system profile.
environment.systemPackages = with pkgs; [
cargo
curl
docker-compose
gcc
git
gnupg
imv
lmstudio
mpv
neovim
openssl
# Alias vi even with sudo.
(pkgs.writeShellScriptBin "vi" ''
exec ${pkgs.neovim}/bin/nvim "$@"
'')
pinentry-curses
rsync
rustc
tldr
vscodium
# Hyprland essentials
hyprpaper # Wallpaper daemon
hypridle # Idle daemon
hyprlock # Lock screen
xdg-utils # XDG utilities
#polkit-kde-agent # Polkit authentication agent
];
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
hardware.graphics = {
enable = true;
extraPackages = with pkgs; [
rocmPackages.clr.icd # ROCm OpenCL runtime
rocmPackages.clr
rocmPackages.rocminfo
rocmPackages.rocm-runtime
];
};
networking.hostName = "crossbox";
# Enables wireless support via wpa_supplicant.
# networking.wireless.enable = true;
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
networking.networkmanager.enable = true;
time.timeZone = "America/Los_Angeles";
i18n.defaultLocale = "en_US.UTF-8";
i18n.extraLocaleSettings = {
LC_ADDRESS = "en_US.UTF-8";
LC_IDENTIFICATION = "en_US.UTF-8";
LC_MEASUREMENT = "en_US.UTF-8";
LC_MONETARY = "en_US.UTF-8";
LC_NAME = "en_US.UTF-8";
LC_NUMERIC = "en_US.UTF-8";
LC_PAPER = "en_US.UTF-8";
LC_TELEPHONE = "en_US.UTF-8";
LC_TIME = "en_US.UTF-8";
};
programs.gnupg.agent = {
enable = true;
pinentryPackage = pkgs.pinentry-curses;
};
# Hyprland configuration
programs.hyprland = {
enable = true;
xwayland.enable = true;
};
# Display manager for Hyprland
services.displayManager.sddm = {
enable = true;
wayland.enable = true;
};
# XDG portal for screen sharing and other desktop features
xdg.portal = {
enable = true;
extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
};
services.xserver = {
enable = true;
xkb = {
layout = "us";
variant = "";
};
};
# Enable CUPS to print documents.
services.printing.enable = true;
# Enable sound with pipewire.
services.pulseaudio.enable = false;
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
# If you want to use JACK applications, uncomment this
#jack.enable = true;
};
# Define a user account. Don't forget to set a password with 'passwd'.
users.users.brimlock = {
isNormalUser = true;
home = "/home/brimlock";
description = "brimlock";
extraGroups = [ "docker" "networkmanager" "wheel" "video" "render" ];
packages = with pkgs; [
# Hyprland utilities and applications
waybar # Status bar
wofi # Application launcher
kitty # Terminal emulator
dunst # Notification daemon
swaylock # Screen locker
swayidle # Idle management daemon
wlogout # Logout menu
grim # Screenshot tool
slurp # Screen area selector
wl-clipboard # Clipboard utilities
brightnessctl # Brightness control
pavucontrol # Audio control
networkmanagerapplet # Network manager applet
# File manager and utilities
nautilus
gnome-themes-extra
# Additional tools
libreoffice
grub2_efi
exfatprogs
];
};
# Install firefox system-wide as well
programs.firefox.enable = true;
# Allow unfree packages
nixpkgs.config.allowUnfree = true;
# Add cachix for faster builds
nix.settings = {
substituters = [
"https://cache.nixos.org/"
"https://nix-community.cachix.org"
];
trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
];
};
environment.variables.EDITOR = "nvim";
# Polkit for privilege escalation
#security.polkit.enable = true;
networking.firewall.allowedTCPPorts = [ 22 ];
system.stateVersion = "25.11";
# Crossbox Configuration
environment.shellAliases = {
vi = "nvim";
vim = "nvim";
};
security.sudo = {
enable = true;
extraRules = [
{
users = [ "brimlock" ];
commands = [
{
command = "ALL";
options = [ "NOPASSWD" ];
}
];
}
];
};
programs.steam = {
enable = true;
remotePlay.openFirewall = true;
dedicatedServer.openFirewall = true;
};
# List services that you want to enable:
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
};
};
# Disable automatic suspend.
# Otherwise SSH tunnels and HDMI signals break.
services.logind = {
settings = {
Login = {
HandleLidSwitch = "ignore";
HandleHibernateKey = "ignore";
HandleSuspendKey = "ignore";
HandlePowerKey = "ignore";
};
};
};
# Disable automatic suspend for SystemD.
systemd.targets.sleep.enable = false;
systemd.targets.suspend.enable = false;
systemd.targets.hibernate.enable = false;
systemd.targets.hybrid-sleep.enable = false;
virtualisation.docker = {
enable = true;
autoPrune = {
enable = true;
dates = "weekly";
};
rootless = {
enable = true;
setSocketVariable = true;
};
};
}

43
docuseal.nix Normal file
View file

@ -0,0 +1,43 @@
{ config, pkgs, lib, ... }:
let
# Generate a secret key if it doesn't exist
secretKeyFile = "/var/lib/docuseal/secret-key-base";
in
{
services.docuseal = {
enable = true;
port = 3030;
host = "docuseal.binning.net";
# Point to the secret key file in the state directory
# The service will have access to this since StateDirectory is set
secretKeyBaseFile = secretKeyFile;
};
# Create the secret key file if it doesn't exist
# This runs before the docuseal service starts
systemd.services.docuseal-init-secret = {
description = "Initialize DocuSeal secret key";
wantedBy = [ "docuseal.service" ];
before = [ "docuseal.service" ];
serviceConfig = {
Type = "oneshot";
StateDirectory = "docuseal";
StateDirectoryMode = "0750";
DynamicUser = true;
};
script = ''
if [ ! -f ${secretKeyFile} ]; then
echo "Generating new secret key for DocuSeal..."
${pkgs.openssl}/bin/openssl rand -hex 64 > ${secretKeyFile}
chmod 640 ${secretKeyFile}
echo "Secret key generated at ${secretKeyFile}"
else
echo "Secret key already exists at ${secretKeyFile}"
fi
'';
};
}

49
forgejo.nix Normal file
View file

@ -0,0 +1,49 @@
{ config, pkgs, lib, ... }:
{
services.forgejo = {
enable = true;
# Set data directory
stateDir = "/srv/forgejo";
# Database configuration
database = {
type = "sqlite3";
path = "/srv/forgejo/data/forgejo.db";
};
# Server settings
settings = {
server = {
DOMAIN = "forgejo.binning.net";
ROOT_URL = "https://forgejo.binning.net/";
HTTP_ADDR = "127.0.0.1";
HTTP_PORT = 3000;
};
# Repository settings - uses default: /srv/forgejo/repositories
# No need to override repository.ROOT as the default location is good
service = {
DISABLE_REGISTRATION = true; # Set to true to disable new user registration
};
# Session and security
session = {
COOKIE_SECURE = true; # Since we're using HTTPS
};
# Recommended security settings
security = {
INSTALL_LOCK = true;
};
};
};
# Ensure the data directory exists with proper permissions
systemd.tmpfiles.rules = [
"d /srv/forgejo 0750 forgejo forgejo -"
"d /srv/forgejo/data 0750 forgejo forgejo -"
];
}

177
nginx.nix Normal file
View file

@ -0,0 +1,177 @@
{ config, pkgs, lib, ... }:
let
# Read multiple API keys from the secrets file at build time
# Note: This embeds the secrets in the Nix store, which is a trade-off
# Alternative: Keep secrets file and read via njs module or external auth service
secretsFile = "/srv/nginx/secrets";
# Read API keys from file (one key per line, will be evaluated at build time)
# If the file doesn't exist yet, this will fail - create it first
apiKeysRaw = builtins.readFile secretsFile;
apiKeys = lib.filter (k: k != "") (lib.splitString "\n" apiKeysRaw);
# Generate map entries for each key
mapEntries = lib.concatMapStringsSep "\n "
(key: ''"Bearer ${key}" "authorized";'')
apiKeys;
in
{
services.nginx = {
enable = true;
# Recommended settings
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
# Increase bucket size for long Bearer tokens
mapHashBucketSize = 128;
# Map directive to check Authorization header against multiple keys
appendHttpConfig = ''
# Check if the Authorization header matches any expected value
map $http_authorization $auth_status {
default "unauthorized";
"" "no_auth";
${mapEntries}
}
'';
# Virtual hosts configuration
virtualHosts = {
# Main website - Static HTML/CSS
"www.binning.net" = {
forceSSL = true;
#enableACME = true;
sslCertificate = "/srv/nginx/binning.net.pem";
sslCertificateKey = "/srv/nginx/binning.net.key.pem";
root = "/srv/www/binning.net";
locations."/" = {
index = "index.html";
tryFiles = "$uri $uri/ =404";
extraConfig = ''
# Enable Server Side Includes for navbar/footer includes
ssi on;
'';
};
# Private blog articles with HTTP basic authentication
locations."/blog/private/" = {
extraConfig = ''
auth_basic "Private Articles";
auth_basic_user_file /srv/nginx/.htpasswd;
# Enable Server Side Includes
ssi on;
'';
};
# Optional: Custom 404 page
extraConfig = ''
error_page 404 /404.html;
'';
};
# Ollama with Bearer token authentication
"ollama.binning.net" = {
forceSSL = true;
#enableACME = true;
sslCertificate = "/srv/nginx/binning.net.pem";
sslCertificateKey = "/srv/nginx/binning.net.key.pem";
locations."/" = {
extraConfig = ''
# Check auth status
if ($auth_status = "no_auth") {
return 401 "Unauthorized: Bearer token required\n";
}
if ($auth_status = "unauthorized") {
return 403 "Forbidden: Invalid API key\n";
}
# Proxy to Ollama (only if authorized)
proxy_pass http://localhost:11434;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts for long-running requests
proxy_read_timeout 300s;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
# Allow large request bodies
client_max_body_size 100M;
# Logging
access_log /var/log/nginx/ollama_access.log;
error_log /var/log/nginx/ollama_error.log;
'';
};
};
# Forgejo
"forgejo.binning.net" = {
forceSSL = true;
#enableACME = true;
sslCertificate = "/srv/nginx/binning.net.pem";
sslCertificateKey = "/srv/nginx/binning.net.key.pem";
locations."/" = {
proxyPass = "http://127.0.0.1:3000";
# No extraConfig needed - recommendedProxySettings handles headers
};
};
# Radicale
"radicale.binning.net" = {
forceSSL = true;
#enableACME = true;
sslCertificate = "/srv/nginx/binning.net.pem";
sslCertificateKey = "/srv/nginx/binning.net.key.pem";
locations."/" = {
proxyPass = "http://127.0.0.1:5232";
# recommendedProxySettings handles most headers
extraConfig = ''
proxy_set_header X-Script-Name "";
'';
};
};
# DocuSeal
"docuseal.binning.net" = {
forceSSL = true;
#enableACME = true;
sslCertificate = "/srv/nginx/binning.net.pem";
sslCertificateKey = "/srv/nginx/binning.net.key.pem";
locations."/" = {
proxyPass = "http://127.0.0.1:3030";
proxyWebsockets = true;
};
};
};
};
# Firewall
networking.firewall.allowedTCPPorts = [ 80 443 ];
# ACME/Let's Encrypt
security.acme = {
acceptTerms = true;
defaults.email = "hvanb@pm.me";
};
}

22
ollama.nix Normal file
View file

@ -0,0 +1,22 @@
{ config, pkgs, lib, ... }:
{
services.ollama = {
enable = true;
host = "0.0.0.0";
port = 11434;
};
# Open firewall port for Ollama
networking.firewall.allowedTCPPorts = [ 11434 ];
# Install ollama-rocm package
environment.systemPackages = with pkgs; [
ollama-rocm
];
# Add CA certificate for Ollama
security.pki.certificateFiles = [
/home/brimlock/ollama-ca.crt
];
}

37
radicale.nix Normal file
View file

@ -0,0 +1,37 @@
{ config, pkgs, lib, ... }:
{
services.radicale = {
enable = true;
# Configuration settings
settings = {
server = {
hosts = [ "127.0.0.1:5232" "[::1]:5232" ];
};
# Authentication (you can customize this)
auth = {
type = "htpasswd";
htpasswd_filename = "/srv/radicale/users";
htpasswd_encryption = "bcrypt";
};
# Storage configuration
storage = {
filesystem_folder = "/srv/radicale/collections";
};
# Logging
logging = {
level = "info";
};
rights = {
type = "from_file";
file = "/srv/radicale/rights";
};
};
};
}

13
sdr.nix Normal file
View file

@ -0,0 +1,13 @@
{ config, pkgs, ... }:
{
environment.systemPackages = with pkgs; [
hackrf
urh
usbutils
];
services.udev.packages = with pkgs; [
hackrf
rtl-sdr
];
}

26
syncthing.nix Normal file
View file

@ -0,0 +1,26 @@
{ config, pkgs, ... }:
{
services.syncthing = {
enable = true;
openDefaultPorts = true;
user = "brimlock";
group = "users";
dataDir = "/home/brimlock/syncthing";
configDir = "/home/brimlock/.config/syncthing";
settings = {
/* gui = {
user = "brimlock";
};*/
devices = {
"dagger" = { id = "TODPOIO-CEK5N7S-I2X6PLL-YZ4NVEA-L4QRN4Y-7R4FR46-53S2EC2-C7AEAA4-ID-GOES-HERE"; };
};
folders = {
"Sync" = {
path = "/home/brimlock/Sync";
devices = [ "dagger" ];
};
};
};
};
}