Skip to content

Instantly share code, notes, and snippets.

@paulknulst
Created October 22, 2022 21:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paulknulst/58543c289a08d193d9fbe850750ce0a9 to your computer and use it in GitHub Desktop.
Save paulknulst/58543c289a08d193d9fbe850750ce0a9 to your computer and use it in GitHub Desktop.
Uptime Kuma Docker Compose file to run in a Docker Swarm with Traefik reverse proxy.
version: '3.6'
services:
uptime-kuma:
image: louislam/uptime-kuma:latest
container_name: uptime-kuma
volumes:
- data:/app/data
restart: always
networks:
- traefik-public
deploy:
placement:
constraints:
- node.labels.monitor == true
labels:
- traefik.enable=true
- traefik.docker.network=traefik-public
- traefik.constraint-label=traefik-public
- traefik.http.routers.uptime-kuma-http.rule=Host(`monitor.${PRIMARY_DOMAIN?Variable not set}`)
- traefik.http.routers.uptime-kuma-http.entrypoints=http
- traefik.http.routers.uptime-kuma-http.middlewares=https-redirect
- traefik.http.routers.uptime-kuma-https.rule=Host(`monitor.${PRIMARY_DOMAIN?Variable not set}`)
- traefik.http.routers.uptime-kuma-https.entrypoints=https
- traefik.http.routers.uptime-kuma-https.tls=true
- traefik.http.routers.uptime-kuma-https.tls.certresolver=le
- traefik.http.services.uptime-kuma.loadbalancer.server.port=3001
networks:
traefik-public:
external: true
volumes:
data:
@PatelShukan
Copy link

hello Paul,
I tried the script but looks like the service is running but I am not able to access it from the URL
I get 504 on browser
no error in traefik, I can see the service on the dashboard with correct traefik-public network ip address
service itself is running ok no issue but cannot access it from the url

@paulknulst
Copy link
Author

Are you using Docker in Swarm mode? Or do you use a simple single server Docker environment?
If you use Swarm, check if cert resolver, entrypoints and everything else is correct.
Please see this tutorial for traefik swarm setup: https://www.paulsblog.dev/services-you-want-to-have-in-a-swarm-environment/

And this one for traefik single server setup: https://www.paulsblog.dev/how-to-setup-traefik-with-automatic-letsencrypt-certificate-resolver/

Alternatively, you can see both Uptime Kuma installation setups (Swarm/normal) in this article: https://www.paulsblog.dev/use-docker-uptime-kuma-and-traefik-to-monitor-your-website/

@PatelShukan
Copy link

PatelShukan commented Apr 10, 2024

version: '3.5'

