skip to Main Content

I am in the process of deploying a Django project on an Ubuntu EC2. It should connect to a MySQL server on AWS RDS. The project works fine on the built-in Django development server you start with runserver and it also connects to the RDS instance properly there. However, if I try running it in production, it throws a 500 Internal Server Error that creates the following output in the error log:

mod_wsgi (pid=18656): Exception occurred processing WSGI script '/home/ubuntu/mysite/mysite/wsgi.py'.
Traceback (most recent call last):
File "/home/ubuntu/mysite/mysite_venv/lib/python3.8/site-packages/pymysql/connections.py", line 613, in connect 
  sock = socket.create_connection(
File "/usr/lib/python3.8/socket.py", line 808, in create_connection
  raise err
File "/usr/lib/python3.8/socket.py", line 796, in create_connection
  sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:

...
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")

This socket error occurs both with my custom views and with the mydomain.com/admin view. The relevant snippet of views.py looks like this:

# get environment variables
db_host = os.environ.get('DB_HOST')
db_user = os.environ.get('DB_USER')
db_pass = os.environ.get('DB_PASS')

# connect to db
conn = pymysql.connect(host=db_host,
                   user=db_user,
                   password=db_pass)

c = conn.cursor()
c.execute('''USE mysitedatabase''')

The file is generally executed properly, log statements I inserted as a test before the database connection are created without errors. I have already tried removing all inbound traffic rules from my RDS security group, setting it to all IPv4 traffic with 0.0.0.0/0 but the error persisted. I assume that the socket error and the localhost error are connected since I don’t think it would make sense to connect via a unix socket when not being on localhost.

How do I stop pymysql from trying to connect on localhost when it should connect to RDS?

I use Ubuntu 20.04, Django 4.0, Apache/2.4.41 (Ubuntu) and Python 3.8.

2

Answers


  1. Chosen as BEST ANSWER

    The environment variables were not configured in production, thank you @Mark B for pointing me in the right direction. There are multiple ways of going about this. I decided to take an easy route and add the database credentials to settings.py like so:

    DB_HOST = 'your_rds_endpoint'
    DB_PASS = 'your_secure_password'
    DB_USER = 'your_username'
    

    Then just import settings.py into views.py and access the variable you need. In views.py:

    from django.conf import settings as my_settings
    
    db_host = my_settings.DB_HOST
    db_user = my_settings.DB_USER
    db_pass = my_settings.DB_PASS
    

    However, this is not the best way to do it because from what I could find, you should reference the settings file as little as possible because of security concerns.

    Better alternatives to this problem are probably django-environ (which, contrary to intuition, also works outside of Django) and python-decouple.


  2. What you probably experiencing is that the RDS has a Host Address that you need to point to shown on the Image.

    The possible reason why it’s working on your development environment (Assuming it local) is because you have set

    db_host = localhost

    so try setting

    DB_HOST = rds_address
    DB_USER = rds_access_username
    DB_PASS = rds_access_password

    RDS Instance

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search