diff --git a/top.sls b/top.sls index effb15ecc69f2fa8b42c2b34cee058b8d5771ed1..6f648164bf888ea384c33093fa19b34bde3b8d9c 100644 --- a/top.sls +++ b/top.sls @@ -42,6 +42,9 @@ base: - bird.ospf - kernel.sysctl - network + 'roles:traefik': + - match: pillar + - traefik 'roles:netbox': - match: pillar - netbox diff --git a/traefik/files/traefik.toml.j2 b/traefik/files/traefik.toml.j2 new file mode 100644 index 0000000000000000000000000000000000000000..67bbd21bd0bc316bbab52a8bae2e93c08a31dd05 --- /dev/null +++ b/traefik/files/traefik.toml.j2 @@ -0,0 +1,84 @@ +{% set traefik = pillar.get('traefik', {}) -%} +{% set letsencrypt = pillar.get('letsencrypt', {}) -%} +{% set letsencrypt_domains = traefik.get('letsencrypt', {}) -%} +{% set backend = traefik.get('backend', {}) -%} +{% set backend_auth = backend.get('auth', {}) -%} + +debug = {% if traefik.get('debug', false) %}true{% else %}false{% endif %} + +logLevel = "{{ traefik.get('log_level', 'ERROR') }}" +defaultEntryPoints = ["https","http"] + +[entryPoints] + [entryPoints.http] + address = ":80" + [entryPoints.http.redirect] + entryPoint = "https" + + [entryPoints.https] + address = ":443" + [entryPoints.https.tls] + + [entryPoints.traefik] + address = "127.0.0.1:8880" + + {% if backend_auth -%} + [entryPoints.traefik.auth] + [entryPoints.traefik.auth.basic] + users = [ + {%- for user,pass in backend_auth.items()|sort %} + "{{ user }}:{{ pass }}", + {%- endfor %} + ] + {%- endif %} + +[file] +[backends] + [backends.traefik-backend] + [backends.traefik-backend.servers.backend1] + url = "http://127.0.0.1:8880" + +[frontends] + [frontends.traefik-frontend] + entryPoints = ["https"] + backend = "traefik-backend" + [frontends.traefik-frontend.routes.traefik] + rule = "PathPrefixStrip:/traefik;Host:{{ backend.get('host', grains.fqdn ) }}" + +[retry] + +[docker] + endpoint = "unix:///var/run/docker.sock" + domain = "{{ traefik.get('default-domain', grains.get('domain', grains.fqdn)) }}" + watch = true + exposedByDefault = false + +{% if letsencrypt.get('email') and letsencrypt.get('agree-tos', false) and letsencrypt_domains -%} +[acme] + email = "{{ letsencrypt.email }}" + storage = "acme.json" + entryPoint = "https" + onHostRule = false + acmeLogging = {% if traefik.get('debug', false) %}true{% else %}false{% endif %} + {% if letsencrypt.get('environment', 'production') != 'staging' -%} + caServer = "https://acme-v02.api.letsencrypt.org/directory" + {%- else %} + caServer = "https://acme-staging-v02.api.letsencrypt.org/directory" + {%- endif %} + [acme.httpChallenge] + entryPoint = "http" + {% for domain, sans in letsencrypt_domains.items() %} + [[acme.domains]] + main = "{{ domain }}" + {% if sans -%} + sans = {{ sans }} + {%- endif %} + {%- endfor %} +{%- endif %} + +[api] + entryPoint = "traefik" + [api.statistics] + +[metrics.prometheus] + entryPoint = "traefik" diff --git a/traefik/init.sls b/traefik/init.sls new file mode 100644 index 0000000000000000000000000000000000000000..36334df4b9d3e0b9bbb7629282e235d8688c4f8b --- /dev/null +++ b/traefik/init.sls @@ -0,0 +1,70 @@ +{% set docker = pillar.get('docker', {}) %} +{% set traefik = pillar.get('traefik', {}) %} +{% set backend = traefik.get('backend', {}) %} +{% set volume = docker.volume_root | default('/srv/docker') ~ '/traefik' %} +{% set container = traefik.get('container', 'traefik') %} +{% set version = traefik.get('container', 'latest') %} + +include: + - docker + +docker-volume-traefik: + file.directory: + - name: {{ volume }} + - makedirs: True + - require: + - file: docker-volume-root + +{{ volume }}/traefik.toml: + file.managed: + - user: root + - group: root + - mode: 644 + - template: jinja + - source: salt://traefik/files/traefik.toml.j2 + - require: + - file: docker-volume-traefik + +{{ volume }}/acme.json: + file.managed: + - user: www-data + - group: www-data + - mode: 600 + - replace: false + - require: + - file: docker-volume-traefik + +docker-image-traefik:latest: + docker_image.present: + - name: traefik:latest + - force: true + - watch: + - pkg: docker + - require: + - file: docker-volume-root + +docker-container-traefik: + docker_container.running: + - image: traefik:latest + - name: traefik + - command: --docker + - restart_policy: always + - port_bindings: + - "80:80" + - "443:443" + - binds: + - /var/run/docker.sock:/var/run/docker.sock + - {{ volume }}/traefik.toml:/traefik.toml + - {{ volume }}/acme.json:/acme.json + - require: &traefik-require + - pkg: docker + - file: {{ volume }}/traefik.toml + - file: {{ volume }}/acme.json + - watch: *traefik-require + +grains-traefik-metrics-host: + grains.present: + - name: traefik-metrics-host + - value: {{ backend.get('host', grains.fqdn) }} + - require: + - docker_container: docker-container-traefik