Proper way to serve updated files without user refreshing on nginx - django

This is a pretty core question. I have a django app that I run in an nginx/gunicorn configuration. Nginx is responsible for proxying to gunicorn, but it also serves the static files of the project directly.
The issue is, when I update the static files, the browser doesn't load the latest version. Sometimes a refresh fixes it, but sometimes it requires clearing the cache. (I should mention I'm using require.js, which does not help).
To alleviate this issue I'm doing this trick:
VERSION = '2.03'
STATIC_URL = '/static/' + VERSION + '/'
STATIC_ROOT = BASE_DIR + '/static/' + VERSION + '/'
This way, when I change static files, I simply bump the version. But for various reasons, I need to stop doing this. Is there a way to configure nginx to better serve updated static files when they are available?
I'm just not sure if the browser or nginx is to blame.
Update: Here's my nginx configuration with the comments removed:
upstream mycoolsite_server {
server unix:/webapps/mycoolsite/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name www.mycoolsite.com;
return 301 http://mycoolsite.com$request_uri;
}
server {
listen 80;
server_name mycoolsite.com 42.42.42.42;
client_max_body_size 4G;
access_log /webapps/mycoolsite/logs/nginx-access.log;
error_log /webapps/mycoolsite/logs/nginx-error.log;
location /static/ {
alias /webapps/mycoolsite/site/static/;
}
location /media/ {
alias /webapps/mycoolsite/site/media/;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://mycoolsite_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /webapps/mycoolsite/site/static/;
}
}

You can set expire for the static files in nginx configuration. For example if you don't want to cache css, js and png files. you can define sth. like:
location ~* \.(css|js|png)$ {
expires 0;
break;
}
so they won't been cached. But i assume you are making ./manage.py collectstatic after you change your static files on your repository or dev. environment.

Related

NGINX configuration for Django static files and Vue.js statics directory

I have an NGINX configuration for a containerized Django application that does three things:
routes traffic to a container running daphne (on /api/, /admin/ and /ws/ routes)
serves Django static files
serves static files for a Vue.js application that uses Quasar
My Vue.js application includes a few small images that should be served on /statics/ (with an s), and my Django static files are served on /static/. I can either have the /statics/ images from Vue.js working, or the /static/ files from Django working, but no both. Here's the configuration that makes Django static files work but Vue.js /statics/ files fail to load:
# static files
location /static {
autoindex on;
alias /usr/src/app/assets/static;
}
If I change the above to location /static/ {, then the Vue.js statics images will work but the Django static files will fail to load.
Here's my full NGINX configuration file:
user nginx;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
client_max_body_size 100m;
upstream backend {
server backend:9000;
}
server {
listen 80;
charset utf-8;
root /dist/;
index index.html;
# frontend
location / {
try_files $uri $uri/ #rewrites;
}
location #rewrites {
rewrite ^(.+)$ /index.html last;
}
# static files
location /static {
autoindex on;
alias /usr/src/app/assets/static;
}
# backend urls
location ~ ^/(admin|api|ws) {
proxy_redirect off;
proxy_pass http://backend;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header Connection "upgrade";
proxy_set_header Upgrade $http_upgrade;
}
}
}
I would like to keep the route names /static/ and /statics/ in the NGINX configuration the same, I probably need to change the Django /static block.
I'm now trying to change the options described here: https://nginx.org/en/docs/http/ngx_http_core_module.html#alias.
I think I have this working correctly now, I had to add a / to the end of the alias path:
# static files
location /static {
autoindex on;
alias /usr/src/app/assets/static/;
}

Nginx giving 403 code for django static files

