{ lib, pkgs, config, ... }: let inherit (lib) mkIf mkEnableOption mkPackageOption mkOption ; cfg = config.programs.distrobox; generateConfig = lib.generators.toKeyValue { mkKeyValue = name: value: if lib.isString value then ''${name}="${value}"'' else "${name}=${builtins.toString value}"; }; iniFormat = pkgs.formats.ini { listsAsDuplicateKeys = true; }; iniAtomType = iniFormat.lib.types.atom; in { meta.maintainers = with lib.hm.maintainers; [ aguirre-matteo ]; options.programs.distrobox = { enable = mkEnableOption "distrobox"; package = mkPackageOption pkgs "distrobox" { nullable = true; }; enableSystemdUnit = mkOption { type = lib.types.bool; default = cfg.containers != { } && cfg.package != null; defaultText = "config.programs.distrobox.containers != { } && config.programs.distrobox.package != null"; example = false; description = '' Whatever to enable a Systemd Unit that automatically rebuilds your containers when changes are detected. ''; }; settings = mkOption { type = lib.types.attrsOf iniAtomType; default = { }; example = { container_always_pull = "1"; container_generate_entry = 0; container_manager = "docker"; container_image_default = "registry.opensuse.org/opensuse/toolbox:latest"; container_name_default = "test-name-1"; container_user_custom_home = "$HOME/.local/share/container-home-test"; container_init_hook = "~/.local/distrobox/a_custom_default_init_hook.sh"; container_pre_init_hook = "~/a_custom_default_pre_init_hook.sh"; container_manager_additional_flags = "--env-file /path/to/file --custom-flag"; container_additional_volumes = "/example:/example1 /example2:/example3:ro"; non_interactive = "1"; skip_workdir = "0"; }; description = '' Configuration settings for Distrobox. All the available options can be found here: ''; }; containers = mkOption { inherit (iniFormat) type; default = { }; example = { python-project = { image = "fedora:40"; additional_packages = "python3 git"; init_hooks = "pip3 install numpy pandas torch torchvision"; }; common-debian = { image = "debian:13"; entry = true; additional_packages = "git"; init_hooks = [ "ln -sf /usr/bin/distrobox-host-exec /usr/local/bin/docker" "ln -sf /usr/bin/distrobox-host-exec /usr/local/bin/docker-compose" ]; }; office = { clone = "common-debian"; additional_packages = "libreoffice onlyoffice"; entry = true; }; random-things = { clone = "common-debian"; entry = false; }; }; description = '' A set of containers and all its respective configurations. Each option can be either a bool, string or a list of strings. If passed a list, the option will be repeated for each element. See common-debian in the example config. All the available options for the containers can be found in the distrobox-assemble documentation at . ''; }; }; config = mkIf cfg.enable { assertions = [ (lib.hm.assertions.assertPlatform "programs.distrobox" pkgs lib.platforms.linux) { assertion = cfg.enableSystemdUnit -> (cfg.containers != { }); message = "Cannot set `programs.distrobox.enableSystemdUnit` if `programs.distrobox.containers` is unset."; } { assertion = cfg.enableSystemdUnit -> (cfg.package != null); message = "Cannot set `programs.distrobox.enableSystemdUnit` if `programs.distrobox.package` is set to null."; } ]; home.packages = mkIf (cfg.package != null) [ cfg.package ]; xdg.configFile = { "distrobox/containers.ini" = mkIf (cfg.containers != { }) { source = iniFormat.generate "distrobox-containers.ini" cfg.containers; }; "distrobox/distrobox.conf" = mkIf (cfg.settings != { }) { text = generateConfig cfg.settings; }; }; systemd.user.services.distrobox-home-manager = mkIf (cfg.enableSystemdUnit && cfg.package != null) { Unit.Description = "Build the containers declared in ~/.config/distrobox/containers.ini"; Install.WantedBy = [ "default.target" ]; Service.ExecStart = "${pkgs.writeShellScript "distrobox-home-manager" '' PATH=/run/current-system/sw/bin: containers_file=${config.xdg.configHome}/distrobox/containers.ini prev_hash_file=${config.xdg.configHome}/distrobox/prev_hash new_hash=$(sha256sum $containers_file | cut -f 1 -d " ") if [[ -f $prev_hash_file ]]; then prev_hash=$(cat $prev_hash_file) else prev_hash=0 fi if [[ $prev_hash != $new_hash ]]; then rm -rf /tmp/storage-run-1000/containers rm -rf /tmp/storage-run-1000/libpod/tmp ${cfg.package}/bin/distrobox-assemble create --file $containers_file echo $new_hash > $prev_hash_file fi ''}"; }; }; }