How to configure a proxy with a subdomain servername - nginx

I have the following vhost configuration in nginx:
upstream mybackendsrv {
server backend:5432;
}
server {
listen 80;
server_name sub.domain.org;
location / {
proxy_pass http://mybackendsrv;
}
}
When I use a server_name like sub.domain.org, I get the default nginx fallback and my server is not matched.
When I use a server_name like customroute, I get the correct behaviour and my server is matched.
I googled this issue a bit and I believe that subdomain matching is supported in nginx so I'm not sure what's wrong. I checked the access.log and error.log and I get no relevant log.
Any idea how to diagnose this?
I should be able to display route matching logic in debug mode in nginx, but I'm not sure how to accomplish this.
Any help is appreciated.

After investigation, it seems the problem was unrelated to the fact that our URL was a subdomain.
To debug the situation, a $host variable was introduced in the log_format directive in /etc/nginx/nginx.conf:
log_format main '$remote_addr - $host - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
This $host variable allowed to understand that there was a problem with sub.domain.org: when we accessed sub.domain.org, the host was changed to the NGINX server's hostname, contrary to customroute which host was not changed.
It appears sub.domain.org was not a simple DNS config but was an Apache proxy pass configuration. Apache was changing the host name when passing the request, causing NGINX to not match the rewritten host because it received in the request host it's own host instead of the target host.
To correct this behavior, we had to add the following configuration in Apache: ProxyPreserveHost on.
Once we restarted Apache, it the host was preserved and our server_name sub.domain.org was correctly matched in NGINX.

Related

How to see the resolved proxy_pass URL in Nginx?

I have a setup like this for reflecting requests:
location ~ ^/prefix/string/(.*)$
{
proxy_pass https://abc.example.com/$1;
access_log /var/log/nginx/unique.log logformat
}
Visit my site at /prefix/string/more_stuff
Logs show 404 with $upstream_addr only containing the IP of abc.example.com,
not the full URL
Log lines show up in unique.log, so I know I'm hitting this location block.
I want to eliminate the possibility that the URL construction with $1 is wrong.
I would like to be able to log the resolved complete proxy_pass URL so I can
fix it or move on to other types of debugging.
Note: I realize that I can read docs to figure out nginx's behavior in this case. But just logging the resolved URL would be way faster if possible.
Question: How to log the resolved URL that NGINX actually visits for a proxy_pass like this?
You can use named capture group to capture your URI suffix as some unique variable instead of $1:
location ~ ^/prefix/string/(?<suffix>.*)$ {
access_log /var/log/nginx/unique.log unique;
proxy_pass https://abc.example.com/$suffix;
}
Define a new unique log format at the http context level (for example, adding this $suffix value to the default combined log format):
# should be defined outside the server block!
log_format unique '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"'
' Proxy path: "$suffix"';
server {
...
}

Enable HTTP2 Server Push Nginx

I installed nginx with HTTP2 support. My nginx is behind application load balancer and SSL termination is happening at LB only.
I first enabled HTTP2_PUSH like below:
http2_push_preload on;
location /mx {
http2_push https://example.com/css/style.css;
http2_push https://example.com/js/main.js
}
But it did not work. My browser debugger network tab was showing initiator is "index", and nghttp also did not show anything.
Another approach I tried is:
http2_push_preload on;
location /mx {
add_header Link "<https://example.com/css/style.css>; rel=preload; as=style,<http2_push https://example.com/js/main.js>; rel=preload; as=script";
}
Next approach changed initiator from index to other in network tab, but nghttp tool still confirms that no server push is happening.
My understanding is the AWS Application Load Balancer is a level 7 (HTTP) load balancer and only supports HTTP/2 on the front end and not to your Nginx back end.
You can check this by adding $server_protocol to your Nginx log_format:
log_format my_log_format '$remote_addr - $remote_user [$time_local] $server_protocol "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';
access_log /usr/local/nginx/nginx-access.log my_log_format;
I’d guess the traffic is coming in as HTTP/1.1.
Even if AWS ALB does support HTTP/2 to the backend now, that doesn’t mean it will support HTTP/2 Push. This gets complicated when multiple pieces of infrastructure is involved like this (what if the ALB and Nginx both support push but client doesn’t) and best advice is to push from the edge node, especially if it supports that via HTTP preload header instructions.
You are probably better using a level 4 (TCP) load balancer to get this to work.

