Change:
let cfg = config.services.traefik; <del> configFile = if cfg.configFile == null then pkgs.runCommand "config.toml" { buildInputs = [ pkgs.remarshal ]; preferLocalBuild = true; } '' remarshal -if json -of toml  < ${pkgs.writeText "config.json" (builtins.toJSON cfg.configOptions)}  > $out '' else cfg.configFile; </del> <ins> jsonValue = with types; let valueType = nullOr (oneOf [ bool int float str (lazyAttrsOf valueType) (listOf valueType) ]) // { description = "JSON value"; emptyValue.value = { }; }; in valueType; dynamicConfigFile = if cfg.dynamicConfigFile == null then pkgs.runCommand "config.toml" { buildInputs = [ pkgs.remarshal ]; preferLocalBuild = true; } '' remarshal -if json -of toml  < ${ pkgs.writeText "dynamic_config.json" (builtins.toJSON cfg.dynamicConfigOptions) }  > $out '' else cfg.dynamicConfigFile; staticConfigFile = if cfg.staticConfigFile == null then pkgs.runCommand "config.toml" { buildInputs = [ pkgs.yj ]; preferLocalBuild = true; } '' yj -jt -i  < ${ pkgs.writeText "static_config.json" (builtins.toJSON (recursiveUpdate cfg.staticConfigOptions { providers.file.filename = "${dynamicConfigFile}"; })) }  > $out '' else cfg.staticConfigFile; </ins> in { options.services.traefik = { enable = mkEnableOption "Traefik web server"; <del> configFile = mkOption { </del> <ins> staticConfigFile = mkOption { </ins> default = null; <del> example = literalExample "/path/to/config.toml"; </del> <ins> example = literalExample "/path/to/static_config.toml"; </ins> type = types.nullOr types.path; description = '' <del> Path to verbatim traefik.toml to use. (Using that option has precedence over <literal>configOptions</literal>) </del> <ins> Path to traefik's static configuration to use. (Using that option has precedence over <literal>staticConfigOptions</literal> and <literal>dynamicConfigOptions</literal>) </ins> ''; }; <del> configOptions = mkOption { </del> <ins> staticConfigOptions = mkOption { </ins> description = '' <del> Config for Traefik. </del> <ins> Static configuration for Traefik. </ins> ''; <del> type = types.attrs; default = { defaultEntryPoints = ["http"]; entryPoints.http.address = ":80"; }; </del> <ins> type = jsonValue; default = { entryPoints.http.address = ":80"; }; </ins> example = { <del> defaultEntrypoints = [ "http" ]; web.address = ":8080"; </del> <ins> entryPoints.web.address = ":8080"; </ins> entryPoints.http.address = ":80"; <del> file = {}; frontends = { frontend1 = { backend = "backend1"; routes.test_1.rule = "Host:localhost"; }; }; backends.backend1 = { servers.server1.url = "http://localhost:8000"; </del> <ins> api = { }; }; }; dynamicConfigFile = mkOption { default = null; example = literalExample "/path/to/dynamic_config.toml"; type = types.nullOr types.path; description = '' Path to traefik's dynamic configuration to use. (Using that option has precedence over <literal>dynamicConfigOptions</literal>) ''; }; dynamicConfigOptions = mkOption { description = '' Dynamic configuration for Traefik. ''; type = jsonValue; default = { }; example = { http.routers.router1 = { rule = "Host(`localhost`)"; service = "service1"; </ins> }; <ins> http.services.service1.loadBalancer.servers = [{ url = "http://localhost:8080"; }]; </ins> }; };

Discussion:
Project description Traefik is a microservice oriented reverse proxy written in Go. It configures itself by container labels from docker/other provider or from text files. It does TLS termination and can fetch certs from let's encrypt automatically. A nixOS module to add configuration to the file backend (similar to the nginx ones) seems easy to implement. Traefik 1.0 is currently packaged (, ) Traefik 2.0 is NOT backwards compatible A package for 2.0 (not source built) has been written up by Metadata homepage URL: source URL: license: MIT platforms: linux, darwin, freebsd, openbsd, windows