services:

  traefik:
    # Use the latest v2.6.1 Traefik image available
    image: traefik:latest
    ports:
      # Listen on port 80, default for HTTP, necessary to redirect to HTTPS
      - 80:80
      # Listen on port 443, default for HTTPS
      - 443:443
    deploy:
      placement:
        constraints:
          # Make the traefik service run only on the node with this label
          # as the node with it has the volume for the certificates
          - node.labels.traefik-public.traefik-public-certificates == true
      labels:
        # Enable Traefik for this service, to make it available in the public network
        - traefik.enable=true
        # Use the traefik-public network (declared below)
        - traefik.docker.network=traefik-public
        # Use the custom label "traefik.constraint-label=traefik-public"
        # This public Traefik will only use services with this label
        # That way you can add other internal Traefik instances per stack if needed
        - traefik.constraint-label=traefik-public
        # admin-auth middleware with HTTP Basic auth
        # Using the environment variables USERNAME and HASHED_PASSWORD
        - traefik.http.middlewares.admin-auth.basicauth.users=${USERNAME?Variable not set}:${HASHED_PASSWORD?Variable not set}
        # https-redirect middleware to redirect HTTP to HTTPS
        # It can be re-used by other stacks in other Docker Compose files
        - traefik.http.middlewares.https-redirect.redirectscheme.scheme=https
        - traefik.http.middlewares.https-redirect.redirectscheme.permanent=true
        # traefik-http set up only to use the middleware to redirect to https
        # Uses the environment variable DOMAIN
        - traefik.http.routers.traefik-public-http.rule=Host(`${DOMAIN?Variable not set}`)
        - traefik.http.routers.traefik-public-http.entrypoints=http
        - traefik.http.routers.traefik-public-http.middlewares=https-redirect
        # traefik-https the actual router using HTTPS
        # Uses the environment variable DOMAIN
        - traefik.http.routers.traefik-public-https.rule=Host(`${DOMAIN?Variable not set}`)
        - traefik.http.routers.traefik-public-https.entrypoints=https
        - traefik.http.routers.traefik-public-https.tls=true
        # Use the special Traefik service api@internal with the web UI/Dashboard
        - traefik.http.routers.traefik-public-https.service=api@internal
        # Use the "le" (Let's Encrypt) resolver created below
        - traefik.http.routers.traefik-public-https.tls.certresolver=le
        # Enable HTTP Basic auth, using the middleware created above
        - traefik.http.routers.traefik-public-https.middlewares=admin-auth
        # Define the port inside of the Docker service to use
        - traefik.http.services.traefik-public.loadbalancer.server.port=8080
    volumes:
      # Add Docker as a mounted volume, so that Traefik can read the labels of other services
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /etc/localtime:/etc/localtime:ro
      # Mount the volume to store the certificates
      #- traefik-public-certificates:/certificates
      - /mnt/nfs/docker/swarm_traefik/letsencrypt:/letsencrypt
    command:
      # We need to read in the static configs as well
      #- --providers.file=true
      #- --providers.file.filename=/rules.toml
      #- --providers.file.watch=true
      # Enable Docker in Traefik, so that it reads labels from Docker services
      - --providers.docker
      - --providers.docker.network=traefik-public
      # Add a constraint to only use services with the label "traefik.constraint-label=traefik-public"
      - --providers.docker.constraints=Label(`traefik.constraint-label`, `traefik-public`)
      # Do not expose all Docker services, only the ones explicitly exposed
      - --providers.docker.exposedbydefault=false
      # Enable Docker Swarm mode
      - --providers.docker.swarmmode
      # Create an entrypoint "http" listening on port 80
      - --entrypoints.http.address=:80
      # Create an entrypoint "https" listening on port 443
      - --entrypoints.https.address=:443
      # Create the certificate resolver "le" for Let's Encrypt, uses the environment variable EMAIL
      - --certificatesresolvers.le.acme.email=${EMAIL?Variable not set}
      # Store the Let's Encrypt certificates in the mounted volume
      - --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
      # Use the TLS Challenge for Let's Encrypt
      - --certificatesresolvers.le.acme.tlschallenge=true
      - --certificatesResolvers.le.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory
      # Enable the access log, with HTTP requests
      - --accesslog
      # Enable the Traefik log, for configurations and errors
      - --log
      # Enable the Dashboard and API
      - --api
    networks:
      # Use the public network created to be shared between Traefik and
      # any other service that needs to be publicly available with HTTPS
      - traefik-public
