Can we add ssl directive inside if condition?
I want to achieve something like:
if ($host ~ "^localhost") {
ssl on;
ssl_certificate /home/ssl/nginx.crt;
ssl_certificate_key /home/ssl/nginx.key;
}
If the host is localhost then apply ssl otherwise don't.
Is this possible in nginx.conf?
Related
I have an issue wherein I am building an nginx reverse proxy for directing to multiple microservices at different url paths.
The system is entirely docker based and as a result the same environment is used for development and production. This has caused an issue for me when installing SSL as the SSL certs will only be available in production so when I configure NGINX with SSL the development environment no longer works as the ssl certs are not present.
Here is the relevant part of my conf file -
server {
listen 80;
listen 443 default_server ssl;
server_name atvcap.server.com;
ssl_certificate /etc/nginx/certs/atvcap_cabundle.crt;
ssl_certificate_key /etc/nginx/certs/atvcap.key;
...
}
But this throws the following when running my application in development mode -
nginx: [emerg] BIO_new_file("/etc/nginx/certs/atvcap_cabundle.crt") failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/etc/nginx/certs/atvcap_cabundle.crt','r') error:2006D080:BIO routines:BIO_new_file:no such file)
Is it possible to only turn on SSL if the "/etc/nginx/certs/atvcap_cabundle.crt" is available?
I had tried something like the following -
if (-f /etc/nginx/certs/atvcap_cabundle.crt) {
ssl_certificate /etc/nginx/certs/atvcap_cabundle.crt;
ssl_certificate_key /etc/nginx/certs/atvcap.key;
}
But that threw the following error -
nginx: [emerg] "ssl_certificate" directive is not allowed here in
/etc/nginx/conf.d/default.conf:7
Any one have any ideas on how to achieve something like this?
Thanks
You can create an additional file ssl.conf and put here ssl configs:
ssl_certificate /etc/nginx/certs/atvcap_cabundle.crt;
ssl_certificate_key /etc/nginx/certs/atvcap.key;
Then include from the main config:
server_name atvcap.server.com;
include /somepath/ssl.conf*;
Make sure to include * symbol - this will not break when the file does not exist at development mode.
The answer of #super_p is correct. But to answer to #AbdolHosein comment I add my answer here if it's not clear.
You need to include your ssl_certificate directive in the included file.
# sample nginx config
http {
server {
listen 80 deferred;
server_name _;
include /ssl/ssl.conf*;
client_body_timeout 5s;
client_header_timeout 5s;
root /code;
}
}
Then in your /ssl/ssl.conf you can do whatever you want, such as enabling HTTPS:
# this is the /ssl/ssl.conf file
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /ssl/cert.cer;
ssl_certificate_key /ssl/key.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
The trick is that we don't look if the certificate exists but we check if the /ssl/ssl.conf exists. This is thanks to the * in the include /ssl/ssl.conf*; directory as stated by #super_p
I have this NGINX configuration as follows:
# jelastic is a wildcard certificate for *.shared-hosting.xyz
server {
listen 443;
server_name _;
ssl on;
ssl_certificate /var/lib/jelastic/SSL/jelastic.chain;
ssl_certificate_key /var/lib/jelastic/SSL/jelastic.key;
}
# fullchain2 is a certificate for custom domain
server {
listen 443 ssl;
server_name my-custom-domain-demo.xyz www.my-custom-domain-demo.com;
ssl_certificate /var/lib/nginx/ssl/my-custom-domain-demo.xyz/fullchain2.pem;
ssl_certificate_key /var/lib/nginx/ssl/my-custom-domain-demo.xyz/privkey2.pem;
}
# additional configuration for other custom domains follows
The NGINX server receives requests with host having a pattern like of *.shared-hosting.xyz, e.g. website1.shared-hosting.xyz, website2.shared-hosting.xyz
and also with variable hosts having different domains like my-custom-domain-demo.xyz or another-custom-domain-demo.xyz etc.
Now the problem is the lower server NGINX configuration overrides the upper configuration. Having it, the upper does not work anymore,
and accessing *.shared-hosting.xyz returns certificate error, and browser is telling the certificate is for my-custom-domain-demo.xyz only.
What can be done with this such that the lower NGINX config triggers for *.shared-hosting.xyz domains and every other additional server configuration will not trigger
when host is in the pattern of *.shared-hosting.xyz?
The server_name _; is irrelevant (and is not required in modern versions of nginx). If a server with a matching listen and server_name cannot be found, nginx will use the default server.
In the absence of a default_server suffix to the listen directive, nginx will use the first server block with a matching listen.
If your configurations are spread across multiple files, there evaluation order will be ambiguous, so you need to mark the default server explicitly.
Try this for the jelastic server block:
server {
listen 443 ssl default_server;
ssl_certificate /var/lib/jelastic/SSL/jelastic.chain;
ssl_certificate_key /var/lib/jelastic/SSL/jelastic.key;
...
}
See this document for more.
How do I set a reverse proxy for nextcloud?
This is my current config but it doesn't work:
server {
listen 8000;
server_name cloud.prjctdesign.com;
return 301 https://$host$request_uri;
}
server {
listen 4430 ssl http2;
server_name cloud.prjctdesign.com;
ssl_certificate /certs/cloud.prjctdesign.com.crt;
ssl_certificate_key /certs/cloud.prjctdesign.com.key;
include /etc/nginx/conf/ssl_params.conf;
client_max_body_size 10G; # change this value it according to $UPLOAD_MAX_SIZE
location / {
proxy_pass http://192.168.178.32;
include /etc/nginx/conf/proxy_params;
}
}
Also I enabled SSL using a let's encrypt cert. I run Nextcloud in the official VM image provided by Nextcloud / Techandme
I believe there is something wrong with the HSTS but I have no idea how it works. Also I based my forwarding off of this
I figured it out.
The reference to the ssl certificate is incorrect. Either run NGINX on the same server you are running nextcloud and redirect nginx to the position of the .cert file as in these lines:
ssl_certificate /certs/cloud.prjctdesign.com.crt;
ssl_certificate_key /certs/cloud.prjctdesign.com.key;
or generate a new cert on the nginx server and point the config towards it.
Since I only have a single domain cert I would like to reject all subdomains (*.domain.com) with a nginx return code 444 and allow just the base domain (domain.com). This config below seems like it match all the subdomains of domain.com.
server {
listen 443;
/* ssl cert stuff */
server_name domain.com
}
I tried to add the snippet below after the snippet above as a catch all but that didn't seem to work either.
server {
listen 443;
server_name .domain.com
reject 444
}
Thanks in advance.
Change your config for SSL reject to:
server {
listen 443;
server_name *.domain.com;
return 444;
}
I need to use Nginx as an SSL proxy, which forwards traffic to different back ends depending on the subdomain.
I have seem everywhere that I should define multiple "server {" sections but that doesn't work correctly for SSL. Doing that I would always have the SSL being processed in the first virtual host as the server name is unknown until you process the https traffic.
Scenario:
One IP address
One SSL wildcard wildcard
Multiple backends which needs to be accessed like the following:
https://one.mysite.com/ -> http://localhost:8080
https://two.mysite.com/ -> http://localhost:8090
Nginx says "if" is evil: http://wiki.nginx.org/IfIsEvil, but what else can I do?
I have tried this, but it doesn't work, I get an 500 error but nothing in the error logs.
server {
listen 443;
server_name *.mysite.com;
ssl on;
ssl_certificate ssl/mysite.com.crt;
ssl_certificate_key ssl/mysite.com.key;
location / {
if ($server_name ~ "one.mysite.com") {
proxy_pass http://localhost:8080;
}
if ($server_name ~ "two.mysite.com") {
proxy_pass http://localhost:8090;
}
}
Has anyone managed to accomplish this with Nginx? Any help/alternatives, link, would be much appreciated.
I found the solution which is basically to define the SSL options and the SSL certificate outside the "server" block:
ssl_certificate ssl/mysite.com.crt;
ssl_certificate_key ssl/mysite.com.key;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+EXP;
ssl_prefer_server_ciphers on;
server {
listen 80;
server_name *.mysite.com;
rewrite ^ https://$host$request_uri? permanent;
}
server {
listen 443 ssl;
server_name one.mysite.com;
ssl on;
location / {
proxy_pass http://localhost:8080;
}
}
server {
listen 443 ssl;
server_name two.mysite.com;
ssl on;
location / {
proxy_pass http://localhost:8090;
}
}
Key things:
"ssl on;" is the only thing that needs to be within the "server" blocks that listen in https, you can put it outside too, but what will make the "server" blocks that listen in port 80 to use https protocol and not the expected http.
Because the "ssl_certificate", "ssl_ciphers: and other "ssl_*" are outside the "server" block, Nginx does the SSL offloading without a server_name. Which is what it should do, as the SSL decryption cannot happen based on any host name, as at this stage the URL is encrypted.
JAVA and curl don't fail to work now. There is no server_name - host miss match.
The short answer is to use Server Name Indication. This should work by default in common browsers and cURL.
according to http://www.informit.com/articles/article.aspx?p=1994795, you should indeed have two "server" sections, with two different server names.
In each one, you should include your ssl_* directives.