NGINX http to https with exceptions - nginx

We have 2 files in our nginx/sites-available/ folder. The odoo-80 and the odoo-443. How can we add a exception for 1 specific path without creating a loop? If we add the exception to the 443 file it redirects back to the 80 file and opposite... Im normally working with apache and not nginx so I would be very happy for some help!
To summ up: we want this path: /pos/web to run with http and all the rest with https.
odoo-80 file
server {
listen 80;
server_name odoo.server.com;
access_log /var/log/nginx/odoo.access.log;
error_log /var/log/nginx/odoo.error.log;
location / {
rewrite ^/(.*) https://odoo.server.com:443/$1 permanent;
}}
Odoo-443 file
#odoo server
upstream odoo {
server 127.0.0.1:8069;
}
upstream odoochat {
server 127.0.0.1:8072;
}
server {
listen 443;
server_name odoo.server.com;
proxy_read_timeout 720s;
proxy_connect_timeout 720s;
proxy_send_timeout 720s;
# Add Headers for odoo proxy mode
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
# SSL parameters
***
# log
***
# Redirect longpoll requests to odoo longpolling port
location /longpolling {
proxy_pass http://odoochat;
}
# Redirect requests to odoo backend server
location / {
proxy_redirect off;
proxy_pass http://odoo;
}
# common gzip
gzip_types text/css text/less text/plain text/xml application/xml application/json application/javascript;
gzip on;
}
#pos20.07
#server {
# listen 443 default_server ssl;
# server_name odoo.server.com;
# Force pos in http for the posbox
# location ~ ^/pos/web {
# rewrite ^(.*)$ http://$host:80$1 permanent;
#}

You can declare a location {} in your odoo-80 file, this should override the catch-all you have in place so it shouldn't send it to 443 in the first place.
server {
listen 80;
server_name odoo.server.com;
access_log /var/log/nginx/odoo.access.log;
error_log /var/log/nginx/odoo.error.log;
location ~ ^/pos/web {
proxy_redirect off;
proxy_pass http://odoo;
}
location / {
rewrite ^/(.*) https://odoo.server.com:443/$1 permanent;
}
}
Also, what Richard Smith mentioned, add the same block to 443 just in case someone types in https:// and heed his call re: HSTS (which I doubt is setup)
"we" should also be posting on Serverfault by the way :D

Related

Nginx WSS (port 443) to WS (port 80) rewrite rule containing regex URL

