PhpMyAdmin behind reverse proxy (with docker) shows blank page in browser - docker

So, I spent an hour or so to solve a problem, which I solved a year ago and did not remember. For this reason, I am showing the solution here for myself (in another year :-) and for everybody else, who has the same problem.
The setup is like this:
PhpMyAdmin
Docker
nginx
Docker-Compose file:
phpmyadmin:
image: phpmyadmin/phpmyadmin:latest
container_name: k3635013_phpmyadmin
restart: always
environment:
MYSQL_ROOT_PASSWORD: <your PW here>
PMA_HOST: k3635013_db
PMA_ABSOLUTE_URI: https://phpmyadmin.domain.com/
Wrong nginx file:
server {
listen 443 ssl;
client_max_body_size 5900M;
server_name phpmyadmin.domain.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/phpmyadmin.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/phpmyadmin.domain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
resolver 127.0.0.11 valid=30s;
set $upstream k3635013_phpmyadmin;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://$upstream:80/;
}
}
The problem, when you open https://phpmyadmin.domain.com in your browser:
Blank page
If you look at the console, you see that the index page is fetched correctly, which triggers to loads JavaScript files. But instead of the correct JavaScript files, the start page is loaded again. Also, Chrome tells you, a HTML file was loaded instead of JS. (Some error about a wrong mime type or so).

And here the solution/answer:
Correct nginx file:
server {
listen 443 ssl;
client_max_body_size 5900M;
server_name phpmyadmin.domain.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/phpmyadmin.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/phpmyadmin.domain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
resolver 127.0.0.11 valid=30s;
set $upstream k3635013_phpmyadmin;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://$upstream:80;
}
}
You notice the little and subtile difference?
proxy_pass http://$upstream:80;
instead of
proxy_pass http://$upstream:80/;
So one slash too much at the end, which totally stops PhpMyAdmin from loading correctly.
Remove the slash, restart nginx and it works!
PS: You wonder about resolver and $upstream ?
With this setup, you can start nginx even when the docker containers are not running. If you use the hostnames directly in the proxy_pass statments, the docker containers must run, bevor starting nginx.

Related

Nginx & Docker - how to forward to an internal address?

I'm searching for a long time for a solution that can solve my problem. I guess the answer is already given but I'm not searching for the right terms.
I'm using NGINX to forward all requests for port 80 and this works well. Because these ones are forwarded to my own public domain. Now I got a service that I do not want to publish on the internet and just have a different port in my network for it so e.g. 192.168.123.1:10000.
That is what my nginx.conf looks like for exemplary service. I got more server blocks for different services. The important part is the proxy_pass which is set here to be forwarded to the Docker container nextcloudpi. But how can I internally proxy_pass something without a real domain?
server {
listen 80 default_server;
server_name _;
server_name_in_redirect off;
location / {
return 404;
}
}
server {
listen 80;
listen [::]:80;
server_name my-domain.de cloud.my-domain.de www.my-domain.de;
return 301 https://$host$request_uri;
}
# Cloud
server {
server_name cloud.my-domain.de;
#access_log /var/log/nginx/cloud-access.log;
error_log /var/log/nginx/cloud-error.log;
listen 443 ssl http2;
listen [::]:443 ssl http2;
client_max_body_size 100G;
location / {
proxy_send_timeout 1d;
proxy_read_timeout 1d;
proxy_buffering off;
proxy_hide_header Upgrade;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#add_header Front-End-Https on;
proxy_pass https://nextcloudpi;
}
}
I want to use it for invoice ninja for example. How do I set it in Docker then? I normally use expose to let NGINX do everything to do with port 80. But if I want a different internal IP how do I do this? I know how to do it normally in Docker like I tried but that won't work without NGINX:
invoiceninja:
container_name: invoiceninja
image: invoiceninja/invoiceninja:latest
ports:
- 10000:80
restart: always
volumes:
- /storage/appdata/invoiceninja/public:/var/app/public
- /storage/appdata/invoiceninja/storage:/var/app/storage
networks:
- invoiceninja
env_file:
- .secrets/invoiceninja.env
depends_on:
- invoiceninja-db
Basically, how do I forward port 80 of the invoice ninja Docker container to a different port to access it internally like 192.168.123.1:10000.

How fix nginx error "invalid number of arguments"?

