Nginx HTTPS only works after page is refreshed - nginx

I have set up letsencrypt for https and it works fine when there is no www. For some reason I can only get 'example.com' to work fine with https (ie. redirect to https://example.com) but when I go to 'www.example.com' it doesn't go straight to https, only after I refresh the page it does so. Heres my nginx default conf:
server {
listen 80;
server_name www.example.com example.com;
return 301 https://$host$request_uri;
}
server {
# listen 80 default_server;
# listen [::]:80 default_server;
listen 443 ssl;
server_name example.com www.example.com;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
}
I've tried all sorts of redirects in the conf but none of them seem to be working. So the https seems to be working but only after a page refresh. Any help would be appreciated, thanks.

I have noticed you have use two entries for server name.
I want to know what was the purpose.
Please try this configuration.
server {
listen 80;
server_name www.example.com example.com;
rewrite ^ https://$host$request_uri? permanent;
}
server {
listen 443;
server_name example.com www.example.com;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
ssl on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
ssl_session_cache shared:SSL:2m;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}

I have no idea why this worked and other answers didn't which seemed to do the exact same thing. I changed the top server block to this. Might be useful as I couldn't find an answer to this particular problem.
server {
listen 80;
listen [::]:80;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}

Related

LetsEncrypt SSL for my React and NodeJS app not working

I have followed some tutorials that teaches to implement ssl but most of them are not working for some reason, http works fine tho, don't know what I'm missing
This is my default config, It looks like I have something wrong on my default config because I can create an httpServer in my backend.
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/metroville/{{domain}}/build;
index index.html index.htm index.nginx-debian.html;
server_name {{domain}};
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/{{domain}}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{domain}}/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
try_files $uri /index.html;
}
location /api/ {
proxy_pass http://localhost:5000;
}
}

NGINX + CentOS 8 mydomain.com shows NGINX welcome page whereas mydomain.com/index.html shows website index page

