modules/containers: a hacc-specific containers module #11
10 changed files with 134 additions and 135 deletions
19
flake.nix
19
flake.nix
|
@ -38,33 +38,20 @@
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
config.allowUnfree = true;
|
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 {
|
in {
|
||||||
nixosConfigurations.parsons = nixpkgs.lib.nixosSystem {
|
nixosConfigurations.parsons = nixpkgs.lib.nixosSystem {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
modules = [
|
modules = [
|
||||||
./parsons/configuration.nix
|
./parsons/configuration.nix
|
||||||
./modules/buildinfo.nix
|
./modules/buildinfo.nix
|
||||||
|
./modules/containers.nix
|
||||||
sops-nix.nixosModules.sops
|
sops-nix.nixosModules.sops
|
||||||
{ nixpkgs.pkgs = pkgs; }
|
{ nixpkgs.pkgs = pkgs; }
|
||||||
];
|
];
|
||||||
specialArgs = {
|
specialArgs = {
|
||||||
sources = inputs;
|
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";
|
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 = {
|
hacc.containers.forgejo = {
|
||||||
privateNetwork = true;
|
config = { lib, pkgs, ... }: {
|
||||||
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, ... }: {
|
|
||||||
system.stateVersion = "21.11";
|
system.stateVersion = "21.11";
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.forgejo ];
|
environment.systemPackages = [ pkgs.forgejo ];
|
||||||
|
@ -79,7 +68,7 @@
|
||||||
services.openssh = {
|
services.openssh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
listenAddresses = [ {
|
listenAddresses = [ {
|
||||||
addr = "192.168.100.10";
|
addr = config.containers.forgejo.localAddress;
|
||||||
port = 22;
|
port = 22;
|
||||||
} ];
|
} ];
|
||||||
settings = {
|
settings = {
|
||||||
|
@ -87,7 +76,7 @@
|
||||||
AcceptEnv = "GIT_PROTOCOL";
|
AcceptEnv = "GIT_PROTOCOL";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts."git.infra4future.de" = {
|
services.nginx.virtualHosts."git.infra4future.de" = {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, lib, pkgs, evalConfig, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -6,20 +6,11 @@
|
||||||
"hedgedoc-hacc/env" = {};
|
"hedgedoc-hacc/env" = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
containers.pad-hacc = {
|
containers.pad-hacc.bindMounts = {
|
||||||
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;
|
|
||||||
};
|
|
||||||
"/secrets".hostPath = "/run/secrets/hedgedoc-hacc";
|
"/secrets".hostPath = "/run/secrets/hedgedoc-hacc";
|
||||||
};
|
};
|
||||||
path = evalConfig ({ config, lib, ... }: {
|
hacc.containers.pad-hacc = {
|
||||||
|
config = { config, lib, ... }: {
|
||||||
services.hedgedoc = {
|
services.hedgedoc = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
|
@ -78,7 +69,7 @@
|
||||||
location = "/persist/backups/postgres";
|
location = "/persist/backups/postgres";
|
||||||
};
|
};
|
||||||
hacc.bindToPersist = [ "/var/lib/hedgedoc" ];
|
hacc.bindToPersist = [ "/var/lib/hedgedoc" ];
|
||||||
});
|
};
|
||||||
};
|
};
|
||||||
services.nginx.virtualHosts."pad.hacc.earth" = {
|
services.nginx.virtualHosts."pad.hacc.earth" = {
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
|
|
|
@ -1,19 +1,8 @@
|
||||||
{ config, lib, pkgs, evalConfig, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
containers.pad-i4f = {
|
hacc.containers.pad-i4f = {
|
||||||
privateNetwork = true;
|
config = { config, lib, ... }: {
|
||||||
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, ... }: {
|
|
||||||
services.hedgedoc = {
|
services.hedgedoc = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
|
@ -57,7 +46,7 @@
|
||||||
location = "/persist/backups/postgres";
|
location = "/persist/backups/postgres";
|
||||||
};
|
};
|
||||||
hacc.bindToPersist = [ "/var/lib/hedgedoc" ];
|
hacc.bindToPersist = [ "/var/lib/hedgedoc" ];
|
||||||
});
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts."pad.infra4future.de" = {
|
services.nginx.virtualHosts."pad.infra4future.de" = {
|
||||||
|
|
|
@ -1,26 +1,14 @@
|
||||||
{ config, pkgs, lib, evalConfig, ...}:
|
{ config, pkgs, lib, ...}:
|
||||||
|
|
||||||
{
|
{
|
||||||
sops.secrets = {
|
sops.secrets = {
|
||||||
"mattermost/env" = {};
|
"mattermost/env" = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
containers.mattermost = {
|
hacc.containers.mattermost = {
|
||||||
autoStart = true;
|
bindSecrets = true;
|
||||||
privateNetwork = true;
|
|
||||||
hostAddress = "192.168.100.1";
|
|
||||||
localAddress = "192.168.100.3";
|
|
||||||
ephemeral = true;
|
|
||||||
|
|
||||||
bindMounts = {
|
config = { config, lib, pkgs, ... }: {
|
||||||
"/persist" = {
|
|
||||||
hostPath = "/persist/containers/mattermost";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
|
||||||
"/secrets".hostPath = "/run/secrets/mattermost";
|
|
||||||
};
|
|
||||||
|
|
||||||
path = evalConfig ({ config, lib, pkgs, ... }: {
|
|
||||||
systemd.services.mattermost.serviceConfig.EnvironmentFile =
|
systemd.services.mattermost.serviceConfig.EnvironmentFile =
|
||||||
lib.mkForce "/secrets/env";
|
lib.mkForce "/secrets/env";
|
||||||
|
|
||||||
|
@ -218,7 +206,7 @@
|
||||||
startAt = "*-*-* 23:45:00";
|
startAt = "*-*-* 23:45:00";
|
||||||
location = "/persist/backups/postgres";
|
location = "/persist/backups/postgres";
|
||||||
};
|
};
|
||||||
});
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts."mattermost.infra4future.de" = {
|
services.nginx.virtualHosts."mattermost.infra4future.de" = {
|
||||||
|
|
|
@ -1,19 +1,8 @@
|
||||||
{ config, lib, pkgs, evalConfig, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
containers.nextcloud = {
|
hacc.containers.nextcloud = {
|
||||||
autoStart = true;
|
config = { config, lib, pkgs, ... }: {
|
||||||
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, ... }: {
|
|
||||||
environment.systemPackages = [ pkgs.htop ];
|
environment.systemPackages = [ pkgs.htop ];
|
||||||
|
|
||||||
services.nextcloud = {
|
services.nextcloud = {
|
||||||
|
@ -82,7 +71,7 @@
|
||||||
requires = ["postgresql.service"];
|
requires = ["postgresql.service"];
|
||||||
after = ["postgresql.service"];
|
after = ["postgresql.service"];
|
||||||
};
|
};
|
||||||
});
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts."cloud.infra4future.de" = {
|
services.nginx.virtualHosts."cloud.infra4future.de" = {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, lib, pkgs, evalConfig, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
tracktrain-config = ''
|
tracktrain-config = ''
|
||||||
|
@ -25,14 +25,14 @@ in
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://192.168.42.41:4000";
|
proxyPass = "http://${config.containers.tracktrain.localAddress}:4000";
|
||||||
proxyWebsockets = true;
|
proxyWebsockets = true;
|
||||||
};
|
};
|
||||||
# note: this shadows the /metrics endpoint of tracktrain
|
# note: this shadows the /metrics endpoint of tracktrain
|
||||||
# in case you remove this, please consider putting something
|
# in case you remove this, please consider putting something
|
||||||
# else here to keep it from being publicly scrapable
|
# else here to keep it from being publicly scrapable
|
||||||
locations."/metrics/" = {
|
locations."/metrics/" = {
|
||||||
proxyPass = "http://192.168.42.41:2342";
|
proxyPass = "http://${config.containers.tracktrain.localAddress}:2342";
|
||||||
proxyWebsockets = true;
|
proxyWebsockets = true;
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
rewrite ^/metrics/(.*) /$1 break;
|
rewrite ^/metrics/(.*) /$1 break;
|
||||||
|
@ -40,21 +40,10 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
containers.tracktrain = {
|
hacc.containers.tracktrain = {
|
||||||
privateNetwork = true;
|
bindSecrets = 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";
|
|
||||||
};
|
|
||||||
|
|
||||||
path = evalConfig ({ config, lib, pkgs, ... }: {
|
config = { config, lib, pkgs, ... }: {
|
||||||
system.stateVersion = "21.11";
|
system.stateVersion = "21.11";
|
||||||
|
|
||||||
users.users.tracktrain = {
|
users.users.tracktrain = {
|
||||||
|
@ -151,7 +140,7 @@ in
|
||||||
systemd.services.grafana.serviceConfig.EnvironmentFile =
|
systemd.services.grafana.serviceConfig.EnvironmentFile =
|
||||||
"/secrets/env";
|
"/secrets/env";
|
||||||
hacc.bindToPersist = [ "/var/lib/grafana" ];
|
hacc.bindToPersist = [ "/var/lib/grafana" ];
|
||||||
});
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,8 @@
|
||||||
{ config, lib, pkgs, evalConfig, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
containers.uffd = {
|
hacc.containers.uffd = {
|
||||||
privateNetwork = true;
|
config = { config, lib, pkgs, ... }: {
|
||||||
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, ... }: {
|
|
||||||
services.uwsgi = {
|
services.uwsgi = {
|
||||||
enable = true;
|
enable = true;
|
||||||
plugins = [ "python3" ];
|
plugins = [ "python3" ];
|
||||||
|
@ -29,7 +18,7 @@
|
||||||
hook-pre-app = "exec:FLASK_APP=${pkgs.uffd}/lib/python3.10/site-packages/uffd flask db upgrade";
|
hook-pre-app = "exec:FLASK_APP=${pkgs.uffd}/lib/python3.10/site-packages/uffd flask db upgrade";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
};
|
||||||
};
|
};
|
||||||
services.nginx.virtualHosts."login.infra4future.de" = {
|
services.nginx.virtualHosts."login.infra4future.de" = {
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
|
|
Loading…
Reference in a new issue