Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Traefik: 1.7.14 -> 2.2.0 #76723

Merged
merged 4 commits into from
Apr 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 85 additions & 40 deletions nixos/modules/services/web-servers/traefik.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,64 +4,110 @@ 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;

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;
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 <literal>configOptions</literal>)
Path to traefik's static configuration to use.
Mic92 marked this conversation as resolved.
Show resolved Hide resolved
(Using that option has precedence over <literal>staticConfigOptions</literal> and <literal>dynamicConfigOptions</literal>)
'';
};

configOptions = mkOption {
staticConfigOptions = mkOption {
description = ''
Config for Traefik.
Static configuration for Traefik.
'';
type = types.attrs;
default = {
defaultEntryPoints = ["http"];
entryPoints.http.address = ":80";
};
type = jsonValue;
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 <literal>dynamicConfigOptions</literal>)
'';
};

dynamicConfigOptions = mkOption {
description = ''
Dynamic configuration for Traefik.
'';
type = jsonValue;
default = { };
example = {
http.routers.router1 = {
rule = "Host(`localhost`)";
service = "service1";
};

http.services.service1.loadBalancer.servers =
[{ url = "http://localhost:8080"; }];
};
};

dataDir = mkOption {
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
'';
};

Expand All @@ -84,16 +130,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;
Expand All @@ -120,6 +165,6 @@ in {
isSystemUser = true;
};

users.groups.traefik = {};
users.groups.traefik = { };
};
}
2 changes: 2 additions & 0 deletions nixos/tests/all-tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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 {};
Expand Down
87 changes: 87 additions & 0 deletions nixos/tests/traefik.nix
Original file line number Diff line number Diff line change
@@ -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/"
)
'';
})
42 changes: 20 additions & 22 deletions pkgs/servers/traefik/default.nix
Original file line number Diff line number Diff line change
@@ -1,39 +1,37 @@
{ stdenv, buildGoPackage, fetchFromGitHub, bash, go-bindata}:
{ stdenv, buildGoModule, fetchFromGitHub, go-bindata, nixosTests }:

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 ];
jokogr marked this conversation as resolved.
Show resolved Hide resolved

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")
'';

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 ];
};
}