I'm trying to deploy my django project. In my django settings, static file settings are like this:
STATIC_URL = '/static/'
STATIC_ROOT = '/root/www/static'
so my static files are in /root/www/static directory, i can see them in the server. My nginx server block is like this:
server{
listen 80;
location /static/ {
root /root/www;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
when i browse my application with browser, i'm getting
403 - Forbidden
error for static files.
You shouldn't put the static files under /root: that's for files accessible via the root user only.
The problem seems to be with user permissions. You need to change the path that is accessible by the user for which the app is deployed.
The location should look something like this:
location /static {
alias /home/ubuntu/srv/webapps/[app_name]/static;
}
Try this tutorial for more help.

Django static files in live server using nginx

I have a live server running django, the address is http://179.188.3.54/ . As you can see, the app works but looks like the static files arent working. Also if I click in any other link, doesnt work.
This website is running without any problems in development version. Im not sure what I should do to fix this problem.
Here is my nginx config file and my settings.py
STATIC_URL = '/static/'
STATIC_ROOT = '/cinegloria/cinegloria/cinegloria/static/'
PS: I tried to run collectstatic ;)
server {
root /usr/share/nginx/www;
index index.html index.htm;
access_log /var/log/nginx/domain-access.log;
server_name 0.0.0.0;
location / {
try_files $uri $uri/ /index.html;
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 10;
proxy_read_timeout 10;
proxy_pass http://0.0.0.0:8000/;
}
}
Any ideas or sample code will be appreciated!
Add the static serving to the nginx conf before the / pattern:
location /static {
alias /cinegloria/cinegloria/cinegloria/static/;
}
location / {
...
}
Or set the STATIC_ROOT to the directory under the www root:
STATIC_ROOT = '/usr/share/nginx/www/static'
Or add the symlink from www root to you static dir:
$ ln -s /cinegloria/cinegloria/cinegloria/static /usr/share/nginx/www/static
Add another nginx directive for the static files. Static files should be served by nginx, not the Django server.
location /static/ {
alias /cinegloria/cinegloria/cinegloria/static/;
}
If that still doesn't work, you may need to add the mime type directive. I had to do that yesterday, because for some reason nginx wasn't serving the correct mime type when I used an alias.
As a helpful pointer, whenever you run into problems like this, take a look at your nginx error log and paste the last few lines for debugging. It is located at /var/log/nginx/error.log or a similar path.

Nginx + Django + Phpmyadmin Configuration

I've migrated my server to amazon ec2, and trying to set up the following environment there:
Nginx in the front serving static content, passing to django for dynamic content. I also would like to use phpmyadmin in this setting.
I am not a server admin, so I simply followed a few tutorials to make nginx and django up and running. But I've been working for two days now trying to hook phpmyadmin to this setup, with no avail. I am sending my current server configuration now, how can I serve phpmyadmin here?
server {
listen 80;
server_name localhost;
access_log /opt/django/logs/nginx/vc_access.log;
error_log /opt/django/logs/nginx/vc_error.log;
# no security problem here, since / is always passed to upstream
root /opt/django/;
# serve directly - analogous for static/staticfiles
location /media/ {
# if asset versioning is used
if ($query_string) {
expires max;
}
}
location /admin/media/ {
# this changes depending on your python version
root /path/to/test/lib/python2.7/site-packages/django/contrib;
}
location /static/ {
# if asset versioning is used
if ($query_string) {
expires max;
}
}
location / {
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 10;
proxy_read_timeout 10;
proxy_pass http://localhost:8000/;
}
# what to serve if upstream is not available or crashes
error_page 500 502 503 504 /media/50x.html;
}
This question should rightly belong to http://serverfault.com
Nevertheless, the first thing you ought to do is to configure a separate subdomain for your phpmyadmin for ease of administration.
So there will be two apps running with nginx as reverse proxy, one nginx server for your above django app and another server (also known as virtualhost) for your phpmyadmin with a configuration similar to this:-
server {
server_name phpmyadmin.<domain.tld>;
access_log /srv/http/<domain>/logs/phpmyadmin.access.log;
error_log /srv/http/<domain.tld>/logs/phpmyadmin.error.log;
location / {
root /srv/http/<domain.tld>/public_html/phpmyadmin;
index index.html index.htm index.php;
}
location ~ \.php$ {
root /srv/http/<domain.tld>/public_html/phpmyadmin;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /srv/http/<domain.tld>/public_html/phpmyadmin/$fastcgi_script_name;
include fastcgi_params;
}
}
Each of your server configuration can point at different domain names via the server_name configuration. In this example, server_name phpmyadmin.<domain.tld>;
Here's an example taken from http://wiki.nginx.org/ServerBlockExample
http {
index index.html;
server {
server_name www.domain1.com;
access_log logs/domain1.access.log main;
root /var/www/domain1.com/htdocs;
}
server {
server_name www.domain2.com;
access_log logs/domain2.access.log main;
root /var/www/domain2.com/htdocs;
}
}
As you can see, there are two declarations of server inside the large http brackets. Each declaration of the server should contain the configuration you have for django and another for the configuration of phpmyadmin.
2 "virtual hosts" ("server" instances) taken care by nginx.

Nginx cannot serve backend's static files

Nginx is set up with both frontend and backend services in Docker - both are working without any issues apart from backend static files which are not being served by nginx (http://api.example.com/static/...). Since frontend is SPA and consists of static files already - they have no issues being served from within nginx container. However, nginx is not serving backend static files. The static files are definitely in the nginx container (/home/app/web/static/) - however nginx is giving the following error when checked in the console - this is probably because the CSS file below would return 404 (which is html page) - hence it cannot apply html to CSS . Nginx log files are clear.
Refused to apply style from
http://api.example.com/static/admin/css/responsive.css because its
MIME type ('text/html') is not a supported stylesheet MIME type, and
strict MIME checking is enabled.
P.S. Backend framework is Django whereas Frontend is Vue.
nginx.conf file
upstream api {
server backend:8000;
}
server {
listen 80;
server_name example.com;
root /usr/share/nginx/html;
index index.html index.htm;
# frontend
location / {
try_files $uri $uri/ /index.html;
}
location #rewrites {
rewrite ^(.+)$ /index.html last;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
server {
listen 80;
server_name api.example.com;
# backend
location ~ ^/(admin|api) {
proxy_pass http://api;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
# backend static files (django)
location /static/ {
autoindex on;
alias /home/app/web/static/;
}
}