Disable gzip compression only for https connections on nginx - nginx

Having a server block that should serve content both for http and https :
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
include snippets/certificate.conf;
include snippets/ssl-params.conf;
root ...
}
Is it possible configure the gzip compression off only for the https connection in the same server block, or do i have to slipt them ?
EDIT:
Actually could be done checking the request scheme inside the location block and set gzip to off if is equal to https:
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
include snippets/certificate.conf;
include snippets/ssl-params.conf;
location / {
if ($scheme = "https") {
gzip off;
}
try_files $uri $uri/ =404;
}
...
}
problem is it seem safe only use rewrite and return statement inside if block https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/

Well it is not possible
Syntax: gzip on | off;
Default:
gzip off;
Context: http, server, location, if in location
As you can see it can be used only in these blocks http, server, location, if in location. And it doesn't allow any parameters for the value
nginx: [emerg] invalid value "$gzip_flag" in "gzip" directive, it must be "on" or "off" in /usr/local/openresty/nginx/conf/nginx.conf:15
So you have to split your servers into two. But since rest of your stuff will be common, you can put everything in a include file. Include that file in both server locations

Related

nginx proxy subdirectory to subdomain on same machine

I'm using the docker image from linuxserver called swag which contains an nginx reverse proxy and a Let's encrypt certbot. Quite some dockerized apps are not designed to be accessed via subdirectory proxying but instead need to be proxied to a subdomain (because otherwise js and css files are requested from the domain, not the subdirectory).
My goal is to make a service at 1.test.example.com available at example.com/1
The config for the subdomain looks like this and works fine:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
root /config/www;
index index.html index.htm index.php;
server_name 1.test.*;
include /config/nginx/ssl.conf;
client_max_body_size 0;
# some app
location / {
include /config/nginx/proxy.conf;
proxy_pass http://172.2.0.2:1234/;
}
}
My try for proxying to the subdomain looks like this but doesn't work as my browser returns "400 Bad request":
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
root /config/www;
index index.html index.htm index.php;
server_name _;
include /config/nginx/ssl.conf;
client_max_body_size 0;
# proxy to some app
location /1/ {
include /config/nginx/proxy.conf;
proxy_pass https://1.test.example.com;
proxy_set_header Host 1.test.example.com;
}
}
What is the correct way to do this using proxy_pass and without using rewrite?

HTTPS on NGINX server running wordpress

