{ config, lib, pkgs, ... }: with lib; { options.services.myDockerStacks = mkOption { type = types.attrsOf (types.submodule { options = { path = mkOption { type = types.path; }; ports = mkOption { type = types.listOf types.int; default = []; }; }; }); default = {}; description = "Attribute set of docker-compose stacks to run."; }; config = { # Generate the systemd services based on the options provided above systemd.services = mapAttrs' (name: value: nameValuePair "${name}_stack" { description = "${name} via Docker Compose"; after = [ "network-online.target" "docker.service" ]; wants = [ "network-online.target" "docker.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { WorkingDirectory = value.path; ExecStartPre = "${pkgs.docker-compose}/bin/docker-compose down"; ExecStart = "${pkgs.docker-compose}/bin/docker-compose up -d"; ExecStop = "${pkgs.docker-compose}/bin/docker-compose down"; RemainAfterExit = true; }; }) config.services.myDockerStacks; # Automatically open firewall ports networking.firewall.allowedTCPPorts = flatten (mapAttrsToList (n: v: v.ports) config.services.myDockerStacks); }; }