From 8eff0a45fccaf453f8988ce3afe74a86cc39117f Mon Sep 17 00:00:00 2001 From: Jan Beilicke Date: Mon, 23 Mar 2020 23:42:14 +0100 Subject: [PATCH] Initial commit --- .travis.yml | 29 ++++++++++++ LICENSE | 19 ++++++++ README.md | 42 ++++++++++++++++++ defaults/main.yml | 18 ++++++++ handlers/main.yml | 2 + meta/main.yml | 53 ++++++++++++++++++++++ tasks/main.yml | 59 +++++++++++++++++++++++++ templates/docker-compose.traefik.yml.j2 | 38 ++++++++++++++++ templates/traefik.toml.j2 | 48 ++++++++++++++++++++ tests/inventory | 2 + tests/test.yml | 5 +++ vars/main.yml | 2 + 12 files changed, 317 insertions(+) create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 defaults/main.yml create mode 100644 handlers/main.yml create mode 100644 meta/main.yml create mode 100644 tasks/main.yml create mode 100644 templates/docker-compose.traefik.yml.j2 create mode 100644 templates/traefik.toml.j2 create mode 100644 tests/inventory create mode 100644 tests/test.yml create mode 100644 vars/main.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..86aa256 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +MIT License Copyright (c) 2020 Jan Beilicke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1b20408 --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +Traefik (Docker-Compose) +======================== + +Traefik acts as a reverse proxy and loadbalancer in container environments. It will handle Let's Encrypt certificates for Docker Compose services automatically. + +Requirements +------------ + +- Ubuntu or Debian server +- [Docker Engine](https://docs.docker.com/install/) + [Docker Compose](https://docs.docker.com/compose/install/) + +Role Variables +-------------- + +``` +traefik_virtual_host: localhost +traefik: + expose_internally: True + expose_externally: False + use_acme_staging: True + dns_challenge_provider: False + # NOT WORKING YET! + # Extra mapping, for name -> internal address, like myservice: 'http://otherhost:12345' + #extra_mapping: + # myservice: http://otherhost:12345 + # use key:value pairs here to add additional environment variables to your traefik docker image. + # for instance, if you're using a dns challenge provider place your api keys etc here. + #additional_env_vars: + # # DUMMY_KEY: DUMMY_VALUE + # CLOUDFLARE_EMAIL: EMAIL + # CLOUDFLARE_API_KEY: API_KEY +``` + +License +------- + +MIT + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..3f5aad1 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,18 @@ +--- +# defaults file for traefik +traefik_virtual_host: localhost +traefik: + expose_internally: True + expose_externally: False + use_acme_staging: True + dns_challenge_provider: False + # NOT WORKING YET! + # Extra mapping, for name -> internal address, like myservice: 'http://otherhost:12345' + #extra_mapping: + # myservice: http://otherhost:12345 + # use key:value pairs here to add additional environment variables to your traefik docker image. + # for instance, if you're using a dns challenge provider place your api keys etc here. + #additional_env_vars: + # # DUMMY_KEY: DUMMY_VALUE + # CLOUDFLARE_EMAIL: EMAIL + # CLOUDFLARE_API_KEY: API_KEY \ No newline at end of file diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..d95fb00 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for traefik \ No newline at end of file diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..227ad9c --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..4a21e83 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,59 @@ +--- +# tasks file for traefik + +- name: Ensure traefik config directory exists + file: + path: /home/{{ docker_user }}/traefik + state: directory + owner: '{{ docker_user }}' + group: '{{ docker_user }}' + tags: config + +- name: Provide docker-compose.yml + template: + src: templates/docker-compose.traefik.yml.j2 + dest: /home/{{ docker_user }}/traefik/docker-compose.yml + owner: "{{ docker_user }}" + group: "{{ docker_user }}" + mode: '0644' + tags: config + +- name: Provide traefik.toml + template: + src: templates/traefik.toml.j2 + dest: /home/{{ docker_user }}/traefik/traefik.toml + owner: "{{ docker_user }}" + group: "{{ docker_user }}" + mode: '0644' + tags: config + +- name: Configure SSL + copy: + content: "" + force: no + dest: /home/{{ docker_user }}/traefik/acme.json + mode: 0600 + state: touch + tags: config + +- name: "docker-compose: Teardown existing Traefik service (only removes the containers)" + docker_compose: + project_src: "/home/{{ docker_user }}/traefik/" + state: absent + tags: ['never', 'teardown'] + +- name: "docker-compose: Start Traefik service" + docker_compose: + project_src: "/home/{{ docker_user }}/traefik/" + register: output + tags: service_start + +- debug: + var: output + +- name: "Waiting for Traefik service (443/TLS) to become available" + become: false + wait_for: + host: "{{ ansible_ssh_host }}" + port: 443 + delegate_to: localhost diff --git a/templates/docker-compose.traefik.yml.j2 b/templates/docker-compose.traefik.yml.j2 new file mode 100644 index 0000000..b7006be --- /dev/null +++ b/templates/docker-compose.traefik.yml.j2 @@ -0,0 +1,38 @@ +--- +version: '3' + +networks: + traefik: + driver: bridge + +services: + # Load Balancer / SSL / Web Server + traefik: + image: traefik:v2.1 + restart: always + networks: + - traefik + ports: +{% if traefik.expose_internally | default(False) %} + - "8181:8080" +{% endif %} + - "80:80" + - "443:443" +{% if traefik.additional_env_vars | default(False) %} + environment: +{% for item in traefik.additional_env_vars | dict2items %} + - {{item.key}}={{item.value}} +{% endfor %} +{% endif %} + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /home/{{ docker_user }}/traefik/traefik.toml:/traefik.toml + - /home/{{ docker_user }}/traefik/acme.json:/acme.json +{% if traefik.expose_externally | default(False) %} + labels: + - "traefik.enable=true" + - "traefik.docker.network=traefik" + - "traefik.http.frontend.rule=Host:traefik.{{ traefik_virtual_host }}" + - "traefik.http.protocol=http" + - "traefik.http.port=8080" +{% endif %} diff --git a/templates/traefik.toml.j2 b/templates/traefik.toml.j2 new file mode 100644 index 0000000..37fa613 --- /dev/null +++ b/templates/traefik.toml.j2 @@ -0,0 +1,48 @@ +defaultEntryPoints = ["web", "websecure"] + +[log] + level = "ERROR" + +[entryPoints] + [entryPoints.web] + address = ":80" + [entryPoints.websecure] + address = ":443" + +#[api] +# dashboard = true +# insecure = true + +[file] +watch = true + +[providers.docker] + endpoint = "unix:///var/run/docker.sock" + exposedByDefault = false + +[certificatesResolvers.defaultresolver.acme] +{% if traefik.use_acme_staging %} + caServer = "https://acme-staging-v02.api.letsencrypt.org/directory" +{% endif %} + email = "{{ letsencrypt_email }}" + storage = "acme.json" + [certificatesResolvers.defaultresolver.acme.httpChallenge] + entryPoint = "web" + +{% if traefik.extra_mapping | default(False) %} +### NOT WORKING YET! +#[backends] +{% for service_name in traefik.extra_mapping %} +#[backends.{{ service_name }}_backend] +# [backends.{{ service_name }}_backend.servers.server1] +# url = "{{ traefik.extra_mapping[service_name] }}" +{% endfor %} +# +#[frontends] +{% for service_name in traefik.extra_mapping %} +# [frontends.{{ service_name }}_frontend] +# backend = "{{ service_name }}_backend" +# [frontends.{{ service_name }}_frontend.routes.test_1] +# rule = "Host: {{ service_name }}.{{ domain }}" +{% endfor %} +{% endif %} diff --git a/tests/inventory b/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/tests/test.yml b/tests/test.yml new file mode 100644 index 0000000..62bdc80 --- /dev/null +++ b/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - traefik \ No newline at end of file diff --git a/vars/main.yml b/vars/main.yml new file mode 100644 index 0000000..f311284 --- /dev/null +++ b/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for traefik \ No newline at end of file