I am trying to implement HTTPS on a site ased on nginx server, Now even with the below config it only opens HTTP site
My server config for nginx server is like this
server {
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/mydomain.in/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.in/privkey.pem;
server_name mydomain.in www.mydomain.in;
rewrite ^(.*) http://$server_name$1 permanent;
}
server {
server_name mydomain.in www.mydomain.in;
access_log /var/log/nginx/mydomain.in.access.log rt_cache_redis;
error_log /var/log/nginx/mydomain.in.error.log;
root /var/www/mydomain.in/htdocs;
index index.php index.html index.htm;
include common/redis-php7.conf;
include common/wpcommon-php7.conf;
include common/locations-php7.conf;
include /var/www/mydomain.in/conf/nginx/*.conf;
}
The server does not serve HTTPS Requests i.e even if i specifically put https in browser it still takes me back to http site. I am not able to diagnose if its nginx or wordpress which is at fault ?
Note : the traffic is routed through cloudflare dns and certificate is
switch off in cloudflare so that it doesn't interfere. I am Relatively new to nginx
Well below is the basic idea.
server {
server_name mydomain.in www.mydomain.in;
listen 80;
location / {
return 301 https://mydomain.in$request_uri;
}
}
server {
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/mydomain.in/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.in/privkey.pem;
server_name mydomain.in www.mydomain.in;
access_log /var/log/nginx/mydomain.in.access.log rt_cache_redis;
error_log /var/log/nginx/mydomain.in.error.log;
root /var/www/mydomain.in/htdocs;
index index.php index.html index.htm;
include common/redis-php7.conf;
include common/wpcommon-php7.conf;
include common/locations-php7.conf;
include /var/www/mydomain.in/conf/nginx/*.conf;
}
The top server block listens on port 80 (http). It has one location block which does a return 301. return is preferred over rewrites in most cases. I also put it into a location block because you have a letsencrypt ssl cert which might require another location ^~ /.well-known { block to help handle that.
The second server block listens on port 443 (https). It has the SSL certs and includes the information exposed previously for as the http server block.
This setup will handle redirecting from http on either mydomain.in or www.mydomain.in to https mydomain.in. On https both mydomain.in and www.mydomain.in will receive SSL requests.
If you want it to redirect to a primary https domain you can add another server block for the secondary(ies) like so.
server {
server_name www.mydomain.in;
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/mydomain.in/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.in/privkey.pem;
location / {
return 301 https://mydomain.in$request_uri;
}
}
Of course, this means you would have to change the second server block to remove the secondary(ies) domain names.
Also while testing you might want to change the 301s to 302s so that if you misconfigure the first time that it not be stuck in the browser cache. After you get everything to a good state then change back to 301s.

How to fix http redirects with Nginx?

I have a webpage where http redirects are a bit broken.
The current behavior is this:
www.example.com, example.com, http://www.example.com, http://example.com, https://www.example.com all gets redirected to https://www.example.com
and
https://example.com gets an error saying refused to connect.
I want the behavior to be like this:
example.com, http://example.com, https://example.com redirects to https://example.com
www.example.com, http://www.example.com, https://www.example.com redirects to https://www.example.com
Here is my Nginx config file
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
include snippets/ssl-example.com.conf;
include snippets/ssl-params.conf;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location ~ /.well-known {
allow all;
}
location / {
try_files $uri $uri/ =404;
}
}
Reason is because I want these links to work
https://www.ssllabs.com/ssltest/analyze.html?d=example.com
https://www.ssllabs.com/ssltest/analyze.html?d=www.example.com
https://hstspreload.org/?domain=example.com
https://hstspreload.org/?domain=www.example.com
You have two independent issues:
Your requests all redirect to example.com, regardless of which specific domain is originally accessed.
This happens because the $server_name variable that you are using is effectively a static variable in a given server context, and has a very distant relationship to $http_host.
The correct way would be to use $host instead (which is basically $http_host with some edge-corner cleanups).
You're receiving connection issues when trying to contact https://example.com, but not https://www.example.com.
There is not enough information in your question to pinpoint the exact origin of this problem.
It can be a DNS issue (A/AAAA records of example.com set at an IP address where appropriate bindings to the https port aren't made).
It could be an issue with the mismatched certificate:
Does your certificate cover both example.com and www.example.com? If not, then you can't have both.
If you have separate certificates, you may also need to acquire separate IP addresses, or risk preventing a significant number of users from accessing your site due to lack of SNI.
As of note, it should also be pointed out that it is generally a sloppy practice to not have a unified notation on the way your site is accessed. Especially if SEO is of any concern to you, the best practice is to decide on whether you want to go with or without www, and stick to it.
You need something like this:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name www.example.com;
include snippets/ssl-example.com.conf;
include snippets/ssl-params.conf;
add_header Strict-Transport-Security "max-age=300; includeSubdomains; preload";
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name example.com;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
include snippets/ssl-example.com.conf;
include snippets/ssl-params.conf;
add_header Strict-Transport-Security "max-age=300; includeSubdomains; preload";
location ~ /.well-known {
allow all;
}
location / {
try_files $uri $uri/ =404;
}
}
All your requests will be ultimately routed to https://example.com.
Your ssl certificate should also be valid for https://www.example.com which I note you have said it is.

NginX http redirection to https returns unreadable respone

I want to redirect all http requests to https with NginX, but I have some difficulties with it.
Here is my vhost file :
server {
gzip off;
listen 80;
listen [::]:80;
server_name mydomain.fr www.mydomain.fr sub.otherdom.fr otherdom.fr;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
root /usr/share/nginx/html;
index index.html index.htm;
ssl on;
server_name mydomain.fr www.mydomain.fr sub.otherdom.fr otherdom.fr;
ssl_certificate /root/tmp/live-ecdsa/mydomain.fr/0001_chain.pem;
ssl_certificate_key /root/tmp/live-ecdsa/mydomain.fr/privkey-p384.pem;
access_log /var/log/nginx/default.access.log;
charset utf-8;
location / {
try_files $uri $uri/ /index.html;
}
}
Trying to access these domain over plain http with different browsers results in the following :
Chrome/Firefox : downloading a file filled with bytes data
Edge : displays a blank page with €ÿÿÿÿ
A curl -I mydomain.fr outputs ▒▒
Accessing these domains directly over https works.
I have already tried with both return 301 https://$host$request_uri; and return 301 https://$server_name$request_uri;
I suspect it has something to do with the fairly large number of server names you are declaring in the one server name field inside a pretty locally scoped context. Although, if I'm honest thats a fairly unfounded assertion based on habits I've become user to.
I'd suggest a few things, although generally most of this wont fix your problem, it might make it easier to work out whats happening:
split your config into purposed files. Ie. Create a ssl.conf in another folder which contains all youe cert settings, cipher suites etc. Then add an include /path/to/ssl.conf in your config.
dont use $host, this variable can be set by the use so probably a less than great idea
Assuming you have all the other relevant ssl/tls settings referenced from somewhere else then the below should roughly work.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name mydomain.fr;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
root /usr/share/nginx/html;
$server_name mydomain.fr
location / {
try_files $uri $uri/ /index.html;
}
}
Well, although user6788523 response helped me with the debugging, the fault was on my side.
I had several other vhost files with the http2 directive associated with the http port 80 (listen [::]:80 http2;). Removing the http2 directive resolved the problem.
This setting must be used only with ssl enabled server block

Nginx serving any domain with HTTPS to the default_server - How to stop it?

Here's my how my nginx config looks like:
server {
listen 443 default_server ssl;
server_name dlgt.co;
[... bunch of stuff there ...]
}
#HTTP Server redirects to https
server {
server_name _;
rewrite ^ https://dlgt.co$request_uri? permanent;
}
server {
listen 443;
server_name _;
rewrite ^ https://dlgt.co$request_uri? permanent;
}
With that though, accessing the IP with https:// will still work. I'm trying to block that behavior, because it is simply throwing errors. I can't find how to exclude all other server_names from the config, and I thought that my last 2 blocks would do the trick, but visibly not.
Thanks !
Your last block is conflicting with your first block. Defining a default server will make the server block process all unknown server names even if you define an other "catch-all" block.
So the logic must be reversed to this :
server {
listen 80 default_server;
listen 443 default_server ssl;
ssl_certificate /path/to/certificate;
ssl_certificate_key /path/to/key;
return 301 https://dlgt.co$request_uri;
}
server {
listen 443;
server_name dlgt.co;
[ ... ]
}
Note that certificate and key have only to be set in the default server block. As the handshake comes before any HTTP traffic is seen, nginx will elect the server block processing incoming HTTP requests after the handshake took place in the default server block.

Resources