Deleted old module, now part of official NixOS
This commit is contained in:
parent
b659426027
commit
0bac6ba223
2 changed files with 0 additions and 329 deletions
|
|
@ -1,122 +0,0 @@
|
||||||
# ```admonish note title="To do"
|
|
||||||
# Run podman containers run as a non-root user.
|
|
||||||
# ```
|
|
||||||
#
|
|
||||||
# An abstraction over running containers as systemd units, enforcing some good
|
|
||||||
# practices:
|
|
||||||
#
|
|
||||||
# - Container DNS behaves the same under docker and podman.
|
|
||||||
# - Ports are exposed on `127.0.0.1`, rather than `0.0.0.0`.
|
|
||||||
# - Volumes are backed up by bind-mounts to the host filesystem.
|
|
||||||
#
|
|
||||||
# Switching between using docker or podman for the container runtime should be
|
|
||||||
# totally transparent.
|
|
||||||
#
|
|
||||||
# **Erase your darlings:** overrides the `volumeBaseDir`.
|
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
mkPortDef = { host, inner }: "127.0.0.1:${toString host}:${toString inner}";
|
|
||||||
|
|
||||||
mkVolumeDef = container: { name, host, inner }:
|
|
||||||
if host != null
|
|
||||||
then "${host}:${inner}"
|
|
||||||
else "${cfg.volumeBaseDir}/${container.volumeSubDir}/${name}:${inner}";
|
|
||||||
|
|
||||||
shouldPreStart = _name: container: container.pullOnStart;
|
|
||||||
mkPreStart = name: container: nameValuePair "${cfg.backend}-${name}" {
|
|
||||||
preStart = if container.pullOnStart then "${cfg.backend} pull ${container.image}" else "";
|
|
||||||
};
|
|
||||||
|
|
||||||
shouldNetworkService = _name: container: container.network != null;
|
|
||||||
mkNetworkService = _name: container:
|
|
||||||
let package = if cfg.backend == "docker" then pkgs.docker else pkgs.podman;
|
|
||||||
in nameValuePair "${cfg.backend}-net-${container.network}" {
|
|
||||||
description = "Manage the ${container.network} network for ${cfg.backend}";
|
|
||||||
preStart = "${package}/bin/${cfg.backend} network rm ${container.network} || true";
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
ExecStart = "${package}/bin/${cfg.backend} network create -d bridge ${container.network}";
|
|
||||||
ExecStop = "${package}/bin/${cfg.backend} network rm ${container.network}";
|
|
||||||
RemainAfterExit = "yes";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
mkPodService = name: pod:
|
|
||||||
let
|
|
||||||
package = if cfg.backend == "podman" then pkgs.podman else throw "mkPodService only supports podman";
|
|
||||||
aliases = map (cn: "${name}-${cn}") (attrNames pod.containers);
|
|
||||||
ports = concatLists (catAttrs "ports" (attrValues pod.containers));
|
|
||||||
in
|
|
||||||
nameValuePair "${cfg.backend}-pod-${name}" {
|
|
||||||
description = "Manage the ${name} pod for ${cfg.backend}";
|
|
||||||
preStart = "${package}/bin/${cfg.backend} pod rm --force --ignore ${name} || true";
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
ExecStart =
|
|
||||||
let args = map (n: "--network-alias=${n}") aliases ++ map (pd: "-p ${mkPortDef pd}") ports;
|
|
||||||
in "${package}/bin/${cfg.backend} pod create ${concatStringsSep " " args} ${name}";
|
|
||||||
ExecStop = "${package}/bin/${cfg.backend} pod rm ${name}";
|
|
||||||
RemainAfterExit = "yes";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
mkContainer = _name: container: with container;
|
|
||||||
let
|
|
||||||
hasNetwork = container.network != null;
|
|
||||||
hasPod = container.pod != null;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
inherit autoStart cmd environment environmentFiles image login;
|
|
||||||
dependsOn =
|
|
||||||
container.dependsOn ++
|
|
||||||
(if hasNetwork then [ "net-${container.network}" ] else [ ]) ++
|
|
||||||
(if hasPod then [ "pod-${container.pod}" ] else [ ]);
|
|
||||||
extraOptions =
|
|
||||||
container.extraOptions ++
|
|
||||||
(if hasNetwork then [ "--network=${container.network}" ] else [ ]) ++
|
|
||||||
(if hasPod then [ "--pod=${container.pod}" ] else [ ]);
|
|
||||||
/* ports are defined at the pod level */
|
|
||||||
ports = if hasPod then [ ] else map mkPortDef ports;
|
|
||||||
volumes = map (mkVolumeDef container) volumes;
|
|
||||||
};
|
|
||||||
|
|
||||||
cfg = config.nixfiles.oci-containers;
|
|
||||||
|
|
||||||
allContainers =
|
|
||||||
let
|
|
||||||
mkPodContainer = podName: pod: containerName: container: nameValuePair "${podName}-${containerName}" (
|
|
||||||
container //
|
|
||||||
{
|
|
||||||
network = if cfg.backend == "docker" then podName else null;
|
|
||||||
pod = if cfg.backend == "docker" then null else podName;
|
|
||||||
volumeSubDir = pod.volumeSubDir;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
in
|
|
||||||
concatMapAttrs (podName: pod: mapAttrs' (mkPodContainer podName pod) pod.containers) cfg.pods;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./options.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
config = {
|
|
||||||
virtualisation.${cfg.backend} = {
|
|
||||||
enable = true;
|
|
||||||
autoPrune.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtualisation.oci-containers = {
|
|
||||||
backend = cfg.backend;
|
|
||||||
containers = mapAttrs mkContainer allContainers;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services = mkMerge [
|
|
||||||
(mapAttrs' mkPreStart (filterAttrs shouldPreStart allContainers))
|
|
||||||
(mapAttrs' mkNetworkService (filterAttrs shouldNetworkService allContainers))
|
|
||||||
(if cfg.backend == "podman" then mapAttrs' mkPodService cfg.pods else { })
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,207 +0,0 @@
|
||||||
{ lib, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
portOptions = {
|
|
||||||
host = mkOption {
|
|
||||||
type = types.int;
|
|
||||||
description = mdDoc ''
|
|
||||||
Host port (on 127.0.0.1) to expose the container port on.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
inner = mkOption {
|
|
||||||
type = types.int;
|
|
||||||
description = mdDoc ''
|
|
||||||
The container port to expose to the hosti.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
volumeOptions = {
|
|
||||||
name = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = mdDoc ''
|
|
||||||
Name of the volume. This is equivalent to:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
host = "''${volumeBaseDir}/''${volumeSubDir}/''${name}";
|
|
||||||
```
|
|
||||||
|
|
||||||
This option c.logonflicts with `''${host}`.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
host = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = mdDoc ''
|
|
||||||
Directory on the host to bind-mount into the container.
|
|
||||||
|
|
||||||
This option conflicts with `''${name}`.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
inner = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = mdDoc ''
|
|
||||||
Directory in the container to mount the volume to.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
containerOptions = {
|
|
||||||
/* regular oci-containers */
|
|
||||||
autoStart = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = mdDoc ''
|
|
||||||
Start the container automatically on boot.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
cmd = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ ];
|
|
||||||
description = mdDoc ''
|
|
||||||
Command-line arguments to pass to the container image's entrypoint.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
dependsOn = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ ];
|
|
||||||
example = [ "concourse-db" ];
|
|
||||||
description = mdDoc ''
|
|
||||||
Other containers that this one depends on, in `''${pod}-''${name}`
|
|
||||||
format.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
environment = mkOption {
|
|
||||||
type = types.attrsOf types.str;
|
|
||||||
default = { };
|
|
||||||
description = mdDoc ''
|
|
||||||
Environment variables to set for this container.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
environmentFiles = mkOption {
|
|
||||||
type = types.listOf types.path;
|
|
||||||
default = [ ];
|
|
||||||
description = mdDoc ''
|
|
||||||
List of environment files for this container.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
extraOptions = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ ];
|
|
||||||
description = mdDoc ''
|
|
||||||
Extra options to pass to `docker run` / `podman run`.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
image = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = mdDoc ''
|
|
||||||
Container image to run.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
login = {
|
|
||||||
username = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = mdDoc ''
|
|
||||||
Username for the container registry.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
passwordFile = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = mdDoc ''
|
|
||||||
File containing the password for the container registry.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
registry = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
description = mdDoc ''
|
|
||||||
Container registry to authenticate with.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/* changed */
|
|
||||||
ports = mkOption {
|
|
||||||
type = types.listOf (types.submodule { options = portOptions; });
|
|
||||||
default = [ ];
|
|
||||||
description = mdDoc ''
|
|
||||||
List of ports to expose.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
volumes = mkOption {
|
|
||||||
type = types.listOf (types.submodule { options = volumeOptions; });
|
|
||||||
default = [ ];
|
|
||||||
description = mdDoc ''
|
|
||||||
List of volume definitions.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
/* new options */
|
|
||||||
pullOnStart = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = mdDoc ''
|
|
||||||
Pull the container image when starting (useful for `:latest` images).
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.nixfiles.oci-containers = {
|
|
||||||
backend = mkOption {
|
|
||||||
type = types.enum [ "docker" "podman" ];
|
|
||||||
default = "docker";
|
|
||||||
description = mdDoc ''
|
|
||||||
The container runtime.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
pods = mkOption {
|
|
||||||
type = types.attrsOf (types.submodule ({ name, ... }: {
|
|
||||||
options = {
|
|
||||||
containers = mkOption {
|
|
||||||
type = types.attrsOf (types.submodule { options = containerOptions; });
|
|
||||||
default = { };
|
|
||||||
description = mdDoc ''
|
|
||||||
Attrset of container definitions.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
volumeSubDir = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = name;
|
|
||||||
description = mdDoc ''
|
|
||||||
Subdirectory of the `''${volumeBaseDir}` to store bind-mounts
|
|
||||||
under.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
default = { };
|
|
||||||
description = mdDoc ''
|
|
||||||
Attrset of pod definitions.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
volumeBaseDir = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = mdDoc ''
|
|
||||||
Directory to store volume bind-mounts under.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue