modules/services/colima: init

This commit is contained in:
will 2025-09-30 20:31:20 +10:00 committed by Austin Horstman
parent d787ec69c3
commit 58bf3ecb2d
11 changed files with 488 additions and 0 deletions

View file

@ -0,0 +1,9 @@
{
time = "2025-10-14T23:44:58+00:00";
condition = true;
message = ''
A new module is available: `services.colima`
Colima is a tool for orchestrating container runtimes under a linux VM.
'';
}

266
modules/services/colima.nix Normal file
View file

@ -0,0 +1,266 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.colima;
yamlFormat = pkgs.formats.yaml { };
in
{
meta.maintainers = [
lib.hm.maintainers.will-lol
];
options.services.colima = {
enable = lib.mkEnableOption "Colima, a container runtime";
package = lib.mkPackageOption pkgs "colima" { };
dockerPackage = lib.mkPackageOption pkgs "docker" {
extraDescription = "Used by colima to activate profiles. Not needed if no profile is set to isActive.";
};
perlPackage = lib.mkPackageOption pkgs "perl" {
extraDescription = "Used by colima during image download for the shasum command.";
};
sshPackage = lib.mkPackageOption pkgs "openssh" {
extraDescription = "Used by colima to manage the vm.";
};
coreutilsPackage = lib.mkPackageOption pkgs "coreutils" {
extraDescription = "Used in various ways by colima.";
};
curlPackage = lib.mkPackageOption pkgs "curl" {
extraDescription = "Used by colima to donwload images.";
};
bashPackage = lib.mkPackageOption pkgs "bashNonInteractive" {
extraDescription = "Used by colima's internal scripts.";
};
profiles = lib.mkOption {
default = {
default = {
isActive = true;
isService = true;
};
};
description = ''
Profiles allow multiple colima configurations. The default profile is active by default.
If you have used colima before, you may need to delete existing configuration using `colima delete` or use a different profile.
Note that removing a configured profile will not delete the corresponding Colima instance.
You will need to manually run `colima delete <profile-name>` to remove the instance and release resources.
'';
example = ''
{
default = {
isActive = true;
isService = true;
};
rosetta = {
isService = true;
settings.rosetta = true;
};
powerful = {
settings.cpu = 8;
};
};
'';
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
type = lib.types.str;
default = name;
readOnly = true;
description = "The profile's name.";
};
isService = lib.mkOption {
type = lib.types.bool;
default = false;
example = true;
description = ''
Whether this profile will run as a service.
'';
};
isActive = lib.mkOption {
type = lib.types.bool;
default = false;
example = true;
description = ''
Whether to set this profile as:
- active docker context
- active kubernetes context
- active incus remote
Exactly one or zero profiles should have this option set.
'';
};
logFile = lib.mkOption {
type = lib.types.path;
default = "${config.home.homeDirectory}/.local/state/colima-${name}.log";
defaultText = lib.literalExpression "\${config.home.homeDirectory}/.local/state/colima-\${name}.log";
description = "Combined stdout and stderr log file for the Colima service.";
};
settings = lib.mkOption {
inherit (yamlFormat) type;
default = { };
description = "Colima configuration settings, see <https://github.com/abiosoft/colima/blob/main/embedded/defaults/colima.yaml> or run `colima template`.";
example = ''
{
cpu = 2;
disk = 100;
memory = 2;
arch = "host";
runtime = "docker";
hostname = null;
kubernetes = {
enabled = false;
version = "v1.33.3+k3s1";
k3sArgs = [ "--disable=traefik" ];
port = 0;
};
autoActivate = true;
network = {
address = false;
mode = "shared";
interface = "en0";
preferredRoute = false;
dns = [ ];
dnsHosts = {
"host.docker.internal" = "host.lima.internal";
};
hostAddresses = false;
};
forwardAgent = false;
docker = { };
vmType = "qemu";
portForwarder = "ssh";
rosetta = false;
binfmt = true;
nestedVirtualization = false;
mountType = "sshfs";
mountInotify = false;
cpuType = "host";
provision = [ ];
sshConfig = true;
sshPort = 0;
mounts = [ ];
diskImage = "";
rootDisk = 20;
env = { };
}
'';
};
};
}
)
);
};
};
config = lib.mkIf cfg.enable ({
assertions = [
{
assertion = (lib.count (p: p.isActive) (lib.attrValues cfg.profiles)) <= 1;
message = "Only one Colima profile can be active at a time.";
}
];
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
home.file = lib.mkMerge (
lib.mapAttrsToList (profileName: profile: {
".colima/${profileName}/colima.yaml" = {
source = yamlFormat.generate "colima.yaml" profile.settings;
};
}) (lib.filterAttrs (name: profile: profile.settings != { }) cfg.profiles)
);
programs.docker-cli.settings.currentContext =
let
activeProfile = lib.findFirst (p: p.isActive) null (lib.attrValues cfg.profiles);
in
lib.mkIf (activeProfile != null) (
if activeProfile.name != "default" then "colima-${activeProfile.name}" else "colima"
);
launchd.agents = lib.mkIf pkgs.stdenv.isDarwin (
lib.mapAttrs' (
name: profile:
lib.nameValuePair "colima-${name}" {
enable = true;
config = {
ProgramArguments = [
"${lib.getExe cfg.package}"
"start"
name
"-f"
"--activate=${if profile.isActive then "true" else "false"}"
"--save-config=false"
];
KeepAlive = true;
RunAtLoad = true;
EnvironmentVariables.PATH = lib.makeBinPath [
cfg.package
cfg.perlPackage
cfg.dockerPackage
cfg.sshPackage
cfg.coreutilsPackage
cfg.curlPackage
cfg.bashPackage
pkgs.darwin.DarwinTools
];
StandardOutPath = profile.logFile;
StandardErrorPath = profile.logFile;
};
}
) (lib.filterAttrs (_: p: p.isService) cfg.profiles)
);
systemd.user.services = lib.mkIf pkgs.stdenv.isLinux (
lib.mapAttrs' (
name: profile:
lib.nameValuePair "colima-${name}" {
Unit = {
Description = "Colima container runtime (${name} profile)";
After = [ "network-online.target" ];
Wants = [ "network-online.target" ];
};
Service = {
ExecStart = ''
${lib.getExe cfg.package} start ${name} \
-f \
--activate=${if profile.isActive then "true" else "false"} \
--save-config=false
'';
Restart = "always";
RestartSec = 2;
Environment = [
"PATH=${
lib.makeBinPath [
cfg.package
cfg.perlPackage
cfg.dockerPackage
cfg.sshPackage
cfg.coreutilsPackage
cfg.curlPackage
cfg.bashPackage
]
}"
];
StandardOutput = "append:${profile.logFile}";
StandardError = "append:${profile.logFile}";
};
Install = {
WantedBy = [ "default.target" ];
};
}
) (lib.filterAttrs (_: p: p.isService) cfg.profiles)
);
});
}

View file

@ -0,0 +1,39 @@
{
config,
lib,
pkgs,
...
}:
{
services.colima = {
enable = true;
package = config.lib.test.mkStubPackage {
name = "colima";
outPath = "@colima@";
};
dockerPackage = config.lib.test.mkStubPackage {
name = "docker";
outPath = "@docker@";
};
perlPackage = config.lib.test.mkStubPackage {
name = "perl";
outPath = "@perl@";
};
sshPackage = config.lib.test.mkStubPackage {
name = "openssh";
outPath = "@openssh@";
};
profiles.default.settings = {
cpu = 4;
memory = 8;
kubernetes.enabled = true;
};
};
nmt.script = ''
assertFileExists home-files/.colima/default/colima.yaml
assertFileContent home-files/.colima/default/colima.yaml ${./custom-settings-expected.yaml}
'';
}

View file

@ -0,0 +1,61 @@
{
config,
lib,
pkgs,
...
}:
{
nixpkgs.overlays = [
(self: super: {
darwin = super.darwin // {
DarwinTools = config.lib.test.mkStubPackage {
name = "DarwinTools";
outPath = "@DarwinTools@";
};
};
})
];
services.colima = {
enable = true;
package = config.lib.test.mkStubPackage {
name = "colima";
outPath = "@colima@";
};
dockerPackage = config.lib.test.mkStubPackage {
name = "docker";
outPath = "@docker@";
};
perlPackage = config.lib.test.mkStubPackage {
name = "perl";
outPath = "@perl@";
};
sshPackage = config.lib.test.mkStubPackage {
name = "openssh";
outPath = "@openssh@";
};
coreutilsPackage = config.lib.test.mkStubPackage {
name = "coreutils";
outPath = "@coreutils@";
};
curlPackage = config.lib.test.mkStubPackage {
name = "curl";
outPath = "@curl@";
};
bashPackage = config.lib.test.mkStubPackage {
name = "bashNonInteractive";
outPath = "@bashNonInteractive@";
};
};
nmt.script = ''
assertPathNotExists home-files/.colima/default/colima.yaml
serviceFile=LaunchAgents/org.nix-community.home.colima-default.plist
assertFileExists "$serviceFile"
assertFileContent "$serviceFile" ${./expected-agent.plist}
'';
}

