nixos-vps/configuration.nix
ashisgreat22 a47e29ff70 feat(config): enable Netdata monitoring
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 01:45:51 +00:00

252 lines
6.6 KiB
Nix

{ config, pkgs, lib, ... }: {
imports = [
./hardware-configuration.nix
];
# Workaround for https://github.com/NixOS/nix/issues/8502
services.logrotate.checkConfig = false;
boot.tmp.cleanOnBoot = true;
zramSwap = {
enable = true;
memoryPercent = 50;
algorithm = "zstd";
};
networking.hostName = "nixos";
networking.domain = "";
# === IPv6 ===
networking.interfaces.ens6.ipv6.addresses = [{
address = "2a01:239:484:9d00::1";
prefixLength = 80;
}];
networking.defaultGateway6 = {
address = "fe80::1";
interface = "ens6";
};
# === Firewall ===
networking.firewall = {
enable = true;
allowedTCPPorts = [ 22 ]; # SSH (80/443 added by nginx module)
allowPing = false;
};
# === SSH Hardening ===
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
KexAlgorithms = [
"sntrup761x25519-sha512@openssh.com"
"curve25519-sha256"
"curve25519-sha256@libssh.org"
];
Ciphers = [
"chacha20-poly1305@openssh.com"
"aes256-gcm@openssh.com"
];
Macs = [
"hmac-sha2-512-etm@openssh.com"
"hmac-sha2-256-etm@openssh.com"
"umac-128-etm@openssh.com"
];
};
};
# === User Account ===
users.users.ashie = {
isNormalUser = true;
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII0OjmlFPbz/H0sv+Y7L+rHR7KCD9lL7HIevEnqy48qH ashisgreat22@github.com"
];
};
# === Sudo without password for wheel group ===
security.sudo.wheelNeedsPassword = false;
# === SOPS (Secrets Management) ===
sops = {
defaultSopsFile = ./secrets/secrets.yaml;
defaultSopsFormat = "yaml";
age.keyFile = "/var/lib/sops-nix/key.txt";
# Generate with: nix-shell -p age --run "age-keygen -o key.txt"
# Then add the public key to .sops.yaml
};
# === System Maintenance & Updates ===
myModules.system = {
mainUser = "ashie";
autoUpdate = {
enable = true;
allowReboot = false; # Set to true to allow automatic reboots for kernel updates
};
};
system.stateVersion = "23.11";
environment.systemPackages = with pkgs; [
vim
wget
git
nano
kitty.terminfo
claude-code
htop
tmux
headscale
];
nix.settings.experimental-features = [ "nix-command" "flakes" ];
# Allow unfree
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
"open-webui"
"claude-code"
];
# === SearXNG ===
myModules.searxng = {
enable = true;
port = 8888;
domain = "search.ashisgreat.xyz"; # Change to your domain
instanceName = "Ashie Search";
};
# === Nginx Reverse Proxy ===
myModules.nginx = {
enable = true;
email = "info@ashisgreat.xyz";
rateLimit = {
enable = true;
requests = 10;
burst = 20;
};
domains = {
"search.ashisgreat.xyz" = {
port = 8888;
# SearXNG sets its own CSP in settings.yml — omit at Nginx level to avoid conflicts
contentSecurityPolicy = null;
# Search engine — slightly more permissive for bot traffic
rateLimit.requests = 20;
rateLimit.burst = 40;
};
};
};
# === AdGuard Home (DoT) ===
myModules.adguard = {
enable = true;
domain = "dns.ashisgreat.xyz";
};
# === OpenClaw ===
myModules.openclaw-podman = {
enable = true;
superpowers.enable = true;
port = 18789;
domain = "openclaw.ashisgreat.xyz";
};
# OpenClaw secrets
sops.secrets.openclaw_discord_token = { };
sops.secrets.openclaw_zai_api_key = { };
sops.secrets.openclaw_brave_api_key = { };
sops.secrets.github_token = { };
sops.secrets.forgejo_url = { };
sops.secrets.forgejo_token = { };
sops.secrets.forgejo_user = { };
sops.templates."openclaw.env" = {
content = ''
OPENCLAW_GATEWAY_TOKEN=local_bypass_token_for_openclaw_12345
DISCORD_TOKEN=${config.sops.placeholder.openclaw_discord_token}
ZAI_API_KEY=${config.sops.placeholder.openclaw_zai_api_key}
BRAVE_API_KEY=${config.sops.placeholder.openclaw_brave_api_key}
GITHUB_TOKEN=${config.sops.placeholder.github_token}
FORGEJO_URL=${config.sops.placeholder.forgejo_url}
FORGEJO_TOKEN=${config.sops.placeholder.forgejo_token}
FORGEJO_USER=${config.sops.placeholder.forgejo_user}
'';
};
# === Vaultwarden ===
myModules.vaultwarden = {
enable = true;
domain = "vault.ashisgreat.xyz";
signupAllowed = false;
};
# === Forgejo (Self-hosted Git) ===
myModules.forgejo = {
enable = true;
domain = "git.ashisgreat.xyz";
disableRegistration = true; # Admin only
runner = {
enable = true;
tokenFile = config.sops.templates."forgejo-runner.env".path;
};
};
# Forgejo runner secrets
sops.secrets.forgejo_runner_token = { };
sops.templates."forgejo-runner.env" = {
content = ''
TOKEN=${config.sops.placeholder.forgejo_runner_token}
'';
};
# === CrowdSec ===
myModules.crowdsec = {
enable = true;
enableBouncer = false; # Temporarily disabled due to StateDirectory conflict
};
# === Headscale (Self-hosted Tailscale) ===
myModules.headscale = {
enable = true;
domain = "vpn.ashisgreat.xyz";
# OIDC not enabled by default — use pre-shared auth keys:
# headscale apikeys create
# tailscale up --login-server=https://vpn.ashisgreat.xyz --authkey=<key>
#
# To enable OIDC login (Google, GitHub, etc.):
# oidc.enable = true;
# oidc.issuer = "https://accounts.google.com";
# oidc.clientId = "your-client-id";
# oidc.clientSecret = config.sops.placeholder.headscale_oidc_secret;
# And add headscale_oidc_secret to your secrets.yaml
};
# === Netdata (System Monitoring) ===
myModules.netdata = {
enable = true;
domain = "netdata.ashisgreat.xyz";
};
# === Tailscale Client ===
services.tailscale.enable = true;
# === OpenWeb UI ===
myModules.open-webui = {
enable = true;
port = 8081;
domain = "ai.ashisgreat.xyz";
ollamaUrl = "http://100.64.0.1:11434";
};
# === Backups (Restic + B2) ===
myModules.backup = {
enable = true;
repository = "b2:nixos-vps-backup2";
paths = [
"/var/lib/vaultwarden" # Vaultwarden SQLite DB and attachments
"/var/backup/vaultwarden" # Vaultwarden built-in backup snapshots
"/var/lib/private/AdGuardHome" # AdGuard Home config, filters, query logs
"/var/lib/sops-nix" # SOPS age key (critical — decrypts all secrets)
"/var/lib/crowdsec" # CrowdSec state, decisions, custom parsers
];
};
}