How do I redirect all requests to an application running on a specific port using nginx? - redirect

I'm running an application on port 8000, and need to redirect all requests coming on port 80 to my application (port 8000). I understand that using nginx is the way to go about it. I modified ngninx.conf as follows:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/html;
index index.html index.htm;
server_name localhost;
location / {
proxy_pass http://127.0.0.1:8000;
try_files $uri $uri/ =404;
}
}
I'm able to redirect requests to my application server now, but requests of the form xyz.com/abc return 404 not found. I thought the above would match all requests and redirect everything to the application on port 8000. What am I doing wrong here?

try_files checks the existence of a file against the defined root in the server block. What it's doing in the location / block is checking for the file, and then returning 404 when it's not found. Perhaps you wanted your config to look like this instead?:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/html;
index index.html index.htm;
server_name localhost;
location / {
try_files $uri $uri/ #my_proxy;
}
location #my_proxy {
proxy_pass http://127.0.0.1:8000;
}
}
Here, if try_files fails to find anything, it will pass over the request to you app server running on port 8000. If it still returns 404 then the file indeed doesn't exist.

Related

ERR_TOO_MANY_REDIRECTS with nginx

I want to redirect all my http traffic to redirect to https. I am using letsencrypt. I read online that return 301 https://$server_name$request_uri; would redirect all the traffic to my website over to https but instead it results in ERR_TOO_MANY_REDIRECTS.
Everything works fine without the above mention statement, but then I have to specifically specify https in the URL. Here's my /etc/nginx/sites-available/default file:
server {
listen 80 default_server;
listen 443 ssl default_server;
ssl_certificate /etc/letsencrypt/live/mywebsite.me/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mywebsite.me/privkey.pem;
root /home/website/mywebsite/public;
index index.html index.htm index.php;
server_name mywebsite.me www.mywebsite.me;
return 301 https://$server_name$request_uri;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
}
}
Where am I going wrong?
In my case it was Cloudflare. I had to change to Full SSL encryption
Change your config to below
server {
listen 80 default_server;
server_name mywebsite.me www.mywebsite.me;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl default_server;
ssl_certificate /etc/letsencrypt/live/mywebsite.me/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mywebsite.me/privkey.pem;
root /home/website/mywebsite/public;
index index.html index.htm index.php;
server_name mywebsite.me www.mywebsite.me;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
}
}
Your current config redirects on both http and https to https. So it becomes a infinite loop because of the return statement. You want return statement only when connection is http. So you split it into two server blocks
i had the same problem. i found lots of questions/answers and articles about it but nothing helped.
i then tried to access my site from a different browser and it worked just fine!
deleting the cache from my chrome browser solved it.
So - keep in mind when you try different solutions to also clear your cache

SSL for domain, including subdomains

