{ config, lib, ... }: let cfg = config.smalltech.haproxy; # The important thing here is `configText`; you might find it useful to # read this bit bottom-to-top to understand how it's built. mkDirectiveText = directive: " " + directive; mkSectionText = header: directives: builtins.concatStringsSep "\n" ([header] ++ (map mkDirectiveText directives)); mkFrontendText = name: directives: mkSectionText "frontend ${name}" directives; mkBackendText = name: directives: mkSectionText "backend ${name}" directives; globalText = mkSectionText "global" cfg.global; defaultsText = mkSectionText "defaults" cfg.defaults; allFrontendTexts = builtins.attrValues (builtins.mapAttrs mkFrontendText cfg.frontends); allBackendTexts = builtins.attrValues (builtins.mapAttrs mkBackendText cfg.backends); allSectionTexts = [globalText defaultsText] ++ allFrontendTexts ++ allBackendTexts; configText = builtins.concatStringsSep "\n\n" allSectionTexts; in { imports = [ ]; options = { smalltech.haproxy = lib.mkOption { description = '' Options used to provide a higher-level way to configure HAProxy, as opposed to writing out an entire config file as a string literal. ''; type = lib.types.submodule { options = { global = lib.mkOption { type = lib.types.listOf lib.types.str; description = '' Directives to go in HAProxy's "global" section. Ordering is significant. ''; default = [ ]; example = [ "log /dev/log local0 info" "maxconn 2048" ]; }; defaults = lib.mkOption { type = lib.types.listOf lib.types.str; description = '' Directives to go in HAProxy's "defaults" section. Ordering is significant. ''; default = [ ]; example = [ "mode tcp" "log global" ]; }; frontends = lib.mkOption { type = lib.types.attrsOf (lib.types.listOf lib.types.str); description = '' An attribute set of HAProxy frontend definitions; each gives a name and a list of directives. Within each frontend, the ordering of directives is significant. ''; default = { }; example = { "multi_https" = [ "bind 127.0.0.1:443 ssl" "mode http" "use_backend local_https" ]; "multi_http" = [ "bind 127.0.0.1:80" "mode http" "use_backend redirect_to_https" ]; }; }; backends = lib.mkOption { type = lib.types.attrsOf (lib.types.listOf lib.types.str); description = '' An attribute set of HAProxy backend definitions; each gives a name and a list of directives. Within each backend, the ordering of directives is significant. ''; default = { }; example = { "local_https" = [ "server local_https 127.0.0.1:3000 maxconn 256" ]; "redirect_to_https" = [ "http-request redirect scheme https code 301" ]; }; }; }; }; }; }; config = { services.haproxy = { config = configText; }; }; }