Gunicorn Shell Script ModuleNotFoundError: No module named 'myproject'

When I try to run following shell script it results in the error down below. What am I doing wrong?

#!/bin/bash

NAME='myproject'
DJANGODIR=~/webapp/myproject_backend/
SOCKFILE=~/webapp/myproject_backend/run/gunicorn.sock
USER=myprojectuser
GROUP=webapp
NUM_WORKERS=3
DJANGO_SETTINGS_MODULE=myproject.settings
DJANGO_WSGI_MODULE=myproject.wsgi
TIMEOUT=120

cd $DJANGODIR

source ~/webapp/env/bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH

RUNDIR=$(dirname $SOCKFILE)

test -d $RUNDIR || mkdir -p $RUNDIR
exec gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--timeout $TIMEOUT \
--user=$USER --group=$GROUP \
--bind=unix:$SOCKFILE \
--log-level=debug \
--log-file=-
(env) root@debian-s-1vcpu-512mb-10gb-fra1-01:~/webapp/myproject_backend/myproject# ../../env/bin/gunicorn_start
[2024-06-26 10:38:33 +0000] [136171] [DEBUG] Current configuration:
  config: ./gunicorn.conf.py
  wsgi_app: None
  bind: ['unix:/root/webapp/myproject_backend/run/gunicorn.sock']
  backlog: 2048
  workers: 3
  worker_class: sync
  threads: 1
  worker_connections: 1000
  max_requests: 0
  max_requests_jitter: 0
  timeout: 120
  graceful_timeout: 30
  keepalive: 2
  limit_request_line: 4094
  limit_request_fields: 100
  limit_request_field_size: 8190
  reload: False
  reload_engine: auto
  reload_extra_files: []
  spew: False
  check_config: False
  print_config: False
  preload_app: False
  sendfile: None
  reuse_port: False
  chdir: /root/webapp/myproject_backend
  daemon: False
  raw_env: []
  pidfile: None
  worker_tmp_dir: None
  user: 994
  group: 993
  umask: 0
  initgroups: False
  tmp_upload_dir: None
  secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
  forwarded_allow_ips: ['127.0.0.1']
  accesslog: None
  disable_redirect_access_to_syslog: False
  access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
  errorlog: -
  loglevel: debug
  capture_output: False
  logger_class: gunicorn.glogging.Logger
  logconfig: None
  logconfig_dict: {}
  logconfig_json: None
  syslog_addr: udp://localhost:514
  syslog: False
  syslog_prefix: None
  syslog_facility: user
  enable_stdio_inheritance: False
  statsd_host: None
  dogstatsd_tags:
  statsd_prefix:
  proc_name: myproject
  default_proc_name: myproject.wsgi:application
  pythonpath: None
  paste: None
  on_starting: <function OnStarting.on_starting at 0x7fefb1e20a40>
  on_reload: <function OnReload.on_reload at 0x7fefb1e20b80>
  when_ready: <function WhenReady.when_ready at 0x7fefb1e20cc0>
  pre_fork: <function Prefork.pre_fork at 0x7fefb1e20e00>
  post_fork: <function Postfork.post_fork at 0x7fefb1e20f40>
  post_worker_init: <function PostWorkerInit.post_worker_init at 0x7fefb1e21080>
  worker_int: <function WorkerInt.worker_int at 0x7fefb1e211c0>
  worker_abort: <function WorkerAbort.worker_abort at 0x7fefb1e21300>
  pre_exec: <function PreExec.pre_exec at 0x7fefb1e21440>
  pre_request: <function PreRequest.pre_request at 0x7fefb1e21580>
  post_request: <function PostRequest.post_request at 0x7fefb1e21620>
  child_exit: <function ChildExit.child_exit at 0x7fefb1e21760>
  worker_exit: <function WorkerExit.worker_exit at 0x7fefb1e218a0>
  nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0x7fefb1e219e0>
  on_exit: <function OnExit.on_exit at 0x7fefb1e21b20>
  ssl_context: <function NewSSLContext.ssl_context at 0x7fefb1e21d00>
  proxy_protocol: False
  proxy_allow_ips: ['127.0.0.1']
  keyfile: None
  certfile: None
  ssl_version: 2
  cert_reqs: 0
  ca_certs: None
  suppress_ragged_eofs: True
  do_handshake_on_connect: False
  ciphers: None
  raw_paste_global_conf: []
  strip_header_spaces: False
  permit_unconventional_http_method: False
  permit_unconventional_http_version: False
  casefold_http_method: False
  header_map: drop
  tolerate_dangerous_framing: False
