Traefik with self-signed certificate - ssl

I have a Traefik reverse proxy which generate ACME certificate and I would like to have SSL enabled on my docker container.
In my container I have a self-signed certificate but Traefik refuse to connect to it.
My docker-compose.yml:
version: "2"
services:
magento:
image: lavoweb/php-5.6
expose:
- 80
- 443
volumes:
- ./data/src/:/var/www/html
labels:
- "traefik.port=80"
- "traefik.backend=swarm"
- "traefik.protocol=https"
- "traefik.frontend.rule=Host:1.swarm.lavoweb.net"
- "traefik.docker.network=web"
networks:
- web
- internal
networks:
web:
external:
name: web
internal:
driver: bridge
I got this error:
Internal Server Error

This is how I've managed to get this working with the LetsEncrypt automated renewal using Docker Swarm and Docker Compose V3:
version: '3'
services:
traefik:
image: traefik
command: --web --docker --docker.domain=docker.localhost --docker.watch \
--logLevel=DEBUG \
--defaultEntryPoints='http,https' \
--entryPoints='Name:http Address::80' \
--entryPoints='Name:https Address::443 TLS' \
--docker.swarmmode=true \
--docker.exposedbydefault=false \
--acme \
--acme.entryPoint='https' \
--acme.email='sugarcane#gmail.com' \
--acme.ondemand=false \
--acme.acmelogging=true \
--acme.onhostrule=true \
--acme.storage='/etc/traefik/acme/acme.json'
networks:
- default
- traefik-net
ports:
- "80:80"
- "8080:8080"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- traefikdata:/etc/traefik/acme
mytestservice:
image: blah/mytestservice
networks:
- default
- traefik-net
ports:
- "8001:80"
deploy:
labels:
- "traefik.port=80"
- "traefik.enable=true"
- "traefik.backend=machine-mytestservice"
- "traefik.docker.network=traefik-net"
- "traefik.frontend.rule=Host:mydomain.com,www.mydomain.com"
networks:
traefik-net:
volumes:
traefikdata:

Related

Traefik different entrypoint and rule combos

I have a docker compose file, I want to host my container on example.com:8080 and api.example.com:443, I can accomplish that goal right now.
However I don't want 2 seperate service for that, I want to eliminate either my_api or abcxyz and have 1 service only and accomplish the same behavior, i.e. my container should be hosted at example.com:8080 and not on example.com:443 AND api.example.com:443 but not on api.example.com:8080
Is there a way to do it under 1 service.
version: "3"
services:
traefik:
image: traefik
command:
- --api.dashboard=false
- --api.insecure=false
- --providers.docker
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=web-secure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.web.http.redirections.entrypoint.permanent=true
- --entrypoints.web-secure.address=:443
- --entrypoints.spiderman.address=:8080
- --providers.file.directory=/configuration/
- --providers.file.watch=true
ports:
- 80:80
- 443:443
- 8080:8080
volumes:
- ./certificates.yml:/configuration/certificates.yml:ro
- /etc/letsencrypt:/letsencrypt:ro
- /var/run/docker.sock:/var/run/docker.sock
my_api:
image: traefik/whoami
deploy:
replicas: 5
labels:
- "traefik.http.routers.my_api.entrypoints=spiderman"
- "traefik.http.routers.my_api.rule=Host(`example.com`)"
- "traefik.http.routers.my_api.tls=true"
abcxyz:
image: traefik/whoami
deploy:
replicas: 5
labels:
- "traefik.http.routers.abcxyz.entrypoints=web-secure"
- "traefik.http.routers.abcxyz.rule=Host(`api.example.com`)"
- "traefik.http.routers.abcxyz.tls=true"
I could do -
labels:
- "traefik.http.routers.my_api.entrypoints=spiderman,web-secure"
- "traefik.http.routers.my_api.rule=Host(`example.com`,`api.example.com`)"
- "traefik.http.routers.my_api.tls=true"
but it would also serve at example.com:443 which I don't want because i want to host my cool wordpress site there! :)
I think you're looking for something like this:
services:
traefik:
image: traefik
command:
- --api.dashboard=false
- --api.insecure=false
- --providers.docker
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=web-secure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.web.http.redirections.entrypoint.permanent=true
- --entrypoints.web-secure.address=:443
- --entrypoints.spiderman.address=:8080
ports:
- 127.0.0.3:80:80
- 127.0.0.3:443:443
- 127.0.0.3:8080:8080
volumes:
- /run/docker.sock:/run/docker.sock
my_api:
image: traefik/whoami
hostname: my_api
labels:
- traefik.enable=true
- traefik.http.routers.example_com.entrypoints=spiderman
- traefik.http.routers.example_com.rule=Host(`example.com`)
- traefik.http.routers.example_com.service=my_api
- traefik.http.routers.example_com.tls=true
- traefik.http.routers.my_api.entrypoints=web-secure
- traefik.http.routers.my_api.rule=Host(`api.example.com`)
- traefik.http.routers.my_api.tls=true
- traefik.http.services.my_api.loadBalancer.server.port=80
Note that here I've bound everything to local address 127.0.0.3 for testing, but of course that's not necessary; I did that to avoid conflicts with existing services I have listening on ports 80, 443, and 8080.
Testing
I've defined this shell function that ensures the various hostname:port combinations resolve correctly (you could edit /etc/hosts instead to accomplish the same thing) and shows the HTTP status code for each request:
fetch() {
curl -sf \
--resolve api.example.com:443:127.0.0.3 \
--resolve api.example.com:8080:127.0.0.3 \
--resolve example.com:443:127.0.0.3 \
--resolve example.com:8080:127.0.0.3 \
-k -w '%{stderr}%{http_code}\n' $1
}
Using that, let's test our your various requirements.
my container should be hosted at example.com:8080
$ fetch https://example.com:8080 | grep -i host
200
Hostname: my_api
Host: example.com:8080
X-Forwarded-Host: example.com:8081
and not on example.com:443
$ fetch https://example.com:443 | grep -i host
404
AND api.example.com:443
$ fetch https://api.example.com:443 | grep -i host
200
Hostname: my_api
Host: api.example.com
X-Forwarded-Host: api.example.com
but not on api.example.com:8080
$ fetch https://api.example.com:8080 | grep -i host
404
I think that covers your requirements!

