Change:
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

Discussion:
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> }; };

default = "/var/lib/traefik"; type = types.path; description = '' <del> Location for any persistent data traefik creates, ie. acme </del> <ins> Location for any persistent data traefik creates, ie. acme </ins> ''; };

}; config = mkIf cfg.enable { <del> systemd.tmpfiles.rules = [ "d '${cfg.dataDir}' 0700 traefik traefik - -" ]; </del> <ins> systemd.tmpfiles.rules = [ "d '${cfg.dataDir}' 0700 traefik traefik - -" ]; </ins> systemd.services.traefik = { description = "Traefik web server"; after = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { <del> ExecStart = ''${cfg.package.bin}/bin/traefik --configfile=${configFile}''; </del> <ins> ExecStart = "${cfg.package}/bin/traefik --configfile=${staticConfigFile}"; </ins> Type = "simple"; User = "traefik"; Group = cfg.group;

isSystemUser = true; }; <del> users.groups.traefik = {}; </del> <ins> users.groups.traefik = { }; </ins> }; }

timezone = handleTest ./timezone.nix {}; tinydns = handleTest ./tinydns.nix {}; tor = handleTest ./tor.nix {}; <ins> # traefik test relies on docker-containers traefik = handleTestOn ["x86_64-linux"] ./traefik.nix {}; </ins> transmission = handleTest ./transmission.nix {}; trac = handleTest ./trac.nix {}; trilium-server = handleTestOn ["x86_64-linux"] ./trilium-server.nix {};

<ins> # Test Traefik as a reverse proxy of a local web service # and a Docker container. import ./make-test-python.nix ({ pkgs, ... }: { name = "traefik"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ joko ]; }; nodes = { client = { config, pkgs, ... }: { environment.systemPackages = [ pkgs.curl ]; }; traefik = { config, pkgs, ... }: { docker-containers.nginx = { extraDockerOptions = [ "-l" "traefik.enable=true" "-l" "traefik.http.routers.nginx.entrypoints=web" "-l" "traefik.http.routers.nginx.rule=Host(`nginx.traefik.test`)" ]; image = "nginx-container"; imageFile = pkgs.dockerTools.examples.nginx; }; networking.firewall.allowedTCPPorts = [ 80 ]; services.traefik = { enable = true; dynamicConfigOptions = { http.routers.simplehttp = { rule = "Host(`simplehttp.traefik.test`)"; entryPoints = [ "web" ]; service = "simplehttp"; }; http.services.simplehttp = { loadBalancer.servers = [{ url = "http://127.0.0.1:8000"; }]; }; }; staticConfigOptions = { global = { checkNewVersion = false; sendAnonymousUsage = false; }; entryPoints.web.address = ":80"; providers.docker.exposedByDefault = false; }; }; systemd.services.simplehttp = { script = "${pkgs.python3}/bin/python -m http.server 8000"; serviceConfig.Type = "simple"; wantedBy = [ "multi-user.target" ]; }; users.users.traefik.extraGroups = [ "docker" ]; }; }; testScript = '' start_all() traefik.wait_for_unit("docker-nginx.service") traefik.wait_until_succeeds("docker ps | grep nginx-container") traefik.wait_for_unit("simplehttp.service") traefik.wait_for_unit("traefik.service") traefik.wait_for_open_port(80) traefik.wait_for_unit("multi-user.target") client.wait_for_unit("multi-user.target") with subtest("Check that a container can be reached via Traefik"): assert "Hello from NGINX" in client.succeed( "curl -sSf -H Host:nginx.traefik.test http://traefik/" ) with subtest("Check that dynamic configuration works"): assert "Directory listing for " in client.succeed( "curl -sSf -H Host:simplehttp.traefik.test http://traefik/" ) ''; }) </ins>

<del> { stdenv, buildGoPackage, fetchFromGitHub, bash, go-bindata}: </del> <ins> { stdenv, buildGoModule, fetchFromGitHub, go-bindata, nixosTests }: </ins> <del> buildGoPackage rec { </del> <ins> buildGoModule rec { </ins> pname = "traefik"; <del> version = "1.7.14"; goPackagePath = "github.com/containous/traefik"; </del> <ins> version = "2.2.0"; </ins> src = fetchFromGitHub { owner = "containous"; repo = "traefik"; rev = "v${version}"; <del> sha256 = "1j3p09j8rpdkp8v4d4mz224ddakkvhzchvccm9qryrqc2fq4022v"; </del> <ins> sha256 = "1dcazssabqxr9wv3dds3z7ks3y628qa07vgnn3hpdwxzm2b2ma92"; </ins> }; <del> nativeBuildInputs = [ go-bindata bash ]; buildPhase = '' runHook preBuild ( cd go/src/github.com/containous/traefik bash ./script/make.sh generate CODENAME=$(awk -F "=" '/CODENAME=/ { print $2}' script/binary) go build -ldflags " -X github.com/containous/traefik/version.Version=${version}  -X github.com/containous/traefik/version.Codename=$CODENAME  " -a -o $bin/bin/traefik ./cmd/traefik ) runHook postBuild </del> <ins> modSha256 = "0w3ssxvsmq8i6hbfmn4ig2x13i2nlqy5q1khcblf9pq5vhk202qx"; subPackages = [ "cmd/traefik" ]; nativeBuildInputs = [ go-bindata ]; passthru.tests = { inherit (nixosTests) traefik; }; preBuild = '' go generate CODENAME=$(awk -F "=" '/CODENAME=/ { print $2}' script/binary) makeFlagsArray+=("-ldflags= -X github.com/containous/traefik/version.Version=${version}  -X github.com/containous/traefik/version.Codename=$CODENAME") </ins> ''; meta = with stdenv.lib; { homepage = "https://traefik.io"; description = "A modern reverse proxy"; license = licenses.mit; <del> maintainers = with maintainers; [ hamhut1066 vdemeester ]; </del> <ins> maintainers = with maintainers; [ vdemeester ]; </ins> }; }