Serving Django and Vue with Nginx - django

I have a website which uses Django for the API and Vue for the frontend. Currently when I deploy the site I do the following:
Create a production build of the Vue app (npm run build)
Copy the Vue dist folder into a specific folder within the Django app
One of the Django urls is setup as a TemplateView which serves up the Vue index.html
By doing the above, Nginx in production simply serves up the Django app using gunicorn and everything works.
However I would prefer to have Nginx serve up the Vue index.html and static files. For example / will serve the Django app and /spa will serve the Vue app which will itself call the api.
Here is my current Nginx config:
upstream appserver_wsgi_app {
server localhost:8000 fail_timeout=0;
}
server {
listen 80;
server_name www.example.com;
rewrite ^(.*) https://$server_name$1 permanent;
}
server {
server_name www.example.com;
listen 443 ssl;
...
...
...
location /static {
autoindex on;
alias /home/user/static_django_files/;
}
location /media {
autoindex on;
alias /home/user/media_django_files/;
}
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://appserver_wsgi_app;
break;
}
}
}
What needs to be changed in Nginx so that it will serve the Vue index.html and static files as well as the Django app? Also, does anything need to change on the Vue side since im currently just calling the api as follows:
axios.post("/api/dosomething/", data)
EDIT
I have added the following to my nginx config and uploaded the Vue dist folder:
location /spa {
autoindex on;
alias /path/to/dist/;
try_files $uri $uri/ /index.html;
}
I have also added the following to vue.config.js:
baseUrl: '/spa'
And to my Vue Router: mode: history
When restarting nginx, the index.html page for the vue app attempts to load in the browser but it cannot find the css and js files which it tries to find at:
www.example.com/spa/js/...
www.example.com/spa/css/...

I have a similar setup where I run the Django REST backend with uwsgi on port 8090 and serve the production build of angular 4 frontend via nginx. Here is my nginx.conf
server {
listen 80;
server_name **url**;
rewrite ^ https:// **url** $request_uri? permanent;
}
server {
listen 443 ssl;
server_name **url**;
ssl_certificate **.pem;
ssl_certificate_key **.key;
root *path to your vue production build folder where index.html resides*;
index index.html;
error_page 502 /gateway.html;
location /assests {
autoindex on;
alias *path to you Django assets *;
}
location /static {
autoindex on;
alias *path to you static files both django static files and vue related static files*;
}
// this to server the django admin
location /manage/ {
proxy_pass http://127.0.0.1:8090/manage/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
// this is for the REST backend
location /api/{
proxy_pass http://127.0.0.1:8090;
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;
}
}
I think similar setup should work for Django + Vue.js project. Let me know if it works.
** EDIT
for your second issue create another location with '/spa/static' in nginx.conf similar to the '/static'.

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/;
}

How to serve React app AND Django blog from Nginx?

I'm using nginx to serve a React app from my domain root / and a Django blog app from /blog. I'm also using nginx to redirect all http to https.
The problem is some weird behaviour... If I navigate to the blog with a clear cache, it shows the blog. If I then navigate to the index page it shows the react app. All good so far. But then, if I return to /blog it continues to show the react app, not the blog! I think the problem involves caching, but I'm not sure where.
I am not using react-router, so I'm not sure how the urls could get redirected on the client side.
Here is my nginx config:
server {
listen 80;
server_name mydomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name mydomain.com;
root /production_build;
location /static/ {
root /var/www/mysite;
}
location /blog {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://upstream_django_server;
}
location /cms {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://upstream_django_server;
}
location / {
try_files $uri /index.html;
}
}
You should disable the service worker in react, as it is interfering with your /blog url and returning its own response the next time.
Since you are mixing 2 apps here, you don't want to take a risk of having something which is difficult to get rid of.
Service workers can be sometimes very nasty because of caching responses

Django: serve static section of a web-app

I have:
a Django web app
a separate static HTML site (blog)
The static site is a separate directory tree.
I want the static site to be served as a sub-section of the web app.
For example, the app is at http://app.com/ and the static is site served from http://app.com/blog
Here's my /etc/nginx/sites-available/app:
upstream app_server {
server 127.0.0.1:9000 fail_timeout=0;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
...
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
proxy_buffering off;
proxy_pass http://app_server;
}
}
server {
server_name yourdomain.com;
location /blog{
root /path/to/static/html;
}
location /{
# your django app configuration
proxy_pass http://localhost:8000$request_uri;
# other configurations
}
}

Configure Django App as nginx location

I am trying to deploy a Django app along a static html website. The general www.example.com will provide the basic website. The URI /app should then proxy to a Gunicorn WSGI server. The nginx configuration in sites-enabled looks as follows:
upstream gunicorn {
server 127.0.0.1:8000;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/website;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
location /app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://gunicorn;
}
}
I am getting a 404 error when trying www.example.com/app. It seems the URI gets messed up somehow. The complete URL that is created is http://www.example.com/accounts/login/?next=/app/
Setting up the App alone exactly following this tutorial http://hackedexistence.com/project/raspi/django-on-raspberry-pi.html does work.
Is the setup I am aiming at even possible? And if yes, where is my misunderstanding of the location concept?
You need to set the SCRIPT_NAME header in your location directive.
proxy_set_header SCRIPT_NAME /app;
See this blog post for an example.

taking a django site down for maintenance?

I am running django with nginx/gunicorn. I am not deeply familiar with how nginx and gunicorn work, but suppose that I want to take my django site down for maintenance.
I assume I would be wanting to redirect to some simple maintenance page by going into the nginx/gunicorn settings and redirecting something but I could be wrong.
What is the correct (easiest) way to do this?
EDIT adding nginx config proxy statements:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
EDIT 2: adding nginx sites-enabled file
upstream app_server {
server 127.0.0.1:9000 fail_timeout=0;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/html;
index index.html index.htm;
client_max_body_size 4G;
server_name _;
keepalive_timeout 5;
# Your Django project's media files - amend as required
location /media {
alias /home/django/mysite/media;
}
# your Django project's static files - amend as required
location /static {
alias /home/django/mysite/static_dump;
}
location / {
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header Host $http_host;
#proxy_redirect off;
#proxy_pass http://app_server;
if (-f /usr/share/nginx/html/index.html) {
return 503;
}
}
error_page 503 #maintenance;
location #maintenance {
rewrite ^(.*)$ /503.html break;
}
}
One of the ways to do is to add the maintenance page somewhere in the server, and then in your nginx file ( In the sites-enabled folder) redirect requests to the site to that maintenance page.
Your nginx page should contain:
server_name myhost.example.com;
root /path/to/html/file/directory;
index index.html;
Only the above 3 lines are enough