How can I host multiple apps under one domain name?

Say I own a domain name: domain, and I host a static blog at www.domain.com. The advantage of having a static site is that I can host it for free on sites like netlify.
I'd now like to have several static webapps under the same domain name, so I don't have to purchase a domain for each webapp. I can do this by adding a subdomain for my apps. Adding a subdomain is easy enough. This video illustrates how to do it with GoDaddy for example. I can create a page for my apps called apps.domain.com where apps is my subdomain.
Say, I have several static webapps: app1, app2, app3. I don't want a separate subdomain for each of these, e.g., app1.domain.com. What I'd like instead is to have each app as a subfolder under the apps subdomain. In other words, I'd like to have the following endpoints:
apps.domain.com/app1
apps.domain.com/app2
apps.domain.com/app3
At the apps.domain.com homepage, I'll probably have a static page listing out the various apps that can be accessed.
How do I go about setting this up? Do I need to have a server of some sort (e.g., nginx) at apps.domain.com? The thing is I'd like to be able to develop and deploy app1, app2, app3 etc. independently of each other, and independently of the apps subdomain. Each of these apps will probably be hosted by netlify or something similar.
Maybe there's an obvious answer to this issue, but I have no idea how to go about it at the moment. I would appreciate a pointer in the right direction.
Something along the lines of below should get you started if you decide to use nginx. This is a very basic setup. You may need to tweak it quite a bit to suit your requirements.
apps.domain.com will serve index.html from /var/www
apps.domain.com/app1 will server index.html from /var/www/app1
apps.domain.com/app2 will server index.html from /var/www/app2
apps.domain.com/app3 will server index.html from /var/www/app3
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
index index.html;
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name apps.domain.com;
root /var/www;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
location /app1 {
}
location /app2 {
}
location /app3 {
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
I initially solved this problem using nginx. But, I was very unhappy with that because I needed to pay for a server, and needed to set up the architecture for it etc.
The easiest way to do this, that I know of today, is to make use of URL rewrites. E.g. Netlify rewrites, Next.js rewrites.
Rewrites allow you to map an incoming request path to a different destination path.
Here is an example usage in my website.
Just one addition: if you're hosting the apps on an external server you might want to setup nginx and use the proxy plugin to forward incoming requests from your nginx installation to the external webserver:
web-browser -> nginx -> external-web-server
And for the location that needs to be forwarded:
location /app1 {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass https://url-of-external-webserver;
}
It would seem that you're asking the question prematurely — what actual issues are you having when doing what you're trying to do using the naive approach?!
It is generally the best idea to have each app run on its own domain or subdomain; this is done to prevent XSS attacks, where vulnerability in one of your apps may result in your whole domain becoming vulnerable. This is because security features are generally implemented in the browser on a per-domain basis, where it is presumed that the whole domain is under the control of a single party (e.g., running a single app, at the end of the day).
Otherwise, there's really nothing that special that must be done to have multiple apps on a single domain. Provided that your paths within each app are correct (e.g., they're either relative, or absolute with the full path of the location of the specific app), there's really not any specific issues to be aware of, frankly.

nginx reverse proxy alfresco

I have alfresco installed on a server, I want to force alfresco to only serve 1 language (italian) so, since it normally reads the language wanted from the http header, i set up an nginx reverse proxy to change the header.
The proxy runs on the server and listens to connections on port 80 and redirects them to the port 8080 where the alfresc otomcat server is running.
This is my server code in the nginx conf file:
server {
set $language 'it-IT';
add_header Accept-Language $language;
listen 80;
server_name alfresco
access_log logs/host.access.log main;
location / {
root html;
proxy_pass http://<serverip>:8080;
proxy_set_header Accept-Language $language;
proxy_set_header Host $host;
}
}
Everything works nicely, now i wanted to substitue with localhost (or 127.0.0.1), i thought that it should work since nginx is running on the same server as alfresco but it doesn't.
In particular, when i use and type the ip in the address bad of another machine i will get redirected correctly to http:///share/page/ and the page will be in italian (as expected)
but when i try to put localhost or 127.0.0.1 i will get redirected to http://:8080/share/page/ and the page will have the language i have in my browser.
Does anyone have an idea as to why this happens?

