From 07f1844c582e80087bc721ea032ec3400d47bec3 Mon Sep 17 00:00:00 2001 From: Ioannis Koutras Date: Sun, 29 Dec 2019 16:01:19 +0100 Subject: [PATCH 1/4] traefik: 1.7.14 -> 2.2.0 --- pkgs/servers/traefik/default.nix | 40 ++++++++++++++------------------ 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/pkgs/servers/traefik/default.nix b/pkgs/servers/traefik/default.nix index d2a784cdf1317..cb3f01d77ee2b 100644 --- a/pkgs/servers/traefik/default.nix +++ b/pkgs/servers/traefik/default.nix @@ -1,39 +1,35 @@ -{ stdenv, buildGoPackage, fetchFromGitHub, bash, go-bindata}: +{ stdenv, buildGoModule, fetchFromGitHub, go-bindata }: -buildGoPackage rec { +buildGoModule rec { pname = "traefik"; - version = "1.7.14"; - - goPackagePath = "github.com/containous/traefik"; + version = "2.2.0"; src = fetchFromGitHub { owner = "containous"; repo = "traefik"; rev = "v${version}"; - sha256 = "1j3p09j8rpdkp8v4d4mz224ddakkvhzchvccm9qryrqc2fq4022v"; + sha256 = "1dcazssabqxr9wv3dds3z7ks3y628qa07vgnn3hpdwxzm2b2ma92"; }; - 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 + modSha256 = "0w3ssxvsmq8i6hbfmn4ig2x13i2nlqy5q1khcblf9pq5vhk202qx"; + subPackages = [ "cmd/traefik" ]; + + nativeBuildInputs = [ go-bindata ]; + + 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") ''; meta = with stdenv.lib; { homepage = "https://traefik.io"; description = "A modern reverse proxy"; license = licenses.mit; - maintainers = with maintainers; [ hamhut1066 vdemeester ]; + maintainers = with maintainers; [ vdemeester ]; }; } From bc766b003a3e98159c8f0c46a1689bb70e4a40c2 Mon Sep 17 00:00:00 2001 From: Ioannis Koutras Date: Tue, 31 Dec 2019 01:41:18 +0100 Subject: [PATCH 2/4] nixos/traefik: Adapt to traefik v2 This commit: 1. Updates the path of the traefik package, so that the out output is used. 2. Adapts the configuration settings and options to Traefik v2. 3. Formats the NixOS traefik service using nixfmt. --- .../modules/services/web-servers/traefik.nix | 109 +++++++++++------- 1 file changed, 70 insertions(+), 39 deletions(-) diff --git a/nixos/modules/services/web-servers/traefik.nix b/nixos/modules/services/web-servers/traefik.nix index 5b0fc467ea469..436136f4736a2 100644 --- a/nixos/modules/services/web-servers/traefik.nix +++ b/nixos/modules/services/web-servers/traefik.nix @@ -4,56 +4,88 @@ with lib; let cfg = config.services.traefik; - 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; - + 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; in { options.services.traefik = { enable = mkEnableOption "Traefik web server"; - configFile = mkOption { + staticConfigFile = mkOption { default = null; - example = literalExample "/path/to/config.toml"; + example = literalExample "/path/to/static_config.toml"; type = types.nullOr types.path; description = '' - Path to verbatim traefik.toml to use. - (Using that option has precedence over configOptions) + Path to traefik's static configuration to use. + (Using that option has precedence over staticConfigOptions and dynamicConfigOptions) ''; }; - configOptions = mkOption { + staticConfigOptions = mkOption { description = '' - Config for Traefik. + Static configuration for Traefik. ''; type = types.attrs; - default = { - defaultEntryPoints = ["http"]; - entryPoints.http.address = ":80"; - }; + default = { entryPoints.http.address = ":80"; }; example = { - defaultEntrypoints = [ "http" ]; - web.address = ":8080"; + entryPoints.web.address = ":8080"; entryPoints.http.address = ":80"; - file = {}; - frontends = { - frontend1 = { - backend = "backend1"; - routes.test_1.rule = "Host:localhost"; - }; - }; - backends.backend1 = { - servers.server1.url = "http://localhost:8000"; + 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 dynamicConfigOptions) + ''; + }; + + dynamicConfigOptions = mkOption { + description = '' + Dynamic configuration for Traefik. + ''; + type = types.attrs; + default = { }; + example = { + http.routers.router1 = { + rule = "Host(`localhost`)"; + service = "service1"; }; + + http.services.service1.loadBalancer.servers = + [{ url = "http://localhost:8080"; }]; }; }; @@ -61,7 +93,7 @@ in { default = "/var/lib/traefik"; type = types.path; description = '' - Location for any persistent data traefik creates, ie. acme + Location for any persistent data traefik creates, ie. acme ''; }; @@ -84,16 +116,15 @@ in { }; config = mkIf cfg.enable { - systemd.tmpfiles.rules = [ - "d '${cfg.dataDir}' 0700 traefik traefik - -" - ]; + systemd.tmpfiles.rules = [ "d '${cfg.dataDir}' 0700 traefik traefik - -" ]; systemd.services.traefik = { description = "Traefik web server"; after = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { - ExecStart = ''${cfg.package.bin}/bin/traefik --configfile=${configFile}''; + ExecStart = + "${cfg.package}/bin/traefik --configfile=${staticConfigFile}"; Type = "simple"; User = "traefik"; Group = cfg.group; @@ -120,6 +151,6 @@ in { isSystemUser = true; }; - users.groups.traefik = {}; + users.groups.traefik = { }; }; } From 1f61fbf3260dc01afd4d44d309aef682d3558fb3 Mon Sep 17 00:00:00 2001 From: Ioannis Koutras Date: Sat, 8 Feb 2020 12:38:38 +0100 Subject: [PATCH 3/4] nixos/traefik: make config deep mergeable --- nixos/modules/services/web-servers/traefik.nix | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/nixos/modules/services/web-servers/traefik.nix b/nixos/modules/services/web-servers/traefik.nix index 436136f4736a2..4ab7307c3b671 100644 --- a/nixos/modules/services/web-servers/traefik.nix +++ b/nixos/modules/services/web-servers/traefik.nix @@ -4,6 +4,20 @@ with lib; let cfg = config.services.traefik; + 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 ]; @@ -52,7 +66,7 @@ in { description = '' Static configuration for Traefik. ''; - type = types.attrs; + type = jsonValue; default = { entryPoints.http.address = ":80"; }; example = { entryPoints.web.address = ":8080"; @@ -76,7 +90,7 @@ in { description = '' Dynamic configuration for Traefik. ''; - type = types.attrs; + type = jsonValue; default = { }; example = { http.routers.router1 = { From 9360e3723dd9a0c3aa13000bfce2ccc2a974a27e Mon Sep 17 00:00:00 2001 From: Ioannis Koutras Date: Mon, 6 Apr 2020 08:21:35 +0200 Subject: [PATCH 4/4] nixos/traefik: add test --- nixos/tests/all-tests.nix | 2 + nixos/tests/traefik.nix | 87 ++++++++++++++++++++++++++++++++ pkgs/servers/traefik/default.nix | 4 +- 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 nixos/tests/traefik.nix diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 5819879b30e9e..4f60892488ab3 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -303,6 +303,8 @@ in timezone = handleTest ./timezone.nix {}; tinydns = handleTest ./tinydns.nix {}; tor = handleTest ./tor.nix {}; + # traefik test relies on docker-containers + traefik = handleTestOn ["x86_64-linux"] ./traefik.nix {}; transmission = handleTest ./transmission.nix {}; trac = handleTest ./trac.nix {}; trilium-server = handleTestOn ["x86_64-linux"] ./trilium-server.nix {}; diff --git a/nixos/tests/traefik.nix b/nixos/tests/traefik.nix new file mode 100644 index 0000000000000..0e21a7cf8437f --- /dev/null +++ b/nixos/tests/traefik.nix @@ -0,0 +1,87 @@ +# 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/" + ) + ''; +}) diff --git a/pkgs/servers/traefik/default.nix b/pkgs/servers/traefik/default.nix index cb3f01d77ee2b..0487ed177d045 100644 --- a/pkgs/servers/traefik/default.nix +++ b/pkgs/servers/traefik/default.nix @@ -1,4 +1,4 @@ -{ stdenv, buildGoModule, fetchFromGitHub, go-bindata }: +{ stdenv, buildGoModule, fetchFromGitHub, go-bindata, nixosTests }: buildGoModule rec { pname = "traefik"; @@ -16,6 +16,8 @@ buildGoModule rec { nativeBuildInputs = [ go-bindata ]; + passthru.tests = { inherit (nixosTests) traefik; }; + preBuild = '' go generate