Overwrite Cache-Control: Private in Nginx - http-headers

Just wonder if there is any way to overwrite / drop the response back Cache-Control: private from a proxied remote server. The setup architecture looks like this (yes, it's a reverse-proxy set up):
[my server] --> [remote server]
The setting for my server site-available/default:
server {
listen 80; ## listen for ipv4
listen [::]:80 default ipv6only=on; ## listen for ipv6
server_name localhost;
location / {
if ($arg_AWSACCESSKEY) {
proxy_pass http://localhost:8088;
}
try_files $uri $uri/ /index.php /index.html /index.htm;
}
# other setting goes here
}
The setting for my server site-available/remote:
server {
listen 8088; ## listen for ipv4; this line is default and implied
# Make site accessible from http://localhost/
# server_name localhost;
location / {
proxy_pass http://remoteserver;
proxy_set_header Host remoteserverhostname.com;
proxy_ignore_headers Cache-Control Expires;
proxy_pass_header Set-Cookie;
}
}
But Firebug still report the header contains Cache-Control: private. Did I missed something?
Thanks.

You want proxy_hide_header instead of proxy_ignore_headers

Related

How to serve devpi with https?

I have an out-of-the-box devpi-server running on http://
I need to get it to work on https:// instead.
I already have the certificates for the domain.
I followed the documentation for nginx-site-config, and created the /etc/nginx/conf.d/domain.conf file that has the server{} block that points to my certificates (excerpt below).
However, my devpi-server --start --init is totally ignoring any/all nginx configurations.
How do i point the devpi-server to use the nginx configurations? Is it even possible, or am I totally missing the point?
/etc/nginx/conf.d/domain.conf file contents:
server {
server_name localhost $hostname "";
listen 8081 ssl default_server;
listen [::]:8081 ssl default_server;
server_name domain;
ssl_certificate /root/certs/domain/domain.crt;
ssl_certificate_key /root/certs/domain/domain.key;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
gzip on;
gzip_min_length 2000;
gzip_proxied any;
gzip_types application/json;
proxy_read_timeout 60s;
client_max_body_size 64M;
# set to where your devpi-server state is on the filesystem
root /root/.devpi/server;
# try serving static files directly
location ~ /\+f/ {
# workaround to pass non-GET/HEAD requests through to the named location below
error_page 418 = #proxy_to_app;
if ($request_method !~ (GET)|(HEAD)) {
return 418;
}
expires max;
try_files /+files$uri #proxy_to_app;
}
# try serving docs directly
location ~ /\+doc/ {
try_files $uri #proxy_to_app;
}
location / {
# workaround to pass all requests to / through to the named location below
error_page 418 = #proxy_to_app;
return 418;
}
location #proxy_to_app {
proxy_pass https://localhost:8081;
proxy_set_header X-outside-url $scheme://$host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
}
}
This is the answer I gave to the same question on superuser.
Devpi doesn't know anything about Nginx, it will just serve HTTP traffic. When we want to interact with a web-app via HTTPS instead, we as the client need to talk to a front-end which can handle it (Nginx) which will in turn communicate with our web-app. This application of Nginx is known as a reverse proxy. As a reverse proxy we can also benefit from Nginx's ability to serve static files more efficiently than getting our web-app to do it itself (hence the "try serving..." location blocks).
Here is a complete working Nginx config that I use for devpi. Note that this is /etc/nginx/nginx.conf file rather than a domain config like yours because I'm running Nginx and Devpi in docker with compose but you should be able to pull out what you need:
worker_processes 1;
events {
worker_connections 1024;
}
http {
# Define the location for devpi
upstream pypi-backend {
server localhost:8080;
}
# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.co.uk; # This is the accessing address eg. https://example.co.uk
root /devpi/server; # This is where your devpi server directory is
gzip on;
gzip_min_length 2000;
gzip_proxied any;
proxy_read_timeout 60s;
client_max_body_size 64M;
ssl_certificate /etc/nginx/certs/cert.crt; Path to certificate
ssl_certificate_key /etc/nginx/certs/cert.key; Path to certificate key
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/pypi.access.log;
# try serving static files directly
location ~ /\+f/ {
error_page 418 = #pypi_backend;
if ($request_method !~ (GET)|(HEAD)) {
return 418;
}
expires max;
try_files /+files$uri #pypi_backend;
}
# try serving docs directly
location ~ /\+doc/ {
try_files $uri #pypi_backend;
}
location / {
error_page 418 = #pypi_backend;
return 418;
}
location #pypi_backend {
proxy_pass http://pypi-backend; # Using the upstream definition
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-outside-url $scheme://$host:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}
With Nginx using this configuration and devpi running on http://localhost:8080, you should be able to access https://localhost or with your machine with appropriate DNS https://example.co.uk. A request will be:
client (HTTPS) > Nginx (HTTP) > devpi (HTTP) > Nginx (HTTPS) > client
This also means that you will need to make sure that Nginx is running yourself, as devpi start won't know any better. You should at the very least see an Nginx welcome page.

Nginx, API (https + redirect) and Vue.js application on subdomain

I need to configure nginx config for three (possibly four) server running on one physical server.
I have Rails API and Rails also do server rendering html pages + a separate Vue.js application.
Basically, I need two nginx servers for Rails with https protocol, server configs look like this (it's working :)):
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server_names_hash_bucket_size 64;
upstream puma {
server unix:///home/deploy/apps/example/shared/tmp/sockets/example-puma.sock;
}
server {
listen 443 ssl;
server_name www.example.me;
ssl on;
ssl_certificate /home/deploy/apps/example/current/certs/cert_chain.crt;
ssl_certificate_key /home/deploy/apps/example/current/certs/private.key;
root /home/deploy/apps/example/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri #puma;
location #puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 10M;
keepalive_timeout 30;
}
So here I need to add Vue.js application server, and here is where thing are getting mess up and stop working (it's config for Vue in history mode):
server {
listen 80;
server_name backoffice.example.me;
root /home/deploy/apps/example-front;
index index.html;
location / {
try_files $uri $uri/ #rewrites;
}
location #rewrites {
rewrite ^(.+)$ /index.html last;
}
location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
expires max;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
}
Is there any way to make it work on one physical server?

Cannot activate HTTPS links with Django and Nginx

I have a django rest framework app running on a secured Nginx server.
When I navigate on the DRF api, the protocol in the navigation bar is well redirected to https.
My problem is that all the generated urls are in http instead of https.
I watched in the code, the differents url are build with this method:
def build_absolute_uri(self, location=None):
"""
Build an absolute URI from the location and the variables available in
this request. If no ``location`` is specified, bulid the absolute URI
using request.get_full_path(). If the location is absolute, convert it
to an RFC 3987 compliant URI and return it. If location is relative or
is scheme-relative (i.e., ``//example.com/``), urljoin() it to a base
URL constructed from the request variables.
"""
if location is None:
# Make it an absolute url (but schemeless and domainless) for the
# edge case that the path starts with '//'.
location = '//%s' % self.get_full_path()
bits = urlsplit(location)
if not (bits.scheme and bits.netloc):
current_uri = '{scheme}://{host}{path}'.format(scheme=self.scheme,
host=self.get_host(),
path=self.path)
# Join the constructed URL with the provided location, which will
# allow the provided ``location`` to apply query strings to the
# base path as well as override the host, if it begins with //
location = urljoin(current_uri, location)
return iri_to_uri(location)
In my case, this method always returns unsecured urls (HTTP instead of HTTPS).
I have edited my settings like it's described in this post:
https://security.stackexchange.com/questions/8964/trying-to-make-a-django-based-site-use-https-only-not-sure-if-its-secure
But the generated url are still in HTTP.
Here is my Nginx configuration:
server {
listen 80;
listen [::]:80;
server_name backend.domaine.na.me www.backend.domaine.na.me server_ip:8800;
return 301 https://$server_name$request_uri;
}
server {
# SSL configuration
listen 443 ssl http2;
listen [::]:443 ssl http2;
include snippets/ssl-backend.domaine.na.me.conf;
include snippets/ssl-params.conf;
location / {
proxy_pass http://server_ip:8800/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_redirect off;
}
}
server {
listen 8800;
server_name server_ip;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /projects/my_django_app;
}
location /media/ {
root /projects/my_django_app;
}
location / {
include proxy_params;
proxy_pass http://unix:/projects/my_django_app.sock;
}
location ~ /.well-known {
allow all;
}
}
And my django configuration:
In wsgi.py:
os.environ['HTTPS'] = "on"
os.environ['wsgi.url_scheme'] = "https"
In settings.py(Note: I've tried both first two lines):
#SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_PROXY_SSL_HEADER = ('HTTP_X_SCHEME', 'https')
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
I really need to fix this probem because my DRF api returns some image URL wich must be in HTTPS, else the site cannot be considered 100% secure.
What is wrong with my configuration? Am I missing some options?
The indirection isn't needed; you can merge the settings from the SSL block and the :8800 block to give something like this:
server {
listen 80;
listen [::]:80;
server_name backend.domaine.na.me www.backend.domaine.na.me;
return 301 https://$server_name$request_uri;
}
server {
# SSL configuration
listen 443 ssl http2;
listen [::]:443 ssl http2;
include snippets/ssl-backend.domaine.na.me.conf;
include snippets/ssl-params.conf;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /projects/my_django_app;
}
location /media/ {
root /projects/my_django_app;
}
location ~ /.well-known {
allow all;
}
location / {
proxy_pass http://unix:/projects/my_django_app.sock;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_redirect off;
}
}
Then, set SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') and it should work.
I can't find anything about include proxy_params, and I suspect that the headers that you set in the first proxy block aren't forwarded to the Django app at all.

nginx - browser can't stop directing to https?

Why nginx keep on directing without instructions?
I followed this guide to redirect port 80 to 3000:
server {
listen 80;
server_name example.co.uk www.example.co.uk;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:3000;
}
}
It worked fine. Then I tried to roll back as before, and it just keeps on redirecting to https!
I even have removed nginx, but the browser is still redirecting to https! Why? What have done wrong? How can I fix it?
Any ideas?
This was the config before I tried on the redirect thingy:
server {
listen 80;
server_name example.co.uk www.example.co.uk;
return 301 https://$host$request_uri;
}
server {
# listen 80;
listen 433 ssl;
server_name example.co.uk www.example.co.uk;
ssl on;
ssl_certificate /etc/letsencrypt/live/example.co.uk/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.co.uk/privkey.pem;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location ~ /.well-known {
allow all;
}
the HTTPS was working fine to before that.
EDIT:
I have re-installed nginx and tested it with nginx -t:
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Assets Directory returning 404 via SSL on unicorn nginx Ubuntu 14

This is similar question to this one, but suggested answer does not work.
I have confirmed that the assets exist, and restart nginx as well as unicorn service.
$ service nginx restart
$ service unicorn_app_name restart
This is my /etc/nginx/sites-enabled/[app_name] config.
upstream unicorn {
server unix:/home/unicorn_user/apps/app_name/shared/sock/unicorn.unicorn_user.sock fail_timeout=0;
}
server {
listen 80;
server_name staging.mydomain.org mydomain.org;
# Do not use a /tmp folder or other users can obtain certificates.
location '/.well-known/acme-challenge' {
default_type "text/plain";
root /etc/letsencrypt/webrootauth;
}
location / {
rewrite ^/(.*) https://staging.mydomain.org/$1 permanent;
}
}
ssl_certificate /etc/letsencrypt/live/staging.mydomain.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/staging.mydomain.org/privkey.pem;
server {
listen 443 ssl;
server_name www.staging.mydomain.org;
rewrite ^(.*) https://staging.mydomain.org/$1 permanent;
}
server {
listen 443 ssl;
server_name staging.mydomain.org;
root /home/unicorn_user/apps/app_name/current/public;
try_files $uri/index.html $uri #unicorn;
location #unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_pass http://unicorn;
}
location ~ ^/(assets)/ {
gzip_static on;
expires max;
add_header Cache-Control public;
#add_header Last-Modified "";
#add_header ETag "";
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 60;
}
Seeing the 404's in the error and access logs. For example:
2016/05/18 07:46:01 [error] 2490#0: *4 open() "/home/unicorn_user/apps/app_name/current/public/assets/loading.gif" failed (2: No such file or directory), client: ip_address, server: staging.mydomain.org, request: "GET /assets/loading.gif HTTP/1.1", host: "staging.mydomain.org", referrer: "https://staging.mydomain.org/path/to/page"
Permissions on all the assets are 644 and 755, owned by unicorn_user and in same group name.
Can anyone make another suggestion for a log or configuration to check, a service to restart? Is there an nginx config misconfiguration?
the 404 i was getting was because one particular asset, loading.gif was generated in current/app/assets/ while the server is looking in current/public/assets/.
I had assumed that other javascript errors were being caused because of this setting, but it's simply because my Rails ignorance is so vast, I wasn't sure where to look for what.