version: '3.7'

services:
  ingress:
    image: traefik:v2.8.4
    networks:
      - inbound
      - traefik
    ports:
      - target: 80
        published: 80
        mode: host
      - target: 443
        published: 443
        mode: host
      - target: 8080
        published: 8080
        protocol: tcp
        mode: ingress
    command:
      ###                          ###
      # Traefik Global Configuration #
      ###                          ###
      # Enable DEBUG logs
      - '--ping=true'
      - '--api.insecure=true'
      # Enable api access without authentification (only GET route so it only possible to get IPs)
      # Set the provider to Docker
      - '--accesslog=true'
      - '--accesslog.filepath=/logs/access.log'
      - '--accessLog.bufferingSize=100' # Configuring a buffer of 100 lines
      # Set the docker network
      - '--providers.docker=true'
      - '--providers.docker.network=traefik'
      - '--providers.docker.swarmMode=true'
      # - '--providers.providersThrottleDuration=2s'
      # Set to docker swarm cluster
      - '--metrics.prometheus=true'
      - '--metrics.prometheus.addEntryPointsLabels=true'
      - '--metrics.prometheus.addServicesLabels=true'
      - '--metrics.prometheus.buckets=0.1,0.3,1.2,5.0'
      # If False : Do not expose containers to the web by default
      # - "--providers.docker.exposedByDefault=false"
      # Default rule to service-name.example.com
      # Default http port
      - '--entrypoints.web.address=:80'
      # Default https port
      - '--entrypoints.websecure.address=:443'
      # Enable let's encrypt
      - "--certificatesResolvers.zerossl.acme.httpChallenge=true"
      - '--certificatesResolvers.zerossl.acme.httpChallenge.entrypoint=web'
      # - '--certificatesResolvers.zerossl.acme.caServer=https://acme.zerossl.com/v2/DV90'
      - '--certificatesResolvers.zerossl.acme.email=tomas.krcal@geekcoders.cz'
      - '--certificatesResolvers.zerossl.acme.storage=/acme.json'
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./acme.json:/acme.json
      - ./access.log:/logs/access.log
    deploy:
      placement:
        constraints:
          - "node.role==manager"
      mode: global
      labels:
        ###               ###
        # Traefik Dashboard #
        ###               ###
        # Enable this endpoint
        - traefik.enable=true
        - traefik.docker.network=inbound
        ##
        # Http
        #
        # Set the service route
        - traefik.http.routers.traefik_http.rule=Host(`monitor.${BASE_HOST}`)
        # Set the entrypoint (http or https)
        - traefik.http.routers.traefik_http.entrypoints=web
        ##
        # Register Middlewares
        #
        #
        # Prevent DDOS
        - traefik.http.middlewares.ratelimit.ratelimit.average=50
        - traefik.http.middlewares.ratelimit.ratelimit.burst=70
        - traefik.http.middlewares.ratelimit.ratelimit.period=1
        # VPN
        - traefik.http.middlewares.vpn.ipwhitelist.sourcerange=92.119.66.178/32, 127.0.0.1/32, 0.0.0.0/32
        - traefik.http.middlewares.traefik-auth.basicauth.users=admin:$2a$12$IkE6p/N84M.mP3NYm5KqV.sFPY0RxbxZ1exBupB9/ZhLd7nyuwkwG

        # Security headers
        - traefik.http.middlewares.security-headers.headers.customrequestheaders.X-Frame-Options=SAMEORIGIN
        - traefik.http.middlewares.security-headers.headers.contentTypeNosniff=true
        - traefik.http.middlewares.security-headers.headers.referrerPolicy=no-referrer
        - traefik.http.middlewares.security-headers.headers.browserXssFilter=true
        - traefik.http.middlewares.security-headers.headers.stsSeconds=15552000
        - traefik.http.middlewares.security-headers.headers.forceSTSHeader=true
        # Health check
        - traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100
        # Rule to redirect to http to https
        - traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https
        # Enable Https redirection
        - traefik.http.routers.traefik_http.middlewares=traefik-https-redirect@docker
        ##
        # Https
        #
        - traefik.http.routers.traefik_https.rule=Host(`monitor.${BASE_HOST}`)
        # Set the entrypoint (http or https)
        - traefik.http.routers.traefik_https.entrypoints=websecure
        - traefik.http.routers.traefik_https.tls=true
        # Enable certificat creation
        - traefik.http.routers.traefik_https.tls.certresolver=zerossl
        # Set VPN Middleware
        # - traefik.http.routers.traefik_https.middlewares=vpn@docker
        # Set the service port
        - traefik.http.services.traefik.loadbalancer.server.port=8080


      restart_policy:
        condition: any
        delay: 5s
        max_attempts: 3
        window: 120s
      update_config:
        delay: 10s
        order: stop-first
        parallelism: 1
      rollback_config:
        parallelism: 0
        order: stop-first
    logging:
      driver: json-file
      options:
        'max-size': '10m'
        'max-file': '5'

  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus/:/etc/prometheus/
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.enable-lifecycle'
      - '--web.console.libraries=/usr/share/prometheus/console_libraries'
      - '--web.console.templates=/usr/share/prometheus/consoles'
    networks:
      - inbound
      - traefik
    deploy:
      labels:
        - traefik.enable=true
        - traefik.docker.network=inbound
        - traefik.http.routers.prometheus_http.rule=Host(`prometheus.${BASE_HOST}`)
        # Set the entrypoint (http or https)
        - traefik.http.routers.prometheus_http.entrypoints=web
        # Enable Https redirection
        # - traefik.http.routers.prometheus_http.middlewares=traefik-https-redirect@docker
        ##
        # Https
        #
        - traefik.http.routers.prometheus_https.rule=Host(`prometheus.${BASE_HOST}`)
        # Set the entrypoint (http or https)
        - traefik.http.routers.prometheus_https.entrypoints=websecure
        - traefik.http.routers.prometheus_https.tls=true
        # Enable Let's encrypt auto certificat creation
        # - traefik.http.routers.prometheus_https.tls.certresolver=zerossl
        # - traefik.http.routers.prometheus_https.middlewares=vpn@docker
        - traefik.http.routers.prometheus_https.middlewares=traefik-auth@docker
        - traefik.http.routers.prometheus_https.service=prometheus
        - traefik.http.services.prometheus.loadbalancer.server.port=9090

      restart_policy:
        condition: on-failure

  node_exporter:
    image: prom/node-exporter
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.rootfs=/rootfs'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)'
    ports:
      - 9100
    networks:
      - inbound
    labels:
      org.label-schema.group: "monitoring"
    deploy:
      mode: global

      restart_policy:
        condition: on-failure

  grafana:
    image: grafana/grafana
    depends_on:
      - prometheus
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana/provisioning/:/etc/grafana/provisioning/
    env_file:
      - ./grafana/config.monitoring
    networks:
      - inbound
      - traefik
    user: "104"
    deploy:
      labels:
        - traefik.enable=true
        - traefik.docker.network=inbound
        - traefik.http.routers.grafana_http.rule=Host(`grafana.${BASE_HOST}`)
        # Set the entrypoint (http or https)
        - traefik.http.routers.grafana_http.entrypoints=web
        # Enable Https redirection
        - traefik.http.routers.grafana_http.middlewares=traefik-https-redirect@docker
        ##
        # Https
        #
        - traefik.http.routers.grafana_https.rule=Host(`grafana.${BASE_HOST}`)
        # Set the entrypoint (http or https)
        - traefik.http.routers.grafana_https.entrypoints=websecure
        - traefik.http.routers.grafana_https.tls=true
        # Enable Let's encrypt auto certificat creation
        - traefik.http.routers.grafana_https.tls.certresolver=zerossl
        # Set VPN Middleware
        # - traefik.http.routers.grafana_https.middlewares=vpn@docker, latency-check@docker
        - traefik.http.routers.grafana_https.service=grafana
        - traefik.http.services.grafana.loadbalancer.server.port=3000

      restart_policy:
        condition: on-failure


networks:
  traefik:
    driver: overlay
    name: traefik
  inbound:
    driver: overlay
    external: true
    name: inbound

volumes:
  prometheus_data: { }
  grafana_data: { }
