Compare commits

..

16 commits

Author SHA1 Message Date
bdb287e492 remove containers from other machines 2026-02-10 15:23:47 +01:00
7bf6768323 merge 2026-02-10 15:20:30 +01:00
ada4538ac8 merge 2026-02-10 15:18:38 +01:00
8aab959e42 idk I fixed some stuff 2026-02-10 15:17:32 +01:00
4c66c514a3 runs on prod now :) 2026-02-10 01:07:35 +01:00
fde1d41bb8 add acme shit 2026-02-09 14:38:02 +01:00
d7812f37c3 Merge branch 'main' into containers 2026-02-09 14:11:22 +01:00
a6bff8a467 gonna deploy now 2026-02-09 13:45:20 +01:00
c340cf4ff3 add public server 2026-02-09 13:19:41 +01:00
7019a80883 finally works 2026-02-09 13:09:23 +01:00
18f05807d2 Merge branch 'main' into containers 2026-01-19 22:24:31 +01:00
047940d0db Merge branch 'main' into containers 2026-01-19 22:15:42 +01:00
423bfff09d idk 2026-01-02 23:09:16 +01:00
02eb92a443 forgejo works now but vaultwarden is fucky 2025-12-29 01:45:04 +01:00
f1b3559434 Foregejo containers fully operational 2025-12-25 13:11:54 +01:00
2de1a62d2f init 2025-12-23 19:46:22 +01:00
9 changed files with 448 additions and 13 deletions

View file

