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 = [
|
||||
./global.nix
|
||||
./hardware/default.nix
|
||||
./mail/default.nix
|
||||
./misc/default.nix
|
||||
./networking/default.nix
|
||||
./packages/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";
|
||||
pod = "immich";
|
||||
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
|
||||
composeText = ''
|
||||
|
||||
@@ -31,6 +31,7 @@ with lib;
|
||||
extraOptions ? {},
|
||||
extraConfig ? {},
|
||||
delaySec ? 180,
|
||||
useSopsSecrets ? false, # New argument to enable sops integration
|
||||
middlewares ? [ "secureHeaders" ],
|
||||
dependencies ? [ "traefik.service" "${config.numbus.services.dns}.service" ],
|
||||
}:
|
||||
@@ -135,7 +136,7 @@ ${concatStringsSep "\n" (map (m: " - ${m}") middlewares)}
|
||||
Type = "exec";
|
||||
ExecStartPre = [
|
||||
"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";
|
||||
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