self-host-playbook/starter/configuration.nix
2025-03-06 08:19:24 +01:00

198 lines
5.0 KiB
Nix

{
lib,
pkgs,
...
}:
# Read configuration from JSON
let
jsonConfig = builtins.fromJSON (builtins.readFile ./config.json);
in {
imports = [
./disko-config.nix
./hardware-configuration.nix
];
# Enable flakes and nix commands
nix = {
settings = {
experimental-features = ["nix-command" "flakes"];
# Enable automatic garbage collection
auto-optimise-store = true;
trusted-users = [jsonConfig.username];
};
# Automatic cleanup of old generations
gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
};
# Boot configuration
boot.loader.grub = {
enable = true;
devices = [jsonConfig.rootDevice];
efiSupport = true;
efiInstallAsRemovable = true;
};
# Networking
networking = {
firewall = {
enable = true;
# Only allow necessary ports
allowedTCPPorts = [80 443 2222]; # HTTP, HTTPS, and SSH
};
};
environment.etc = {
environment-files = {
source = pkgs.copyPathToStore ./env;
};
};
# System packages
environment.systemPackages = with pkgs; [
# System utilities
neovim
git
# Docker tools
docker
docker-compose
];
# Enable Docker with recommended settings
virtualisation.docker = {
enable = true;
# Enable docker daemon to start on boot
enableOnBoot = true;
# Use overlay2 storage driver
storageDriver = "overlay2";
# Enable live restore
liveRestore = true;
};
# Services configuration
services = {
# SSH server configuration
openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
# Additional security settings
MaxAuthTries = 3;
LoginGraceTime = "30s";
};
ports = [2222];
};
# Caddy configuration with security headers
caddy = {
enable = true;
virtualHosts = {
"${jsonConfig.domains.portainer}" = {
extraConfig = ''
reverse_proxy localhost:9000
header {
# Security headers
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
Referrer-Policy "strict-origin-when-cross-origin"
}
'';
};
"${jsonConfig.domains.n8n}" = {
extraConfig = ''
reverse_proxy localhost:5678
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
Referrer-Policy "strict-origin-when-cross-origin"
}
'';
};
"${jsonConfig.domains.baserow}" = {
extraConfig = ''
reverse_proxy localhost:3000
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
Referrer-Policy "strict-origin-when-cross-origin"
}
'';
};
};
};
};
# User configuration
users.users.${jsonConfig.username} = {
isNormalUser = true;
extraGroups = ["wheel" "docker"];
hashedPassword = jsonConfig.hashedPassword;
openssh.authorizedKeys.keys = [jsonConfig.sshKey];
# Set default shell to bash
shell = pkgs.bash;
};
# Container configurations
virtualisation.oci-containers = {
backend = "docker";
containers = {
"portainer" = {
image = "docker.io/portainer/portainer-ce:latest";
ports = ["127.0.0.1:9000:9000"];
volumes = [
"/etc/localtime:/etc/localtime:ro"
"/var/run/docker.sock:/var/run/docker.sock:ro"
"portainer_data:/data"
];
extraOptions = [
"--network=web"
];
};
"n8n" = {
image = "docker.io/n8nio/n8n:latest";
environmentFiles = ["/etc/environment-files/n8n.env"];
ports = ["127.0.0.1:5678:5678"];
volumes = ["n8n_data:/home/node/.n8n"];
extraOptions = ["--network=web"];
};
"baserow" = {
image = "docker.io/baserow/baserow:latest";
environmentFiles = ["/etc/environment-files/baserow.env"];
ports = ["127.0.0.1:3000:80"];
volumes = ["baserow_data:/baserow/data"];
extraOptions = ["--network=web"];
};
};
};
systemd.services.docker-network-web = {
description = "Create Docker Network Web";
requires = ["docker.service"];
after = ["docker.service"];
wantedBy = ["multi-user.target"];
# Run on startup if network doesn't exist
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
if ! /run/current-system/sw/bin/docker network ls | grep -q 'web'; then
/run/current-system/sw/bin/docker network create web
fi
'';
};
# System state version (do not change)
system.stateVersion = "24.11";
}