@ -1,4 +1,6 @@
{...}: {
{config, ...}: let
username = config.horseman.username;
in {
imports = [
../../modules
];
@ -6,6 +8,15 @@
config.horseman = {
users.default.enable = true;
containers = {
enable = true;
backupDir = "/home/${username}/backups";
nginx.enable = true;
vaultwarden.enable = true;
forgejo.enable = true;
};
base = {
nix.enable = true;
locale.enable = true;

View file

@ -6,7 +6,7 @@
}: let
inherit (lib) mkEnableOption mkIf;
cfg = config.horseman.base.secrets;
secretFile = path: ../../secrets/${path};
secretFile = path: ../../secrets/${path}.age;
username = config.horseman.username;
in {
options = {
@ -19,38 +19,45 @@ in {
environment.systemPackages = [pkgs.ragenix];
age.secrets = {
wifi.file = secretFile "wifi.age";
wifi.file = secretFile "wifi";
personalSSHpub = {
file = secretFile "ssh/id_personal.pub.age";
file = secretFile "ssh/id_personal.pub";
owner = username;
group = "users";
path = "/home/horseman/.ssh/id_ed25519.pub";
path = "/home/${username}/.ssh/id_ed25519.pub";
};
personalSSH = {
file = secretFile "ssh/id_personal.age";
file = secretFile "ssh/id_personal";
owner = username;
group = "users";
path = "/home/horseman/.ssh/id_ed25519";
path = "/home/${username}/.ssh/id_ed25519";
};
githubSSHpub = {
file = secretFile "ssh/id_github.pub.age";
file = secretFile "ssh/id_github.pub";
owner = username;
group = "users";
path = "/home/horseman/.ssh/id_github.pub";
path = "/home/${username}/.ssh/id_github.pub";
};
githubSSH = {
file = secretFile "ssh/id_github.age";
file = secretFile "ssh/id_github";
owner = username;
group = "users";
path = "/home/horseman/.ssh/id_github";
path = "/home/${username}/.ssh/id_github";
};
sshConfig = {
file = secretFile "ssh/config.age";
file = secretFile "ssh/config";
owner = username;
group = "users";
path = "/home/horseman/.ssh/config";
path = "/home/${username}/.ssh/config";
};
forgejo-secret = {
file = secretFile "containers/forgejo-secret";
path = "/run/forgejo-secrets/secret";
symlink = false;
mode = "444";
};
};
};

View file

@ -0,0 +1,34 @@
{
config,
lib,
...
}: let
inherit (lib) mkIf mkEnableOption mkOption types;
cfg = config.horseman.containers;
in {
imports = [
./nginx.nix
./forgejo.nix
./vaultwarden.nix
];
options = {
horseman.containers = {
enable = mkEnableOption "Containers";
backupDir = mkOption {
type = types.str;
};
};
};
config = mkIf cfg.enable {
networking.nat = {
enable = true;
# Use "ve-*" when using nftables instead of iptables
internalInterfaces = ["ve-+"];
externalInterface = "enp2s0";
# Lazy IPv6 connectivity for the container
enableIPv6 = true;
};
};
}

View file

@ -0,0 +1,185 @@
{
inputs,
outputs,
lib,
config,
pkgs,
...
}: let
inherit (lib) types mkOption mkEnableOption mkIf;
cfg = config.horseman.containers.forgejo;
username = config.horseman.username;
BACKUP_DIR = config.horseman.containers.backupDir;
DATA_DIR = "/home/${username}/backups/volumes/forgejo";
in {
options = {
horseman.containers.forgejo = {
enable = mkEnableOption "forgejo containers";
port = mkOption {
default = 3000;
type = types.int;
};
sshPort = mkOption {
default = 34916;
type = types.int;
};
url = mkOption {
default = "https://git.koendev.nl";
type = types.str;
};
};
};
config = mkIf cfg.enable {
systemd.timers."backup-forgejo" = {
wantedBy = ["timers.target"];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
};
};
environment.systemPackages = [pkgs.gnutar];
systemd.services."backup-forgejo" = {
script = ''
cd ${BACKUP_DIR}
${pkgs.gnutar}/bin/tar -cf forgejo-$(date +'%Y-%m-%d').tar ${DATA_DIR}
'';
serviceConfig = {
User = "root";
};
};
containers.forgejoRunner = {
autoStart = true;
privateNetwork = true;
hostAddress = "192.168.100.2";
localAddress = "192.168.100.102";
bindMounts = {
"/var/lib/secrets" = {
hostPath = "/run/forgejo-secrets";
isReadOnly = true;
};
};
config = {
config,
pkgs,
...
}: let
configFile = pkgs.writeText "runner.yml" ''
runner:
labels:
- "self-hosted:host"
'';
in {
environment.systemPackages = with pkgs; [
forgejo-runner
];
users.groups.runner = {};
users.users.runner = {
isNormalUser = true;
group = "runner";
};
systemd.services.startup = {
script = ''
cd ${config.users.users.runner.home}
${pkgs.forgejo-runner}/bin/forgejo-runner create-runner-file --instance ${cfg.url} --secret $(cat /var/lib/secrets/secret) --name runner
sleep 10
${pkgs.forgejo-runner}/bin/forgejo-runner daemon --config ${configFile}
'';
serviceConfig.User = "runner";
wantedBy = ["multi-user.target"];
};
system.stateVersion = "23.11";
};
};
containers.forgejo = {
autoStart = true;
privateNetwork = true;
hostAddress = "192.168.100.3";
localAddress = "192.168.100.103";
bindMounts = {
"/var/lib/forgejo" = {
hostPath = DATA_DIR;
isReadOnly = false;
};
"/var/lib/secrets" = {
hostPath = "/run/forgejo-secrets";
isReadOnly = true;
};
};
config = {
config,
pkgs,
...
}: {
environment.systemPackages = [pkgs.forgejo];
services.openssh = {
enable = true;
ports = [cfg.sshPort];
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
# AllowUsers = ["git"];
};
};
services.forgejo = {
enable = true;
stateDir = "/var/lib/forgejo";
settings = {
server = {
HTTP_PORT = cfg.port;
SSH_PORT = cfg.sshPort;
ROOT_URL = cfg.url;
};
session = {
COOKIE_SECURE = true;
};
service = {
DISABLE_REGISTRATION = true;
};
};
};
systemd.services.startup = {
script = ''
cd ${config.users.users.forgejo.home}
${pkgs.forgejo}/bin/forgejo forgejo-cli actions register --name runner --secret $(cat /var/lib/secrets/secret) --config ${config.services.forgejo.stateDir}/custom/conf/app.ini
'';
serviceConfig.User = "forgejo";
wantedBy = ["multi-user.target"];
};
networking = {
firewall = {
enable = true;
allowedTCPPorts = [cfg.port cfg.sshPort];
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
useHostResolvConf = lib.mkForce false;
};
system.stateVersion = "23.11";
};
};
};
}

View file

@ -0,0 +1,83 @@
{
lib,
config,
...
}: let
inherit (lib) mkEnableOption mkIf mkOption types;
cfg = config.horseman.containers.nginx;
in {
options = {
horseman.containers.nginx = {
enable = mkEnableOption "nginx container";
domain = mkOption {
type = types.str;
default = "koendev.nl";
};
};
};
config = mkIf cfg.enable {
security.acme = {
acceptTerms = true;
defaults.email = "koen.de.ruiter@hotmail.com";
};
services.fail2ban.enable = true;
services.nginx = {
enable = true;
streamConfig = ''
server {
listen ${toString config.horseman.containers.forgejo.sshPort};
proxy_pass ${config.containers.forgejo.localAddress}:${toString config.horseman.containers.forgejo.sshPort};
}
'';
virtualHosts = {
"${cfg.domain}" = {
forceSSL = true;
enableACME = true;
root = "/var/www/portfolio";
default = true;
extraConfig = ''
error_page 404 /404.html;
'';
};
"public.${cfg.domain}" = {
forceSSL = true;
enableACME = true;
root = "/var/www/public";
};
"git.${cfg.domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://${config.containers.forgejo.localAddress}:${toString config.horseman.containers.forgejo.port}";
};
};
"vault.${cfg.domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://${config.containers.vaultwarden.localAddress}:${toString config.horseman.containers.vaultwarden.port}";
};
};
};
};
networking = {
firewall = {
enable = true;
allowedTCPPorts = [80 443 config.horseman.containers.forgejo.sshPort];
};
};
};
}

