NGINX Static Files Over Https? - django

I have the following docker-compose set up that is working for displaying pictures when deployed locally and without https:
NGINX:
events{
}
http{
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
location / {
proxy_pass http://frontend:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
}
docker-compose:
frontend:
build:
context: ../../
restart: always
volumes:
- '../../:/app'
- '/app/node_modules'
ports:
- "3000:3000"
depends_on:
- "backend"
environment:
- CHOKIDAR_USEPOLLING=true
stdin_open: true
tty: true
nginx:
build:
context: ../../nginx
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- volume1:/usr/share/nginx/html
links:
- "backend"
- "db"
- "frontend"
frontend:
<img
onError={()=>{
console.log("inside the onError function")
setImgError(true)
}}
src={"http://localhost:9000/static/"+comment.file_name}
className='commentimage'
/>
This is not working when using https. Which is to say - / and /api/ work as expected but not /images/.
events{
}
http{
server {
listen 80;
server_name localhost lightchan.org www.lightchan.org;
root /usr/share/nginx/html;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
return 301 https://lightchan.org$request_uri;
}
server {
listen 443 default_server ssl http2;
listen [::]:443 ssl http2;
server_name localhost lightchan.org www.lightchan.org;
#ssl_certificate /etc/nginx/ssl/live/lightchan.org/fullchain.pem;
#ssl_certificate_key /etc/nginx/ssl/live/lightchan.org/privkey.pem;
ssl_certificate /etc/letsencrypt/live/lightchan.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/lightchan.org/privkey.pem;
location / {
proxy_pass http://frontend:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location ^~ /api/ {
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://backend:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location ^~ /images/ {
rewrite ^/images/(.*)$ /$1 break;
proxy_pass https://164.92.157.124/static/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
}
My docker-compose:
frontend:
build:
context: ../../
restart: always
volumes:
- '../../:/app'
- '/app/node_modules'
ports:
- "3000:3000"
depends_on:
- "backend"
environment:
- CHOKIDAR_USEPOLLING=true
stdin_open: true
tty: true
links:
- 'backend'
nginx:
build:
context: ../../nginx
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- volume1:/usr/share/nginx/html
- varwwwcertbot:/var/www/certbot
- certbotconf:/etc/letsencrypt
links:
- "backend"
- "db"
- "frontend"
certbot:
image: certbot/certbot:latest
volumes:
- varwwwcertbot:/var/www/certbot
- certbotconf:/etc/letsencrypt
My frontend in this case I don't know how to reference. I have
<img
onError={()=>{
console.log("inside the onError function")
setImgError(true)
}}
src={"https://nginx:80/images/"+comment.file_name}
className='commentimage'
/>
Which doesn't look right. I've docker execed into the running nginx container and double checked that the image that I want to display exists in the static directory (which it does). If I attempt to navigate to <DNS>/images/<image.extension> I'm routed back through my frontend application. I've attempted to replace the line
proxy_pass https://164.92.157.124/static/;
with
proxy_pass https://backend:3000/static/;
but that will route through my Django application for static files and I want NGINX to serve them just as a folder.
I've also attempted to rewrite the /images/ block like this:
location ^~ /images/ {
root /usr/share/nginx/html/static;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
But that didn't work either, and I'm not positive that I'm allowed to rewrite the root for a server block when I redirect using https. In this instance, <DNS>/image/<image.ext> 404's rather than routing to the frontend again.
From reading other Stack Overflow posts people have mentioned that the ^~ signifier takes precedence over absolute routes so I would expect /images/ would be replaced first over /. So I don't understand why this is not true in the first two instances.
Routing to the backend, the IP address of the host, and the NGINX root are the three options that I can think of for the block content.
Any ideas?

Related

Django channels connection failed (nginx + daphne + certbot + docker-compose)

I'm using Django channels using docker-compose
and nginx outside it
websockets were working just fine but after installing certbot, it stopped working
it returns 404 as if it is treated as just normal http request
VM253:1 WebSocket connection to 'wss://example.com/ws/results/tjrtudvzanxxqbyt' failed:
daphne : "GET /ws/results/tjrtudvzanxxqbyt" 404 2618
my nginx file for the server is
upstream language_transcriber{
server localhost:8000;
}
# the nginx server instance
server {
listen 443 default_server;
server_name example.com;
access_log /var/log/nginx/example.com.log;
ssl_certificate_key /etc/nginx/ssl/example.com.private_key.pem;
ssl_certificate /etc/nginx/ssl/fullchain.crt;
root /var/www;
ssl on;
# pass the request to the node.js server with the correct headers
# and much more can be added, see nginx config options
location /ws/ {
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;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto$scheme;
proxy_set_header X-Url-Scheme $scheme; proxy_redirect off;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://127.0.0.1:8000;
}
location /static/ {
alias /var/www/example.com/static/;
autoindex off;
}
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Url-Scheme $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://language_transcriber/;
proxy_redirect off;
}
}
and here's my docker-compose.yml
version: "3.8"
services:
django:
build: .
container_name: django
command: daphne -b 0.0.0.0 -p 8001 project.asgi:application --access-log=/code/media/daphne.access.log
ports:
- "8000:8001"
volumes:
- ./media:/code/media
environment:
- redis_host=redis://redis:6379/0
celery:
build: .
command: celery -A project worker --concurrency=10 --loglevel=info --pool=gevent -E -Ofair --logfile=/code/media/celery.log
restart: always
stdin_open: true # docker run -i
tty: true # docker run -t
environment:
- redis_host=redis://redis:6379/0
depends_on:
- django
- redis
volumes:
- ./media:/code/media
redis:
image: "redis:alpine"
worker_channels:
build: .
command: python manage.py runworker thumbnails-generate thumbnails-delete
depends_on:
- django
- redis
environment:
- redis_host=redis://redis:6379/0
volumes:
waves-volume:
the app works just fine on my localhost but on production it just serves http not ws

How Reverse Proxy Django to a subdomain

I'm trying to use Nginx to reverse proxy some applications to different subdomain, the problem is when I try to do this with a Django application it doesn't work well, I get the message that the path does not exist or 404 Page not found.
this is a pice of my docker-compose.yaml
version: "3.9"
services:
ww4api:
build: .
hostname: ww4api
command: gunicorn --bind 0.0.0.0:8000 authApi.wsgi --workers=4
depends_on:
- db
- orion
restart: always
container_name: ww4api
environment:
- WW4API_ALLOWED_HOSTS=ww4,ww4api,localhost
ports:
- 8000:8000
volumes:
- .:/app
pgadmin:
container_name: pgadmin
image: dpage/pgadmin4
hostname: pgadmin
restart: always
depends_on:
- timescale
environment:
- PGADMIN_LISTEN_PORT=5050
nginx:
hostname: nginx
build: settings/nginx
restart: always
ports:
- 80:80
- 434:434
tty: true
volumes:
- ./data-models/context:/srv/ww4/context
- ./syncthingFolder/Sync:/srv/ww4/projects
- ./:/srv/ww4
networks:
- default
and this is part of my nginx.config
worker_processes auto;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
server_tokens off;
upstream ww4api {
server ww4api:8000;
}
upstream mintaka {
server mintaka:8080;
}
server {
listen 80;
root /srv/ww4;
index index.html;
keepalive_timeout 1s;
keepalive_requests 5000;
location / {
try_files $uri $uri/ =404;
}
location /pgadmin4/ {
resolver 127.0.0.11 ipv6=off;
proxy_pass http://pgadmin:5050/;
proxy_set_header X-Script-Name /pgadmin4;
proxy_set_header X-Scheme $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header 'Access-Control-Allow-Origin' '*';
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
location /ww4/ {
proxy_pass http://ww4api;
proxy_set_header X-Script-Name /ww4;
proxy_set_header X-Scheme $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect http://localhost/ww4/ http://$host/ww4/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header 'Access-Control-Allow-Origin' '*';
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
}
}
What am I doing wrong?

Cannot access Strapi in a container using AWS Lightsail, Ubuntu, Docker and NGINX

I'm trying to practice and I have created an instance using AWS Lightsail with Ubuntu 20.04 LTS, also I've installed Docker and Docker Compose.
I would like to run this applications:
MariaDB
Strapi CMS
Let's assume that my public IP is: 1.20.20.20
When I try to access "http://1.20.20.20:1337", I receives "This site can’t be reached".
I thought that maybe I needed a web server and I have included NGINX in my docker-compose configuration.
My folders in the instance:
envs/strapi.env
nginx/strapi.conf
docker-compose.yml
docker-compose.yml
version: '3.8'
services:
nginx:
image: nginx:stable
container_name: nginx
volumes:
- ./nginx/strapi.conf:/etc/nginx/conf.d/default.conf
ports:
- 80:80
restart: on-failure
depends_on:
- strapi
db:
image: mariadb:10.6.4
container_name: db
restart: always
env_file:
- envs/db.env
volumes:
- db-data:/var/lib/mysql
networks:
- apps
strapi:
image: strapi/strapi:3.6.8
container_name: strapi
env_file:
- envs/strapi.env
restart: always
depends_on:
- db
ports:
- 1337:1337
networks:
- apps
volumes:
db-data:
networks:
apps:
driver: bridge
nginx/strapi.conf (I have copied the configuration from Strapi docs):
server {
# Listen HTTP
listen 1337;
server_name 1.20.20.20;
# Static Root
location / {
root /var/www/html;
}
# Strapi API
location /api/ {
rewrite ^/api/?(.*)$ /$1 break;
proxy_pass http://strapi;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $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_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass_request_headers on;
}
# Strapi Admin
location /admin {
proxy_pass http://strapi/admin;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $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_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass_request_headers on;
}
}
Still cannot access the CMS using my browser.
For some reason, when I do "docker ps -a", the status of the nginx container is always Restarting....
I have tried to follow and read steps that I have found on a few articles without luck. I don't have a lot of experience using NGINX and Ubuntu servers.
My goal is to be able to access the web app (Strapi CMS) through my browser.
Any help would be appreciated.

No connection with dockerized nginx gunicorn

I've created simple example for dockerized django with nginx and gunicorn. But for some reason connection doesn't go through nginx.
Here is nginx.conf contents
worker_processes 1;
error_log /var/log/nginx/error.log info;
events {
worker_connections 1024;
}
http {
gzip on;
gzip_http_version 1.1;
gzip_comp_level 2;
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 80;
server_name www.example.dj example.dj;
location = /favicon.ico {
alias /app/static_root/favicon.ico;
}
location /static/ {
alias /app/static_root/;
}
location / {
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;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://unix:/app/example.sock;
}
}
}
docker-compose.yml file
version: '3'
services:
web:
build: .
hostname: web
command: bash -c "python manage.py migrate && gunicorn example.wsgi:application --workers 3 --bind unix:/app/example.sock"
volumes:
- ./src:/app
expose:
- "8000"
nginx:
image: nginx:latest
ports:
- "80:8000"
volumes:
- ./src:/app
- ./config/nginx/nginx.conf:/etc/nginx/nginx.conf
depends_on:
- web
In /etc/hosts I have
127.0.0.1 www.example.dj example.dj
So when I run docker-compose up I expect to see django start page by http://example.dj url, but there is no connection. Can you guys help me with it?
Code available on the github

Can not connect to websocket using django-channels , nginx on docker as services

I'm using docker compose to build a project with django, nginx as services. When I launch the daphne server, and a client tries to connect to the websocket server, I get this error:
*1 recv() failed (104: Connection reset by peer) while reading response header from upstream
Client-side shows this
failed: Error during WebSocket handshake: Unexpected response code: 502
Here is my docker-compose.yml
version: '3'
services:
nginx:
image: nginx
command: nginx -g 'daemon off;'
ports:
- "1010:80"
volumes:
- ./config/nginx/nginx.conf:/etc/nginx/nginx.conf
- .:/makeup
links:
- web
web:
build: .
command: /usr/local/bin/circusd /makeup/config/circus/web.ini
environment:
DJANGO_SETTINGS_MODULE: MakeUp.settings
DEBUG_MODE: 1
volumes:
- .:/makeup
expose:
- '8000'
- '8001'
links:
- cache
extra_hosts:
"postgre": 100.73.138.65
Nginx:
server {
listen 80;
server_name thelab518.cloudapp.net;
keepalive_timeout 15;
root /makeup/;
access_log /dev/stdout;
error_log /dev/stderr;
location /api/stream {
proxy_pass http://web:8001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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-Host $server_name;
}
location / {
try_files $uri #proxy_to_app;
}
location #proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://web:8000;
}
And the circusd's web.ini file:
[watcher:web]
cmd = /usr/local/bin/gunicorn MakeUp.wsgi:application -c config/gunicorn.py
working_dir = /makeup/
copy_env = True
user = www-data
[watcher:daphne]
cmd = /usr/local/bin/daphne -b 0.0.0.0 -p 8001 MakeUp.asgi:channel_layer
working_dir = /makeup/
copy_env = True
user = root
[watcher:worker]
cmd = /usr/bin/python3 manage.py runworker
working_dir = /makeup/
copy_env = True
user = www-data
As quite explicitly stated in the fine manual, to successfully run Channels you need to have a dedicated application server implementing the ASGI protocol, such as the supplied daphne
The entire Django execution model has been changed with Channels, so that there are separate "interface servers" taking care of receiving and sending messages over, for example, WebSockets or HTTP or SMS, and "worker servers" that run the actual code (potentially on a different server or VM or container or...). The two are connected by a "Channel layer" that carries messages and replies back and forth.
The current implementation supplies 3 channel layers that talk ASGI between an interface server and a worker server:
An In-memory channel layer, used mainly for running the test server (it's single process)
An IPC based channel layer, usable to run different workers on the same server
A redis based channel layer, that should be used for heavy production sites, able to connect interface servers to multiple worker servers.
You configure them like you do for DATABASES::
CHANNEL_LAYERS = {
"default": {
"BACKEND": "asgi_redis.RedisChannelLayer",
"ROUTING": "my_project.routing.channel_routing",
"CONFIG": {
"hosts": [("redis-channel-1", 6379), ("redis-channel-2", 6379)],
},
},
}
Of course this means that your docker config has to change and add one or more interface servers instead of, or in addition to, nginx (even if, in that case, you'll need to accept websocket connections on a different port with all the connected possible problems) and, quite likely, an instance of redis connectin all them.
This in turn means that until circus and nginx can support ASGI, it won't be possible to use them with django-channels, or that this support will only be for the regular http part of your system.
You can find more info in the Deploying section of the official documentation.
It looks that you stared daphne on port 8001, and trying to expose port 8000 and 8001 in docker-compose. The port 8000 is not pointing to any server (daphne is on 8001). In your nginx please set proxy to 8001 ports and expose only port 8001 in docker-compose.
I have created a simple example how it can be set on github where I have proxy to asgi and wsgi servers, but you can go with only asgi server:
The nginx:
upstream app {
server wsgiserver:8000;
}
upstream ws_server {
server asgiserver:9000;
}
server {
listen 8000 default_server;
listen [::]:8000;
client_max_body_size 20M;
location / {
try_files $uri #proxy_to_app;
}
location /tasks {
try_files $uri #proxy_to_ws;
}
location #proxy_to_ws {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_pass http://ws_server;
}
location #proxy_to_app {
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Url-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app;
}
}
The docker-compose.yml:
version: '2'
services:
nginx:
extends:
file: docker-common.yml
service: nginx
ports:
- 8000:8000
volumes:
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
volumes_from:
- asgiserver
asgiserver:
extends:
file: docker-common.yml
service: backend
entrypoint: /app/docker/backend/asgi-entrypoint.sh
links:
- postgres
- redis
- rabbitmq
expose:
- 9000
wsgiserver:
extends:
file: docker-common.yml
service: backend
entrypoint: /app/docker/backend/wsgi-entrypoint.sh
links:
- postgres
- redis
- rabbitmq
expose:
- 8000