Traefik serving SSL certificate as invalid

Traefik is setup, redirecting to https and seems to be configured correctly. However, when I try to access my project in the browser, the certificate is untrusted with a NET::ERR_CERT_INVALID error:
I can SSH into the container and cat the certificate files and it looks like docker is mounting the files and carrying over permissions as expected.
Locally, I've generated my certificate:
openssl req -x509 -newkey rsa:4096 -keyout infrastructure/certs/mysite-dev.com.key -out infrastructure/certs/mysite-dev.com.crt -days 10000 -nodes -subj "/C=US/ST=State/L=City/O=cicd/CN=mysite-dev.com"
Adjusted permissions using:
chmod 644 infrastructure/certs/*.crt
chmod 600 infrastructure/certs/*.key
traefik-conf.yml
tls:
certificates:
- certFile: /certs/mysite-dev.com.crt
keyFile: /certs/mysite-dev.com.key
stores:
- default
stores:
default: { }
Here's my relevant compose configuration:
services:
web:
build:
context: .
dockerfile: infrastructure/web/Dockerfile
image: registry.gitlab.com/my-org/my-project:web
env_file: .env
volumes:
- ./:/var/www/html
- ./infrastructure/web:/etc/nginx/conf.d
depends_on:
- redis
- db
labels:
traefik.enable: true
traefik.http.routers.mysite-web.entrypoints: web,websecure
traefik.http.middlewares.mysite-web.redirectscheme.scheme: https
traefik.http.middlewares.mysite-web.redirectscheme.permanent: true
traefik.http.routers.mysite-web.tls: true
traefik.http.routers.mysite-web.rule: Host(`mysite-dev.com`)
traefik.http.services.mysite-web.loadbalancer.server.port: 80
traefik:
command:
- --api.dashboard=true
- --api.insecure=true
- --accesslog=true
- --providers.docker.exposedbydefault=false
- --providers.docker=true
- --entryPoints.web.address=:80
- --entryPoints.websecure.address=:443
- --providers.file.filename=/conf/dynamic.yml
image: traefik:2.7
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./infrastructure/certs:/certs:ro
- ./infrastructure/traefik-conf.yml:/conf/dynamic.yml:ro
While I wasn't able to figure this one out, I ended up resolving the issue by using LetsEncrypt to provide an SSL certificate instead. Here's my new traefik service:
traefik:
command:
- --api.dashboard=true
- --api.insecure=true
# - --accesslog=true
- --log.level=INFO
- --providers.docker.exposedbydefault=false
- --providers.docker=true
- --entryPoints.web.address=:80
- --entryPoints.websecure.address=:443
- --certificatesresolvers.myresolver.acme.dnschallenge=true
- --certificatesresolvers.myresolver.acme.dnschallenge.provider=route53
- --certificatesresolvers.myresolver.acme.email=me#mysite.com
- --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json
environment:
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
AWS_HOSTED_ZONE_ID: ${AWS_HOSTED_ZONE_ID}
image: traefik:2.7
ports:
- "80:80"
- "443:443"
# The Web UI (enabled by --api.insecure=true)
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./infrastructure:/letsencrypt # this is an empty directory, to store generated json

Traefik. Split configuration and redirect to https

I'm new to Traefik and have following basic question. Traefik should proxy NGINX. My goal is to start the stack either with http (f.e. locally) or with https (production): Therefore I've split the docker config in two yml files:
docker-compose-https.yml
version: "3.3"
services:
traefik:
image: "traefik:v2.4"
container_name: "traefik"
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.email=my#email.com"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "443:443"
- "8080:8080"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
docker-compose.yml
nginx:
image: nginx:alpine
ports:
- 80:80
labels:
- "traefik.enable=true"
- "traefik.http.routers.nginx.rule=Host('test.example.com')"
- "traefik.http.routers.nginx.entrypoints=websecure"
- "traefik.http.routers.nginx.tls.certresolver=myresolver"
This works so far. If I run docker-compose up -d with -f docker-compose-ssl.yml trafik jumps in for https and issues a cert. Without using it I can still start nginx over http. Unfortuantely what is not working is, as soon as Traefik is up it does not redirect http to https as my config should ask for. What do I oversee?
You need to use the RedirectScheme for the redirection from http to https and the middleware to the router as mentioned in https://doc.traefik.io/traefik/middlewares/overview/#configuration-example
So, your docker-compose.yml should look like this
nginx:
image: nginx:alpine
ports:
- 80:80
labels:
- "traefik.enable=true"
- "traefik.http.routers.nginx.entrypoints=web"
- "traefik.http.routers.nginx.rule=Host(`test.example.com`)"
- "traefik.http.middlewares.nginx-redirectscheme.redirectscheme.scheme=https"
- "traefik.http.routers.nginx.middlewares=nginx-redirectscheme"
- "traefik.http.routers.nginx-secured.entrypoints=websecure"
- "traefik.http.routers.nginx-secured.rule=Host(`test.example.com`)"
- "traefik.http.routers.nginx-secured.tls=true"
- "traefik.http.routers.nginx-secured.tls.certresolver=myresolver"

Builds stuck in pending state drone

I'm using drone:0.8 with the following configuration but the only two first jobs are succeeded in building. The rest of jobs are stuck in the pending state.
I'm deploying drone using Docker Swarm stack deploy. Here is my configuration file:
version: '3'
services:
server:
image: drone/drone:0.8
ports:
- 8000
- 9000
volumes:
- /data/local/drone:/var/lib/drone/
environment:
- DRONE_OPEN=true
- DRONE_HOST=http://example.com
- DRONE_GITHUB=true
- DRONE_ORGS=my_fake_company
- DRONE_ADMIN=my_github
- DRONE_GITHUB_CLIENT=my_secret
- DRONE_GITHUB_SECRET=my_client
- DRONE_SECRET=my_drone_secret
- VIRTUAL_HOST=virtual_host.nginx.com
- VIRTUAL_PORT=8000
networks:
- edge
agent:
image: drone/agent:0.8
command: agent
depends_on:
- drone-server
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- DRONE_SERVER=drone_server:9000
- DRONE_SECRET=my_secret
networks:
- edge
networks:
- edge
external: true
It's running behind nginx-proxy by jwlinder.

Unsupported config option for services service: 'httpd'

I am getting this on Ubuntu with a fresh install of Docker 1.12.0
It works on all other colleagues installations with the same version of Docker.
This is the docker-compose.yml
version: '2'
networks:
backend:
services:
httpd:
image: httpd:2.4
depends_on:
- tomcat
networks:
- backend
ports:
- "80:80"
volumes:
- ./httpd/httpd.conf:/usr/local/apache2/conf/httpd.conf
tomcat:
image: tomcat:8.0-jre8-alpine
depends_on:
- mongodb
networks:
- backend
ports:
- "8080:8080"
volumes:
- ./tomcat/webapps:/usr/local/tomcat/webapps/
environment:
- ITONICS_CONFIG=docker
- CATALINA_OPTS=-Xms512M -Xmx2048M
mongodb:
image: mongo:3.2
volumes:
- ./mongo/db:/data/db
networks:
- backend
ports:
- "27017:27017"