View file

@ -0,0 +1,95 @@
{
inputs,
outputs,
lib,
config,
pkgs,
...
}: let
inherit (lib) types mkOption mkEnableOption mkIf;
cfg = config.horseman.containers.vaultwarden;
username = config.horseman.username;
BACKUP_DIR = config.horseman.containers.backupDir;
DATA_DIR = "/home/${username}/backups/volumes/vaultwarden";
in {
options = {
horseman.containers.vaultwarden = {
enable = mkEnableOption "Password manager";
port = mkOption {
default = 3000;
type = types.int;
};
url = mkOption {
default = "https://vault.koendev.nl";
type = types.str;
};
};
};
config = mkIf cfg.enable {
systemd.timers."backup-vaultwarden" = {
wantedBy = ["timers.target"];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
};
};
environment.systemPackages = [pkgs.gnutar];
systemd.services."backup-vaultwarden" = {
script = ''
cd ${BACKUP_DIR}
${pkgs.gnutar}/bin/tar -cf vaultwarden-$(date +'%Y-%m-%d').tar ${DATA_DIR}
'';
serviceConfig = {
User = "root";
};
};
containers.vaultwarden = {
autoStart = true;
privateNetwork = true;
hostAddress = "192.168.100.4";
localAddress = "192.168.100.104";
bindMounts = {
"/var/lib/bitwarden_rs" = {
hostPath = DATA_DIR;
isReadOnly = false;
};
};
config = {
config,
pkgs,
...
}: {
environment.systemPackages = with pkgs; [
vaultwarden.webvault
];
services.vaultwarden = {
enable = true;
config = {
ROCKET_PORT = cfg.port;
ROCKET_ADDRESS = "0.0.0.0";
WEB_VAULT_FOLDER = "${pkgs.vaultwarden.webvault}/share/vaultwarden/vault";
};
};
networking = {
firewall = {
enable = true;
allowedTCPPorts = [cfg.port];
};
useHostResolvConf = lib.mkForce false;
};
system.stateVersion = "23.11";
};
};
};
}

View file

@ -12,6 +12,7 @@ in {
./base
./boot
./catppuccin
./containers
./hardware
./network
./timers

View file

@ -17,6 +17,7 @@ let
"ssh/id_github"
"ssh/id_github.pub"
"ssh/config"
"containers/forgejo-secret"
];
attrs = map (secret: {"secrets/${secret}.age".publicKeys = all;}) secrets;
in

View file

@ -0,0 +1,18 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IC9tczZkdyAvWjRI
VkpQNWpZNHdiZm9jVlZvcTYxS04wUk1hTWtmdWRXL2dydGwxc3pVCklSOWZYNThu
aVBSeDBwRldwTjVzT0VOaG9kNnV5SWJnT2M1YXVRSjUwUFkKLT4gc3NoLWVkMjU1
MTkgZ1BJZFpBIExmTUxudEFaR21CQzg5ejlUaXRoQW5ORmVqcUlRd1o2L0pZbTd5
UVBIeWcKZWVSV3k4bHZqV3pDaDMxYzBnZW9FL085TG14bkl0UlZoQ25CbW9iVENv
RQotPiBzc2gtZWQyNTUxOSBXeUlGekEgY2Zkd0VaZmxRaVV4cXBlRnNHeDMyUFFV
YVVzZlF2SXFjak5LREZINFRTMAp6dmFKOTd5eUMrczZ0WUU2T3hER3lkSHlTTGZj
U1k4ZVV1THJMK0RSd21zCi0+IHNzaC1lZDI1NTE5IGRiT2VoQSB0WkJpSkZHZ1BM
QitLdG9SdDdjckxVa0dxQ2dmQlNGekVITlllN2R3OWxZCmt2Zk5VSjNTdnB4Z2ln
TnExNytuZ2FtVE83NWZWcm1Fd25MS1NEL3JsbzgKLT4gc3NoLWVkMjU1MTkgdHYv
Q3pnIFVDMU9Kbld0aHFia3FmTEs2aGF2THdaSk1Ec2h2WWlMVjZvUkNHTFpCR1EK
NkR6R2JaZkZtbitBMmk1UjRFS3FFZ293bFhDUWxmR2M0ZHFoSVRGV2E1ZwotPiAn
eCFtQ3htLWdyZWFzZQp4VFZWeTlDNWlsNDI5WWlPTzNGbQotLS0gRmZIdXk3UUVw
ZEJjOGdnVVdlWWN5Y0VxaUJORG0ycTBQdVFGVGw1RVpZdwqD8VD14PUaG2u0/h9o
6VeX+m3nJkJgsXUkGPskTHHEc+1NaZ9MQM5dXzrmjfVHBT7N27bDcYlGG2RIfehC
Xz5jRZwSTG58wzt9
-----END AGE ENCRYPTED FILE-----