View file

@ -0,0 +1,4 @@
cpu: 4
kubernetes:
enabled: true
memory: 8

View file

@ -0,0 +1,4 @@
{
"colima-default-config" = ./colima-default-config.nix;
"colima-custom-settings" = ./colima-custom-settings.nix;
}

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>@colima@/bin:@perl@/bin:@docker@/bin:@openssh@/bin:@coreutils@/bin:@curl@/bin:@bashNonInteractive@/bin:@DarwinTools@/bin</string>
</dict>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>org.nix-community.home.colima-default</string>
<key>ProgramArguments</key>
<array>
<string>@colima@/bin/colima</string>
<string>start</string>
<string>default</string>
<string>-f</string>
<string>--activate=true</string>
<string>--save-config=false</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/home/hm-user/.local/state/colima-default.log</string>
<key>StandardOutPath</key>
<string>/home/hm-user/.local/state/colima-default.log</string>
</dict>
</plist>

View file

@ -0,0 +1,3 @@
{ lib, pkgs, ... }:
(lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin (import ./darwin/default.nix))
// (lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux (import ./linux/default.nix))

View file

@ -0,0 +1,50 @@
{
config,
lib,
pkgs,
...
}:
{
services.colima = {
enable = true;
package = config.lib.test.mkStubPackage {
name = "colima";
outPath = "@colima@";
};
dockerPackage = config.lib.test.mkStubPackage {
name = "docker";
outPath = "@docker@";
};
perlPackage = config.lib.test.mkStubPackage {
name = "perl";
outPath = "@perl@";
};
sshPackage = config.lib.test.mkStubPackage {
name = "openssh";
outPath = "@openssh@";
};
coreutilsPackage = config.lib.test.mkStubPackage {
name = "coreutils";
outPath = "@coreutils@";
};
curlPackage = config.lib.test.mkStubPackage {
name = "curl";
outPath = "@curl@";
};
bashPackage = config.lib.test.mkStubPackage {
name = "bashNonInteractive";
outPath = "@bashNonInteractive@";
};
};
nmt.script = ''
assertPathNotExists home-files/.colima/default/colima.yaml
assertFileExists home-files/.config/systemd/user/colima-default.service
assertFileContent \
home-files/.config/systemd/user/colima-default.service \
${./expected-service.service}
'';
}

View file

@ -0,0 +1,3 @@
{
"colima-default-config" = ./colima-default-config.nix;
}

View file

@ -0,0 +1,19 @@
[Install]
WantedBy=default.target
[Service]
Environment=PATH=@colima@/bin:@perl@/bin:@docker@/bin:@openssh@/bin:@coreutils@/bin:@curl@/bin:@bashNonInteractive@/bin
ExecStart=@colima@/bin/colima start default \
-f \
--activate=true \
--save-config=false
Restart=always
RestartSec=2
StandardError=append:/home/hm-user/.local/state/colima-default.log
StandardOutput=append:/home/hm-user/.local/state/colima-default.log
[Unit]
After=network-online.target
Description=Colima container runtime (default profile)
Wants=network-online.target