Nginx non-www not redirecting - nginx

I am a total noob when it comes to servers but I am learning. I got this Nginx server block that is working as we would like it to do. The only thing that goes wrong is that when someone goes to the url mysite.nl instead of https://mysite.nl or https://www.mysite.nl, they will get an error page saying the page is insecure.
I tried looking on Google and Stackoverflow for examples but I cannot get them to work either.
Can anyone tell me how I can fix this? my server block is displayed below. The top part should redirect any non-www to www but I think it is not working. So what I want is when someone goes to mysite.nl they will end up at https://www.mysite.nl.
Hope someone can help me out.
server {
server_name mysite.nl;
listen 443 ssl; # managed by Certbot
return 301 $scheme://www.mysite.nl$request_uri;
ssl_certificate /etc/letsencrypt/live/mysite.nl-0001/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.nl-0001/privkey.pem; # managed by Certbot
}
server {
root /var/www/mysite.nl/;
index index.html index.htm index.php;
server_name *.mysite.nl;
location / {
proxy_pass http://localhost:3009/;
}
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy "origin";
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mysite.nl-0001/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.nl-0001/privkey.pem; # managed by Certbot
}
server {
root /var/www/mysite.nl/;
index index.html index.htm index.php;
server_name mysite.nl;
location / {
proxy_pass http://localhost:3009/;
}
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy "origin";
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mysite.nl-0001/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mysite.nl-0001/privkey.pem; # managed by Certbot
}
server {
if ($host = www.mysite.nl) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = mysite.nl) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name mysite.nl www.mysite.nl;
listen 80;
return 301 https://$host$request_uri; # managed by Certbot
} ```

There are a few issues with your config. Namely that you have 2 server blocks using the same sever_name so that's going to cause odd behavior. Recommend using a single server block. Also, the return blocks at the bottom are kind of broken and may be adding to the confusion.
You could just have the cert issued with all the names you're going to access the server with.
One option is to use docker + nginx-proxy + acme-companion to handle all the heavy lifting. https://github.com/nginx-proxy/nginx-proxy and https://github.com/nginx-proxy/acme-companion

Related

nginx add_header not applied to some server contexts

I have several add_header directives in my main http context of the nginx.conf file, such as:
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
There no other such directives in server and location contexts. For some reason, the header is not applied to server contexts. For example, this one:
server {
server_name my.example.com;
location / {
proxy_pass http://192.168.1.1:12345;
}
location /robots.txt {
return 200 "User-agent: *\nDisallow: /\n";
}
client_max_body_size 300M;
listen 443 ssl; # managed by Certbot
ssl_certificate fullchain.pem; # managed by Certbot
ssl_certificate_key privkey.pem; # managed by Certbot
include options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam ssl-dhparams.pem; # managed by Certbot
}
What could be causing this?
EDIT: nginx version is 1.23.3.
The file options-ssl-nginx.conf in /etc/letsencrypt/ has:
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
# + one line of ssl_ciphers
As explained in comment, adding the always parameter to the add_header directive allows the header to be added for all kind of HTTP responses (errors included), see the doc for more details: http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header

Unknown directive in NGINX default.conf

I accidently deleted my default.conf file. Luckily, I copied and pasted the original text into another file. My problem is, when I try to start NGINX after creating a new default.conf file and pasting in the text using nano editor, I get the following error:
unknown directive " " in /etc/nginx/conf.d/default.conf:3
I suspect the pasted text is injecting some unneeded stuff. If I'm correct, how do I identify that and clear it out?
Here's what I'm adding to the default.conf file:
server {
#listen 80;
server_name xr7tsi.com www.xr7tsi.com;
access_log /home/ubuntu/client/server_logs/host.access.log main;
location / {
root /home/ubuntu/client/build;
index index.html index.htm;
try_files $uri /index.html;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
}
large_client_header_buffers 4 64k;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
server_tokens off;
location ~ /\.ht {
deny all;
}
location /api {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:5000;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/xr7tsi.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/xr7tsi.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.xr7tsi.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = xr7tsi.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 default_server;
listen [::]:80 default_server;
server_name xr7tsi.com www.xr7tsi.com;
return 404; # managed by Certbot
}

SNI not working? multiple ssl reverse proxies nginx

I want to configure two reverse proxies with ssl that proxy pass to different applications
https://api.example.com --> http://app:8080
https://pg.example.com --> http://pgadmin:80
Given the following nginx configuration, both sub-domains redirect to the first 443-server config (app). The problem occurs when hitting the 443 port. The redirect from 80 to 433 works fine for both. But when I browse https://pg.example.com it passes to app instead of pgadmin.
server {
listen 80;
listen [::]:80;
server_name api.example.com pg.example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name api.example.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://app:8080;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name pg.example.com;
server_tokens off;
# note that api.example.com certificate has pg.example.com as alias
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_set_header X-Scheme $scheme;
proxy_set_header Host $host;
proxy_pass http://pgadmin:80;
proxy_redirect off;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
}
}
Feels like the SNI is not working or so..?! But it is enabled in nginx:
nginx -V
nginx version: nginx/1.17.10
built by gcc 9.2.0 (Alpine 9.2.0)
built with OpenSSL 1.1.1d 10 Sep 2019 (running with OpenSSL 1.1.1g 21 Apr 2020)
TLS SNI support enabled
What am I missing to make both reverse proxies work?
Edit:
When I remove the server block for server_name api.example.com; (on 443) then the other (pg.example.com:443) does work as expected. The api.example.com:443 then shows the same pgadmin upstream).
I think the easiest way is to split up the first server block into two server-blocks.
For example:
server {
listen 80;
listen [::]:80;
server_name api.example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
and
server {
listen 80;
listen [::]:80;
server_name pg.example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
I hope this helps, but I can't guarantee, that this config is working properly with certbot.
Turns out the reason is a misspelled domain for the sever_name of the
pg.example.com:433. Hence, not sever_name would match and nginx would then use the best match - which is the api.example.com:433.
I found out by adding a default (by making them the first in the conf file and both using sever_name _) server config for both 80 and 443 so I could ensure that the specific server configs are only used if the server_name matches. The result was that api.example.com:433 showed the same behavior as before (indicating that it works) while the pg.example.com:433 would show the newly configured default server - so it must be something that prevents the proper match on the server_name in the config. I triple checked the sever_name and finally saw the typo.

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)

Use subdomain instead of another subdomain

I know this asks too much but I really don't get it.
I am using a subdomain for my server like sub.domain.com. I can reach it with ssh with typing ssh root#sub.domain.com.
I am trying use nextcloud on this server like cloud.domain.com. I can reach nextcloud when I type sub.domain.com/nextcloud. My conf file is:
upstream php-handler {
server 127.0.0.1:9000;
#server unix:/var/run/php5-fpm.sock;
}
server {
listen 80;
server_name sub.domain.com;
# enforce https
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name sub.domain.com;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
# Add headers to serve security related headers
# Before enabling Strict-Transport-Security headers please read into this
# topic first.
add_header Strict-Transport-Security "max-age=15768000;
includeSubDomains; preload;";
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
# Path to the root of your installation
root /usr/share/nextcloud/;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
I am trying to change sub.domain.com to cloud.domain.com but it doesn't working.
Where is my mistake? Can you guys help me?
Thanks.

Resources