commit d7ee3ce4965b17f73674f7704eb6c41e7d4386e7 Author: olli Date: Sun Jul 10 10:51:13 2022 +0200 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/traefik.yml b/traefik.yml new file mode 100644 index 0000000..1ea9561 --- /dev/null +++ b/traefik.yml @@ -0,0 +1,296 @@ +--- + +- name: traefik + hosts: all + tasks: + + - name: Create a network + community.docker.docker_network: + name: traefik + enable_ipv6: yes + driver_options: + com.docker.network.bridge.name: br-traefik + ipam_config: + - subnet: 192.168.41.0/24 + gateway: 192.168.41.1 + # Local v6 IP + - subnet: fdaa:a192:b168:cd41::/64 + gateway: fdaa:a192:b168:cd41::1 + notify: Restart traefik + + - name: /home/docker/traefik/docker-compose.yml Traefik Container Configuration + blockinfile: + path: /home/docker/traefik/docker-compose.yml + create: yes + mode: 0440 + owner: root + group: docker + marker: "# {mark} ANSIBLE MANAGED BLOCK" + block: | + version: '3.6' + services: + traefik: + image: traefik:latest + #extra_hosts: + # - "host.docker.internal:host-gateway" + command: + # Try to enable this if something isn't working. + # Chances are, Traefik will tell you why. + # Be careful in production as it exposes the traffic you might not want to expose. + - --log.level=INFO + # http -> https redirect + - --entrypoints.http.address=:80 + - --entrypoints.http.http.redirections.entryPoint.to=https + - --entrypoints.http.http.redirections.entryPoint.scheme=https + - --entrypoints.http.http.redirections.entrypoint.permanent=true + - --entrypoints.https.address=:443 + # Docker + - --providers.docker=true + - --providers.docker.endpoint=unix:///var/run/docker.sock + - --providers.docker.exposedByDefault=false + # Traefik + - --api=true + - --api.dashboard=true + - --api.insecure=false + # LetsEncrypt + # Staging Server - uncomment when testing + #- --certificatesResolvers.letsencrypt.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory + - --certificatesresolvers.letsencrypt.acme.httpchallenge=true + - --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=http + - --certificatesresolvers.letsencrypt.acme.email=ssl@{{inventory_hostname}} + - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json + # non-docker services + - --providers.file=true + - --providers.file.directory=/etc/traefik/providers.local + - --providers.file.watch=true + container_name: traefik + restart: unless-stopped + security_opt: + - no-new-privileges:true + networks: + traefik: + ipv4_address: 192.168.41.200 + ports: + - 80:80 + - 443:443 + volumes: + - /etc/localtime:/etc/localtime:ro + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./letsencrypt:/letsencrypt + - ./providers:/etc/traefik/providers.local + labels: + - traefik.enable=true + - traefik.http.routers.traefik.rule=Host(`traefik.{{inventory_hostname}}`) + - traefik.http.routers.traefik.entrypoints=https + - traefik.http.routers.traefik.middlewares=secHeaders@file,auth + - traefik.http.routers.traefik.service=api@internal + - traefik.http.routers.traefik.tls=true + - traefik.http.routers.traefik.tls.certresolver=letsencrypt + - traefik.http.middlewares.to-https.redirectscheme.scheme=https + # echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g + - traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$XLxGs/Ba$$3phZ1a2RtfExOp8x6NFjZ. + networks: + traefik: + external: true + + backup: yes + notify: Restart traefik + + - name: Create traefik dir + ansible.builtin.file: + path: /home/docker/traefik/providers + owner: root + group: docker + state: directory + mode: '0755' + + - name: Defaults for TLS,... + blockinfile: + path: /home/docker/traefik/providers/_default.yml + create: yes + mode: 0444 + owner: root + group: docker + marker: "# {mark} ANSIBLE MANAGED BLOCK" + block: | + --- + tls: + options: + default: + minVersion: VersionTLS12 + cipherSuites: + - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 # TLS 1.2 + - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 # TLS 1.2 + - TLS_AES_256_GCM_SHA384 # TLS 1.3 + - TLS_CHACHA20_POLY1305_SHA256 # TLS 1.3 + curvePreferences: + - CurveP521 + - CurveP384 + sniStrict: true + http: + middlewares: + secHeaders: + compress: false + headers: + browserXssFilter: true + contentTypeNosniff: true + frameDeny: true + # HSTS Configuration + forceSTSHeader: true + stsIncludeSubdomains: true + stsPreload: true + stsSeconds: 31536000 + customFrameOptionsValue: "SAMEORIGIN" + sslProxyHeaders: + X-Forwarded-Proto: "https" + notify: Restart traefik + + - name: /usr/local/sbin/traefik-qualys-ssl-labs-check.sh + blockinfile: + path: /usr/local/sbin/traefik-qualys-ssl-labs-check.sh + mode: "0700" + owner: root + group: root + create: yes + marker: "# {mark} ANSIBLE MANAGED BLOCK" + block: | + . /etc/bash/gaboshlib.include + g_lockfile + g_nice + g_all-to-syslog + g_echo_ok "Starting $0" + + + # Using official API-CLI-Tool + # https://www.ssllabs.com/projects/ssllabs-apis/ + # https://github.com/ssllabs/ssllabs-scan/ + + # Download and install if unavailable + if ! [ -f /usr/local/bin/ssllabs-scan ] + then + cd /tmp + rm -rf ssllabs-scan + git clone https://github.com/ssllabs/ssllabs-scan/ || g_echo_error "Could not download ssllabs-scan" + cd ssllabs-scan + make >${g_tmp}/ssllabs-scan-make.out + if [ -f ssllabs-scan-v3 ] + then + cp ssllabs-scan-v3 /usr/local/bin/ssllabs-scan + chmod 755 /usr/local/bin/ssllabs-scan + chown root. /usr/local/bin/ssllabs-scan + else + g_echo_error "Could not build ssllabs-scan $(cat ${g_tmp}/ssllabs-scan-make.out)" + fi + fi + + # Check every Traefik Host + if [ -f /usr/local/bin/ssllabs-scan ] + then + find /home/docker -maxdepth 1 -mindepth 1 -type d | while read dir + do + if grep -q Host "$dir"/docker-compose.override.yml >/dev/null 2>&1 + then + grep Host "$dir"/docker-compose.override.yml >>$g_tmp/hosts + else + [ -f "$dir"/docker-compose.yml ] && grep Host "$dir"/docker-compose.yml >>$g_tmp/hosts + fi + done + grep Host /home/docker/traefik/providers/*.yml >>$g_tmp/hosts + cat $g_tmp/hosts | cut -d '`' -f2 | sort -u | while read host + do + ssllabs-scan --quiet ${host} | jq '.[] | .endpoints | .[] | .grade' >${g_tmp}/ssllabs-scan-result + if ! grep -q 'A+' ${g_tmp}/ssllabs-scan-result + then + if ! grep -q T ${g_tmp}/ssllabs-scan-result + then + g_echo_error "Qualys SSL Labs scan-result for ${host} not A+: $(cat ${g_tmp}/ssllabs-scan-result) + + https://www.ssllabs.com/ssltest/analyze.html?d=${host}&hideResults=on" + fi + else + g_echo_ok "Qualys SSL Labs scan-result for ${host}: $(cat ${g_tmp}/ssllabs-scan-result)" + fi + done + fi + backup: yes + validate: /bin/bash -n %s + + - name: /usr/local/sbin/traefik-qualys-ssl-labs-check.sh shebang + lineinfile: + path: /usr/local/sbin/traefik-qualys-ssl-labs-check.sh + insertbefore: BOF + line: "#!/bin/bash" + + - name: /usr/local/sbin/runchecks.d/traefik.check + blockinfile: + path: /usr/local/sbin/runchecks.d/traefik.check + mode: "0700" + owner: root + group: root + create: yes + marker: "# {mark} ANSIBLE MANAGED BLOCK" + block: | + find /home/docker -maxdepth 1 -mindepth 1 -type d | while read dir + do + if grep -q Host "$dir"/docker-compose.override.yml >/dev/null 2>&1 + then + grep Host "$dir"/docker-compose.override.yml >>$g_tmp/hosts + else + [ -f "$dir"/docker-compose.yml ] && grep Host "$dir"/docker-compose.yml >>$g_tmp/hosts + fi + done + grep Host /home/docker/traefik/providers/*.yml >>$g_tmp/hosts + + cat $g_tmp/hosts | cut -d '`' -f2 | sort -u | while read host + do + if ! wget --dns-timeout=120 -t5 --waitretry=120 --connect-timeout=300 --read-timeout=15 http://${host} >${g_tmp}/traefik-wget-check -O /dev/null 2>&1 + then + if ! grep -q "401 Unauthorized" ${g_tmp}/traefik-wget-check + then + g_echo_error "Error while connecting ${host} with wget: + + $(cat ${g_tmp}/traefik-wget-check)" + fi + fi + done + backup: yes + validate: /bin/bash -n %s + + - name: /etc/cron.d/traefik-qualys-ssl-labs-check_local + blockinfile: + path: /etc/cron.d/traefik-qualys-ssl-labs-check_local + create: yes + mode: 0644 + owner: root + group: root + marker: "# {mark} ANSIBLE MANAGED BLOCK" + block: | + @daily root /usr/local/sbin/traefik-qualys-ssl-labs-check.sh + backup: yes + + - name: Allow http from all clients + community.general.ufw: + rule: allow + port: '80' + proto: tcp + + - name: Allow https from all clients + community.general.ufw: + rule: allow + port: '443' + proto: tcp + + - name: Allow access from br-traefik to Docker-Host for services running without docker + community.general.ufw: + rule: allow + interface: br-traefik + direction: in + + + handlers: + + - name: Restart traefik + ansible.builtin.shell: docker-compose up -d + args: + chdir: /home/docker/traefik +