i try redirect to proxy-server nginx.
location /phpmyadmin {
proxy_http_version 1.1;
proxy_pass https://${PMA}:5000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
But i get error:
nginx: [emerg] invalid number of arguments in "proxy_set_header" directive in /etc/nginx/nginx.conf:26
full code for inspect error in this listing, because i'm real can't find some error's (${env} = correctry changing in script
user root;
worker_processes auto;
pcre_jit on;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
keepalive_timeout 3000;
sendfile on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
server {
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/ssl/nginx.crt;
ssl_certificate_key /etc/ssl/nginx.key;
root /home;
index default.html /default.html;
location /phpmyadmin {
proxy_http_version 1.1;
proxy_pass https://${PMA}:5000/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
}
location /wordpress {
return 307 http://${WP}:5050/;
}
location / {
try_files /default.html default.html default.htm;
}
}
server {
listen 80;
listen [::]:80;
return 301 https://$host$request_uri;
}
}
daemon off;
how much simvols need for post)
I used envsubst for environment replacing, and this util tried swap $host and other nginx envs, solved with:
envsubst '\$WP \$PMA' < nginx.template.conf > nginx.ready.conf; rm nginx.template.conf
Expanding on the working answer from #mikhail-prigorodov:
The situation described by the OP arises when using the Nginx Docker container with Docker Compose. In the documentation, it reads:
Out-of-the-box, nginx doesn't support environment variables inside most configuration blocks. But this image has a function, which will extract environment variables before nginx starts.
So, if you are using environment variables in your docker-compose.yml as part of a 12-Factor App design, you have to figure out how to get them into your Nginx config file properly.
The solution in the Nginx Docker documentation is to run envsubst on a template configuration file and send the output to the Nginx config file. The Dockerfile syntax, which is mentioned in this GitHub issue is:
CMD envsubst < /etc/nginx/templates/default.conf.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'
But that solution runs into a problem if you have Nginx-defined variables AND environment variable placeholders in your configuration template. In the directory where I'm building my Nginx container (where my Dockerfile is), I have a templates directory with a file called default.conf.template, as directed in the documentation. The file contains Nginx variables and environment variables. For example:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
location /static {
alias /usr/share/nginx/html/${STATIC_DIR};
}
The problem (I think) is that envsubst is looking for the "$" character that marks the start of the environment variables. In any case, you'll find that after running envsubst successfully, each line in your new Nginx config file that has a Nginx-defined variable (leading "$") in the template gives an error when you try and start Nginx.
To solve this problem, use the syntax provided by #mikhail-prigorodov. Applied to my example:
CMD envsubst '\$STATIC_DIR' < /etc/nginx/templates/default.conf.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'
This was the solution that worked for me after hours of frustration.

Jenkins URL localhost:8080 redirects me out to localhost, breaking webpage