I have a domain, example.com. From that, I have these:
blog.example.com
api.example.com
books.example.com
I have acquired SSL cert for root domain and its subdomains.
And I want the redirections to be like so:
http://example.com => https://example.com
http://blog.example.com => https://blog.example.com
http://books.example.com => https://books.example.com
This is my example.com nginx conf
server {
listen 443 ssl default_server;
root /home/django/khophi;
index index.html index.htm;
server_name example.com;
include /etc/nginx/globalssl.conf; //ssl config
}
server {
listen 80 default_server;
server_name example.com;
return 301 https://$host$request_uri;
}
nginx conf for blog.example.com
server {
listen 443 ssl; // now listens for https
root /var/www/html/blog;
index index.php index.html index.htm;
server_name blog.example.com;
#include /etc/nginx/globalssl.conf;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
// error pages
location ~ \.php$ {
//php specific things
}
}
server {
listen 80;
server_name blog.example.com;
return 301 https://blog.example.com$request_uri;
}
books.example.com follows similar structure as blog.example.com conf
What happens With the above setup?
Visit to http://example.com redirects to https://example.com (just as I want
Visit to http://blog.example.com redirects to https://blog.example.com BUT, shows page of https://example.com
In my case, I want:
example.com to remain as default_server
http://example.com to redirect to https://example.com
ALL http:// requested subdomains to redirect to their respective https:// versions
if a subdomain is requested which doesn't exist, it should redirect to default_server (https://example.com)
Instead of using return, i use rewrite instead on the redirection server block on the main domain and its subdomains, like so:
// blog.example.com
server {
listen 80;
server_name blog.example.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
// example.com
server {
listen 80 default_server;
server_name example.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
This link helped

How to redirect from http to https and example.com to www.example.com

I need help with the following redirect example, using NGINX:
http://example.com must redirect to https://www.example.com
http://www.example.com must redirect to https://www.example.com
https://example.com must redirect to https://www.example.com
I've read related questions but still can't get both redirects to work together.
I've tried this configuration, but I get an error when trying to load the site: The connection was interrupted.
# Redirect any http:// request to https://www.example.com
server {
listen 80;
return 301 https://www.example.com$request_uri;
}
# Redirect http://example.com to https://www.example.com
server {
listen 443 ssl;
server_name example.com
return 301 https://www.example.com$request_uri;
}
server {
listen 443;
server_name www.example.com;
ssl on;
ssl_certificate /foo.crt;
ssl_certificate_key /foo.key;
root /foo/;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
# pass the PHP scripts to FastCGI server listening on /var/run/php5-fpm.sock
location ~ \.php$ {
try_files $uri /index.php =404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
You have no SSL certificate defined in the server{} block for https://example.com, and this is what causes your problems. You have to add a certificate there. (And, BTW, this information should be in your error log. It's always a good idea to look into it if something goes wrong.)
Usually it's the same cert as for www.example.com, so you have to use:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /foo.crt;
ssl_certificate_key /foo.key;
return 301 https://www.example.com$request_uri;
}
Note well that ssl on; is not needed as you are using listen ... ssl;, see here for details.

Redirect all traffic to SSL except one location

I have an nginx server running serving my website. All the connections are redirected to SSL for security reasons.
However, I was desperately looking how to exclude one location from this redirect. I already tried rewrite, redirect, proxy_pass etc. but it doesn't seem to work.
I don't want to (301 or 302) redirect my site, I only want SSL to be optional. The location various types of files (js, php, html).
For example
server {
listen 80;
server_name example.com
root /var/www/example;
location /unsafe {
try_files $uri $uri/ /index.php;
}
location / {
rewrite ^ https://$server_name$request_uri? permanent;
}
# other rules...
}
server {
listen 443;
server_name example.com
root /var/www/example;
location / {
try_files $uri $uri/ /index.php;
}
# other rules...
}
does not work.
I also tried using redirect or rewrite instead of try_files, but no luck at all. The thing is, I don't want to the traffic to be redirected, rewritten or proxy'd, I only want nginx to pass all requests on example.com/unsafe
All I get is a bunch of 404's ands 502's.
What am I doing wrong?
Cheers
You should have separate server blocks for the normal http connections (on port 80) and the https SSL connections (on port 443).
server {
listen 80;
server_name your-domain.com
root /var/www/;
location /unsafe {
try_files $uri $uri/ /index.php;
}
# your other rules...
}
server {
listen 443;
server_name your-domain.com
root /var/www/;
location / {
try_files $uri $uri/ /index.php;
}
# your other rules...
}
Amended code:
If you want all files on your site to use https connections (SSL, port 443) EXCEPT those files inside the /unsafe directory, this is what your server blocks should look like:
# This server block handles all requests on port 80 and serves only files inside
# the /unsafe directory. Everything else is redirected to an SSL connection on
# port 443.
server {
listen 80;
server_name your-domain.com
root /var/www/;
# only serve requests to files in the /unsafe directory
location /unsafe {
try_files $uri $uri/ =404;
}
# all other locations redirect to https connection
location / {
return 301 https://your-domain.com$request_uri;
}
# this location block proxies requests for PHP files to
# your fcgi php processor
location ~ /unsafe/.*\.php$ {
try_files $uri =404;
# your fcgi rules here...
}
# your other rules...
}
# This server block handles all SSL (port 443) connections.
server {
listen 443;
server_name your-domain.com
root /var/www/;
location / {
try_files $uri $uri/ =404;
}
# this location block proxies requests for PHP files to
# your fcgi php processor
location ~ \.php$ {
try_files $uri =404;
# your fcgi rules here...
}
# your other rules...
}

Nginx Redirect HTTP to HTTPS and non-www to ww

I'm setting up an Nginx server with an SSL.
The domain with the SSL is www.mydomain.example
I want to redirect all requests from:
http://mydomain.example, http://www.mydomain.example, & https://mydomain.example to
https://www.mydomain.example
I have the following server blocks setup currently:
server{
listen 443 ssl;
root /www/mydomain.example/;
ssl_certificate /ssl/domain.crt;
ssl_certificate /ssl/domain.key;
.
.
.
}
server{
listen 80;
server_name mydomain.example;
return 301 https://www.mydomain.example$request_uri;
}
server{
listen 80;
server_name www.mydomain.example;
return 301 https://www.mydomain.example$request_uri;
}
server{
listen ssl 443;
server_name mydomain.example;
return 301 https://www.mydomain.example$request_uri;
}
This currently does not work, but I don't understand why not. I can get a combination of either HTTP -> HTTPS working or no-www to -> www working, but mixing them as above does not work.
The SSL redirect won't work if your SSL certificate doesn't support the non-www domain.
The config is correct but can be reduced to just 1 redirect server
Also don't forget to reload Nginx sudo service nginx reload
server {
listen 80;
listen 443 ssl;
server_name example.com;
# add ssl settings
return 301 https://www.example.com$request_uri;
}
I am late, But you can do like this
server{
listen 443 ssl;
server_name www.mydomain.example;
root /www/mydomain.example/;
ssl on;
ssl_certificate /ssl/domain.crt;
ssl_certificate /ssl/domain.key;
.
.
.
}
server{
listen 80;
server_name www.mydomain.example mydomain.example;
return 301 https://$server_name$request_uri;
}
server{
listen 443;
server_name mydomain.example;
return 301 https://www.$server_name$request_uri;
}
Or you can replace return 301 https://www.$server_name$request_uri; with rewrite ^ http://www.$server_name$request_uri? permanent;, both will work.
You also need to set this in google webmaster for better SEO.
this works for me for HTTP to HTTPS redirection,
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
server_name example.com;
#For HTTP to HTTPS:
proxy_set_header X-Forwarded-Proto $scheme;
if ( $http_x_forwarded_proto != 'https' )
{
return 301 https://$host$request_uri;
}
location / {
try_files $uri $uri/ /index.php;
add_header 'Access-Control-Allow-Origin' '*';
}
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
Use a rewrite to send all HTTP traffic to HTTPS:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
This configuration listens on port 80 as the default server for both IPv4 and IPv6 and
for any hostname. The return statement returns a 301 permanent redirect to the
HTTPS server at the same host and request URI.
#If you like to redirect all "http" to "https" then add the following:
server {
listen 80;
server_name yourdomain.example;
server_name www.yourdomain.example;
if ($scheme = "http")
{
rewrite ^(.*)$ https://yourdomain.example$1 permanent;
}
}
Please add two given things on your file.
Code to paste on top:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
Code to paste on bottom:
server {
listen 443 ssl http2;
server_name www.example.com;
# . . . other code
return 301 https://example.com$request_uri;
}
Source
I was trying to fix the problem by redirecting the request URI to HTTPS if it was requested with the HTTP scheme. But this solution does not work in some conditions.
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
When we type a domain name in the search bar of a browser, it makes a request with the HTTP scheme by default. This behavior of the browser is not handled by nginx, but it can be done manually. We have to handle 497 status code by adding error_page 497 https://$server_name$request_uri;.
error_page 497 https://$server_name$request_uri;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
What does the 497 indicate, and when occur?
The 497 HTTP Request Sent to HTTPS Port is used when a client has made an HTTP request to a port that is listening for HTTPS requests specifically.
I couldn't figure out why HTTP http://example.com wouldn't redirect to HTTPS https://example.com. i had configured it the following way like others have and according to https://nginx.org/en/docs/http/configuring_https_servers.html, even after restarting the server with nginx -s reload && sudo systemctl restart nginx
/etc/nginx/sites-available/example.com
server {
listen 80;
server_name www.example.com example.com;
return 301 https://$server_name$request_uri;
}
server {
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 1m;
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name www.example.com example.com;
root /var/www/build;
index index.html;
location / {
try_files $uri /index.html =404;
}
}
But even though i'm using the latest browsers, the redirection from HTTP to HTTPS only works with the latest in incognito window:
Firefox: 110.0 (64-bit) (both on Desktop and Mobile)
But not with the latest in incognito window even after clear cache and hard reload:
Brave: Version 1.48.164 Chromium: 110.0.5481.100 (Official Build) (x86_64)
Chrome: Version 110.0.5481.100 (Official Build) (x86_64)
With Brave and Chrome it just loads the default HTTP page "Welcome to nginx!" from /var/www/html/
index.nginx-debian.html