dev #1
10 changed files with 271 additions and 0 deletions
35
roles/deploy_container_traefik/defaults/main.yml
Normal file
35
roles/deploy_container_traefik/defaults/main.yml
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
container_traefik_version: "latest"
|
||||||
|
container_traefik_http_port: 80
|
||||||
|
container_traefik_https_port: 443
|
||||||
|
container_traefik_domain: "example.com"
|
||||||
|
container_traefik_san_domains:
|
||||||
|
- "example.com"
|
||||||
|
- "example.org"
|
||||||
|
container_traefik_cloudflare_mail: "your-email@example.com"
|
||||||
|
container_traefik_cloudflare_token: "your-cloudflare-token"
|
||||||
|
container_traefik_basicauth_user: "admin"
|
||||||
|
container_traefik_basicauth_password: "yourpassword"
|
||||||
|
|
||||||
|
# Static Traefik Routes
|
||||||
|
container_traefik_routers:
|
||||||
|
traefik:
|
||||||
|
entryPoints:
|
||||||
|
- "https"
|
||||||
|
rule: "Host(`example.example.com`)"
|
||||||
|
middlewares:
|
||||||
|
- default-headers
|
||||||
|
tls: {}
|
||||||
|
service: traefik
|
||||||
|
|
||||||
|
container_traefik_services:
|
||||||
|
traefik:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
- url: "http://127.0.0.1"
|
||||||
|
passHostHeader: true
|
||||||
|
serversTransport: insecure-https
|
||||||
|
|
||||||
|
container_traefik_serversTransports:
|
||||||
|
insecure-https:
|
||||||
|
insecureSkipVerify: true
|
0
roles/deploy_container_traefik/handlers/main.yml
Normal file
0
roles/deploy_container_traefik/handlers/main.yml
Normal file
0
roles/deploy_container_traefik/meta/main.yml
Normal file
0
roles/deploy_container_traefik/meta/main.yml
Normal file
57
roles/deploy_container_traefik/tasks/main.yml
Normal file
57
roles/deploy_container_traefik/tasks/main.yml
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
---
|
||||||
|
- name: Ensure data directories exist
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ traefik_container_dir }}/data/{{ item }}"
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
loop:
|
||||||
|
- "traefik"
|
||||||
|
- "certs"
|
||||||
|
- "logs"
|
||||||
|
- "traefik/config.d"
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Ensure log files exist
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ traefik_container_dir }}/data/logs/{{ item }}"
|
||||||
|
state: touch
|
||||||
|
mode: '0644'
|
||||||
|
loop:
|
||||||
|
- "traefik.log"
|
||||||
|
- "access.log"
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Deploy Traefik configuration files
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ item.src }}"
|
||||||
|
dest: "{{ traefik_container_dir }}/data/{{ item.dest }}"
|
||||||
|
mode: '0644'
|
||||||
|
loop:
|
||||||
|
- { src: 'traefik.yml.j2', dest: 'traefik/traefik.yml' }
|
||||||
|
- { src: 'default.yml.j2', dest: 'traefik/config.d/default.yml' }
|
||||||
|
- { src: 'hosts.yml.j2', dest: 'traefik/config.d/hosts.yml' }
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Deploy Docker Compose and .env files
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "{{ item.src }}"
|
||||||
|
dest: "{{ traefik_container_dir }}/{{ item.dest }}"
|
||||||
|
mode: '0644'
|
||||||
|
loop:
|
||||||
|
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
|
||||||
|
- { src: '.env.j2', dest: '.env' }
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Ensure Docker network exists
|
||||||
|
community.docker.docker_network:
|
||||||
|
name: traefik
|
||||||
|
state: present
|
||||||
|
docker_host: "unix:///run/user/1000/docker.sock"
|
||||||
|
become: false
|
||||||
|
|
||||||
|
- name: Start Traefik container
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
project_src: "{{ traefik_container_dir }}"
|
||||||
|
pull: always
|
||||||
|
docker_host: "unix:///run/user/1000/docker.sock"
|
||||||
|
become: false
|
29
roles/deploy_container_traefik/templates/.env.j2
Normal file
29
roles/deploy_container_traefik/templates/.env.j2
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# Traefik Version
|
||||||
|
# Defines the version of Traefik to be used. By default, "latest" is used.
|
||||||
|
TRAEFIK_VERSION={{ container_traefik_version }}
|
||||||
|
|
||||||
|
TRAEFIK_DOMAIN={{ container_traefik_domain }}
|
||||||
|
|
||||||
|
# Ports
|
||||||
|
# Defines the ports on which Traefik will be available for HTTP and HTTPS traffic.
|
||||||
|
# By default, these are 80 (HTTP) and 443 (HTTPS).
|
||||||
|
TRAEFIK_HTTP_PORT={{ container_traefik_http_port }}
|
||||||
|
TRAEFIK_HTTPS_PORT={{ container_traefik_https_port }}
|
||||||
|
|
||||||
|
# Cloudflare API Access
|
||||||
|
# Your Cloudflare API credentials that Traefik uses to automatically obtain TLS certificates
|
||||||
|
# via the Cloudflare DNS provider.
|
||||||
|
# Replace the following placeholders with your actual Cloudflare details:
|
||||||
|
# - CLOUDFLARE_MAIL: Your Cloudflare email address
|
||||||
|
# - CLOUDFLARE_TOKEN: Your Cloudflare API token
|
||||||
|
CLOUDFLARE_MAIL={{ container_traefik_cloudflare_mail }}
|
||||||
|
CLOUDFLARE_TOKEN={{ container_traefik_cloudflare_token }}
|
||||||
|
|
||||||
|
# Basic Auth Configuration
|
||||||
|
# Basic authentication credentials for securing the Traefik dashboard.
|
||||||
|
# You can generate the password using the following command:
|
||||||
|
# echo $(htpasswd -nB yourusername) | sed -e s/\\$/\\$\\$/g
|
||||||
|
# Replace `yourusername` with the desired username.
|
||||||
|
# The generated value can then be placed in the `BASICAUTH_PASSWORD` variable.
|
||||||
|
TRAEFIK_BASICAUTH_USER={{ container_traefik_basicauth_user }}
|
||||||
|
TRAEFIK_BASICAUTH_PASSWORD={{ container_traefik_basicauth_password }}
|
19
roles/deploy_container_traefik/templates/default.yml.j2
Normal file
19
roles/deploy_container_traefik/templates/default.yml.j2
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
http:
|
||||||
|
middlewares:
|
||||||
|
https-redirect:
|
||||||
|
redirectScheme:
|
||||||
|
scheme: https
|
||||||
|
|
||||||
|
default-headers:
|
||||||
|
headers:
|
||||||
|
frameDeny: true
|
||||||
|
sslRedirect: true
|
||||||
|
browserXssFilter: true
|
||||||
|
contentTypeNosniff: true
|
||||||
|
forceSTSHeader: true
|
||||||
|
stsIncludeSubdomains: true
|
||||||
|
stsPreload: true
|
||||||
|
stsSeconds: 15552000
|
||||||
|
customFrameOptionsValue: SAMEORIGIN
|
||||||
|
customRequestHeaders:
|
||||||
|
X-Forwarded-Proto: https
|
|
@ -0,0 +1,44 @@
|
||||||
|
---
|
||||||
|
services:
|
||||||
|
traefik:
|
||||||
|
image: traefik:${TRAEFIK_VERSION}
|
||||||
|
container_name: traefik
|
||||||
|
restart: always
|
||||||
|
security_opt:
|
||||||
|
- "no-new-privileges:true"
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
ports:
|
||||||
|
- ${TRAEFIK_HTTP_PORT}:80
|
||||||
|
- ${TRAEFIK_HTTPS_PORT}:443
|
||||||
|
volumes:
|
||||||
|
- /run/user/1000/docker.sock:/var/run/docker.sock:ro
|
||||||
|
- ./data/traefik:/etc/traefik
|
||||||
|
- ./data/certs:/etc/certs:ro
|
||||||
|
- ./data/logs/traefik.log:/var/log/traefik.log
|
||||||
|
- ./data/logs/access.log:/var/log/crowdsec/traefik.log
|
||||||
|
environment:
|
||||||
|
- "CF_API_EMAIL=${CLOUDFLARE_MAIL:?error}"
|
||||||
|
- "CF_DNS_API_TOKEN=${CLOUDFLARE_TOKEN:?error}"
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.traefik.entrypoints=http"
|
||||||
|
- "traefik.http.routers.traefik.rule=Host(`${TRAEFIK_DOMAIN}`)"
|
||||||
|
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
|
||||||
|
- "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
|
||||||
|
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
|
||||||
|
- "traefik.http.routers.traefik-secure.entrypoints=https"
|
||||||
|
- "traefik.http.middlewares.basic-auth.basicauth.users=${TRAEFIK_BASICAUTH_USER}:${TRAEFIK_BASICAUTH_PASSWORD}"
|
||||||
|
- "traefik.http.routers.traefik-secure.middlewares=basic-auth"
|
||||||
|
- "traefik.http.routers.traefik-secure.rule=Host(`${TRAEFIK_DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.traefik-secure.tls=true"
|
||||||
|
- "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"
|
||||||
|
{% for domain in container_traefik_san_domains %}
|
||||||
|
- "traefik.http.routers.traefik-secure.tls.domains[{{ loop.index0 }}].main={{ domain }}"
|
||||||
|
- "traefik.http.routers.traefik-secure.tls.domains[{{ loop.index0 }}].sans=*.{{ domain }}"
|
||||||
|
{% endfor %}
|
||||||
|
- "traefik.http.routers.traefik-secure.service=api@internal"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
external: true
|
42
roles/deploy_container_traefik/templates/hosts.yml.j2
Normal file
42
roles/deploy_container_traefik/templates/hosts.yml.j2
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
http:
|
||||||
|
routers:
|
||||||
|
{% for router_name, router in container_traefik_routers.items() %}
|
||||||
|
{{ router_name }}:
|
||||||
|
entryPoints:
|
||||||
|
{% for ep in router.entryPoints %}
|
||||||
|
- "{{ ep }}"
|
||||||
|
{% endfor %}
|
||||||
|
rule: "{{ router.rule }}"
|
||||||
|
{% if router.middlewares is defined and router.middlewares %}
|
||||||
|
middlewares:
|
||||||
|
{% for m in router.middlewares %}
|
||||||
|
- {{ m }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% if router.tls is defined and router.tls %}
|
||||||
|
tls: {}
|
||||||
|
{% endif %}
|
||||||
|
service: {{ router.service }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
services:
|
||||||
|
{% for service_name, service in container_traefik_services.items() %}
|
||||||
|
{{ service_name }}:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
{% for server in service.loadBalancer.servers %}
|
||||||
|
- url: "{{ server.url }}"
|
||||||
|
{% endfor %}
|
||||||
|
passHostHeader: {{ service.loadBalancer.passHostHeader | default(true) | lower }}
|
||||||
|
{% if service.loadBalancer.serversTransport is defined %}
|
||||||
|
serversTransport: {{ service.loadBalancer.serversTransport }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
serversTransports:
|
||||||
|
{% for transport_name, transport in container_traefik_serversTransports.items() %}
|
||||||
|
{{ transport_name }}:
|
||||||
|
{% for key, value in transport.items() %}
|
||||||
|
{{ key }}: {{ value | lower if value is boolean else value }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
43
roles/deploy_container_traefik/templates/traefik.yml.j2
Normal file
43
roles/deploy_container_traefik/templates/traefik.yml.j2
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
api:
|
||||||
|
dashboard: true
|
||||||
|
|
||||||
|
log:
|
||||||
|
level: INFO
|
||||||
|
format: json
|
||||||
|
filePath: "/var/log/traefik.log"
|
||||||
|
|
||||||
|
accessLog:
|
||||||
|
filePath: "/var/log/access.log"
|
||||||
|
bufferingSize: 50
|
||||||
|
|
||||||
|
entryPoints:
|
||||||
|
http:
|
||||||
|
address: ":80"
|
||||||
|
https:
|
||||||
|
address: ":443"
|
||||||
|
|
||||||
|
serversTransport:
|
||||||
|
insecureSkipVerify: false
|
||||||
|
forwardingTimeouts:
|
||||||
|
dialTimeout: 10s
|
||||||
|
responseHeaderTimeout: 10s
|
||||||
|
|
||||||
|
providers:
|
||||||
|
docker:
|
||||||
|
endpoint: "unix:///var/run/docker.sock"
|
||||||
|
exposedByDefault: false
|
||||||
|
watch: true
|
||||||
|
file:
|
||||||
|
directory: "/etc/traefik/config.d/"
|
||||||
|
watch: true
|
||||||
|
|
||||||
|
certificatesResolvers:
|
||||||
|
cloudflare:
|
||||||
|
acme:
|
||||||
|
email: "{{ container_traefik_cloudflare_mail }}"
|
||||||
|
storage: acme.json
|
||||||
|
dnsChallenge:
|
||||||
|
provider: cloudflare
|
||||||
|
resolvers:
|
||||||
|
- "1.1.1.1:53"
|
||||||
|
- "1.0.0.1:53"
|
2
roles/deploy_container_traefik/vars/main.yml
Normal file
2
roles/deploy_container_traefik/vars/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
---
|
||||||
|
traefik_container_dir: "/opt/docker/traefik"
|
Loading…
Add table
Reference in a new issue