I am using Traefik in my VPS to route the traffic to my websites, after hours of messing around with it I finally managed to get it working with https using Le's Encrypt.
Now, one thing that I need to do is be able to also access my website via plain http as this is a hobby project for older browsers and the only reason I added tls is because Firefox doesn't like my website without it.
The problem is that, with my current configuration, I can access my website via https normally but when I try it with plain http I get a 404 error.
Here's what my config on docker-compose looks like:
version: "3"
services:
traefik:
image: "traefik:v2.5"
container_name: "traefik"
command:
#- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.teeresolver.acme.tlschallenge=true"
- "--certificatesresolvers.teeresolver.acme.email=me#gmail.com"
- "--certificatesresolvers.teeresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "443:443"
- "80:80"
- "8080:8080"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- mywebsite
# [...]
mywebsite:
image: my-web-site/site
build:
context: ~/mywebsite-runner/_work/my-web-site-php/my-web-site-php
dockerfile: Dockerfile
volumes:
- ./tee-downloads:/var/www/build/downloads
- ./tee-contents:/var/www/build/contents
ports:
- "0.0.0.0:8001:80"
labels:
- "traefik.enable=true"
- "traefik.http.routers.themywebsite.rule=Host(`mywebsite.com`, `www.mywebsite.com`)"
- "traefik.http.routers.themywebsite.entrypoints=websecure,web"
- "traefik.http.routers.themywebsite.tls.certresolver=teeresolver"
networks:
- mywebsite
networks:
mywebsite:
I have been searching for a solution for hours but the only things I can find on google are configs to redirect http to https, which I can't do.
Does anyone know how to do that?
Thanks in advance for the help.
In traefik , each router defines a set of policies to apply depending of rules and entrypoints.
If you want 2 policies, one for http and one for https, you need to define 2 traefik routers :
mywebsite:
...
labels:
- "traefik.enable=true"
- "traefik.http.routers.themywebsite.entrypoints=websecure"
- "traefik.http.routers.themywebsite.tls.certresolver=teeresolver"
- "traefik.http.routers.themywebsite.rule=Host(`mywebsite.com`, `www.mywebsite.com`)"
- "traefik.http.routers.httpwebsite.entrypoints=web"
- "traefik.http.routers.httpwebsite.rule=Host(`mywebsite.com`, `www.mywebsite.com`)"
One called themywebsite
Another one called httpwebsite
As a result, you do not use a certresolver for httpwebsite router.
Related
I am trying to host a few different websites on a single Raspberry Pi using Docker. I was told that I would need to use something like Traefik to route everything properly.
I tried using the Docker Basic Example under User Guides in their documentation as a test. I followed along with the example and created the docker-compose.yml file and copied in the example from the docs:
version: "3.3"
services:
traefik:
image: "traefik:v2.2"
container_name: "traefik"
command:
# - "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
whoami:
image: "containous/whoami"
container_name: "simple-service"
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
- "traefik.http.routers.whoami.entrypoints=web"
Using this example going to the devices local IP I recieve a page that simply says:
404 Page not found
I've tried changing the Traefik container image version, and editing the example with my relevant information as well as recreating the example on another host and still I receive the above 404.
Am I doing something incorrect with Traefik to receive this 404?
In the user guide you have mentioned, there is this note:
Replace whoami.localhost by your own domain within the traefik.http.routers.whoami.rule label of the whoami service.
So, after you replace whoami.localhost with you local IP, you should be able to see whoami service responding correctly.
I am trying to setup Treafik2 as a reverse proxy/SSL termination for a simple flask app (uwsgi is listening on port 8080) in another container. I want to be able to access the site via http or https (I know, I know, we should be using https! EVERYWHERE, trust me there is a good reason for having http and https in this scenario). For the life of me I can't get both the work simultaneously, I can only get http or https. TLS, when used, should terminate at traefik, otherwise the connection should just be unencrypted. Here is my docker-compose file (below only https works, if I comment out the last two router labels (the tls ones) then only http works). Unfortunately I find the traefik documentation a bit lacking, which makes it confusing to me. Any help is appreciated.
version: '3.3'
services:
traefik:
image: "traefik:v2.0.0-rc3"
container_name: "traefik"
command:
- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.address=:80"
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
- "--certificatesresolvers.mytlschallenge.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.mytlschallenge.acme.email=me#example.com"
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
ports:
- "443:443"
- "8080:8080"
- "80:80"
volumes:
- "/mnt/volume_04/letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
example:
image: exampleflask
container_name: example
expose:
- "8080"
labels:
- "traefik.enable=true"
- "traefik.http.routers.example.rule=Host(`example.com`)"
- "traefik.http.routers.example.entrypoints=web,websecure"
- "traefik.http.routers.example.tls.certresolver=mytlschallenge"
- "traefik.http.routers.example.tls.domains[0].main=example.com"
restart: always
You had two entrypoints "web" and "websecure"
So you can set two routers, it looks like the below:
For http:
- "traefik.http.routers.exampleforhttp.rule=Host(`example.com`)"
- "traefik.http.routers.exampleforhttp.entrypoints=web"
For https:
- "traefik.http.routers.exampleforhttps.rule=Host(`example.com`)"
- "traefik.http.routers.exampleforhttps.entrypoints=websecure"
- "traefik.http.routers.exampleforhttps.tls.certresolver=mytlschallenge"
Or you want http redirect to https, like the blow:
- "traefik.http.routers.exampleforhttp.rule=Host(`example.com`)"
- "traefik.http.routers.exampleforhttp.entrypoints=web"
- "traefik.http.routers.exampleforhttp.middlewares=http-redirect"
- "traefik.http.middlewares.http-redirect.redirectscheme.scheme=https
- "traefik.http.routers.exampleforhttps.rule=Host(`example.com`)"
- "traefik.http.routers.exampleforhttps.entrypoints=websecure"
- "traefik.http.routers.exampleforhttps.tls.certresolver=mytlschallenge"
Have a good time.
I'm using Traefik as a reverse proxy for a lot of services and for tls termination. This works properly excepted Nifi. When trying to forward incomming requests to Nifi I get "Bad Gateway" responses.
Does anybody have an idea how to fix that?
Thanks a lot :-)
traefik:
image: "traefik:v2.2"
container_name: "traefik"
restart: always
networks:
- monitoring
- website
- iot
command:
#- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.httpchallenge=true"
- "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
#s- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.myresolver.acme.email=test#test.de"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
# prom metrics
- "--metrics.prometheus=true"
---
nifi:
image: apache/nifi:latest
container_name: nifi
restart: on-failure
environment:
- NIFI_WEB_PROXY_CONTEXT_PATH=/
- NIFI_WEB_HTTP_PORT= 8080
expose:
- 8080
networks:
- iot
labels:
- "traefik.enable=true"
- "traefik.http.routers.nifi.rule=Host(`nifi.example.de`)"
- "traefik.http.routers.nifi.entrypoints=web"
- "traefik.http.routers.nifi.middlewares=nifi-auth"
# Basic Auth
- "traefik.http.middlewares.nifi-auth.basicauth.users=admin:$$xyz$$xyz$$xyz"
Any idea?? :-)
Since there are several ports open for the ui etc. it's required to define the routing port by using (e. g.):
- "traefik.http.services.nifi.loadbalancer.server.port=8080"
I'm using traefik 2.1 and would like to setup basic auth for all containers, in 1.x it was easy to do:
[entryPoints.http.auth.basic]
usersFile = "/etc/traefik/.htpasswd"
But how to setup it in 2.x? I'd like to avoid inserting code in all my docker-compose.yml files - got a lot of them.
The main idea is:
we can use built-in middleware https://docs.traefik.io/middlewares/basicauth/
we need to connect middleware from above to a container which needs to be secured
Please find an example of docker-compose.yml
version: '3.7'
services:
traefik:
image: "traefik:v2.2.1"
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=default"
- "--entrypoints.web.address=:80"
- "--api"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
ports:
- 80:80
# management console
- 8080:8080
labels:
- "traefik.enable=true"
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.entrypoints=web"
# auth middleware with user / password
- "traefik.http.middlewares.my-auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
whoami:
image: "containous/whoami"
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
- "traefik.http.routers.whoami.entrypoints=web"
# connect your auth middleware to a service which you want to protect
- "traefik.http.routers.whoami.middlewares=my-auth"
So, now we can check that:
auth has prompted on http://whoami.localhost
the valid user name is "test:test" or "test2:test2"
You should use htpasswd command for generating a list of users and connect it according to the Traefik docs.
That's it. Happy coding ;)
Is it possible to have a wildcard subdomain that does not include a specific subdomain?
*.mydomain.com OK
login.mydomain.com SKIP
I cannot access my login container when using a wildcard on my app container. Below is an image of what I am trying to accomplish. (the traffic logo should technically be between the list of routes and the containers)
The following configuration does not work if the rule HostRegexp:{subdomain:[a-z]+}.${HOST_DOMAIN} is included.
This configuration successfully works after removing the host regex for everything EXCEPT the wildcard subdomains.
services:
traefik:
image: traefik
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- .traefik.toml:/etc/traefik/traefik.toml:ro
ports:
- "80:80"
- "443:443"
api:
image: my-api-image
labels:
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=Host:app.${HOST_DOMAIN}; PathPrefix: /api"
app:
image: my-app-image
labels:
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=Host:app.${HOST_DOMAIN}"
- "traefik.frontend.rule=HostRegexp:{subdomain:[a-z]+}.${HOST_DOMAIN}" # this second rule overwrites the first rule and I am aware of that, I am just showing what rules i've tried :)
login:
image: my-login-image
labels:
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=Host:login.${HOST_DOMAIN}"
My problem is currently with the app container. I am getting a bad gateway if I have the following included as a frontend rule:
"traefik.frontend.rule=HostRegexp:{subdomain:[a-z]+}.${HOST_DOMAIN}"
I also tried leaving the above under app, and removing the following without any luck:
"traefik.frontend.rule=Host:app.${HOST_DOMAIN}"
Any suggestions or ideas would be appreciated. Thanks.
Edit:
Rewording this a bit.
So this is what worked for me:
version: '2'
services:
traefik:
image: traefik
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
# I removed your traefik.toml as you did not specify what is in it, so it's irrelevant
ports:
- "80:80"
- "443:443"
# Very helpful for debugging dashboard can be seen at http://localhost:8080 if the port is exposed
- "8080:8080"
labels:
# You don't want traefik trying to create proxy for itself
- "traefik.enable=false"
# Since we have no traefik.toml any longer, let's put the essentials on the command line
command: ["--api","--docker"]
app:
# this is my test image of a web server that dumps request back to the caller
image: andrewsav/talkback
# the hostname is a part of the dump, so let's specify something that we can relate to
hostname: "app"
labels:
# note that you want this frontened to match the last. otherwise it will match login.${HOST_DOMAIN}"
- "traefik.frontend.priority=1"
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=HostRegexp:{subdomain:[a-z]+}.${HOST_DOMAIN}"
api:
image: andrewsav/talkback
hostname: "api"
labels:
# this frontend needs to match before the one above
- "traefik.frontend.priority=2"
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=Host:app.${HOST_DOMAIN}; PathPrefix: /api"
login:
image: andrewsav/talkback
hostname: "login"
labels:
- "traefik.frontend.priority=3"
- "traefik.enable=true"
- "traefik.port=80"
- "traefik.frontend.rule=Host:login.${HOST_DOMAIN}"
A few notes:
Bad Gateway indicates that the endpoint you told traefik to talk to is not listening. Look at at the dashboard and find out which backend is used and double check that ip/port is correct.
You have to use priorities for matching order. Please refer to the documentation on how it works.