Added the rest of the configuration. Still some things to add.
This commit is contained in:
@@ -1,2 +1,30 @@
|
|||||||
# numbus-server-module
|
# ☁️ Numbus Server: Your Personal Cloud, Simplified 🚀
|
||||||
|
|
||||||
|
Welcome to the **Numbus Server** project!
|
||||||
|
|
||||||
|
⚠️ This repository contains the NixOS module that configures the numbus server. **Please head to https://gittea.dev/numbus/numbus-server to get more information and installation instructions.**
|
||||||
|
|
||||||
|
This repository provides a complete NixOS configuration to deploy a personal home server with a rich set of services in minutes. Our goal is to make self-hosting accessible to everyone, allowing you to take back control of your data with a solution that is easy to manage and highly reliable.
|
||||||
|
|
||||||
|
## 🛠️ Key Technologies
|
||||||
|
|
||||||
|
- **NixOS:** A declarative Linux distribution that makes system management a breeze.
|
||||||
|
- **Nix Flakes:** For reproducible builds and dependency management.
|
||||||
|
- **Numbus Server NixOS module:** To make user's configuration simpler.
|
||||||
|
- **Podman:** To run containerized services with ease.
|
||||||
|
- **Traefik:** A modern reverse proxy to access services securely.
|
||||||
|
- **Sops-nix:** For a secure and convenient way of managing secrets.
|
||||||
|
- **NixOS-anywhere:** For a seamless initial deployment to any machine.
|
||||||
|
- **Disko:** For a declarative and predictable disk partitioning.
|
||||||
|
|
||||||
|
## 🔧 Numbus Server NixOS Module
|
||||||
|
|
||||||
|
This repository contains the code of this module. This modules contains the **complex NixOS configuration** : networking, user creation, container management, secrets provisioning, power settings, and much more. Since all the **complexity** of the configuration is contained in this module, this allows the end user configuration to be very **simple and clean**.
|
||||||
|
|
||||||
|
## 🤝 Contributing
|
||||||
|
|
||||||
|
Contributions are welcome! If you have any ideas, suggestions, or bug reports, please open an issue or submit a pull request.
|
||||||
|
|
||||||
|
## 📄 License
|
||||||
|
|
||||||
|
This project is licensed under the AGPLv3. See the [LICENSE](LICENSE) file for details.
|
||||||
+6
-1
@@ -2,7 +2,12 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./global.nix
|
./hardware/default.nix
|
||||||
|
./mail/default.nix
|
||||||
|
./misc/default.nix
|
||||||
|
./networking/default.nix
|
||||||
|
./packages/default.nix
|
||||||
./services/default.nix
|
./services/default.nix
|
||||||
|
./global.nix
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
boot.initrd.systemd.enable = true;
|
||||||
|
boot.loader.systemd-boot.enable = true;
|
||||||
|
boot.loader.efi.canTouchEfiVariables = true;
|
||||||
|
|
||||||
|
boot.kernel.sysctl = {
|
||||||
|
"vm.overcommit_memory" = 1;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
hardware.enableRedistributableFirmware = true;
|
||||||
|
hardware.cpu.intel.updateMicrocode = true;
|
||||||
|
hardware.cpu.amd.updateMicrocode = true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./boot.nix
|
||||||
|
./cpu.nix
|
||||||
|
./disks.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,322 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.numbus.hardware;
|
||||||
|
|
||||||
|
mkDataDisk = idx: device: {
|
||||||
|
name = "content-${toString idx}";
|
||||||
|
value = {
|
||||||
|
type = "disk";
|
||||||
|
device = device;
|
||||||
|
content = {
|
||||||
|
type = "gpt";
|
||||||
|
partitions = {
|
||||||
|
luks = {
|
||||||
|
size = "100%";
|
||||||
|
content = {
|
||||||
|
type = "luks";
|
||||||
|
name = "crypted-content-${toString idx}";
|
||||||
|
initrdUnlock = false;
|
||||||
|
settings = {
|
||||||
|
keyFile = "/etc/secrets/disks/content-${toString idx}";
|
||||||
|
allowDiscards = true;
|
||||||
|
crypttabExtraOpts = [ "nofail" ];
|
||||||
|
};
|
||||||
|
content = {
|
||||||
|
type = "filesystem";
|
||||||
|
format = cfg.dataDisksFilesystem;
|
||||||
|
mountpoint = "/mnt/content-${toString idx}";
|
||||||
|
mountOptions = [ "nofail" "noauto" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mkParityDisk = idx: device: {
|
||||||
|
name = "parity-${toString idx}";
|
||||||
|
value = {
|
||||||
|
type = "disk";
|
||||||
|
device = device;
|
||||||
|
content = {
|
||||||
|
type = "gpt";
|
||||||
|
partitions = {
|
||||||
|
luks = {
|
||||||
|
size = "100%";
|
||||||
|
content = {
|
||||||
|
type = "luks";
|
||||||
|
name = "crypted-parity-${toString idx}";
|
||||||
|
initrdUnlock = false;
|
||||||
|
settings = {
|
||||||
|
keyFile = "/etc/secrets/disks/parity-${toString idx}";
|
||||||
|
allowDiscards = true;
|
||||||
|
crypttabExtraOpts = [ "nofail" ];
|
||||||
|
};
|
||||||
|
content = {
|
||||||
|
type = "filesystem";
|
||||||
|
format = cfg.parityDisksFilesystem;
|
||||||
|
mountpoint = "/mnt/parity-${toString idx}";
|
||||||
|
mountOptions = [ "nofail" "noauto" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
isMirror = length cfg.bootDisksList > 1;
|
||||||
|
|
||||||
|
bootDisksConfig = if isMirror then {
|
||||||
|
mdadm = {
|
||||||
|
boot = {
|
||||||
|
type = "mdadm";
|
||||||
|
level = 1;
|
||||||
|
metadata = "1.2";
|
||||||
|
content = {
|
||||||
|
type = "filesystem";
|
||||||
|
format = "vfat";
|
||||||
|
mountpoint = "/boot";
|
||||||
|
mountOptions = [ "umask=0077" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
disk = listToAttrs (imap1 (i: device: {
|
||||||
|
name = "boot-${toString i}";
|
||||||
|
value = {
|
||||||
|
type = "disk";
|
||||||
|
device = device;
|
||||||
|
content = {
|
||||||
|
type = "gpt";
|
||||||
|
partitions = {
|
||||||
|
ESP = {
|
||||||
|
size = "1G";
|
||||||
|
type = "EF00";
|
||||||
|
content = {
|
||||||
|
type = "mdraid";
|
||||||
|
name = "boot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
luks = {
|
||||||
|
size = "100%";
|
||||||
|
content = {
|
||||||
|
type = "luks";
|
||||||
|
name = "crypted-boot-${toString i}";
|
||||||
|
settings = {
|
||||||
|
allowDiscards = true;
|
||||||
|
keyFile = "/etc/secrets/disks/boot-${toString i}";
|
||||||
|
};
|
||||||
|
content = {
|
||||||
|
type = "lvm_pv";
|
||||||
|
vg = "pool";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}) cfg.bootDisksList);
|
||||||
|
} else {
|
||||||
|
disk = {
|
||||||
|
"boot-1" = {
|
||||||
|
type = "disk";
|
||||||
|
device = head cfg.bootDisksList;
|
||||||
|
content = {
|
||||||
|
type = "gpt";
|
||||||
|
partitions = {
|
||||||
|
ESP = {
|
||||||
|
size = "1G";
|
||||||
|
type = "EF00";
|
||||||
|
content = {
|
||||||
|
type = "filesystem";
|
||||||
|
format = "vfat";
|
||||||
|
mountpoint = "/boot";
|
||||||
|
mountOptions = [ "umask=0077" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
luks = {
|
||||||
|
size = "100%";
|
||||||
|
content = {
|
||||||
|
type = "luks";
|
||||||
|
name = "crypted-boot-1";
|
||||||
|
settings = {
|
||||||
|
keyFile = "/etc/secrets/disks/boot-1";
|
||||||
|
allowDiscards = true;
|
||||||
|
};
|
||||||
|
content = {
|
||||||
|
type = "lvm_pv";
|
||||||
|
vg = "pool";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
lvmConfig = {
|
||||||
|
lvm_vg = {
|
||||||
|
pool = {
|
||||||
|
type = "lvm_vg";
|
||||||
|
lvs = {
|
||||||
|
swap = {
|
||||||
|
size = cfg.swapSize;
|
||||||
|
content = {
|
||||||
|
type = "swap";
|
||||||
|
};
|
||||||
|
} // optionalAttrs isMirror { lvm_type = "mirror"; };
|
||||||
|
snapraid = {
|
||||||
|
size = "1G";
|
||||||
|
content = {
|
||||||
|
type = "filesystem";
|
||||||
|
format = "btrfs";
|
||||||
|
mountpoint = "/mnt/content-0";
|
||||||
|
};
|
||||||
|
} // optionalAttrs isMirror { lvm_type = "mirror"; };
|
||||||
|
root = {
|
||||||
|
size = "100%";
|
||||||
|
content = {
|
||||||
|
type = "btrfs";
|
||||||
|
extraArgs = [ "-f" ];
|
||||||
|
subvolumes = {
|
||||||
|
"/rootfs" = {
|
||||||
|
mountpoint = "/";
|
||||||
|
mountOptions = [ "compress=zstd" "noatime" ];
|
||||||
|
};
|
||||||
|
"/home" = {
|
||||||
|
mountpoint = "/home";
|
||||||
|
mountOptions = [ "compress=zstd" ];
|
||||||
|
};
|
||||||
|
"/nix" = {
|
||||||
|
mountpoint = "/nix";
|
||||||
|
mountOptions = [ "compress=zstd" "noatime" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} // optionalAttrs isMirror { lvm_type = "mirror"; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.numbus.hardware = {
|
||||||
|
dataDisksList = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = [ "/dev/disk/by-id/WD_Blue_ATO431_159Ejz224G0000382b" "/dev/disk/by-id/Seagate_Barracuda_159Ejz224G" ];
|
||||||
|
description = "List by-id path of devices for data disks";
|
||||||
|
};
|
||||||
|
parityDisksList = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = [ "/dev/disk/by-id/WD_Blue_ATO431_159Ejz224G0000382b" "/dev/disk/by-id/Seagate_Barracuda_159Ejz224G" ];
|
||||||
|
description = "List of by-id path of devices for parity disks";
|
||||||
|
};
|
||||||
|
bootDisksList = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = [ "/dev/disk/by-id/nvme_SAMSUNG_MZVPYEHCO_159Ejz224G0000" "/dev/disk/by-id/ata-San_Disk_159Ejz224G" ];
|
||||||
|
description = "List of by-id path of devices for boot disks";
|
||||||
|
};
|
||||||
|
swapSize = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "16G";
|
||||||
|
example = "16G";
|
||||||
|
description = "Size of the swap partition";
|
||||||
|
};
|
||||||
|
dataDisksFilesystem = mkOption {
|
||||||
|
type = types.enum [ "xfs" "ext4" "btrfs" ];
|
||||||
|
default = "xfs";
|
||||||
|
example = "xfs";
|
||||||
|
description = "Filesystem for data disks. Available filesystem options : xfs, ext4, btrfs";
|
||||||
|
};
|
||||||
|
parityDisksFilesystem = mkOption {
|
||||||
|
type = types.enum [ "xfs" "ext4" "btrfs" ];
|
||||||
|
default = "xfs";
|
||||||
|
example = "xfs";
|
||||||
|
description = "Filesystem for parity disks. Available filesystem options : xfs, ext4, btrfs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf (cfg.bootDisksList != []) {
|
||||||
|
disko.devices = mkMerge [
|
||||||
|
bootDisksConfig
|
||||||
|
lvmConfig
|
||||||
|
{
|
||||||
|
disk = listToAttrs (imap1 mkDataDisk cfg.dataDisksList);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
disk = listToAttrs (imap1 mkParityDisk cfg.parityDisksList);
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
services.snapraid = {
|
||||||
|
enable = true;
|
||||||
|
contentFiles = [ "/mnt/content-0/snapraid.content" ] ++
|
||||||
|
(map (i: "/mnt/content-${toString i}/snapraid.content") (range 1 (length cfg.dataDisksList)));
|
||||||
|
parityFiles = map (i: "/mnt/parity-${toString i}/snapraid.parity") (range 1 (length cfg.parityDisksList));
|
||||||
|
dataDisks = listToAttrs (imap1 (i: _: nameValuePair "d${toString i}" "/mnt/content-${toString i}") cfg.dataDisksList);
|
||||||
|
};
|
||||||
|
|
||||||
|
fileSystems."/mnt/data" = {
|
||||||
|
device = "/mnt/content-*";
|
||||||
|
fsType = "fuse.mergerfs";
|
||||||
|
options = [
|
||||||
|
"category.create=ff"
|
||||||
|
"cache.files=partial"
|
||||||
|
"dropcacheonclose=true"
|
||||||
|
"defaults"
|
||||||
|
"noauto"
|
||||||
|
"nofail"
|
||||||
|
"allow_other"
|
||||||
|
"moveonenospc=1"
|
||||||
|
"minfreespace=50G"
|
||||||
|
"func.getattr=newest"
|
||||||
|
"fsname=mergerfs_data"
|
||||||
|
"x-mount.mkdir"
|
||||||
|
"x-systemd.automount"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.mount-disks = {
|
||||||
|
description = "Mount data and parity disks";
|
||||||
|
before = [ "mnt-data.mount" ];
|
||||||
|
requiredBy = [ "mnt-data.mount" ];
|
||||||
|
path = [ pkgs.cryptsetup pkgs.util-linux ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
script = let
|
||||||
|
mountDataDisk = i: ''
|
||||||
|
if [ ! -e /dev/mapper/crypted-content-${toString i} ]; then
|
||||||
|
cryptsetup luksOpen --key-file /etc/secrets/disks/content-${toString i} /dev/disk/by-partlabel/disk-content-${toString i}-luks crypted-content-${toString i}
|
||||||
|
fi
|
||||||
|
mkdir -p /mnt/content-${toString i}
|
||||||
|
if ! mountpoint -q /mnt/content-${toString i}; then
|
||||||
|
mount -t ${cfg.dataDisksFilesystem} /dev/mapper/crypted-content-${toString i} /mnt/content-${toString i}
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
mountParityDisk = i: ''
|
||||||
|
if [ ! -e /dev/mapper/crypted-parity-${toString i} ]; then
|
||||||
|
cryptsetup luksOpen --key-file /etc/secrets/disks/parity-${toString i} /dev/disk/by-partlabel/disk-parity-${toString i}-luks crypted-parity-${toString i}
|
||||||
|
fi
|
||||||
|
mkdir -p /mnt/parity-${toString i}
|
||||||
|
if ! mountpoint -q /mnt/parity-${toString i}; then
|
||||||
|
mount -t ${cfg.parityDisksFilesystem} /dev/mapper/crypted-parity-${toString i} /mnt/parity-${toString i}
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
in ''
|
||||||
|
${concatMapStrings mountDataDisk (range 1 (length cfg.dataDisksList))}
|
||||||
|
${concatMapStrings mountParityDisk (range 1 (length cfg.parityDisksList))}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./smtp.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.numbus.services.mail;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options.numbus.services.mail = {
|
||||||
|
enable = mkEnableOption "Email sending functionality";
|
||||||
|
|
||||||
|
userAddress = mkOption {
|
||||||
|
description = "The address of the user this server will send emails to";
|
||||||
|
type = types.str;
|
||||||
|
example = "user@your-domain.com";
|
||||||
|
};
|
||||||
|
|
||||||
|
adminAddress = mkOption {
|
||||||
|
description = "The address of the admin this server will send emails to";
|
||||||
|
type = types.str;
|
||||||
|
example = "admin@your-domain.com";
|
||||||
|
};
|
||||||
|
|
||||||
|
smtpUsername = mkOption {
|
||||||
|
description = "The username/email that will be use to authenticate to the SMTP server";
|
||||||
|
type = types.str;
|
||||||
|
example = "your-smtp-enabled-address@your-domain.com";
|
||||||
|
};
|
||||||
|
|
||||||
|
smtpPasswordPath = mkOption {
|
||||||
|
description = "The path to a file containing the password that will be use to authenticate to the SMTP server";
|
||||||
|
type = types.path;
|
||||||
|
example = "/run/secrets/smtp-password";
|
||||||
|
};
|
||||||
|
|
||||||
|
fromAddress = mkOption {
|
||||||
|
description = "This server will send emails from this address";
|
||||||
|
type = types.str;
|
||||||
|
default = "numbus-server-noreply@${config.numbus.services.domain}";
|
||||||
|
example = "numbus-server-noreply@your-domain.com";
|
||||||
|
};
|
||||||
|
|
||||||
|
smtpServer = mkOption {
|
||||||
|
description = "The SMTP server address your server will use to send emails";
|
||||||
|
type = types.str;
|
||||||
|
default = "smtp.gmail.com";
|
||||||
|
example = "smtp.your-provider.com";
|
||||||
|
};
|
||||||
|
|
||||||
|
smtpPort = mkOption {
|
||||||
|
description = "The SMTP port your server will connect to to send emails";
|
||||||
|
type = types.port;
|
||||||
|
default = 587;
|
||||||
|
example = 587;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
environment.etc."aliases".text = ''
|
||||||
|
root: ${cfg.userAddress}, ${cfg.adminAddress}
|
||||||
|
default: ${cfg.userAddress}, ${cfg.adminAddress}
|
||||||
|
'';
|
||||||
|
|
||||||
|
programs.msmtp = {
|
||||||
|
enable = true;
|
||||||
|
defaults = {
|
||||||
|
aliases = "/etc/aliases";
|
||||||
|
timeout = 60;
|
||||||
|
syslog = "on";
|
||||||
|
};
|
||||||
|
accounts.default = {
|
||||||
|
auth = true;
|
||||||
|
host = cfg.smtpServer;
|
||||||
|
port = cfg.smtpPort;
|
||||||
|
from = cfg.fromAddress;
|
||||||
|
user = cfg.smtpUsername;
|
||||||
|
tls = true;
|
||||||
|
tls_starttls = true;
|
||||||
|
passwordeval = "${pkgs.coreutils}/bin/cat ${cfg.smtpPasswordPath}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./internationalisation.nix
|
||||||
|
./power.nix
|
||||||
|
./update.nix
|
||||||
|
./users.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
i18n.defaultLocale = "fr_FR.UTF-8";
|
||||||
|
i18n.extraLocaleSettings = {
|
||||||
|
LC_ADDRESS = "fr_FR.UTF-8";
|
||||||
|
LC_IDENTIFICATION = "fr_FR.UTF-8";
|
||||||
|
LC_MEASUREMENT = "fr_FR.UTF-8";
|
||||||
|
LC_MONETARY = "fr_FR.UTF-8";
|
||||||
|
LC_NAME = "fr_FR.UTF-8";
|
||||||
|
LC_NUMERIC = "fr_FR.UTF-8";
|
||||||
|
LC_PAPER = "fr_FR.UTF-8";
|
||||||
|
LC_TELEPHONE = "fr_FR.UTF-8";
|
||||||
|
LC_TIME = "fr_FR.UTF-8";
|
||||||
|
};
|
||||||
|
|
||||||
|
console.keyMap = "fr";
|
||||||
|
services.xserver.xkb = {
|
||||||
|
layout = "fr";
|
||||||
|
variant = "";
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
hardDrives = config.numbus.hardware.dataDisksList ++ config.numbus.hardware.parityDisksList;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
systemd.services.hd-idle = {
|
||||||
|
description = "External HD spin down daemon";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
ExecStart =
|
||||||
|
let
|
||||||
|
idleTime = toString 1800;
|
||||||
|
hardDriveParameter = lib.strings.concatMapStringsSep " " (x: "-a ${x} -i ${idleTime}") hardDrives;
|
||||||
|
in
|
||||||
|
"${pkgs.hd-idle}/bin/hd-idle -i 0 ${hardDriveParameter}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.autoaspm.enable = true;
|
||||||
|
powerManagement.powertop.enable = true;
|
||||||
|
boot.kernelParams = [
|
||||||
|
"pcie_aspm=force"
|
||||||
|
"consoleblank=60"
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
system.autoUpgrade = {
|
||||||
|
enable = true;
|
||||||
|
allowReboot = false;
|
||||||
|
flake = inputs.self.outPath;
|
||||||
|
flags = [ "--print-build-logs" ];
|
||||||
|
dates = "02:00";
|
||||||
|
randomizedDelaySec = "45min";
|
||||||
|
};
|
||||||
|
|
||||||
|
nix.gc = {
|
||||||
|
automatic = true;
|
||||||
|
dates = "weekly";
|
||||||
|
options = "--delete-older-than 7d";
|
||||||
|
};
|
||||||
|
|
||||||
|
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
||||||
|
nix.settings.auto-optimise-store = true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
users.users.numbus-admin = {
|
||||||
|
shell = pkgs.fish;
|
||||||
|
isNormalUser = true;
|
||||||
|
description = "Numbus Admin";
|
||||||
|
extraGroups = [ "wheel" ];
|
||||||
|
uid = 1000;
|
||||||
|
initialPassword = "changeMe!";
|
||||||
|
# required for auto start before user login
|
||||||
|
linger = true;
|
||||||
|
# required for rootless container with multiple users
|
||||||
|
autoSubUidGidRange = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./firewall.nix
|
||||||
|
./networking.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
networking.nftables.enable = true;
|
||||||
|
networking.firewall = {
|
||||||
|
enable = true;
|
||||||
|
allowPing = true;
|
||||||
|
allowedTCPPorts = [ 53 80 443 ];
|
||||||
|
allowedUDPPorts = [ 53 443 ];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.numbus.services.networking;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options.numbus.services.networking = {
|
||||||
|
ipAddress = mkOption {
|
||||||
|
description = "The IP address that this server will use";
|
||||||
|
type = types.str;
|
||||||
|
example = "192.168.1.100";
|
||||||
|
};
|
||||||
|
interface = mkOption {
|
||||||
|
description = "The interface that this server will use to connect to the network";
|
||||||
|
type = types.str;
|
||||||
|
example = "enp1s0";
|
||||||
|
};
|
||||||
|
routerIpAddress = mkOption {
|
||||||
|
description = "The IP address of the router of your network";
|
||||||
|
type = types.str;
|
||||||
|
example = "192.168.1.1";
|
||||||
|
};
|
||||||
|
dnsServers = mkOption {
|
||||||
|
description = "The list of DNS servers that this server will use";
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ "${cfg.ipAddress}" "9.9.9.9" ];
|
||||||
|
example = [ "${cfg.ipAddress}" "9.9.9.9" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.hostName = "numbus-server";
|
||||||
|
networking.networkmanager.enable = false;
|
||||||
|
|
||||||
|
# Allow rootless containers to bind to port 53 and up
|
||||||
|
boot.kernel.sysctl."net.ipv4.ip_unprivileged_port_start" = 53;
|
||||||
|
|
||||||
|
networking.bridges.br0.interfaces = [ "${cfg.interface}" ];
|
||||||
|
networking.interfaces."${cfg.interface}".useDHCP = false;
|
||||||
|
networking.interfaces.br0.useDHCP = false;
|
||||||
|
networking.nameservers = ${cfg.dnsServers};
|
||||||
|
networking.interfaces.br0.ipv4.addresses = [{
|
||||||
|
address = "${cfg.ipAddress}";
|
||||||
|
prefixLength = 24;
|
||||||
|
}];
|
||||||
|
networking.defaultGateway = {
|
||||||
|
address = "${cfg.routerIpAddress}";
|
||||||
|
interface = "br0";
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./packages.nix
|
||||||
|
./podman.nix
|
||||||
|
./ssh.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
nixpkgs.config.allowUnfree = true;
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
git
|
||||||
|
ncdu
|
||||||
|
fastfetch
|
||||||
|
tpm2-tss
|
||||||
|
sops
|
||||||
|
age
|
||||||
|
powertop
|
||||||
|
pciutils
|
||||||
|
hdparm
|
||||||
|
hd-idle
|
||||||
|
hddtemp
|
||||||
|
smartmontools
|
||||||
|
cpufrequtils
|
||||||
|
intel-gpu-tools
|
||||||
|
snapraid
|
||||||
|
mergerfs
|
||||||
|
mergerfs-tools
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{ config, pkgs, ...}:
|
||||||
|
|
||||||
|
{
|
||||||
|
virtualisation.podman.enable = true;
|
||||||
|
virtualisation.podman.defaultNetwork.settings.dns_enabled = true;
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
podman
|
||||||
|
podman-compose
|
||||||
|
podman-tui
|
||||||
|
slirp4netns
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{ config, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.openssh.enable = true;
|
||||||
|
}
|
||||||
@@ -15,6 +15,14 @@ helper.mkPodmanService {
|
|||||||
name = "immich";
|
name = "immich";
|
||||||
pod = "immich";
|
pod = "immich";
|
||||||
defaultPort = "2283";
|
defaultPort = "2283";
|
||||||
|
useSopsSecrets = true;
|
||||||
|
|
||||||
|
extraConfig = {
|
||||||
|
numbus.services.immich.secretMapping = {
|
||||||
|
DB_PASSWORD = "db_password";
|
||||||
|
DB_USERNAME = "db_username"; # Assuming you add this to schema
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# Compose file good
|
# Compose file good
|
||||||
composeText = ''
|
composeText = ''
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ with lib;
|
|||||||
extraOptions ? {},
|
extraOptions ? {},
|
||||||
extraConfig ? {},
|
extraConfig ? {},
|
||||||
delaySec ? 180,
|
delaySec ? 180,
|
||||||
|
useSopsSecrets ? false, # New argument to enable sops integration
|
||||||
middlewares ? [ "secureHeaders" ],
|
middlewares ? [ "secureHeaders" ],
|
||||||
dependencies ? [ "traefik.service" "${config.numbus.services.dns}.service" ],
|
dependencies ? [ "traefik.service" "${config.numbus.services.dns}.service" ],
|
||||||
}:
|
}:
|
||||||
@@ -135,7 +136,7 @@ ${concatStringsSep "\n" (map (m: " - ${m}") middlewares)}
|
|||||||
Type = "exec";
|
Type = "exec";
|
||||||
ExecStartPre = [
|
ExecStartPre = [
|
||||||
"bash -c 'sleep $((RANDOM % ${toString delaySec}))'"
|
"bash -c 'sleep $((RANDOM % ${toString delaySec}))'"
|
||||||
"-sudo -u numbus-admin podman-compose -f /etc/podman/${name}/compose.yaml pull"
|
"- sudo -u numbus-admin podman-compose -f /etc/podman/${name}/compose.yaml pull"
|
||||||
];
|
];
|
||||||
ExecStart = "sudo -u numbus-admin podman-compose --in-pod ${toString pod} -f /etc/podman/${name}/compose.yaml up --remove-orphans";
|
ExecStart = "sudo -u numbus-admin podman-compose --in-pod ${toString pod} -f /etc/podman/${name}/compose.yaml up --remove-orphans";
|
||||||
ExecStop = "sudo -u numbus-admin podman-compose --in-pod ${toString pod} -f /etc/podman/${name}/compose.yaml down";
|
ExecStop = "sudo -u numbus-admin podman-compose --in-pod ${toString pod} -f /etc/podman/${name}/compose.yaml down";
|
||||||
|
|||||||
Reference in New Issue
Block a user