Skip to content
Snippets Groups Projects
Commit 41326fe3 authored by jurgenhaas's avatar jurgenhaas
Browse files

Update Traefik to 2.9

Update Portainer to 2.17.1
Update Hub to 1.0.1
Add support for automatic cert renewal with http or dns challenge
parent af048bc5
No related branches found
No related tags found
1 merge request!8Merging develop into main [MINOR_VERSION]
Pipeline #783431 passed
...@@ -17,42 +17,67 @@ class Traefik { ...@@ -17,42 +17,67 @@ class Traefik {
* *
* @var string * @var string
*/ */
protected $name; protected string $name;
/** /**
* @var string * @var string
*/ */
protected $domain; protected string $domain;
/** /**
* @var int * @var int
*/ */
protected $http_port; protected int $http_port;
/** /**
* @var int * @var int
*/ */
protected $https_port; protected int $https_port;
/** /**
* @var string * @var string
*/ */
protected $cert_filename; protected string $cert_filename;
/** /**
* @var string * @var string
*/ */
protected $key_filename; protected string $key_filename;
/** /**
* @var bool * @var bool
*/ */
protected $addon_portainer = FALSE; protected bool $addon_portainer = FALSE;
/** /**
* @var string * @var string
*/ */
protected $hub_token = ''; protected string $hub_token = '';
/**
* @var array
*/
protected array $env;
/**
* @var bool
*/
protected bool $tls;
/**
* @var bool
*/
protected bool $dns_challenge;
/**
* @var string
*/
protected string $dns_challenge_provider;
/**
* @var string
*/
protected string $dns_challenge_resolver;
/** /**
* Traefik constructor. * Traefik constructor.
...@@ -70,14 +95,45 @@ class Traefik { ...@@ -70,14 +95,45 @@ class Traefik {
* Filename of the SSL certificate. * Filename of the SSL certificate.
* @param string $key_filename * @param string $key_filename
* Filename of the private key for the SSL certificate. * Filename of the private key for the SSL certificate.
* @param array $env
* A list of environment variables for the Traefik container.
* @param bool $tls
* Whether TLS should be supported.
* @param bool $dns_challenge
* If TLS is supported, it uses the http challenge by default. Set to TRUE
* to use the DNS challenge.
* @param string $dns_challenge_provider
* If DNS challenge should be used, a provider is required. For a list of
* supported providers:
* @see https://doc.traefik.io/traefik/https/acme/#providers
* @param string $dns_challenge_resolver
* In some scenarios, the DNS resolver needs to be defined in order to
* prevent local or shadow DNS servers being used.
*/ */
public function __construct(string $name, $domain = 'docker.localhost', $http_port = 8000, $https_port = 8443, $cert_filename = 'fullchain.pem', $key_filename = 'privkey.pem') { public function __construct(
string $name,
string $domain = 'docker.localhost',
int $http_port = 8000,
int $https_port = 8443,
string $cert_filename = '',
string $key_filename = '',
array $env = [],
bool $tls = FALSE,
bool $dns_challenge = FALSE,
string $dns_challenge_provider = '',
string $dns_challenge_resolver = ''
) {
$this->name = $name; $this->name = $name;
$this->domain = $domain; $this->domain = $domain;
$this->http_port = $http_port; $this->http_port = $http_port;
$this->https_port = $https_port; $this->https_port = $https_port;
$this->cert_filename = $cert_filename; $this->cert_filename = $cert_filename;
$this->key_filename = $key_filename; $this->key_filename = $key_filename;
$this->env = $env;
$this->tls = $tls;
$this->dns_challenge = $dns_challenge;
$this->dns_challenge_provider = $dns_challenge_provider;
$this->dns_challenge_resolver = $dns_challenge_resolver;
} }
/** /**
...@@ -146,6 +202,13 @@ class Traefik { ...@@ -146,6 +202,13 @@ class Traefik {
* @return bool * @return bool
*/ */
private function updateFile(string $filename, string $content): bool { private function updateFile(string $filename, string $content): bool {
if ($content === '') {
if (file_exists($filename)) {
unlink($filename);
return TRUE;
}
return FALSE;
}
if (file_exists($filename) && file_get_contents($filename) === $content) { if (file_exists($filename) && file_get_contents($filename) === $content) {
return FALSE; return FALSE;
} }
...@@ -162,15 +225,13 @@ class Traefik { ...@@ -162,15 +225,13 @@ class Traefik {
'services' => [ 'services' => [
'traefik' => [ 'traefik' => [
'container_name' => 'traefik', 'container_name' => 'traefik',
'image' => 'traefik:2.7', 'image' => 'traefik:2.9',
'command' => [ 'command' => [
'--api=true', '--api=true',
'--api.dashboard=true', '--api.dashboard=true',
'--api.insecure=true', '--api.insecure=true',
'--log.level=warning',
'--entrypoints.web.address=:80', '--entrypoints.web.address=:80',
'--entrypoints.websecure.address=:443',
'--entrypoints.websecure.http.tls.domains[0].main=' . $this->domain,
'--entrypoints.websecure.http.tls.domains[0].sans=.' . $this->domain,
'--providers.file.directory=/configuration/', '--providers.file.directory=/configuration/',
'--providers.file.watch=true', '--providers.file.watch=true',
'--providers.docker=true', '--providers.docker=true',
...@@ -182,7 +243,6 @@ class Traefik { ...@@ -182,7 +243,6 @@ class Traefik {
], ],
'ports' => [ 'ports' => [
$this->http_port . ':80', $this->http_port . ':80',
$this->https_port . ':443',
], ],
'labels' => [ 'labels' => [
'traefik.enable=true', 'traefik.enable=true',
...@@ -203,10 +263,13 @@ class Traefik { ...@@ -203,10 +263,13 @@ class Traefik {
], ],
], ],
]; ];
if (!empty($this->env)) {
$config['services']['traefik']['environment'] = $this->env;
}
if ($this->addon_portainer) { if ($this->addon_portainer) {
$config['services']['portainer'] = [ $config['services']['portainer'] = [
'container_name' => 'portainer', 'container_name' => 'portainer',
'image' => 'portainer/portainer-ce:2.11.1', 'image' => 'portainer/portainer-ce:2.17.1',
'command' => '-H unix:///var/run/docker.sock', 'command' => '-H unix:///var/run/docker.sock',
'restart' => 'unless-stopped', 'restart' => 'unless-stopped',
'networks' => [ 'networks' => [
...@@ -238,7 +301,7 @@ class Traefik { ...@@ -238,7 +301,7 @@ class Traefik {
$config['services']['traefik']['ports'][] = '9901:9901'; $config['services']['traefik']['ports'][] = '9901:9901';
$config['services']['hub-agent'] = [ $config['services']['hub-agent'] = [
'container_name' => 'hub-agent', 'container_name' => 'hub-agent',
'image' => 'ghcr.io/traefik/hub-agent-traefik:v0.7.0', 'image' => 'ghcr.io/traefik/hub-agent-traefik:v1.0.1',
'command' => [ 'command' => [
'run', 'run',
'--hub.token=' . $this->hub_token, '--hub.token=' . $this->hub_token,
...@@ -258,6 +321,33 @@ class Traefik { ...@@ -258,6 +321,33 @@ class Traefik {
], ],
]; ];
} }
if ($this->tls) {
$config['services']['traefik']['command'][] = '--entrypoints.websecure.address=:443';
$config['services']['traefik']['command'][] = '--entrypoints.web.http.redirections.entrypoint.to=websecure';
$config['services']['traefik']['command'][] = '--certificatesresolvers.lakedrops.acme.email=admin@' . $this->domain;
$config['services']['traefik']['ports'][] = $this->https_port . ':443';
$config['services']['traefik']['labels'][] = 'traefik.http.routers.traefik.tls=true';
$config['services']['traefik']['labels'][] = 'traefik.http.routers.traefik.tls.certresolver=lakedrops';
if ($this->addon_portainer) {
$config['services']['portainer']['labels'][] = 'traefik.http.routers.traefik.tls=true';
$config['services']['portainer']['labels'][] = 'traefik.http.routers.traefik.tls.certresolver=lakedrops';
}
if ($this->hub_token) {
$config['services']['hub-agent']['labels'][] = 'traefik.http.routers.traefik.tls=true';
$config['services']['hub-agent']['labels'][] = 'traefik.http.routers.traefik.tls.certresolver=lakedrops';
}
if ($this->dns_challenge && $this->dns_challenge_provider !== '') {
$config['services']['traefik']['command'][] = '--certificatesresolvers.lakedrops.acme.dnschallenge=true';
$config['services']['traefik']['command'][] = '--certificatesresolvers.lakedrops.acme.dnschallenge.provider=' . $this->dns_challenge_provider;
if ($this->dns_challenge_resolver !== '') {
$config['services']['traefik']['command'][] = '--certificatesresolvers.lakedrops.acme.dnschallenge.resolvers=' . $this->dns_challenge_resolver;
}
}
else {
$config['services']['traefik']['command'][] = '--certificatesresolvers.lakedrops.acme.storage=/etc/traefik/acme/acme.json';
$config['services']['traefik']['command'][] = '--certificatesresolvers.lakedrops.acme.httpchallenge.entrypoint=web';
}
}
return $config; return $config;
} }
...@@ -265,6 +355,9 @@ class Traefik { ...@@ -265,6 +355,9 @@ class Traefik {
* @return string * @return string
*/ */
private function defaultCertificatesConfig(): string { private function defaultCertificatesConfig(): string {
if ($this->cert_filename === '' || $this->key_filename === '') {
return '';
}
return <<<EOF return <<<EOF
[[tls.certificates]] [[tls.certificates]]
certFile = "/certs/$this->cert_filename" certFile = "/certs/$this->cert_filename"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment