0

I would like to deploy a django application with the django-tenants library. The project works fine locally, I can create tenants and access them via localhost:8000 and <tenant>.localhost:8000 (mind that this redirects to localhost:8000/en and <tenant>.localhost:8000/en because of internationalization)

Now I am trying to deploy the application on DigitalOcean using docker-compose and I have an issue with configuring the nginx server. As the log suggests I am able to start the gunicorn server on 0.0.0.0:8000 but I can not reach the application through a client browser:

http://<DOMAIN> returns 504 - Gateway Time-out

Here is my NGINX config (at /etc/nginx/sites-enabled):

server {
    listen                  443 ssl http2;
    listen                  [::]:443 ssl http2;
    server_name             .<DOMAIN>;
    set                     $base /etc/nginx/sites-available/trackeree.com;

    # SSL
    ssl_certificate         /etc/letsencrypt/live/trackeree.com/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/trackeree.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/trackeree.com/chain.pem;

    # security
    include                 /etc/nginx/security.conf;

    # logging
    access_log              /var/log/nginx/access.log combined buffer=512k flush=1m;
    error_log               /var/log/nginx/error.log warn;

    location / {
        uwsgi_pass           web:8000;
        include              /etc/nginx/uwsgi.conf;
    }

    # Django media
    location /media/ {
        alias $base/media/;
    }

    # Django static
    location /static/ {
        alias $base/static/;
    }

    # additional config
    include /etc/nginx/general.conf;
}

# non-www, subdomains redirect
server {
    listen                  443 ssl http2;
    listen                  [::]:443 ssl http2;
    server_name             www.<DOMAIN>;

    # SSL
    ssl_certificate         /etc/letsencrypt/live/trackeree.com/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/trackeree.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/trackeree.com/chain.pem;
    return                  301 https://trackeree.com$request_uri;
}

# HTTP redirect
server {
    listen      80;
    listen      [::]:80;
    server_name .<DOMAIN>;

    # ACME-challenge
    location ^~ /.well-known/acme-challenge/ {
        root /etc/letsencrypt/www/;
    }

    location / {
        return 301 https://trackeree.com$request_uri;
    }

uwsgi.conf

# default uwsgi_params
include                       /etc/nginx/uwsgi_params;

# uwsgi settings
uwsgi_param Host              $host;
uwsgi_param X-Real-IP         $remote_addr;
uwsgi_param X-Forwarded-For   $proxy_add_x_forwarded_for;
uwsgi_param X-Forwarded-Proto $http_x_forwarded_proto;

uwsgi_params

uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_ADDR $server_addr;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;

When accessing https://<DOMAIN> in the browser:

I can not see any error message in gunicorn logs:

[2023-08-20 23:28:45 +0000] [9] [INFO] Listening at: http://0.0.0.0:8000 (9)
[2023-08-20 23:28:45 +0000] [9] [INFO] Using worker: sync
[2023-08-20 23:28:45 +0000] [10] [INFO] Booting worker with pid: 10
[2023-08-20 23:28:45 +0000] [11] [INFO] Booting worker with pid: 11

And this is all I can see in the nginx logs:

2023/08/21 18:33:22 [error] 15#15: *1 upstream timed out (110: Operation timed out) while reading response header from upstream, client: <CLIENT_IP>, server: <DOMAIN>, request: "GET / HTTP/2.0", upstream: "uwsgi://<HOST_IP>:8000", host: "<DOMAIN>"
<CLIENT_IP> - - [21/Aug/2023:18:33:22 +0000] "GET / HTTP/2.0" 504 562 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"
<CLIENT_IP> - - [21/Aug/2023:18:33:25 +0000] "GET / HTTP/2.0" 499 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"
2023/08/21 18:34:25 [error] 15#15: *1 upstream timed out (110: Operation timed out) while reading response header from upstream, client: <CLIENT_IP>, server: <DOMAIN>, request: "GET / HTTP/2.0", upstream: "uwsgi://<HOST_IP>:8000", host: "<DOMAIN>"

Even if I put this in the nginx config the http response is still 504

location / {
        uwsgi_pass           <DOMAIN>:8000;
        include              /etc/nginx/uwsgi.conf;
    }

From the proxy/nginx container:

bash-5.1# curl -vf web:8000
*   Trying 172.29.0.7:8000...
* Connected to web (172.29.0.7) port 8000 (#0)
> GET / HTTP/1.1
> Host: web:8000
> User-Agent: curl/7.83.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Server: gunicorn
< Date: Mon, 21 Aug 2023 18:42:51 GMT
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=utf-8
< Location: https://web:8000/
< X-Content-Type-Options: nosniff
< Referrer-Policy: same-origin
< Cross-Origin-Opener-Policy: same-origin
<
* Closing connection 0


bash-5.1# curl -vf https://web:8000/en
*   Trying 172.29.0.7:8000...
* Connected to web (172.29.0.7) port 8000 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):

The public tenant is successfully created with domain=<DOMAIN> and I tried to create the public tenant to match the container name as well: domain=web

I can access the postgresql database from the web container

All services are on the same docker network:

[
    {
        "Name": "saas-boilerplate_default",
        "Id": "5c27de32563c949bc7b1848ad3fc76fa434b53aa1ddf9bf032c4a5e5a79ad226",
        "Created": "2023-08-20T22:43:58.160670257Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.29.0.0/16",
                    "Gateway": "172.29.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "02d013201492657e2be4614ead90f63c8356f89b6bb5e932a76f2d07ea616aa2": {
                "Name": "saas-boilerplate_redis_1",
                "EndpointID": "7cb890f1aeb79405efbc8093e583e84618a93742dcd52b6b3b8e7b3da48dbaba",
                "MacAddress": "02:42:ac:1d:00:06",
                "IPv4Address": "172.29.0.6/16",
                "IPv6Address": ""
            },
            "15c86cdd4dd14b1af29dd9d60b84fabf0dd49dd5af22f050cde1165e1e652d29": {
                "Name": "saas-boilerplate_flower_1",
                "EndpointID": "bd2c4a86bd28e93c592276ffab4f7fa773575a4673bc442b759bdb67902b3f52",
                "MacAddress": "02:42:ac:1d:00:02",
                "IPv4Address": "172.29.0.2/16",
                "IPv6Address": ""
            },
            "50d275ae08b4591621a467e7559db52857f60dcdfd5bef8adffe941e4fd5f093": {
                "Name": "saas-boilerplate_db_1",
                "EndpointID": "8f250e357ed3cef570e77a5359f6e7bbe4aab951ceb28c5d64921547da5094de",
                "MacAddress": "02:42:ac:1d:00:03",
                "IPv4Address": "172.29.0.3/16",
                "IPv6Address": ""
            },
            "5608aaefa2eafd7d0f6bd213865169dcb910911989df4f3f35f7ef3cb63aac4c": {
                "Name": "saas-boilerplate_celery_worker_1",
                "EndpointID": "e13441d0ffbebf77516204e76292186caa706eb3678f486e57756d0483762712",
                "MacAddress": "02:42:ac:1d:00:04",
                "IPv4Address": "172.29.0.4/16",
                "IPv6Address": ""
            },
            "e10302100dcb45f4c80686ca7cde6be0d6b698bece4fcca5974d665d38d80352": {
                "Name": "saas-boilerplate_web_1",
                "EndpointID": "a37d53b8e5137c08c2c3821ced92ee3e3fb3ae2739293a4df23e343f16d44b89",
                "MacAddress": "02:42:ac:1d:00:07",
                "IPv4Address": "172.29.0.7/16",
                "IPv6Address": ""
            },
            "e8b1564ec18bb763e8f7e0734ae2e4f0249148f1065d071eb3d71da8b14ad0a3": {
                "Name": "saas-boilerplate_celery_beat_1",
                "EndpointID": "56d3078bea5ad480b293c59bf6a4fab0dbc67a4e0923479e5a648681b3c4fac1",
                "MacAddress": "02:42:ac:1d:00:05",
                "IPv4Address": "172.29.0.5/16",
                "IPv6Address": ""
            },
            "eb3da21f295108aad66e247f56a2255e3c3bdab5bf0e09494c6bc8c8ddcbcfd5": {
                "Name": "saas-boilerplate_proxy_1",
                "EndpointID": "155b7121435ed1d948e0ce543571a668e0eb45165654db151d3e99d7d1b851fb",
                "MacAddress": "02:42:ac:1d:00:08",
                "IPv4Address": "172.29.0.8/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "default",
            "com.docker.compose.project": "saas-boilerplate",
            "com.docker.compose.version": "1.29.2"
        }
    }
]

I start gunicorn with this start script:

#!/bin/bash

set -o errexit set -o nounset

python manage.py migrate gunicorn --bind 0.0.0.0:8000 --timeout 600
--workers 2 trackr.wsgi:application

I can successfully get SSL certificate and that is why I think that my nginx configuration is correct, but somehow the application is still unreachable.

I masked the DOMAIN, CLIENT_IP and HOST_IP for security reasons.

I really don't know where to go from here. What am I missing?

ish
  • 75
  • 5

0 Answers0