networks:
  # Use the previously created public network "traefik-public", shared with other
  # services that need to be publicly available via this Traefik
  traefik-public:
    external: true`
    ```
    ```
version: '3.7
services: 
  kuma: 
    image: louislam/uptime-kuma:latest
    ports:
      - 3001:3001
    environment: 
      - PUID=1020
      - PGID=1020
      - TZ=America/New_York
    networks:
      - net
      - traefik-public
    volumes: 
      - /mnt/nfs/docker/swarm/up/data:/app/data
    deploy:
      labels:
        - traefik.enable=true
        - traefik.docker.network=traefik-public
        - traefik.constraint-label=traefik-public
        - traefik.http.routers.kuma-http.rule=Host(`xx`)
        - traefik.http.routers.kuma-http.entrypoints=http
        - traefik.http.routers.kuma-http.middlewares=https-redirect
        - traefik.http.routers.kuma-https.rule=Host(`xx`)
        - traefik.http.routers.kuma-https.entrypoints=https
        - traefik.http.routers.kuma-https.tls=true
        - traefik.http.routers.kuma-https.tls.certresolver=le
        - traefik.http.services.kuma.loadbalancer.server.port=3001

networks:
  net:
    driver: overlay
    attachable: true
  traefik-public:
    external: true`
    ```

@PatelShukan
Copy link

PatelShukan commented Apr 10, 2024

I tried with a simple nginx service but the worker 1 cannot access service running on any other worker or manager

and I cannot see all the containers running on traefik-public , all nodes show different containers ( only the container running on their particular node)

docker network inspect traefik-public -- from manager node
[
    {
        "Name": "traefik-public",
        "Id": "rzjip2e6swqvjwlo1c1k5gnvk",
        "Created": "2024-04-10T13:51:59.545083422Z",
        "Scope": "swarm",
        "Driver": "overlay",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.0.11.0/24",
                    "Gateway": "10.0.11.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "8712a5d3dec503b1202ae96f124d94df482902ee5d48990f0cb67a50d81c69fc": {
                "Name": "portainer_portainer.1.rv2lp342z0sck4datww5xapva",
                "EndpointID": "695762636a73a8d5c6a197fbe94e809eccf1ec9515fcbec07e86a2c159d69744",
                "MacAddress": "02:42:0a:00:0b:06",
                "IPv4Address": "10.0.11.6/24",
                "IPv6Address": ""
            },
            "d70c7097c459cc13e9cfe9ba448619bda1b7a0da881c61862f26ed042a83a4e7": {
                "Name": "traefik_traefik.1.l65qlwvapadztavbcqbd1ie00",
                "EndpointID": "bc55c0a221a0457bc926f73a22f3cc4e5d740cfa957f5606213cb48d2ead0b3d",
                "MacAddress": "02:42:0a:00:0b:07",
                "IPv4Address": "10.0.11.7/24",
                "IPv6Address": ""
            },
            "lb-traefik-public": {
                "Name": "traefik-public-endpoint",
                "EndpointID": "e80130764e2939b10a21a06251a7b8f9d4560a5c933193bd3face8a03d57f9d4",
                "MacAddress": "02:42:0a:00:0b:09",
                "IPv4Address": "10.0.11.9/24",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.driver.overlay.vxlanid_list": "4108"
        },
        "Labels": {},
        "Peers": [
            {
                "Name": "f3399340f093",
                "IP": "192.168.0.44"
            },
            {
                "Name": "ea2cc75fbf59",
                "IP": "192.168.0.43"
            },
            {
                "Name": "6a679237cf2f",
                "IP": "192.168.0.50"
            }
        ]
    }
]


docker network inspect -- from worker node

docker network inspect traefik-public
[
    {
        "Name": "traefik-public",
        "Id": "rzjip2e6swqvjwlo1c1k5gnvk",
        "Created": "2024-04-10T13:51:50.69893543Z",
        "Scope": "swarm",
        "Driver": "overlay",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.0.11.0/24",
                    "Gateway": "10.0.11.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "1d25441fc115302bfdab4850941ae4fcdba2b4c49b1a92ad079b339ba627e948": {
                "Name": "kuma_kuma.1.usa7hookwh5kcvudd17pya2e1",
                "EndpointID": "279f50cfce6392e51871af168b4afc65fa898b42d42a3828df799db3181149af",
                "MacAddress": "02:42:0a:00:0b:03",
                "IPv4Address": "10.0.11.3/24",
                "IPv6Address": ""
            },
            "lb-traefik-public": {
                "Name": "traefik-public-endpoint",
                "EndpointID": "6ed97c4ab54f5c6309e097e31b83c4845619fb98f4f90b9783091ea5f1ce2241",
                "MacAddress": "02:42:0a:00:0b:04",
                "IPv4Address": "10.0.11.4/24",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.driver.overlay.vxlanid_list": "4108"
        },
        "Labels": {},
        "Peers": [
            {
                "Name": "6a679237cf2f",
                "IP": "192.168.0.50"
            },
            {
                "Name": "ea2cc75fbf59",
                "IP": "192.168.0.43"
            },
            {
                "Name": "f3399340f093",
                "IP": "192.168.0.44"
            }
        ]
    }
]

@paulknulst
Copy link
Author

Im not sure if you created your Docker Swarm correctly. Also I don't know if using a folder for letsencrypt/acme.json works as you did it.
For me, I had to do it like I explained in the previously mentioned articles. Also I had to change the permissions of acme.json file to 600.
Then I do not see any constraints for uptime kuma but I see absolute volume paths which will create the volumes on the worker where i t is deployed. Maybe change to use relative paths so that container volumes will be created in docker folder (/var/lib/docker/volumes).

I would try to use production lets encrypt server instead of staging.
Sorry but I cannot help more. Try to use the same prerequisite I did in my tutorial. Then it should work. To know how to set up a Docker Swarm environment correctly check this article which contains every needed step to set up a Docker Swarm in ~15 minutes: https://www.paulsblog.dev/docker-swarm-in-a-nutshell/

@PatelShukan
Copy link

followed your tutorial to create the swarm and deploy the swarm
permissions for acme.json is set to 600
regarding the volumes, I would want them to share a common volume (NFS) that is why /mnt/nfs/docker
all the nodes have access to this share and is configured correctly -- checked by login into each node

@paulknulst
Copy link
Author

If I have a look at the readme on Uptime Kuma repository at https://github.com/louislam/uptime-kuma it says that NFS is not supported. So please test without using an NFS.

From Uptime Kuma:

Warning
File Systems like NFS (Network File System) are NOT supported. Please map to a local directory or volume.

@PatelShukan
Copy link

still no good

version: '3.7' 
services: 
  kuma: 
    image: louislam/uptime-kuma:latest
    networks:
      - traefik-public
    volumes: 
      - data:/app/data
    deploy:
      labels:
        - traefik.enable=true
        - traefik.docker.network=traefik-public
        - traefik.constraint-label=traefik-public
        - traefik.http.routers.kuma-http.rule=Host(`time.bitsandbots.cc`)
        - traefik.http.routers.kuma-http.entrypoints=http
        - traefik.http.routers.kuma-http.middlewares=https-redirect
        - traefik.http.routers.kuma-https.rule=Host(`time.bitsandbots.cc`)
        - traefik.http.routers.kuma-https.entrypoints=https
        - traefik.http.routers.kuma-https.tls=true
        - traefik.http.routers.kuma-https.tls.certresolver=le
        - traefik.http.services.kuma.loadbalancer.server.port=3001

networks:
  traefik-public:
    external: true

volumes:
  data:

@paulknulst
Copy link
Author

paulknulst commented Apr 10, 2024

I just copied your docker-compose file and adjusted the URL to up.paulsblog.dev and deployed it in my Docker Swarm. It work out of the box. I guess you did not follow my tutorial or have something broken in your server cluster setup.
Sorry, I don't see any error in your

image

I will shut down Uptime Kuma in 10 minutes, it was just a fast test :)

@PatelShukan
Copy link

update: the setup did work on AWS , seems like there is issue with the overlay network. Would you have any idea on how to check for issues in overlay network
H/W setup: ESXI -8 and VMs on it
Screenshot 2024-04-11 at 12 55 23 PM

@PatelShukan
Copy link

the problem was with overlay networks in virtual machines that are running on the ESXI.
It seems like there is a bug in the virtual network driver. In my case it helped to disable the checksum verification, and it started to work as I needed it.
"sudo ethtool -K eth0 rx off tx off"
and it worked

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment