Skip to content

Instantly share code, notes, and snippets.

@lifeofguenter
Created July 31, 2026 08:30
Show Gist options
  • Select an option

  • Save lifeofguenter/ccee0eb4a4fa8f50a1512644bf5e4697 to your computer and use it in GitHub Desktop.

Select an option

Save lifeofguenter/ccee0eb4a4fa8f50a1512644bf5e4697 to your computer and use it in GitHub Desktop.
Docker with Ansible
---
- name: Create grafana network
community.docker.docker_network:
name: grafana
become: true
- name: Create grafana-mysql volume
community.docker.docker_volume:
name: grafana-mysql
labels:
keepme: 'true'
become: true
- name: Run grafana-mysql
community.docker.docker_container:
name: grafana-mysql
image: mysql:8.4-bookworm
pull: always
memory: 2g
memory_swap: 0
restart_policy: always
env:
MYSQL_ROOT_PASSWORD: ''
MYSQL_DATABASE: grafana
capabilities:
- SYS_NICE
command:
- --disable-log-bin
- --max-connections=128
## Performance ##
- --innodb-buffer-pool-size=1g # keep at 80% of total memory
volumes:
- grafana-mysql:/var/lib/mysql
networks:
- name: grafana
healthcheck:
test: ['CMD', 'mysqladmin', 'ping', '-h', '127.0.0.1', '-p${MYSQL_ROOT_PASSWORD}']
start_period: 10s
interval: 20s
timeout: 5s
retries: 3
comparisons:
command: strict
networks: strict
env: strict
healthcheck: strict
become: true
- name: Run grafana
community.docker.docker_container:
name: grafana
image: grafana/grafana:latest
pull: always
memory: 2g
memory_swap: 0
restart_policy: always
env:
GF_LOG_LEVEL: warn
GF_SERVER_ROOT_URL: https://grafana.yourdomain.com
GF_DATABASE_TYPE: mysql
GF_DATABASE_HOST: grafana-mysql:3306
GF_DATABASE_NAME: grafana
GF_DATABASE_USER: root
GF_DATABASE_PASSWORD: ""
GF_AUTH_ANONYMOUS_HIDE_VERSION: 'true'
# https://grafana.com/docs/grafana/latest/setup-grafana/configure-access/configure-authentication/generic-oauth/#configuration-options
GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION: "true"
GF_AUTH_DISABLE_LOGIN_FORM: "true"
GF_AUTH_OAUTH_ALLOW_INSECURE_EMAIL_LOOKUP: "true"
GF_AUTH_GENERIC_OAUTH_ENABLED: "true"
GF_AUTH_GENERIC_OAUTH_NAME: Auth
GF_AUTH_GENERIC_OAUTH_CLIENT_ID: ""
GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET: ""
GF_AUTH_GENERIC_OAUTH_SCOPES: openid email profile groups
GF_AUTH_GENERIC_OAUTH_AUTH_URL: https://auth.yourdomain.com/authorize
GF_AUTH_GENERIC_OAUTH_TOKEN_URL: https://auth.yourdomain.com/api/oidc/token
GF_AUTH_GENERIC_OAUTH_API_URL: https://auth.yourdomain.com/api/oidc/userinfo
GF_AUTH_GENERIC_OAUTH_USE_PKCE: "true"
GF_AUTH_GENERIC_OAUTH_USE_REFRESH_TOKEN: "true"
GF_AUTH_GENERIC_OAUTH_AUTO_LOGIN: "true"
GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP: "true"
GF_AUTH_GENERIC_OAUTH_ALLOW_ASSIGN_GRAFANA_ADMIN: "true"
GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH: contains(groups[*], 'admin') && 'GrafanaAdmin' || 'Viewer'
labels:
traefik.enable: "true"
traefik.docker.network: services
traefik.http.routers.grafana.rule: !unsafe "Host(`grafana.yourdomain.com`)"
traefik.http.routers.grafana.entrypoints: websecure
traefik.http.routers.grafana.tls: "true"
traefik.http.routers.grafana.tls.certresolver: default
traefik.http.routers.grafana.tls.domains[0].main: yourdomain.com
traefik.http.routers.grafana.tls.domains[0].sans: "*.yourdomain.com"
traefik.http.middlewares.grafana_whitelist.ipwhitelist.sourcerange: "{{ known_ips | join(', ') }}"
traefik.http.routers.grafana.middlewares: grafana_whitelist@docker
networks:
- name: services
- name: grafana
healthcheck:
test: ['CMD-SHELL', 'wget -q --spider --proxy=off 127.0.0.1:3000/healthz || exit 1']
start_period: 10s
interval: 20s
timeout: 5s
retries: 3
comparisons:
labels: strict
networks: strict
env: strict
healthcheck: strict
become: true
---
- name: Create traefik-acme volume
community.docker.docker_volume:
name: traefik-acme
labels:
keepme: 'true'
become: true
- name: Create traefik network
community.docker.docker_network:
name: services
become: true
- name: Run traefik
community.docker.docker_container:
name: traefik
image: traefik:3
pull: always
memory: 1g
memory_swap: 0
restart_policy: always
command:
- --ping=true
- --global.checknewversion=false
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.websecure.address=:443
- --entryPoints.websecure.http3
- --certificatesresolvers.default.acme.email=YOUR@EMAIL.COM
- --certificatesresolvers.default.acme.keytype=EC384
- --certificatesresolvers.default.acme.storage=/etc/traefik/acme/acme.json
- --certificatesresolvers.default.acme.dnschallenge=true
- --certificatesresolvers.default.acme.dnschallenge.provider=cloudflare
env:
CF_DNS_API_TOKEN: "xxx"
ports:
- '0.0.0.0:80:80'
- '0.0.0.0:443:443/tcp'
- '0.0.0.0:443:443/udp'
- '[::]:80:80'
- '[::]:443:443/tcp'
- '[::]:443:443/udp'
volumes:
- traefik-acme:/etc/traefik/acme
mounts:
- type: bind
source: /var/run/docker.sock
target: /var/run/docker.sock
read_only: true
networks:
- name: services
healthcheck:
test: ['CMD', 'traefik', 'healthcheck', '--ping']
start_period: 10s
interval: 20s
timeout: 5s
retries: 3
comparisons:
command: strict
volumes: strict
networks: strict
healthcheck: strict
become: true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment