152 lines
4.9 KiB
Nix
152 lines
4.9 KiB
Nix
#
|
||
# Server module — import this instead of configuration_server.nix + manual virtualisation imports.
|
||
#
|
||
# Usage in hosts/<hostname>/default.nix:
|
||
#
|
||
# imports = [
|
||
# ./hardware-configuration.nix
|
||
# ../../modules/server
|
||
# ];
|
||
#
|
||
# myServer.virtualisation.enable = true;
|
||
# myServer.virtualisation.cpu = "amd"; # amd | intel | none (default)
|
||
#
|
||
# myServer.sshPort = 2220; # default
|
||
# myServer.fail2ban.enable = true;
|
||
#
|
||
# myServer.extraSystemPackages = with pkgs; [ some-tool ];
|
||
#
|
||
|
||
{ config, lib, pkgs, user, ... }:
|
||
|
||
let
|
||
cfg = config.myServer;
|
||
in
|
||
{
|
||
# ── Options ──────────────────────────────────────────────────────────────
|
||
|
||
options.myServer = with lib; {
|
||
|
||
uid = mkOption {
|
||
type = types.int;
|
||
default = 3000;
|
||
description = "UID for the server user.";
|
||
};
|
||
|
||
sshPort = mkOption {
|
||
type = types.port;
|
||
default = 2220;
|
||
description = "Port openssh listens on.";
|
||
};
|
||
|
||
sudoRequiresPassword = mkOption {
|
||
type = types.bool;
|
||
default = true;
|
||
description = "Whether wheel users must enter a password for sudo.";
|
||
};
|
||
|
||
autoUpgrade.enable = mkOption {
|
||
type = types.bool;
|
||
default = true;
|
||
description = "Enable automatic NixOS upgrades (inherits flake URL from configuration_common.nix).";
|
||
};
|
||
|
||
virtualisation = {
|
||
enable = mkEnableOption "container/VM stack (podman with docker-compat, KVM tuning)";
|
||
cpu = mkOption {
|
||
type = types.enum [ "amd" "intel" "none" ];
|
||
default = "none";
|
||
description = "CPU type — selects KVM kernel parameters when virtualisation is enabled.";
|
||
};
|
||
};
|
||
|
||
extraGroups = mkOption {
|
||
type = types.listOf types.str;
|
||
default = [];
|
||
description = "Additional groups for the server user beyond the defaults.";
|
||
};
|
||
|
||
extraSystemPackages = mkOption {
|
||
type = types.listOf types.package;
|
||
default = [];
|
||
description = "Additional system packages specific to this host.";
|
||
};
|
||
|
||
fail2ban = {
|
||
enable = mkEnableOption "fail2ban intrusion prevention";
|
||
};
|
||
|
||
};
|
||
|
||
# ── Configuration ────────────────────────────────────────────────────────
|
||
|
||
config = lib.mkMerge [
|
||
|
||
# ── Base server config ────────────────────────────────────────────────
|
||
{
|
||
users.users.${user} = {
|
||
isNormalUser = true;
|
||
uid = cfg.uid;
|
||
extraGroups = [ "wheel" "networkmanager" "kvm" "libvirtd" ] ++ cfg.extraGroups;
|
||
};
|
||
|
||
security.sudo.wheelNeedsPassword = cfg.sudoRequiresPassword;
|
||
|
||
environment.systemPackages = with pkgs; [
|
||
ffmpeg
|
||
smartmontools
|
||
htop
|
||
] ++ cfg.extraSystemPackages;
|
||
|
||
services.openssh = {
|
||
ports = [ cfg.sshPort ];
|
||
openFirewall = true;
|
||
};
|
||
|
||
nix.extraOptions = ''
|
||
keep-outputs = true
|
||
keep-derivations = true
|
||
'';
|
||
|
||
system.autoUpgrade.enable = cfg.autoUpgrade.enable;
|
||
}
|
||
|
||
# ── Virtualisation (podman/docker-compat) ─────────────────────────────
|
||
(lib.mkIf cfg.virtualisation.enable {
|
||
virtualisation.podman = {
|
||
enable = true;
|
||
autoPrune.enable = true;
|
||
dockerCompat = true;
|
||
};
|
||
|
||
users.groups.docker.members = [ user ];
|
||
})
|
||
|
||
# ── KVM – AMD ─────────────────────────────────────────────────────────
|
||
(lib.mkIf (cfg.virtualisation.enable && cfg.virtualisation.cpu == "amd") {
|
||
boot.extraModprobeConfig = ''
|
||
options kvm_amd nested=0 avic=1 npt=1
|
||
'';
|
||
})
|
||
|
||
# ── KVM – Intel ───────────────────────────────────────────────────────
|
||
(lib.mkIf (cfg.virtualisation.enable && cfg.virtualisation.cpu == "intel") {
|
||
boot.extraModprobeConfig = ''
|
||
options kvm_intel nested=1
|
||
options kvm_intel emulate_invalid_guest_state=0
|
||
options kvm ignore_nsrs=1
|
||
'';
|
||
})
|
||
|
||
# ── Fail2ban ──────────────────────────────────────────────────────────
|
||
(lib.mkIf cfg.fail2ban.enable {
|
||
services.fail2ban = {
|
||
enable = true;
|
||
maxretry = 5;
|
||
jails.DEFAULT.settings.findtime = "15m";
|
||
};
|
||
})
|
||
|
||
];
|
||
}
|