Apache
I have the following RewriteRule in the Apache web proxy server configuration:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName myserver.example.com
ServerAdmin admin#myserver.example.com
# Rewrite rule for the WebSocket connection
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/[0-9]+/ws/graph/ [NC]
RewriteRule /(.*) ws://localhost:8000/$1 [P,L]
# Logs for connections at port 443 (HTTPS/WSS)
ErrorLog ${APACHE_LOG_DIR}/myserver.example.com-SSL-error.log
CustomLog ${APACHE_LOG_DIR}/myserver.example.com-SSL-access.log combined
# HTTPS => HTTP redirect for requests to the application
ProxyPass / http://localhost:8000/
ProxyPassReverse / http://localhost:8000/
# Alias and certificate configuration
ServerAlias myserver.example.com
SSLCertificateFile /etc/letsencrypt/live/myserver.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/myserver.example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
(Maybe it can be even simplified to RewriteRule ^/[0-9]+/ws/graph/ ws://localhost:8000/$1 [P,L], I didn't check that.)
This configuration works fine and I successfully connect with the application behind the proxy server using HTTP and WebSockets, depending on which URL I use.
Nginx
Now, I am trying to recreate the same behavior using Nginx.
I tried:
server {
server_name myserver.example.com;
access_log /var/log/nginx/myserver.example.com_SSL-access.log;
error_log /var/log/nginx/myserver.example.com_SSL-error.log;
rewrite ^/[0-9]+/ws/graph/ ws://localhost:8000/$1;
location / {
proxy_pass http://localhost:8000/;
}
listen [::]:443 ssl;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/myserver.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myserver.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
and:
server {
server_name myserver.example.com;
access_log /var/log/nginx/myserver.example.com_SSL-access.log;
error_log /var/log/nginx/myserver.example.com_SSL-error.log;
location ~ ^/[0-9]+/ws/graph/ {
proxy_pass http://localhost:8000/$1;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
location / {
proxy_pass http://localhost:8000/;
}
listen [::]:443 ssl;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/myserver.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myserver.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
I also tried adding the following headers to the WebSocket's location:
location ~ ^/[0-9]+/ws/graph/ {
proxy_pass http://localhost:8000/$1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
and this rewrite rule clause:
if ($request_uri ~ ^/[0-9]+/ws/graph/) {
rewrite (.*) ws://localhost:8000/$1;
}
For all above cases of the nginx configuration all requests are treated as HTTP requests in the application at localhost:8000/.
What I am trying to achieve is to get the following connection working, e.g., connecting from the browser using JavaScript:
const ws = new WebSocket(`wss://myserver.example.com/1234123/ws/graph/`);
I am not an expert on Nginx and the syntax for the rules is hardly documented, or I cannot find it. All suggestions are welcomed.
Sources
https://stackoverflow.com/a/16159322/8877692
https://www.nginx.com/blog/websocket-nginx/
https://www.nginx.com/blog/converting-apache-to-nginx-rewrite-rules/
https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms#location-block-syntax
A colleague helped me with this one. Below I post the answer.
The solution
The proper configuration is:
server {
server_name myserver.example.com;
access_log /var/log/nginx/myserver.example.com_SSL-access.log;
error_log /var/log/nginx/myserver.example.com_SSL-error.log;
# WebSocket support
location ~ ^/[0-9]+/ws/graph/ {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
# HTTP proxy
location / {
proxy_pass http://localhost:8000/;
}
listen [::]:443 ssl;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/myserver.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myserver.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
What I did wrong
My mistake was that I tied:
location ~ ^/[0-9]+/ws/graph/ {
proxy_pass http://localhost:8000/;
...
}
and:
location ~ ^/[0-9]+/ws/graph/ {
proxy_pass http://localhost:8000/$1;
...
}
both of which will not work, with the former (note the "/" at the end of the URL line) resulting in an error:
"proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in /etc/nginx/sites-enabled/vhost-myserver.example.com.conf:10
Also note that a separate location must be there to handle "normal" HTTP requests, else the requests won't be proxied properly:
...
# WebSocket support
location ~ ^/[0-9]+/ws/graph/ {
proxy_pass http://localhost:8000;
...
}
# HTTP proxy
location / {
proxy_pass http://localhost:8000/;
}
...

Nginx - location block misconfigured?

I have a location block inside of my sites-enabled example.conf that should be routing /testing to a 503 error html page but instead for some reason its hitting my app instead of nginx
[2020-06-30T20:36:13.821768 #6059] FATAL -- : [fc9cb972-f314-4a87-89d9-8334521767b3] ActionController::RoutingError (No route matches [GET] "/testing"):
that is a log line from my actual rails app - why is it even getting this far vs nginx routing to where I thought I told it to???
my nginx .conf
server { listen 443 ssl;
server_name status.* www.status.*;
# SSL
ssl_certificate_key /etc/nginx/ssl/server_example.com.key;
# logging
access_log /var/log/nginx/status.access.log;
error_log /var/log/nginx/status.error.log;
# security
include security.conf;
# reverse proxy
location / {
if (-f /opt/staytus/staytus/maint.on) {
return 503;
}
port_in_redirect off;
proxy_pass http://example.com:8787/;
}
error_page 503 #maintenance;
location #maintenance {
root /usr/share/nginx/html
rewrite ^(.*)$ /Performing-Maintenace.html;
}
location = /testing/ {
return 500;
}
}
server {
listen 80;
server_name www.status.* status.* 11.22.123.456;
root /opt/staytus/staytus/public;
client_max_body_size 50M;
# SSL
ssl_certificate_key /etc/nginx/ssl/example.com.key;
port_in_redirect off;
return 301 https://example.com$request_uri;
location #puma {
proxy_intercept_errors on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto http;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://example.com:8787;
}
}

Reverse proxy to port 8069 on Engintron issues while it works on standard NGINX setup

I have an Odoo app running on port 8069, and while this setup worked fine in my old server, my new server is using Engintron which seems to have a different method of working with vhosts. The standout issue is that under common_http.conf, this line becomes a duplicate of the vhost needed to run the app but is included in the automatically generated config that gets overridden whenever a new cpanel account is created, deleted, or when Engintron is updated.
What would be the correct way of setting this up properly within Engintron?
common_http.conf
location / {
try_files $uri $uri/ #backend;
}
# This location / ends up getting included in the custom
# vhost which is needed for all of the sites except this Odoo app.
custom_vhost.com.conf
upstream example{
server 127.0.0.1:8069 weight=1 fail_timeout=0;
}
upstream example-chat {
server 127.0.0.1:8072 weight=1 fail_timeout=0;
}
server {
listen [::]:80;
server_name delegates.example.com;
return 301 https://delegates.example.com$request_uri;
}
server {
listen [::]:80;
server_name vendors.example.com;
return 301 https://vendors.example.com$request_uri;
}
server {
listen [::]:80;
server_name example.com;
return 301 https://example.com;
}
server {
listen [::]:80;
server_name *.example.com;
return 301 https://example.com;
}
server {
listen [::]:443 ssl;
server_name pgadmin.example.com;
# well-known_start
location ^~ /.well-known {
add_header Host-Header 192fc2e7e50945beb8231a492d6a8024;
root /home/example/public_html;
}
# well-known_end
ssl_certificate /var/cpanel/ssl/apache_tls/*.example.com/combined;
ssl_certificate_key /var/cpanel/ssl/apache_tls/*.example.com/combined;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
add_header X-Content-Type-Options nosniff;
add_header Cache-Control public;
location / {
deny all;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://127.0.0.1:5050;
}
}
server {
listen [::]:443 ssl;
server_name example.com www.example.com;
return 301 https://example.com;
}
server {
listen [::]:443 ssl http2;
server_name vendors.example.com delegates.example.com;
client_max_body_size 200m;
proxy_read_timeout 720s;
proxy_connect_timeout 720s;
proxy_send_timeout 720s;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-NginX-Proxy true;
#proxy_set_header X-Odoo-dbfilter ^%d\Z;
proxy_redirect off;
proxy_buffering off;
# well-known_start
location ^~ /.well-known {
add_header Host-Header 192fc2e7e50945beb8231a492d6a8024;
root /home/example/public_html;
}
# well-known_end
ssl_certificate /var/cpanel/ssl/apache_tls/*.example.com/combined;
ssl_certificate_key /var/cpanel/ssl/apache_tls/*.example.com/combined;
access_log /var/log/nginx/odoo.access.log;
error_log /var/log/nginx/odoo.error.log;
# adds gzip options
gzip on;
gzip_types text/css text/plain text/xml application/xml application/javascript application/x-javascript text/javascript application/json text/x-json;
gzip_proxied no-store no-cache private expired auth;
#gzip_min_length 1000;
gzip_disable "MSIE [1-6]\.";
location /longpolling {
proxy_pass http://example-chat;
}
location ~* /web/static/ {
gzip_static on;
proxy_cache_valid 200 90m;
proxy_buffering on;
expires 864000;
add_header Cache-Control public;
proxy_pass http://example;
}
location / {
error_page 403 = https://example.com;
proxy_pass http://example;
proxy_redirect off;
gzip_static on;
}
# The above location becomes a duplicate of the previous default location - which in turn fails the validity of the configuration.
location ~* /web/content/ {
gzip_static on;
proxy_cache_valid 200 90m;
proxy_buffering on;
expires 864000;
add_header Cache-Control public;
proxy_pass http://example;
}
location /web/database/manager {
deny all;
error_page 403 https://example.com;
proxy_pass http://example;
}
}
Since the conf files are added in alphabetical order, and any conflicting or duplicate settings are ignored - I ended up changing the name of the file so that it's included before the other ones. Also made the file immutable with the following command:
chattr +ai 1_custom_vhost.com.conf
I'm quite sure this is not a graceful solution, but it does the job for now.

Odoo 12: Link Redirects broken using Nginx

Ok, I'm using Odoo 12 on Ubuntu 18.04, nginx/1.14.0 with letsencrypt for my ssl certs.
Most everything is working perfectly, however links from the website that redirect are returning the variable I named in the nginx domain config file instead of using the domain.
# Odoo servers
upstream odoo {
server 127.0.0.1:8069;
}
upstream odoochat {
server 127.0.0.1:8072;
}
# HTTP -> HTTPS
server {
if ($host = www.qa.moddulu.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = qa.moddulu.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name www.qa.moddulu.com qa.moddulu.com;
include snippets/letsencrypt.conf;
return 301 https://qa.moddulu.com$request_uri;
}
# WWW -> NON WWW
server {
listen 443 ssl http2;
server_name www.qa.moddulu.com;
ssl_trusted_certificate /etc/letsencrypt/live/qa.moddulu.com/chain.pem;
include snippets/ssl.conf;
include snippets/letsencrypt.conf;
return 301 https://qa.moddulu.com$request_uri;
ssl_certificate /etc/letsencrypt/live/qa.moddulu.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/qa.moddulu.com/privkey.pem; # managed by Certbot
}
server {
listen 443 ssl http2;
server_name qa.moddulu.com;
proxy_read_timeout 720s;
proxy_connect_timeout 720s;
proxy_send_timeout 720s;
# Proxy headers
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
# SSL parameters
ssl_trusted_certificate /etc/letsencrypt/live/qa.moddulu.com/chain.pem;
include snippets/ssl.conf;
include snippets/letsencrypt.conf;
return 301 https://qa.moddulu.com$request_uri;
ssl_certificate /etc/letsencrypt/live/qa.moddulu.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/qa.moddulu.com/privkey.pem; # managed by Certbot
}
server {
listen 443 ssl http2;
server_name qa.moddulu.com;
proxy_read_timeout 720s;
proxy_connect_timeout 720s;
proxy_send_timeout 720s;
# Proxy headers
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
# SSL parameters
ssl_trusted_certificate /etc/letsencrypt/live/qa.moddulu.com/chain.pem;
include snippets/ssl.conf;
include snippets/letsencrypt.conf;
# log files
access_log /var/log/nginx/qa.moddulu.com.access.log;
error_log /var/log/nginx/qa.moddulu.com.error.log;
# Handle longpoll requests
location /longpolling {
proxy_pass http://odoochat;
}
# Handle / requests
location / {
proxy_redirect off;
proxy_pass http://odoo;
}
# Cache static files
location ~* /web/static/ {
proxy_cache_valid 200 90m;
proxy_buffering on;
expires 864000;
proxy_pass http://odoo;
}
# Gzip
gzip_types text/css text/less text/plain text/xml application/xml application/json application/javascript;
gzip on;
ssl_certificate /etc/letsencrypt/live/qa.moddulu.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/qa.moddulu.com/privkey.pem; # managed by Certbot
}
so, for example, I'm trying to log in and and the url is going to 'https://odoo/web' instead of 'https://qa.moddulu.com/web'. the 'odoo' in the link changes with whatever the upstream variable for the server is. I haven't been able to find a solution to this. I've tried rebuilding the server, but that didn't fix the problem.
EDIT: I am also using google cloud services for my hosting.
Ok, so what I did was to change upstream odoo to upstream qa.moddulu.com. this fixes the problem I was having.
It is the bug of odoo12 source code.
Updating it to the newest version solved the problem.

Senaite LIMS (Plone 4.3.18) css not working on Nginx with https enabled

I've installed and set up senaite.lims, which is a Plone extension, running on Plone 4.3.18 installed by the Unified Installer, and adding senaite.lims to the buildout.cfg eggs.
It's running fine on port 8080, and I can get Nginx to work redirecting / to :8080, but when I start using https, suddenly the css of the site doesn't work anymore.
I looked at the source, and the produced html page shows a link to the stylesheet with http://.... which I don't know if may cause problems, but if I actually try to open the .css file in the browser it works fine.
I set up and tried both with port 80 redirecting the https, and serving both a version of http and https, but neither one would get the page to render using .css. If anyone has any tips, or sees something wrongly configured in the nginx below, any help would be greatly appreciated.
Here is my nginx.conf:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 768;
}
http {
default_type application/octet-stream;
include /etc/nginx/mime.types;
sendfile on;
keepalive_timeout 75;
upstream plone {
server 127.0.0.1:8080;
}
server {
listen 80;
listen 443 ssl http2;
server_name 99.99.99.99; # changed for posting on SO
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
error_log /var/log/nginx/nginx.vhost.error.log;
location / {
proxy_pass http://localhost:8080/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_buffer_size 128k;
proxy_buffers 8 128k;
proxy_busy_buffers_size 256k;
}
}
}
You missed to rewrite the URL, e.g:
rewrite ^(.*)$ /VirtualHostBase/$scheme/$host/senaite/VirtualHostRoot/$1 break;
Here is a complete working config for SENAITE:
server {
listen 80;
server_name senaite.mydomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name senaite.mydomain.com;
# https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04
include snippets/ssl-senaite.mydomain.com.conf;
include snippets/ssl-params.conf;
include snippets/well-known.conf;
access_log /var/log/nginx/senaite.access.log;
error_log /var/log/nginx/senaite.error.log error;
# Allow Cross-Origin Resource Sharing from our HTTP domain
add_header "Access-Control-Allow-Origin" "http://senaite.ridingbytes.com";
add_header "Access-Control-Allow-Credentials" "true";
add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS";
add_header "X-Frame-Options" "SAMEORIGIN";
if ($http_cookie ~* "__ac=([^;]+)(?:;|$)" ) {
# prevent infinite recursions between http and https
break;
}
# rewrite ^(.*)(/logged_out)(.*) http://$server_name$1$2$3 redirect;
location / {
set $backend http://haproxy;
# API calls take a different backend w/o caching
if ($uri ~* "##API") {
set $backend http://api;
}
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
rewrite ^(.*)$ /VirtualHostBase/$scheme/$host/senaite/VirtualHostRoot/$1 break;
# proxy_pass $backend;
proxy_pass http://plone;
}
}

Resources