modules/containers: a hacc-specific containers module
this started with emily pointing out to me that it's possible to generate IP addresses for containers in Nix (hence no need to worry about ever having collisions, as we had before), but then I thought, hey, while I'm at it, I can also write a little container module so we have a little less repetition in our configs in general (and a more reasonable place for our custom evalConfig than just keeping it around in flake.nix). See the option descriptions in modules/containers.nix for further details. Apart from giving all containers a new IP address (and also shiny new IPv6 addresses), this should be a no-op for the actual built system.
This commit is contained in:
parent
3dc63acf52
commit
f654b33a56
10 changed files with 134 additions and 135 deletions
19
flake.nix
19
flake.nix
|
@ -38,33 +38,20 @@
|
|||
system = "x86_64-linux";
|
||||
config.allowUnfree = true;
|
||||
};
|
||||
evalConfig = config: (nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
config
|
||||
{
|
||||
nixpkgs.pkgs = pkgs.lib.mkForce pkgs;
|
||||
imports = [ modules.nopersist profiles.container ];
|
||||
}
|
||||
];
|
||||
specialArgs = {
|
||||
# some of our modules import each other, and evalConfig is used for containers
|
||||
inherit modules evalConfig;
|
||||
sources = inputs;
|
||||
};
|
||||
}).config.system.build.toplevel;
|
||||
in {
|
||||
nixosConfigurations.parsons = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./parsons/configuration.nix
|
||||
./modules/buildinfo.nix
|
||||
./modules/containers.nix
|
||||
sops-nix.nixosModules.sops
|
||||
{ nixpkgs.pkgs = pkgs; }
|
||||
];
|
||||
specialArgs = {
|
||||
sources = inputs;
|
||||
inherit modules evalConfig;
|
||||
inherit modules profiles;
|
||||
inherit (nixpkgs.lib) nixosSystem;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -14,12 +14,5 @@
|
|||
'';
|
||||
};
|
||||
|
||||
# I /suspect/ this is not actually needed.
|
||||
# TODO: find spoons to deal with potential breakage, test removing this
|
||||
networking.defaultGateway = {
|
||||
address = "192.168.100.1";
|
||||
interface = "eth0";
|
||||
};
|
||||
|
||||
system.stateVersion = lib.mkDefault "21.05";
|
||||
}
|
||||
|
|
95
modules/containers.nix
Normal file
95
modules/containers.nix
Normal file
|
@ -0,0 +1,95 @@
|
|||
{ config, lib, pkgs, modules, profiles, sources, nixosSystem, ... }:
|
||||
|
||||
let
|
||||
mkIPv4 = index: local:
|
||||
"192.168.${if local then "100" else "101"}.${toString index}";
|
||||
mkIPv6 = index: local:
|
||||
"fd00::${if local then "100" else "101"}:${toString index}";
|
||||
|
||||
evalConfig = nixosConfig: (nixosSystem {
|
||||
inherit (config.nixpkgs) system;
|
||||
modules = [
|
||||
nixosConfig
|
||||
modules.nopersist
|
||||
profiles.container
|
||||
{ nixpkgs.pkgs = lib.mkForce pkgs; }
|
||||
];
|
||||
specialArgs = {
|
||||
inherit modules sources;
|
||||
};
|
||||
}).config.system.build.toplevel;
|
||||
|
||||
in {
|
||||
options.hacc.containers = with lib.options;
|
||||
mkOption {
|
||||
description = ''
|
||||
hacc-specific containers. These are a thin wrapper around "normal" nixos containers:
|
||||
- they automatically get an IPv4/IPv6 address assigned
|
||||
(note that these are not guaranteed to be stable across config changes,
|
||||
so please use {option}`containers.<name>.hostAddress` & friends to
|
||||
reference them elsewhere)
|
||||
- they set a couple default options (e.g. ephemeral, autoStart, privateNetwork)
|
||||
- they are evaluated with our own version of {nix}`evalConfig`, which includes a
|
||||
couple more modules by default, use our version of `nixpkgs`, and includes the
|
||||
{nix}`profiles.containers` profile setting sane defaults for containers.
|
||||
'';
|
||||
default = { };
|
||||
type = with lib.types;
|
||||
types.attrsOf (types.submodule {
|
||||
options = {
|
||||
bindToPersist = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description =
|
||||
"Wether to mount /persist/containers/<name> at /persist into this container.";
|
||||
};
|
||||
|
||||
bindSecrets = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description =
|
||||
"Whether to mount /run/secrets/<name> at /secrets into this container.";
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
type = types.unspecified;
|
||||
description =
|
||||
"The container's config, to be evaluated with our own {nix}`evalConfig`.";
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
# wrapped into imap1, which enumerates the containers; IP addresses are then
|
||||
# simply assigned based on the order the containers are in the list.
|
||||
config.containers = lib.mkMerge (lib.imap1
|
||||
(index: { name, value }: let container = value; in {
|
||||
${name} = {
|
||||
hostAddress = mkIPv4 index false;
|
||||
localAddress = mkIPv4 index true;
|
||||
hostAddress6 = mkIPv6 index false;
|
||||
localAddress6 = mkIPv6 index true;
|
||||
|
||||
privateNetwork = true;
|
||||
autoStart = true;
|
||||
ephemeral = true;
|
||||
|
||||
bindMounts = lib.mkMerge [
|
||||
(lib.mkIf container.bindToPersist {
|
||||
"/persist" = {
|
||||
hostPath = "/persist/containers/${name}";
|
||||
isReadOnly = false;
|
||||
};
|
||||
})
|
||||
(lib.mkIf container.bindSecrets {
|
||||
"/secrets" = {
|
||||
hostPath = "/run/secrets/${name}";
|
||||
isReadOnly = true;
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
path = evalConfig container.config;
|
||||
};
|
||||
}) (lib.attrsToList config.hacc.containers));
|
||||
}
|
|
@ -1,19 +1,8 @@
|
|||
{ config, lib, pkgs, evalConfig, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
containers.forgejo = {
|
||||
privateNetwork = true;
|
||||
hostAddress = "192.168.100.1";
|
||||
localAddress = "192.168.100.10";
|
||||
autoStart = true;
|
||||
ephemeral = true;
|
||||
bindMounts = {
|
||||
"/persist" = {
|
||||
hostPath = "/persist/containers/forgejo";
|
||||
isReadOnly = false;
|
||||
};
|
||||
};
|
||||
path = evalConfig ({ config, lib, pkgs, ... }: {
|
||||
hacc.containers.forgejo = {
|
||||
config = { lib, pkgs, ... }: {
|
||||
system.stateVersion = "21.11";
|
||||
|
||||
environment.systemPackages = [ pkgs.forgejo ];
|
||||
|
@ -79,7 +68,7 @@
|
|||
services.openssh = {
|
||||
enable = true;
|
||||
listenAddresses = [ {
|
||||
addr = "192.168.100.10";
|
||||
addr = config.containers.forgejo.localAddress;
|
||||
port = 22;
|
||||
} ];
|
||||
settings = {
|
||||
|
@ -87,7 +76,7 @@
|
|||
AcceptEnv = "GIT_PROTOCOL";
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."git.infra4future.de" = {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs, evalConfig, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
|
||||
|
@ -6,20 +6,11 @@
|
|||
"hedgedoc-hacc/env" = {};
|
||||
};
|
||||
|
||||
containers.pad-hacc = {
|
||||
privateNetwork = true;
|
||||
hostAddress = "192.168.100.1";
|
||||
localAddress = "192.168.100.5";
|
||||
autoStart = true;
|
||||
ephemeral = true;
|
||||
bindMounts = {
|
||||
"/persist" = {
|
||||
hostPath = "/persist/containers/pad-hacc";
|
||||
isReadOnly = false;
|
||||
};
|
||||
containers.pad-hacc.bindMounts = {
|
||||
"/secrets".hostPath = "/run/secrets/hedgedoc-hacc";
|
||||
};
|
||||
path = evalConfig ({ config, lib, ... }: {
|
||||
hacc.containers.pad-hacc = {
|
||||
config = { config, lib, ... }: {
|
||||
services.hedgedoc = {
|
||||
enable = true;
|
||||
settings = {
|
||||
|
@ -78,7 +69,7 @@
|
|||
location = "/persist/backups/postgres";
|
||||
};
|
||||
hacc.bindToPersist = [ "/var/lib/hedgedoc" ];
|
||||
});
|
||||
};
|
||||
};
|
||||
services.nginx.virtualHosts."pad.hacc.earth" = {
|
||||
enableACME = true;
|
||||
|
|
|
@ -1,19 +1,8 @@
|
|||
{ config, lib, pkgs, evalConfig, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
containers.pad-i4f = {
|
||||
privateNetwork = true;
|
||||
hostAddress = "192.168.100.1";
|
||||
localAddress = "192.168.100.6";
|
||||
autoStart = true;
|
||||
ephemeral = true;
|
||||
bindMounts = {
|
||||
"/persist" = {
|
||||
hostPath = "/persist/containers/pad-i4f";
|
||||
isReadOnly = false;
|
||||
};
|
||||
};
|
||||
path = evalConfig ({ config, lib, ... }: {
|
||||
hacc.containers.pad-i4f = {
|
||||
config = { config, lib, ... }: {
|
||||
services.hedgedoc = {
|
||||
enable = true;
|
||||
settings = {
|
||||
|
@ -57,7 +46,7 @@
|
|||
location = "/persist/backups/postgres";
|
||||
};
|
||||
hacc.bindToPersist = [ "/var/lib/hedgedoc" ];
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."pad.infra4future.de" = {
|
||||
|
|
|
@ -1,26 +1,14 @@
|
|||
{ config, pkgs, lib, evalConfig, ...}:
|
||||
{ config, pkgs, lib, ...}:
|
||||
|
||||
{
|
||||
sops.secrets = {
|
||||
"mattermost/env" = {};
|
||||
};
|
||||
|
||||
containers.mattermost = {
|
||||
autoStart = true;
|
||||
privateNetwork = true;
|
||||
hostAddress = "192.168.100.1";
|
||||
localAddress = "192.168.100.3";
|
||||
ephemeral = true;
|
||||
hacc.containers.mattermost = {
|
||||
bindSecrets = true;
|
||||
|
||||
bindMounts = {
|
||||
"/persist" = {
|
||||
hostPath = "/persist/containers/mattermost";
|
||||
isReadOnly = false;
|
||||
};
|
||||
"/secrets".hostPath = "/run/secrets/mattermost";
|
||||
};
|
||||
|
||||
path = evalConfig ({ config, lib, pkgs, ... }: {
|
||||
config = { config, lib, pkgs, ... }: {
|
||||
systemd.services.mattermost.serviceConfig.EnvironmentFile =
|
||||
lib.mkForce "/secrets/env";
|
||||
|
||||
|
@ -218,7 +206,7 @@
|
|||
startAt = "*-*-* 23:45:00";
|
||||
location = "/persist/backups/postgres";
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."mattermost.infra4future.de" = {
|
||||
|
|
|
@ -1,19 +1,8 @@
|
|||
{ config, lib, pkgs, evalConfig, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
containers.nextcloud = {
|
||||
autoStart = true;
|
||||
privateNetwork = true;
|
||||
hostAddress = "192.168.100.1";
|
||||
localAddress = "192.168.100.2";
|
||||
ephemeral = true;
|
||||
bindMounts = {
|
||||
"/persist" = {
|
||||
hostPath = "/persist/containers/nextcloud";
|
||||
isReadOnly = false;
|
||||
};
|
||||
};
|
||||
path = evalConfig ({ config, lib, pkgs, ... }: {
|
||||
hacc.containers.nextcloud = {
|
||||
config = { config, lib, pkgs, ... }: {
|
||||
environment.systemPackages = [ pkgs.htop ];
|
||||
|
||||
services.nextcloud = {
|
||||
|
@ -82,7 +71,7 @@
|
|||
requires = ["postgresql.service"];
|
||||
after = ["postgresql.service"];
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."cloud.infra4future.de" = {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs, evalConfig, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
tracktrain-config = ''
|
||||
|
@ -25,14 +25,14 @@ in
|
|||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://192.168.42.41:4000";
|
||||
proxyPass = "http://${config.containers.tracktrain.localAddress}:4000";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
# note: this shadows the /metrics endpoint of tracktrain
|
||||
# in case you remove this, please consider putting something
|
||||
# else here to keep it from being publicly scrapable
|
||||
locations."/metrics/" = {
|
||||
proxyPass = "http://192.168.42.41:2342";
|
||||
proxyPass = "http://${config.containers.tracktrain.localAddress}:2342";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
rewrite ^/metrics/(.*) /$1 break;
|
||||
|
@ -40,21 +40,10 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
containers.tracktrain = {
|
||||
privateNetwork = true;
|
||||
hostAddress = "192.168.42.40";
|
||||
localAddress = "192.168.42.41";
|
||||
autoStart = true;
|
||||
ephemeral = true;
|
||||
bindMounts = {
|
||||
"/persist" = {
|
||||
hostPath = "/persist/containers/tracktrain";
|
||||
isReadOnly = false;
|
||||
};
|
||||
"/secrets".hostPath = "/run/secrets/tracktrain";
|
||||
};
|
||||
hacc.containers.tracktrain = {
|
||||
bindSecrets = true;
|
||||
|
||||
path = evalConfig ({ config, lib, pkgs, ... }: {
|
||||
config = { config, lib, pkgs, ... }: {
|
||||
system.stateVersion = "21.11";
|
||||
|
||||
users.users.tracktrain = {
|
||||
|
@ -151,7 +140,7 @@ in
|
|||
systemd.services.grafana.serviceConfig.EnvironmentFile =
|
||||
"/secrets/env";
|
||||
hacc.bindToPersist = [ "/var/lib/grafana" ];
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,19 +1,8 @@
|
|||
{ config, lib, pkgs, evalConfig, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
containers.uffd = {
|
||||
privateNetwork = true;
|
||||
hostAddress = "192.168.100.1";
|
||||
localAddress = "192.168.100.9";
|
||||
autoStart = true;
|
||||
ephemeral = true;
|
||||
bindMounts = {
|
||||
"/persist" = {
|
||||
hostPath = "/persist/containers/uffd";
|
||||
isReadOnly = false;
|
||||
};
|
||||
};
|
||||
path = evalConfig ({ config, lib, pkgs, ... }: {
|
||||
hacc.containers.uffd = {
|
||||
config = { config, lib, pkgs, ... }: {
|
||||
services.uwsgi = {
|
||||
enable = true;
|
||||
plugins = [ "python3" ];
|
||||
|
@ -29,7 +18,7 @@
|
|||
hook-pre-app = "exec:FLASK_APP=${pkgs.uffd}/lib/python3.10/site-packages/uffd flask db upgrade";
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
services.nginx.virtualHosts."login.infra4future.de" = {
|
||||
enableACME = true;
|
||||
|
|
Loading…
Reference in a new issue