Nginx can't find phpMyAdmin

Hello I have installed the newest stable Version of Nginex (1.4.4) and want to install also phpMyAdmin, unfortunately the following error appears when I try to open phpMyAdmin in my browser through http:// 192 . . . /phpmyadmin:
404 Not Found
nginx/1.4.4
What exactly is the reason that Nginx can't find the phpMyAdmin file?
This is the content of my /etc/nginx/nginx.conf file:
user nginx;
worker_processes 4;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
Many Greetings
It's really not a good idea to make a symbolic in your document root, that's just asking for trouble having a phmyadmin shortcut in www.
The right way to do it is to create a file called php and add to /etc/nginx/sites-available. You can copy the file below but change the port number to something else.
server {
listen 30425;
# Don't want to log accesses.
#access_log /dev/null main;
access_log /var/log/nginx/php.acces_log main;
error_log /var/log/nginx/php.error_log info;
root /usr/share/phpmyadmin;
index index.php index.html index.htm;
error_page 401 403 404 /404.php;
location ~ .*.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SERVER_NAME $http_host;
fastcgi_ignore_client_abort on;
}
}
Now you need to make symbolic link to sites enabled directory
ln -s /etc/nginx/sites-available/php//etc/nginx/sites-enabled
now you need to add this code to Logging Settings part of nginx.conf
log_format main ‘$remote_addr – $remote_user [$time_local] ‘
‘”$request” $status $body_bytes_sent “$http_referer” ‘
‘”$http_user_agent” “$http_x_forwarded_for”‘ ;
Now you can access your phpmyadmin with http://example.com:30425
I have followed the instructions on https://www.digitalocean.com/community/articles/how-to-install-phpmyadmin-on-a-lemp-server and linked nginx and phpMyAdmin through the following command:
sudo ln -s /usr/share/phpmyadmin/ /usr/share/nginx/html
(the folder "www" was replaced in the newer versions of Nginx through "html")
sudo service nginx restart
If I now try to start phpMyAdmin through
"http:// 192 . . . /phpmyadmin"
the following error appears in my browser:
403 Forbidden
nginx/1.4.4
If I try to start phpMyAdmin through
"http:// 192 . . . /phpmyadmin/index.php"
the index.php file only gets downloaded.
Many Greetings
The answers provided here did not help me for reasons unknown. I suspect that other parts of my conf file ruled out going into the phpmyadmin directory.
Not wanting to spend too long fixing it to work I simply copied my working conf file from www.example.com to phpmyadmin.example.com and set the directory to /usr/share/phpmyadmin. I then did nginx -s reload and I was good to go without ever having to get to the bottom of the 403/502 errors that I encountered doing it properly. I also believe that http://phpmyadmin.example.com is more secure from random hackers trying their scripts than the http://www.example.com/phpmyadmin domain, however it does entail having the wildcard setup correctly for the DNS for your domain, i.e. so that the address resolves to your server.
Hope this helps anyone frustrated in the simple task of getting phpmyadmin working with nginx.
As user1941083 explain.
You just need to create a symbolic link between phpMyAdmin and your site’s directory.
sudo ln -s /usr/share/phpmyadmin/ /usr/share/nginx/www
And after that, modify nginx setting in /etc/nginx/sites-available.
Change :
index index.html index.html;
to :
index index.html index.html index.php;
Simply try by using http://domain-name-or-ip-address/phpmyadmin/index.php
Sometime Nginx do not use index.php automatically, we have to tell it, either by changing location in nginx.conf file or by adding index.php manually into url, just like above.
I know this is late though but I had the same problem after following some tutorials and suggestions online but to no avail. I also tried #STH answer on this page but still error still exist.
I had to restart the following services:
sudo systemctl restart nginx.service
sudo systemctl restart php-fpm
THIS DID THE TRICK: Configure the Daemons to Start at Boot, to ensure that all of the LEMP programs start automatically after any server restarts:
sudo systemctl enable nginx mysqld php-fpm
Try to create the symbolic link between the phpmyadmin location and nginx www:
sudo ln -s /usr/share/phpmyadmin/ /usr/share/nginx/html
after this you can get the 403 Forbidden but should add the index.php inside the server tag where index.html and others are:
/etc/nginx/sites-available/default
and then restart nginx

Resources