[2024-06-26 10:38:33 +0000] [136171] [INFO] Starting gunicorn 22.0.0
[2024-06-26 10:38:33 +0000] [136171] [DEBUG] Arbiter booted
[2024-06-26 10:38:33 +0000] [136171] [INFO] Listening at: unix:/root/webapp/myproject_backend/run/gunicorn.sock (136171)
[2024-06-26 10:38:33 +0000] [136171] [INFO] Using worker: sync
[2024-06-26 10:38:33 +0000] [136173] [INFO] Booting worker with pid: 136173
[2024-06-26 10:38:33 +0000] [136173] [ERROR] Exception in worker process
Traceback (most recent call last):
  File "/root/webapp/env/lib/python3.11/site-packages/gunicorn/arbiter.py", line 609, in spawn_worker
  File "/root/webapp/env/lib/python3.11/site-packages/gunicorn/workers/base.py", line 134, in init_process
  File "/root/webapp/env/lib/python3.11/site-packages/gunicorn/workers/base.py", line 146, in load_wsgi
  File "/root/webapp/env/lib/python3.11/site-packages/gunicorn/app/base.py", line 67, in wsgi
  File "/root/webapp/env/lib/python3.11/site-packages/gunicorn/app/wsgiapp.py", line 58, in load
  File "/root/webapp/env/lib/python3.11/site-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp
  File "/root/webapp/env/lib/python3.11/site-packages/gunicorn/util.py", line 371, in import_app
  File "/usr/lib/python3.11/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1206, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1178, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1128, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1206, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1178, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1142, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'myproject'
My filestructure:
root/
└── webapp/
    ├── env/
    │   ├── bin/
    │   │   ├── gunicorn
    │   │   ├── gunicorn_start
    │   │   └── ...
    │   └── ... 
    └── myproject_backend/
        ├── myproject/
        │   ├── settings.py
        │   ├── wsgi.py
        │   └── ...
        ├── user
        └── ...

I am following this tutorial: https://www.youtube.com/watch?v=Td3lirXIeRI. I am using Debian and not Ubuntu.

You want your “current directory” (BASE_DIR) to be the directory that is the directory containing the myproject directory.

These references are relative to your current directory. (It’s expecting to find a directory named myproject in the current directory, and files named settings.py and wsgi.py within it.)

#!/bin/bash

NAME='myproject'
DJANGODIR=~/webapp/myproject_backend/
SOCKFILE=~/webapp/myproject_backend/run/gunicorn.sock
USER=myprojectuser
GROUP=webapp
NUM_WORKERS=3

DJANGO_SETTINGS_MODULE=~/webapp/myproject_backend/myproject/settings.py
DJANGO_WSGI_MODULE=~/webapp/myproject_backend/myproject/wsgi.py

TIMEOUT=120

cd $DJANGODIR

source ~/webapp/env/bin/activate

export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE

export PYTHONPATH=$DJANGODIR:$PYTHONPATH

RUNDIR=$(dirname $SOCKFILE)

test -d $RUNDIR || mkdir -p $RUNDIR

exec gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--timeout $TIMEOUT \
--user=$USER --group=$GROUP \
--bind=unix:$SOCKFILE \
--log-level=debug \
--log-file=-

It’s still not working. It still shows that there is no module

Is the myproject directory in the myproject_backend directory? (It’s not clear from the diagram you posted.)

Additionally, your original settings are correct - they’re supposed to be:

Also, you have:

Does this uid/gid have all the necessary permissions into your home directory and everything within the webapp/myproject_backend directory?

Yeah it’s inside of the myproject_backend folder

I gave the user all the necessary permissions :thinking:

How have you verified that?

It looks like you might be running as root. If you haven’t already done so, you could try switching to this account and then trying to access the files in those directories.

I checked it again and you are right. When switching to the myproject_user using su myproject_user and trying to run the gunicorn_start script there it does not work. I wonder why that is like it is because I should have granted the right permission to the user

The /root directory is normally very limited, and I would never recommend having an application installed in it. Your application should be installed somewhere else, such as /home/myproject_user or /opt/myproject.
Those directories can be owned by the desired uid without creating problems.

I changed the location of the folder and it works like a charm! Thanks