I'm trying to configure NGINX on CentOS 8 (with SSL). I believe I have configured it properly, but I can't get rid of the NGINX welcome page. I've tried a lot of things, even deleted the entire /usr/share/nginx/html directory, but I still get NGINX welcome on example.com, whereas example.com/index.html gives me the index page of my website. In fact I have noticed that the http to https and non-www to www redirections I have implemented below don't work on example.com, but do work on example.com/index.html. The root of my website is /var/www/example.com/html. The configure file which is given below is called example.com.conf and located at /etc/nginx/conf.d/.
server {
root /var/www/example.com/html;
index index.html index.htm;
server_name example.com www.example.com;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
listen [::]:443 ssl ipv6only=on default_server; # managed by Certbot
listen 443 ssl default_server; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
# Redirect non-SSL to SSL
server {
listen 80;
listen [::]:80;
server_name .example.com;
return 301 https://$host$request_uri;
}
# Redirect non-www to www
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com;
return 301 https://www.example.com$request_uri;
}
So it appears that you need to edit the global configuration file using sudo nano /etc/nginx/nginx.conf and comment out "default_server" in the listen statements. Alternatively deleting the whole server block in the global conf file also works, as long as you keep the include statement which reads the example.com.conf file.
include /etc/nginx/conf.d/*.conf;
server {
listen 80; # default_server;
listen [::]:80; # default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}

How to prevent redirects on nginx when domain in host header does not match domain in request url?

I have nginx running on my home server at keepsecret.ddns.net. When I request e.g. keepsecret.ddns.net/foo/ it returns to me keepsecret.ddns.net/foo/index.html. So far, so good.
Now I am trying to treat my home server as an upstream server. In front of that upstream server is a remote proxy server at www.mydomain.com. When I request e.g. www.mydomain.com/foo/index.html, it is returned to me no problem. However, when I request www.mydomain.com/foo/, nginx first issues a 301 redirect so that I then get sent to keepsecret.ddns.net/foo/, revealing my home IP Address :(
I have no idea why nginx behaves this way. My only guess is that it has something to do with the fact that the domain in the request host header does not match the domain in the request url.
Questions in summary:
Why does nginx do this?
How can I prevent nginx performing this redirect so that I always remain on www.mydomain.com?
Here is the salient part of my config for reference:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
}
server {
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name keepsecret.ddns.net www.mydomain.com;
location / {
try_files $uri $uri/ =404;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/keepsecret.ddns.net/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/keepsecret.ddns.net/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = keepsecret.ddns.net) {
return 301 https://$host$request_uri;
}
if ($host = www.mydomain.com) {
return 301 https://$host$request_uri;
}
listen 80 ;
listen [::]:80 ;
server_name keepsecret.ddns.net www.mydomain.com;
return 404; # managed by Certbot
}
NGINX will be doing an internal redirect to the index.html file in all cases, but it seems to get externalised when the server_name does not match the primary server_name. I suspect that changing the server_name order so that your public (proxied) name is first may get rid of that behaviour.
The alternative would be to focus on the reverse proxy, and take a look at proxy_redirect to make the reverse-proxy rewrite location headers for you.
See: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect

Is this redirect non-www domain to www domain in nginx actually works?

I have the following nginx server block for my domain name example.com. I want to redirect non www to www for the SEO.
Update
According to this answer I used the following server block. But when I test it, I got the following
nginx: [warn] conflicting server name "www.example.com" on 0.0.0.0:80, ignored
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
So, I have the doubt is it correct or not and Whether it actually redirects the non www to www, please.
/etc/nginx/sites-available/example.com
server {
server_name www.example.com;
rewrite ^(.*) https://www.example.com$1 permanent;
}
server {
root /var/www/abc-company-website/public;
index index.php index.html index.htm index.nginx-debian.html;
server_name example.com;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
location ~ /\.ht {
deny all;
}
#Cache-Control
location ~* \.(?:ico|ttf|png|svg|jpg|jpeg|js)$
{
expires 7d;
add_header Pragma public;
add_header Cache-Control "public";
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}
How can I change the above server block to redirect, please?
It's in the best practices of nginx not to use if (even more of a reason if you are using it for $host), it's better to use server brackets with different server_name.
server {
listen 80;
server_name example.org www.example.org;
return 301 https://www.example.org$request_uri;
}
This will send HTTP www and HTTP non-www to HTTPS www
If you have a cert for non-www set a server bracket and redirect to www:
server{
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
return 301 https://www.example.com$request_uri;
}
And finally you can do whatever you want in the https www.example.com bracket:
server {
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
server_name www.example.com;
# Do whatever you want to do here to get to your application
}
It's better to read the documentation and best practices of nginx, and try to make clean configurations so the next one that comes can understand it on first sight :D
If you've got any question just ask it. (looks like you didn't understand the duplicates given in the comments, so I decided to explain it 1 by 1 for your case)

ngnix www to no-www on config file generated by certbot

I am trying to get requests to example.com as well as www.example.com to go to https://example.com in the configuration file shown below. The file is exactly as generated by certbot.
Changing the two return 301 statements to
return 301 https://example.com$request_uri;
did not work as https://www.example.com still goes to https://www.example.com and not the desired https://example.com
Would appreciate if someone could point out the exact changes needed to get the desired result. Simplified instructions would be a bonus as I am quite new to both nginx and certbot. Thanks.
server {
root /var/www/html/drupal;
index index.php index.html index.htm;
server_name example.com www.example.com;
location / {
try_files $uri /index.php?$query_string;
}
location #rewrite {
rewrite ^/(.*)$ /index.php?q=$1;
}
location ~ [^/]\.php(/|$) {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ ^/sites/.*/files/styles/ {
try_files $uri #rewrite;
}
location ~ ^(/[a-z\-]+)?/system/files/ {
try_files $uri /index.php?$query_string;
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}
Open the brackets for a clearer way.
Instead of one 443 listener, create 2. Same with the 80 ones.
Like that it's much easier for you to know what is doing what, one configuration for each pair of host and schema.
server {
listen 80;
listen [::]:80;
server_name www.example.com; #this will only listen to http://www.example.com
location / {
return 301 https://example.com$request_uri; #and will upgrade to https
}
#we don't want that many redirects, so this will go directly to example.com
}
server {
listen 80;
listen [::]:80;
server_name example.com; #this will only listen to http://example.com
location / {
return 301 https://$host$request_uri; #and will upgrade to https
}
}
server {
server_name www.example.com;
location / {
return 301 https://example.com$request_uri #this redirects to non-www
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server{
#same server configuration as your first server bracket, only accepting https://example.com and not www.
}
I see that you are sending the arriving connection to a Drupal so think that the Drupal has a variable $base_url that any redirect that it makes it's made to that host, so if it's set to www.example.com, it won't matter you nginx conf, as Drupal itself can also make redirects.
Hope it helped, comment for any question.
Its working now, #flaixman. I made one change from your suggestion - which was to make just one block for 80, since they both did exactly the same thing. So, here's the final version : (I have hopefully not messed up something which might cause a problem later.)
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location / {
return 301 https://example.com$request_uri;
}
}
server {
server_name www.example.com;
location / {
return 301 https://example.com$request_uri;
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server{
root /var/www/html/d8;
index index.php index.html index.htm;
server_name example.com;
location / {
try_files $uri /index.php?$query_string;
}
location #rewrite {
rewrite ^/(.*)$ /index.php?q=$1;
}
location ~ [^/]\.php(/|$) {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ ^/sites/.*/files/styles/ {
try_files $uri #rewrite;
}
location ~ ^(/[a-z\-]+)?/system/files/ {
try_files $uri /index.php?$query_string;
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

Resources