I have 3 NGINX hosts, that I only want to serve on HTTPS. Two of them work correctly, however, one of them resolves the wrong host. Here's all of the info
Nginx virtual hosts
# cat alpha.domain-a.tld
server {
listen 80;
server_name alpha.domain-a.tld;
return 301 https://alpha.domain-a.tld$request_uri;
}
server {
listen 443;
ssl on;
ssl_certificate /etc/nginx/certs/alpha.domain-a.tld.pem;
ssl_certificate_key /etc/nginx/certs/alpha.domain-a.tld.key;
ssl_client_certificate /etc/nginx/certs/cloudflare.crt;
ssl_verify_client on;
root /var/www/alpha.domain-a.tld/;
index index.html;
server_name alpha.domain-a.tld;
location / {
try_files $uri $uri/ $uri.html =404;
}
}
# cat mike.domain-a.tld
server {
listen 80;
server_name mike.domain-a.tld;
return 301 https://mike.domain-a.tld$request_uri;
}
server {
listen 443;
ssl on;
ssl_certificate /etc/nginx/certs/domain-a.tld.pem;
ssl_certificate_key /etc/nginx/certs/domain-a.tld.key;
ssl_client_certificate /etc/nginx/certs/cloudflare.crt;
ssl_verify_client on;
root /var/www/mike.domain-a.tld/;
index index.html;
server_name mike.domain-a.tld;
location / {
try_files $uri $uri/ $uri.html =404;
}
}
# cat juliet.domain-b.tld
server {
listen 80;
server_name juliet.dommain-b.tld;
return 301 https://juliet.domain-b.tld$request_uri;
}
server {
listen 443;
ssl on;
ssl_certificate /etc/nginx/certs/domain-b.tld.pem;
ssl_certificate_key /etc/nginx/certs/domain-b.tld.key;
ssl_client_certificate /etc/nginx/certs/cloudflare.crt;
ssl_verify_client on;
root /var/www/juliet.domain-b.tld;
index index.html;
server_name juliet.domain-b.tld;
location / {
try_files $uri $uri/ $uri.html =404;
}
}
Alpha and mike resolve correctly, however, when i try to access http://juliet, it redirects me to alpha rather than https://juliet, as shown below:
# curl -I --resolve alpha.domain-a.tld:80:127.0.0.1 http://alpha.domain-a.tld/
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: #OMMITED
Content-Type: text/html
Content-Length: #OMMITED
Connection: keep-alive
Location: https://alpha.domain-a.tld/
# curl -I --resolve mike.domain-a.tld:80:127.0.0.1 http://mike.domain-a.tld/
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: #OMMITED
Content-Type: text/html
Content-Length: #OMMITED
Connection: keep-alive
Location: https://mike.domain-a.tld/
# curl -I --resolve juliet.domain-b.tld:80:127.0.0.1 http://juliet.domain-b.tld/
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: #OMMITED
Content-Type: text/html
Content-Length: #OMMITED
Connection: keep-alive
Location: https://alpha.domain-a.tld/
Could anyone help me find out why juliet is resolving the first alphanumeric host (alpha) rather than juliet?
Look at the server_name of juliet:
# cat juliet.domain-b.tld
server {
listen 80;
server_name juliet.dommain-b.tld;
return 301 https://juliet.dommain-b.tld$request_uri;
}
juliet.dommain-b.tld probably doesn't exists? I think your curl-command is correct (with the correct url) but in your nginx config you wrote the wrong name. Your nginx server doesn't know the domain but the dns request resolves correctly to your server and so your server returns the first entry of your nginx config.
Related
For Nginx, I'm attempting to do two things:
Redirect anyone who comes in to the site from www to non-www.
The server defaults to error 500 instead of 404 when the URL path doesn't exist.
This is my current configuration of my server:
server {
root /var/www/project/;
index index.php index.html index.htm index.nginx-debian.html;
server_name example.com www.example.com;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
}
location ~ /\.ht {
deny all;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed$
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # manag$
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
}
I attempted adding a forward for any www traffic to move into non-www but that didn't do anything (I think because of certbot). Also I tried to update the URL for returning 404 instead of 500, but what it did was it made anything outside of the homepage a 404. So I reset it to what you see above.
Redirect anyone who comes in to the site from www to non-www.
The cleanest solution is to define a separate server block only for this purpose:
server {
listen 80;
server_name www.example.com;
return 301 http://example.com$request_uri;
}
You can verify that it works by putting
127.0.0.1 localhost example.com www.example.com
in your computer's hosts file.
$ curl -I http://www.example.com
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Fri, 27 Aug 2021 06:14:43 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
Location: http://example.com/
The server defaults to error 500 instead of 404 when the URL path doesn't exist.
The 500 HTTP status code is probably caused by your index.php script.
I am attempting to figure out a redirect for my domain in my nginx config. I have these three domain names:
domain.com //points to server 1
www.domain.com //points to hubspot server 2, no a record to change naked domain
app.domain.com //points to server 1
I need domain.com to redirect to www.domain.com
I need app.domain.com to stay un-redirected
Everything that I am trying is redirecting ALL urls to www.domain.com!
What am I doing wrong?
One attempt, redirects everything:
server {
listen 80;
server_name domain.com;
return 301 www.domain.com;
}
server {
root var/www/domain/public;
index index.php index.html;
server_name app.domain.com;
}
another attempt, redirects everything:
server {
listen 80;
root var/www/domain/public;
index index.php index.html;
server_name domain.com app.domain.com;
return 301 www.domain.com
}
This one just totally breaks my config:
server {
listen 80;
root var/www/domain/public;
index index.php index.html;
server_name domain.com app.domain.com;
location domain.com {
return 301 www.domain.com;
}
}
Update:
I've updated my config to say this:
server {
server_name domain.com;
return 301 $scheme://www.domain.com$request_uri;
}
server {
root /var/www/domain/public;
index index.php index.html;
server_name app.domain.com;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
}
}
Here is what currently is happening:
domain.com and app.domain.com both point to our google cloud server. I want app.domain.com to continue pointing here, and for domain.com to 301 redirect to hubspot
www.domain.com points to our hubspot server
What currently happens with the above is:
www.domain.com goes to the correct place (hubspot)
app.domain.com goes to the correct place (google cloud)
domain.com still goes to the wrong place (google cloud), but using curl -I -L domain.com says it is 301 redirected to the correct location! I'm so confused.
Some friends of mine testing the address for me say they are being correctly 301 redirected, but a few are not (including myself)
Here is the printout from the curl command:
HTTP/1.1 301 Moved Permanently
Server: nginx/1.10.3 (Ubuntu)
Date: Sun, 09 Aug 2020 22:33:49 GMT
Content-Type: text/html
Content-Length: 194
Connection: keep-alive
Location: ht tp://www.domain.com/
HTTP/1.1 200 OK
Date: Sun, 09 Aug 2020 22:33:49 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 54566
Connection: keep-alive
www.example.com and app.example.com use the same root directory? If yes, see example below.
For example.com if you need redirect to www subdomain:
server {
listen 80;
server_name example.com;
return 301 http://www.example.com$request_uri;
}
For www.example.com and app.example.com without redirect and output data from /var/www/example/public:
server {
listen 80;
server_name www.example.com app.example.com;
root /var/www/example/public;
index index.php index.html;
}
Hi need to create rewrite:
Expected results:
FOR REQUEST: sub4.sub3.example.com
LOAD: sub4.example.com/sub3
I tried this:
server{
listen 80 default_server;
server_name ~^(?<subdomain>\w+)\.test\.server$;
location / {
rewrite ^ http://test.server/$subdomain/$request_uri permanent;
}
}
But it not work as suspect with recursive redirects.
Any work around?
UPD:
server{
listen 80;
server_name domain.test.server test.server;
root /usr/share/nginx/html;
location / {
if ($host ~* ^(?<sub>.+)*\.test\.server$ )
{ rewrite ^/(.*)$ http://test.server/$sub/$1; }
}
}
}
THIS WORKS BUT WITH REDIRECT:
curl -I http://domain.test.server/
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.12.2
Date: Fri, 20 Sep 2019 10:17:52 GMT
Content-Type: text/html
Content-Length: 161
Connection: keep-alive
Location: http://test.server/domain/
Is there some way without redirect?
server{
listen 80;
server_name ~^(?<lev4>.+)*\.(?<lev3>.+)*\.(?<lev2>.+)*\.(?<lev1>.+)*$ ;
root /var/www/app;
location / {
proxy_set_header Host $lev4.$lev2.$lev1 ;
proxy_pass http://127.0.0.1:80;
if ($host ~* ^(?<lev4>.+)*\.(?<lev3>.+)*\.(?<lev2>.+)*\.(?<lev1>.+)*$ ) {
rewrite ^/(.*)$ /$lev3/$1 break;
}
}
}
server{
listen 127.0.0.1:80;
server_name sub4.example.com;
root /var/www/app;
location / {
}
}
I installed certbot certificate for nginx:
sudo certbot --nginx -d example.com
and redirect all http to https:
# Redirect non-https traffic to https
if ($scheme != "https") {
return 301 https://$host$request_uri;
} # managed by Certbot
It is working from browser, but I still can make insecure connection via
curl --insecure example.com
Here are the main configurations in nginx.conf:
server {
listen 80;
server_name example.com;
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
location / {
root /www/html/;
...
proxy_pass http://127.0.0.1:80;
}
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
proxy_ssl_trusted_certificate /etc/letsencrypt/live/example.com/cert.pem;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
}
When I issue
curl -iI https://example.com, it returns:
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 04 Jul 2018 09:19:35 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 1218
Connection: keep-alive
X-Powered-By: Express
Accept-Ranges: bytes
Cache-Control: public, max-age=0
Last-Modified: Tue, 01 Jul 2018 12:10:25 GMT
ETag: W/"Zwtf1TTMBhoSbg9LZvHbCg=="
Strict-Transport-Security: max-age=31536000; includeSubDomains
it should return HTTP/1.1 301 Moved Permanently, in which user agent may or may not redirect to new location.
use -L or --location switch in your curl command to automatically follow the redirections.
Edit 2018-07-05:
Here are the main configurations in nginx.conf:
Though that's not a bad config, if directive usage is discouraged.
You'd better split the config into two separate server block, one for http, and other for https.
Something like:
server {
listen 80;
server_name example.com;
# log your http request if you need to
error_log /var/log/nginx/example-com_error.log notice;
access_log /var/log/nginx/example-com_access.log combined;
# certbot endpoint
location ~ ^/\.well-known/ {
root /var/www/certbot/;
access_log off;
}
# other requests should end up here
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name example.com;
# log your http request if you need to
error_log /var/log/nginx/example-com_error.log notice;
access_log /var/log/nginx/example-com_access.log combined;
# default document root and document index
root /var/www/html;
index index.html;
# SSL cert, private key, and configurations.
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;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# https configurations
location / {
proxy_pass http://127.0.0.1:80; # why would you proxy_pass back to nginx again?
# you only need this if your proxy_pass uses https, not http like this example.
proxy_ssl_trusted_certificate /etc/letsencrypt/live/example.com/cert.pem;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
}
}
should suffice.
When I issue curl -iI https://example.com, it returns:
yes, why it wouldn't return a HTTP/1.1 200 OK?
The insecure part of --insecure flag in cURL only disables HTTPS certificate validation, i.e. you can use invalid SSL certificate in your HTTPS request (bad CN, bad SAN, bad expiry date, bad CA, self signed, etc) and cURL will still satisfy your request instead of failing hard.
It works from outside (ipv4).
My nginx configuration has to be messed up, since when I browse for 192.168.xxx.xxx (address of my webserver), I get forwarded to my homepage's DNS. Even if I use "localhost" or "0.0.0.0" in my browser bar on the webserver itself, it doesn't work.
Can anyone tell me how to properly solve this? If I insert anything else than "cooldomain.com", it won't be reachable from the outside, right? But there has to be a solution.
The nginx server is running in a docker container, which is based on the official nginx image.
This is my nginx config file:
server {
listen 80;
listen 443 ssl http2;
server_name cooldomain.com;
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers On;
ssl_certificate /usr/share/nginx/fullchain.pem;
ssl_certificate_key /usr/share/nginx/privkey.pem;
ssl_trusted_certificate /usr/share/nginx/chain.pem;
ssl_session_cache shared:SSL:128m;
add_header Strict-Transport-Security "max-age=31557600; includeSubDomains";
ssl_stapling on;
ssl_stapling_verify on;
# Your favorite resolver may be used instead of the Google one below
# resolver 8.8.8.8;
# /usr/share/nginx/html;
# index index.html;
# charset koi8-r;
# access_log /var/log/nginx/host.access.log main;
location / {
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
root /usr/share/nginx/html;
# index index.html index.htm;
try_files $uri$args $uri$args/ /index.html;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Edit:
Output of docker ps:
faXXXXX nginx "nginx -g 'daemon off" 14 minutes ago, up 14 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp webserver
(this is sadly not a copy paste)
Output of curl -v http://127.0.0.1:
$ curl -v http://127.0.0.1
Rebuilt URL to: http://127.0.0.1/
Trying 127.0.0.1...
Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
GET / HTTP/1.1
Host: 127.0.0.1
User-Agent: curl/7.47.0
Accept:
HTTP/1.1 301 Moved Permanently
Server: nginx/1.13.3
Date: Wed, 20 Sep 2017 15:46:55 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: https://cooldomain.com/
Strict-Transport-Security: max-age=31557600; includeSubDomains
Connection #0 to host 127.0.0.1 left intact
I managed to workaround it. I don't know if this is the right way to do it, but it does the job.
I added another server-block before my server block, which has the default_server prefix.
If you have a better idea, feel free to write an answer. :)
This is how my config file looks now. Pay attention to the first block:
server {
listen 80;
server_name 127.0.0.1 default_server;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
server {
listen 80;
listen 443 ssl http2;
server_name cooldomain.com;
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers On;
ssl_certificate /usr/share/nginx/fullchain.pem;
ssl_certificate_key /usr/share/nginx/privkey.pem;
ssl_trusted_certificate /usr/share/nginx/chain.pem;
ssl_session_cache shared:SSL:128m;
add_header Strict-Transport-Security "max-age=31557600; includeSubDomains";
ssl_stapling on;
ssl_stapling_verify on;
# Your favorite resolver may be used instead of the Google one below
# resolver 8.8.8.8;
# /usr/share/nginx/html;
# index index.html;
# charset koi8-r;
# access_log /var/log/nginx/host.access.log main;
location / {
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
root /usr/share/nginx/html;
# index index.html index.htm;
try_files $uri$args $uri$args/ /index.html;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}