I am pretty new for the topic server configuration and now I got a problem with to reach a container with ssl certificate.
What is my setup:
I’ve got a raspberry pi with docker on it. The container which is connected to port 80 and 443 is a reverse proxy which is directing incoming subdomains to different other container.
Example:
webserver.my-domain.com is leading to IP 192.168.178.69:8080. I archived this through this config in the folder sites-enabled
:
<VirtualHost *:80>
ServerName webserver.my-domain.com
ProxyPreserveHost On
DocumentRoot /var/www/html
ProxyPass /.well-known !
ProxyPass / http://192.168.178.69:8080/
ProxyPassReverse / http://192.168.178.69:8080/
RewriteEngine on
RewriteCond %{SERVER_NAME} =webserver.my-domain.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
I also created a let’s encrypt certificate inside of the reverse proxy container. This created an additional file webserver-le-ssl.conf
:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName webserver.my-domain.com
ProxyPreserveHost On
DocumentRoot /var/www/html
ProxyPass /.well-known !
ProxyPass / http://192.168.178.69:8080/
ProxyPassReverse / http://192.168.178.69:8080/
SSLCertificateFile /etc/letsencrypt/live/my-domain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/my-domain.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
So far so good. My content is available if I try the URL https://webserver.my-domain.com
.
What is my Problem
I use Portainer to manage my docker container and I want Portainer to be available through portainer.my-domain.com
.
So this is the portainer config inside of sites-enabled
:
<VirtualHost *:80>
ServerName portainer.my-domain.com
ProxyPreserveHost On
DocumentRoot /var/www/html
ProxyPass /.well-known !
ProxyPass / http://192.168.178.69:9443/
ProxyPassReverse / http://192.168.178.69:9443/
RewriteEngine on
RewriteCond %{SERVER_NAME} =portainer.my-domain.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
And also the ssl config for this:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName portainer.my-domain.com
ProxyPreserveHost On
DocumentRoot /var/www/html
ProxyPass /.well-known !
ProxyPass / http://192.168.178.69:9443/
ProxyPassReverse / http://192.168.178.69:9443/
SSLCertificateFile /etc/letsencrypt/live/my-domain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/my-domain.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
If I call 192.168.178.69:9443/
I can reach the container without problems.
But if I try to reach the URL portainer.my-domain.com
I just got the Message:
Client sent an HTTP request to an HTTPS server.
But in the URL shows: https://portainer.my-domain.com/
.
So I don’t understand why there is an HTTP request, even if my browser shows me that the connection is with https.
Can someone explain this to me and show me how to fix this?
Update: My solution
With a lot of tries I found a solution:
As I run the reverse proxy and the portainer as docker containers, I put both containers into a network with docker-compose:
version: "3.4"
services:
apache:
build:
context: .
dockerfile: Dockerfile
ports:
- "80:80"
- "443:443"
volumes:
- /home/pi/reverse-proxy/:/etc/apache2
networks:
- homeserver
portainer:
image: portainer/portainer-ce:latest
ports:
- "8000:8000"
- "9000:9000"
- "9443:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
networks:
- homeserver
networks:
homeserver:
volumes:
portainer_data:
The volume of the apache2 is the complete config folder of /etc/apache2
. After that I changed the IP of the ProxyPass to the name of the container:
ProxyPass / http://reverse-proxy_portainer_1:9000/
ProxyPassReverse / http://reverse-proxy_portainer_1:9000/
After this changes it worked.
2
Answers
So based on your question it seems that this works
But this does not:
Note that in both cases a plain http:// protocol is used, even though different port are involved. And a port number of 9443 suggests that you are expected https:// and not http:// here. If this is the case this would explain the error message you got: a plain HTTP request is send because of setting the protocol to http:// instead of https://.
This protocol here is relevant for the connection between client and nginx, not between nginx and the inner server. The latter one depends on the protocol given in the ProxyPass URL.
I had the same problem with Portainer 2.13.1 behind an Apache2 proxy. I solved it by running the image with the option enabling port 9000 which is Portainer’s HTTP port. This assumes that you will block port 9000 externally and access it only via the proxy which is protected by HTTPS. This is my command:
My VirtualHost file then points to port 9000 like so:
Make sure ports 8000, 9000 and 9443 are not accessible externally using a tool like ufw in Linux.