feat: started container implementation

This commit is contained in:
Patrick Großmann 2023-12-03 15:15:42 +01:00
parent 4944ddd61a
commit 04ee323aa6
Signed by: patrick
GPG key ID: 451F95EFB8BECD0F
6 changed files with 159 additions and 7 deletions

View file

@ -11,6 +11,7 @@
../../modules/hardware/zfs.nix
../../modules/services/samba.nix
../../modules/services/nextcloud.nix
./net.nix
./fs.nix

24
lib/containers.nix Normal file
View file

@ -0,0 +1,24 @@
_inputs: _self: super: {
lib =
super.lib
// {
containers.mkConfig = name: config:
super.lib.mkMerge [
{
bindmounts = {
"state" = {
mountpoint = "/state";
hostPath = "/state/containers/${name}";
};
"persist" = {
mountpoint = "/persist";
hostPath = config.zfs.mountpoint;
};
};
#config = {...}: {
#};
}
config
];
};
}

View file

@ -1,3 +1,4 @@
inputs: [
(import ./disko.nix inputs)
(import ./containers.nix inputs)
]

View file

@ -61,6 +61,7 @@ _inputs: _self: super: {
"local/nix" = filesystem "/nix";
"local/state" = filesystem "/state";
"safe" = unmountable;
"safe/containers" = unmountable;
"safe/persist" = filesystem "/persist";
};
unmountable = {type = "zfs_fs";};

View file

@ -0,0 +1,107 @@
{
config,
lib,
utils,
pkgs,
...
}: let
inherit
(lib)
mapAttrsToList
flip
types
mkOption
mkEnableOption
mdDoc
mkIf
disko
makeBinPath
escapeShellArg
mkMerge
;
in {
options.containers = mkOption {
type = types.attrsOf (types.submodule (
{name, ...}: {
options = {
zfs = {
enable = mkEnableOption (mdDoc "persistent data on separate zfs dataset");
pool = mkOption {
type = types.str;
description = mdDoc "The host's zfs pool on which the dataset resides";
};
dataset = mkOption {
type = types.str;
default = "safe/containers/${name}";
description = mdDoc "The host's dataset that should be used for this containers persistent data (will automatically be created, parent dataset must exist)";
};
mountpoint = mkOption {
type = types.str;
default = "/containers/${name}";
description = mdDoc "The host's mountpoint for the containers dataset";
};
};
};
}
));
};
config.disko = mkMerge (flip mapAttrsToList config.containers
(
_: cfg: {
devices.zpool = mkIf cfg.zfs.enable {
${cfg.zfs.pool}.datasets."${cfg.zfs.dataset}" =
disko.zfs.filesystem cfg.zfs.mountpoint;
};
# Ensure that the zfs dataset exists before it is mounted.
}
));
config.systemd = mkMerge (flip mapAttrsToList config.containers
(
name: cfg: {
services = let
fsMountUnit = "${utils.escapeSystemdPath cfg.zfs.mountpoint}.mount";
in
mkIf cfg.zfs.enable {
# Ensure that the zfs dataset exists before it is mounted.
"zfs-ensure-${utils.escapeSystemdPath cfg.zfs.mountpoint}" = {
wantedBy = [fsMountUnit];
before = [fsMountUnit];
after = [
"zfs-import-${utils.escapeSystemdPath cfg.zfs.pool}.service"
"zfs-mount.target"
];
unitConfig.DefaultDependencies = "no";
serviceConfig.Type = "oneshot";
script = let
poolDataset = "${cfg.zfs.pool}/${cfg.zfs.dataset}";
diskoDataset = config.disko.devices.zpool.${cfg.zfs.pool}.datasets.${cfg.zfs.dataset};
in ''
export PATH=${makeBinPath [pkgs.zfs]}":$PATH"
if ! zfs list -H -o type ${escapeShellArg poolDataset} &>/dev/null ; then
${diskoDataset._create}
fi
'';
};
# Ensure that the zfs dataset has the correct permissions when mounted
"zfs-chown-${utils.escapeSystemdPath cfg.zfs.mountpoint}" = {
after = [fsMountUnit];
unitConfig.DefaultDependencies = "no";
serviceConfig.Type = "oneshot";
script = ''
chmod 700 ${escapeShellArg cfg.zfs.mountpoint}
'';
};
"container@${name}" = {
requires = [fsMountUnit "zfs-chown-${utils.escapeSystemdPath cfg.zfs.mountpoint}.service"];
after = [fsMountUnit "zfs-chown-${utils.escapeSystemdPath cfg.zfs.mountpoint}.service"];
};
};
}
));
}

View file

@ -1,6 +1,15 @@
{lib, ...}: {
containers.nextcloud = {
{
lib,
stateVersion,
...
}: {
imports = [./containers.nix];
containers.nextcloud = lib.container.mkConfig "nextcloud" {
autoStart = true;
zfs = {
enable = true;
pool = "panzer";
};
macvlans = [
"lan01"
];
@ -16,7 +25,7 @@
config.adminpassFile = "${pkgs.writeText "adminpass" "test123"}"; # DON'T DO THIS IN PRODUCTION - the password file will be world-readable in the Nix Store!
};
system.stateVersion = "23.05";
system.stateVersion = stateVersion;
networking = {
firewall = {
@ -28,10 +37,19 @@
};
services.resolved.enable = true;
bindMounts.data = {
mountPoint = "/persist";
hostPath = "/persist/containers/nextcloud";
};
};
};
}
#wireguard
#samba/printer finding
#vaultwarden
#nextcloud
#acme
#nginx
#maddy
#kanidm
#xdg portals
#zfs snapshots
#remote backups
#immich