Getting 500 error with self signed certificate - ssl

I 'am trying to get to run two services in a docker environment. One is an Angular application and the other is my small python server. I have added the jwilder nginx reverse proxy for authentication and ssl configuration with my self signed certificate. All the containers are running on the same virtual host, that I am able to access them from another host. I've added the certificates like in the documentation from jwilder and there is written that this will happen
(likely w/ a warning) and subsequently receive a 500 (https://hub.docker.com/r/jwilder/nginx-proxy)
I need to find a solution to access my services threw the nginx proxy with SSL somebody knows how to do this better?
version: "3"
services:
controller:
build: ./controller
expose:
- "5080" #This port should be accessible from the frontend but as they are running on the same host I am not able to distinguish the services
restart: always
frontend:
build: ./frontend
expose:
- "4200"
environment:
- DEFAULT_HOST=my-ip-address #to make it accessible from outside
- VIRTUAL_HOST=my-ip-address
# - VIRTUAL_PORT 4200
# - VIRTUAL_PROTO=https
- PROXY_ADDRESS_FORWARDING=true
- NODE_END = production
depends_on:
- controller
restart: always
nginx-reverse-proxy:
image: jwilder/nginx-proxy #budry/jwilder-nginx-proxy-arm # This will run later on the raspberryPi
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx.htpasswd:/etc/nginx/htpasswd/my-ip-address
# My self signed certificates
- ./ssl/server.crt:/etc/nginx/certs/default.crt
- ./ssl/server.key:/etc/nginx/certs/default.key
restart: always
So I found out somehow in the nginx configuration file from jwilder he is running in this case
{{ if (and (not $is_https) (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
server {
server_name {{ $host }};
listen 443 ssl http2 {{ $default_server }};
{{ if $enable_ipv6 }}
listen [::]:443 ssl http2 {{ $default_server }};
{{ end }}
access_log /var/log/nginx/access.log vhost;
return 500;
ssl_certificate /etc/nginx/certs/default.crt;
ssl_certificate_key /etc/nginx/certs/default.key;
}
Why is he doing this and how can I fix this ?
I am able to access my frontend with http://my-ip-address (should be forwarded to https) but on https://my-ip-address I am getting a "500 Internal Server Error"

Related

Traefik entrypoint redirect to scheme and port

I'm running traefik in docker-compose with network_mode: host to get an accurate remote_ip. My docker hosts ports 80 and 443 are occupied so traefik uses 5080 and 5443 web and websecure entry points. I've forwareded 5080/5443 to my routers 80/443 so my.domain.me routes to traefik. https://my.domain.me works correctly, but http://my.domain.me redirects to port 5443. How can I configure traefik to redirect to port 443?
version: '3.3'
services:
traefik:
image: traefik:v2.4
# use host network for accurate remote_ip
network_mode: host
command: # CLI arguments
- --providers.docker=true
# ports 80 and 443 are used by another process.
- --entryPoints.web.address=:5080
- --entryPoints.websecure.address=:5443
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https

Minio does not seem to recognize TLS/https certificates

Im search now for hours to make minio work with self-signed tls certs using docker.
accroding to the documentation certs just need to be placed at /root/.minio/certs/CAs or /root/.minio/ inside the minio container
I tried both with no success
This is how I start minio (using saltstack):
minio:
docker_container.running:
- order: 10
- hostname: backup
- container_name: backup
- binds:
- /root/backup:/data
- /srv/salt/minio/certs:/root/.minio
- image: minio/minio:latest
- port_bindings:
- 10.10.10.1:9000:443
- environment:
- MINIO_BROWSER=off
- MINIO_ACCESS_KEY=BlaBlaBla
- MINIO_SECRET_KEY=BlaBlaBla
- privileged: false
- entrypoint: sh
- command: -c 'mkdir -p /data/backup && /usr/bin/minio server --address ":443" /data'
- restart_policy: always
If I do "docker logs minio" I just get to see http instead of https:
Endpoint: http://172.17.0.3:443 http://127.0.0.1:443
Both keys public and privat are mounted at the correct location inside the container but they not seem to recognize ...
can smb help, do I need to add some extra parameter here?
Thanks in advance
Per the docs (https://docs.minio.io/docs/how-to-secure-access-to-minio-server-with-tls.html), your keys must be named public.crt and private.key, respectively, and mounted at ~/.minio/certs (e.g. /root/.minio/certs). The CA's directory is for public certs of other servers you want to trust, for example in a distributed setup.
you doesn't need to setup cert in minio. Use nginx server then reverse proxy minio port as like 127.0.0.1:9000 port . then use cert file in nginx server block . your all problem solved

SSL passthrough with Traefik

I need to send the SSL connections directly to the backend, not decrypt at my Traefik. The backend needs to receive https requests.
I tried the traefik.frontend.passTLSCert=true option but getting "404 page not found" error when I access my web app and also get this error on Traefik container
traefik | time="2018-09-16T10:47:41Z" level=error msg="Failed to create TLSClientConfig: no TLS provided"
traefik | time="2018-09-16T10:47:41Z" level=error msg="Failed to create RoundTripper for frontend frontend-Host-dev-mydomain-com-0: no TLS provided"
traefik | time="2018-09-16T10:47:41Z" level=error msg="Skipping frontend frontend-Host-dev-mydomain-com-0..."
Could you suggest any solution? Thank you.
I'm using Traefik version 1.6.6.
Here is my docker-compose.yml for the app container.
version: '3'
services:
app:
image: webdevops/php-nginx-dev:7.2
networks:
- proxy
volumes:
- ./:/app
- ../traefik/ssl/*.mydomain.com.crt:/opt/docker/etc/nginx/ssl/server.crt
- ../traefik/ssl/*.mydomain.com.key:/opt/docker/etc/nginx/ssl/server.key
environment:
- WEB_DOCUMENT_ROOT=/app
labels:
- traefik.enable=true
- traefik.frontend.rule=Host:dev.mydomain.com
- traefik.docker.network=proxy
- traefik.port=443
networks:
proxy:
external: true
The docker-compose.yml of my Traefik container.
version: "3"
services:
traefik:
image: traefik
container_name: traefik
command:
- --api
- --docker
- --docker.exposedbydefault=false
restart: always
ports:
- 80:80
- 443:443
networks:
- proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.toml:/traefik.toml
- ./ssl:/sslcert
networks:
proxy:
external: true
Finally, my traefik.toml file.
debug = true
logLevel = "ERROR"
defaultEntryPoints = ["http","https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "/sslcert/*.mydomain.com.crt"
keyFile = "/sslcert/*.mydomain.com.key"
[retry]
Traefik now has TCP support in its new 2.0 version - which is still in alpha at this time (Apr 2019).
See PR https://github.com/containous/traefik/pull/4587
and the release notes of v2.0.0-alpha1 at https://github.com/containous/traefik/releases/tag/v2.0.0-alpha1 showing this TCP support PR being included
Hence once 2.0 is released (probably within 2-3 months), HTTPS passthrough will become possible.
Answer for traefik 1.0 (outdated)
passTLSCert forwards the TLS Client certificate to the backend, that is, a client that sends a certificate in the TLS handshake to prove it's identity.
Traefik is an HTTP reverse proxy. To establish the SSL connection directly with the backend, you need to reverse proxy TCP and not HTTP, and traefik doesn't (yet ?) support tcp (but there are issues for that on github).
Traefik won't fit your usecase, there are different alternatives, envoy is one of them.
The new passthrough for TCP routers is already available: https://docs.traefik.io/routing/routers/#passthrough

Deploying Traefik with LetsEncrypt and multiple Docker backend

I am considering replacing Apache for Traefik for my web project (Kestrel / .Net Core). After reading the documentation, a few things remain unclear to me regarding Traefik:
1/ Does Traefik automatically handle the LetsEncrypt certificate renewal or does it need to be done manually or via an external script? From the doc it's said that this is performed when adding a new host or restart, but what happens after 3 months of Traefik running without any restart/new host added?
2/ When a Docker backend becomes unreachable, how is it possible to serve a custom static HTML page? I can see how to set specific error page from the documentation, but not how to redirect trafic to it when a given backend becomes unavailable.
3/ When a Docker backend needs to be updated, is there some steps that need to be performed on Traefik prior to performing the Docker stop/restart?
4/ It seems I can't get to have 2 docker backend running at the same time, see the configuration file below, if I uncomment the 2nd backend (api.mydomain.io), then the 1st one becomes not available anymore. Am I missing something here?
version: '3'
services:
reverse-proxy:
image: traefik # The official Traefik docker image
command: --docker # Enables the web UI and tells Træfik to listen to docker
ports:
- "80:80" # The HTTP port
- "443:443" # The HTTPS port
- "8080:8080" # The Web UI (enabled by --api)
networks:
- proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- $PWD/traefik.toml:/etc/traefik/traefik.toml
- $PWD/acme.json:/acme.json
- /root/mydomain_prod/cert/:/certs/
- /root/mydomain_prod/503.html:/503.html
container_name: traefik-reverse-proxy
##############################
# Front - www.mydomain.io
##############################
mydomain-front:
image: mydomain-front
labels:
- traefik.enable=true
- traefik.backend=mydomain-front
- traefik.frontend.rule=Host:traefik.mydomain.io
- traefik.port=8084
networks:
- internal
- proxy
container_name: mydomain-front
##############################
# API - api.mydomain.io
# Note: If I uncomment this one, then www.mydomain.io won't work anymore
##############################
#mydomain-api:
# image: mydomain-api
# labels:
# - traefik.enable=true
# - traefik.backend=mydomain-api
# - traefik.frontend.rule=Host:api.mydomain.io
# - traefik.port=8082
# networks:
# - internal
# - proxy
# container_name: mydomain-api
Many thanks,
Flo
1/ Traefik can handle the LetsEncrypt certificate renewal. Just remember to create a Volume to store the acme.json file. When the certificate expires, Traefik will do the renewal without asking.
2/ I don’t know if it’s possible. If you find a solution, share it.
3/ When you need to update a Docker, just update it. Traefik will be trigger from that change and update is own configuration.
4/ You can have to backend running at the same time. Below you can see a docker-compose.yml configuration :
version: '3'
services:
two-backend-service:
restart: always
image: ……..
labels:
- traefik.enable=true
- traefik.service1.frontend.rule=Host:service1.exemple.com
- traefik.service1.frontend.passHostHeader=true
- traefik.service1.port=8082
- traefik.Service2.backend=service2
- traefik.Service2.frontend.rule=Host:service2.exemple.com
- traefik.Service2.frontend.passHostHeader=true
- traefik.Service2.port=8081
traefik:
build:
context: ./traefik
dockerfile: Dockerfile
restart: always
ports:
- 80:80
- 443:443
labels:
- traefik.enable=false
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- traefik_letsencrypt:/etc/traefik/acme/
volumes:
traefik_letsencrypt:
driver: local

Redis connection refused when using traefik

I'm having a hard time trying to configure one redis container for all my applications using traefik. This is my configuration:
1 - Docker compose for Traefik and Redis:
version: '2'
services:
proxy:
container_name: traefik
image: traefik:1.3.6-alpine
command: --docker
ports:
- 80:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.toml:/traefik.toml
networks:
- proxy
labels:
- traefik.frontend.rule=Host:monitor.company.dev
- traefik.port=8080
redis:
container_name: main_redis
image: redis:3.2
restart: always
volumes:
- ./data/redis:/data
networks:
- proxy
labels:
- traefik.backend=main-redis
- traefik.default.protocol=http
- traefik.frontend.rule=Host:main-redis.company.dev
- traefik.docker.network=proxy
- traefik.port=6379
networks:
proxy:
external: true
2 - Docker compose for my PHP Application.
version: '2'
services:
...
php:
container_name: myapp_php
build: ./docker/php # php:7.1-fpm base image
networks:
- internal
- proxy
labels:
- traefik.enable=false
- traefik.docker.network=proxy
expose:
- 9000
networks:
proxy:
external: true
internal:
external: false
I tried to connect my php application to main-redis.company.dev on both ports 6379 and 80 but I get a Redis::connect(): connect() failed: Connection refused message.
I also changed these stuff in my redis.conf:
Commented the line with bind 127.0.0.1
And changed protected-mode to no
My docker containers are staying in the same network, so I think it should work. Anyone knows why am I having this problem?
2022 UPDATE to #djeeg answer
For some time now you can use TCP mode for your routers. To do that you need to define the labels with TCP instead of HTTP
labels:
- "traefik.enable=true"
- "traefik.tcp.routers.redis.rule=HostSNI(`redis.example.com`)"
- "traefik.tcp.routers.redis.entrypoints=redis" //6379 entrypoint
- "traefik.tcp.routers.redis.tls.certresolver=myresolver" //let's encrypt resolver
- "traefik.tcp.routers.redis.service=redis"
- "traefik.tcp.services.redis.loadbalancer.server.port=6379"
once you got that working in order to connect assuming you are using TSL you will get error Error: Protocol error, got "H" as reply type byte.
To prevent this you need to do things.
Allow for tls connection in the connection string
Setup SNI for your DNS name or provide public certificate file via cert pr cacert
redis-cli -u redis://redis.example.com:6379 --tls --sni redis.example.com
First off, remove the traefik labels from your redis service definition, traefik is currently (Nov 2017) a HTTP proxy, so you can't expose the endpoint like that
See here:
https://github.com/containous/traefik/issues/10
https://github.com/containous/traefik/issues/1611
Then to connect the php service to the redis service, that looks like you are trying to do that within the same docker instance (rather than externally)
Instead of main-redis.company.dev:6379, it should be like on of these:
redis:6379
main_redis:6379
%PROJECT_NAME%_redis:6379
depending upon how you are deploying the container