I'm having issues with the Jenkins proxy. The Jenkins container is behind my NGINX proxy. I access it at http://localhost:8000. After I log in I get kicked to http://localhost. Some links on Jenkins also does the same and removes the port which brakes the screen. I get the error on the from the title on my Manage Jenkins page and tried adding the proxy_pass URL also, but nothing works.
My NGINX conf file is like so...
server {
listen 8000;
server_name "";
access_log off;
location / {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Host $host;
proxy_pass http://jenkins_master_1:8080;
proxy_redirect http://jenkins_master_1:8080 http://localhost:8000;
proxy_max_temp_file_size 0;
proxy_connect_timeout 150;
proxy_send_timeout 100;
proxy_read_timeout 100;
proxy_buffer_size 8k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
}
my docker-compose.yml file is like so...
version: '3'
# Services are the names of each container
services:
master:
# Where to build the container from a Dockerfile
build: ./jenkins-master
# Open which ports to
ports:
- "50000:50000"
# Connecting volumes to in a container
volumes:
- jenkins-log:/var/log/jenkins
- jenkins-data:/var/jenkins_home
# Adding the service to a network
networks:
- jenkins-net
nginx:
build: ./jenkins-nginx
ports:
- "8000:8000"
networks:
- jenkins-net
# List of volumes to create
volumes:
jenkins-data:
jenkins-log:
# List of netorks to create
networks:
jenkins-net:
I'm trying to learn Docker and Jenkins and was following a tutorial, the jenkins_master_1 is from the docker-compose. Any help or guidance would be really appreciative.
Thanks
Assumption 1: NGINX is in front of your app, accepting connections on port 80, then passing to backend port 8080.
Assumption 2: the Jenkins application and NGINX are on the same server here.
You should be accessing it originally from port 80, not 8080 if you are using the proxy.
NGINX gets request on 80, then passes to backend 8080. From the browser you shouldn’t see the 8080 if you are using the proxy. If you are using 8080 and it’s doing something, then your going directly to app.... aka, bypassing the proxy.
So, how to start addressing it:
(1.) Navigate to http://localhost, which should go through your proxy (if it’s set up properly)
(2.) In Manage Jenkins-> Configure System -> Jenkins URL, make sure the URL is set to http://localhost
(3.) Better to use a FQDN for the server name in the NGINX configuration, then make sure Jenkins is only listening for connections on localhost in the Jenkins.xml configuration. Jenkins.xml should have listen address set to 127.0.0.1. Then external requests to that FQDN will not be able to bypass the proxy, as Jenkins will only be allowing connections from localhost (from NGINX, or you playing with the browser on the localhost).
Then, ideally, you have:
http://fqdn->NGINX listening on port 80 -> Jenkins on 127.0.0.1:8080. The user with their browser (safely outside of your server) never sees the 8080 port.
Try adding proxy_redirect directive in location block. This instructs webserver to return different 301/302 http response codes than calculated by the server itself. Sometimes the webserver is unable to properly calculate its address like in docker where the container has no information of the outside world and that the connection is proxied/forwarded.
location / {
proxy_pass http://jenkins_master_1:8080;
proxy_redirect http://jenkins_master_1:8080 http://localhost:8080;
}
SRC: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect
Add X-Forwarded-* headers is the right solution.
Without such headers, I got a lot of errors such as I was redirected to https://jenkinsci:8080 after I set the initial password and click continue button. Many times when I visit https://jenkins.mydomain.com and click the links on the webpage, I was redirected to https://jenkinsci:8080. And https://jenkinsci:8080 can not be visited obviously. I dont't know why. Maybe tomact needs those X-Forwarded-* headers information.
This article - Jenkins behind an NGinX reverse proxy is highly recommended for those who want to run jenkins behind nginx, even if both jenkins and nginx are created through docker container. And once again, you'd better add those X-Forwarded-* headers.
An example nginx vhost configuration file:
server {
charset utf8;
access_log /var/log/nginx/jenkins.yourdomain.com.access_log main;
listen 443 ssl http2;
server_name jenkins.yourdomain.com;
ssl_certificate /etc/nginx/ssl/yourdomain.com.crt;
ssl_certificate_key /etc/nginx/ssl/yourdomain.com.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_request_buffering off;
proxy_buffering off;
proxy_pass http://jenkinsci:8080; #jenkinsci is the service/container name specified in the docker-compose.yml file
}
}

NGINX reverse proxy to Apache docker container 404

I'm trying to host several websites on my droplet. I'm to do that, I'm using NGINX (not container) as reverse proxy to Dockerized apps. One such app I'm using is the dockerized Mediawiki set to run on 0.0.0.0:8081.
Mediawiki container is based on php7.2-apache.
Nginx configuration :
server {
listen 443 ssl;
index index.php;
server_name my.website.com;
ssl_stapling on;
ssl_stapling_verify on;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://0.0.0.0:8081;
}
ssl_certificate /etc/letsencrypt/live/my.website.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/my.website.com/privkey.pem; # managed by Certbot
}
I run the application on port 8081, as can be seen by through docker ps -a
CONTAINER IMAGE PORTS
e40c9815d6cc mediawiki 0.0.0.0:8081 -> 80/tcp
I can access my.website.com, but it shows the default Apache Ubuntu default page. Accessing other pages and resources (index.php, /folder/index.php, images/pic.jpg) returns 404.
Testing the container with similar setup on my machine local works. I think there maybe something up I didn't get with the NGINX config.
Help?

service nginx restart fails

I checked the config syntax by run nginx -t then get the results:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
But when I run service nginx restart goes fail.
I have a config file named a.com in the sites-enabled folder, here's the content:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name a.com;
# root /usr/share/nginx/html;
# index index.html index.htm;
root /home/a/public;
client_max_body_size 10G;
location / {
proxy_pass http://localhost:3000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
}
}
I'm at Ubuntu 14.10 and want to deploy a rails server.
I kill the nginx's process manually, then start nginx again, solved the problem.
I had this issue and using sudo solved it:
sudo service nginx restart
It might help to enable logs to checks the errors:
https://www.nginx.com/resources/admin-guide/logging-and-monitoring/

Resources