6

I deployed a Django App to AWS Elastic Beanstalk and I'm getting "Invalid HTTP_HOST header" error even when I've added it to my allowed hosts settings.

I'm getting this error:

Invalid HTTP_HOST header: 'recordings-env.kf4qfzaijd.us-west-2.elasticbeanstalk.com'. You may need to add 'recordings-env.kf4qfzaijd.us-west-2.elasticbeanstalk.com' to ALLOWED_HOSTS.

This is what I have in my settings.py

settings.py:

ALLOWED_HOSTS = [
    '127.0.0.1',
    'localhost',
    '.amazonaws.com',
    '.elasticbeanstalk.com',
    'recordings-env.kf4qfzaijd.us-west-2.elasticbeanstalk.com',
]

I think the problem is that my settings aren't being updated, because isn't working either if I put ALLOWED_HOSTS = ['*']. I left DEBUG = True and in request information I'm getting: ALLOWED_HOSTS: ['localhost']

after modifying it I run eb deploy without errors.

2 Answers2

5

I've realized that my changes wasn't being deployed because I needed to commit first and I didn't know that (my first time deploying to eb). So, that was the problem.

4

It's a little tricky because you need to dynamically declare your ALLOWED_HOSTS with EB. This article provides some good information in Gotcha #3 on how you could achieve this

I would create a separate settings file called something like settings_production.py then you could place the following code in there:

mysite/settings_production.py

from mysite.settings import *


def is_ec2_linux():
    """Detect if we are running on an EC2 Linux Instance
       See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html
    """
    if os.path.isfile("/sys/hypervisor/uuid"):
        with open("/sys/hypervisor/uuid") as f:
            uuid = f.read()
            return uuid.startswith("ec2")
    return False


def get_linux_ec2_private_ip():
    """Get the private IP Address of the machine if running on an EC2 linux server"""
    from urllib.request import urlopen
    if not is_ec2_linux():
        return None
    try:
        response = urlopen('http://169.254.169.254/latest/meta-data/local-ipv4')
        return response.read().decode("utf-8")
    except:
        return None
    finally:
        if response:
            response.close()


# ElasticBeanstalk healthcheck sends requests with host header = internal ip
# So we detect if we are in elastic beanstalk,
# and add the instances private ip address
private_ip = get_linux_ec2_private_ip()
if private_ip:
    ALLOWED_HOSTS += [private_ip, 'your-django-env.elasticbeanstalk.com']

# Other production overrides
DEBUG = False


Now you set "DJANGO_SETTINGS_MODULE" env variable to mysite.production_settings for your production (.i.e your EB environment).

UPDATE:

I decided to take this for a test spin and managed to get it up and running. I discovered a few things though. The above code adds the internal IP of each instance to the ALLOWED_HOSTS. This is purely for health checks so that AWS console can ping the instances internally and receive a 200OK response. I'm leaving the above solution as it is still useful for that purpose. It will not solve your particular error though. To serve you simply need to add your EB url, that is all. You can find it in the AWS console (highlighted in red below) or in the cli by typing eb status and checking the CNAME property.

enter image description here

CONFIG:

Here are my basic config files I manually created in my source:

.ebextensions/django.config


option_settings:
  aws:elasticbeanstalk:container:python:
    WSGIPath: mysite/wsgi.py
  aws:elasticbeanstalk:application:environment:
    DJANGO_SETTINGS_MODULE: mysite.settings_production

.ebextensions/db-migrate.config


container_commands:
  01_migrate:
    command: "django-admin.py migrate"
    leader_only: true
option_settings:
  aws:elasticbeanstalk:application:environment:
    DJANGO_SETTINGS_MODULE: mysite.settings_production
Lance
  • 895
  • 1
  • 9
  • 18
  • At first thanks for your answer. I've tried this solution and didn't work. But I think the problem is that my settings aren't being updated, because isn't working either if I put ```ALLOWED_HOSTS = ['*']```. I left ```DEBUG = True``` and in request information I'm getting: ```ALLOWED_HOSTS: ['localhost']``` – Josefina Estevez Mar 30 '19 at 22:08
  • 3
    I've realized that my changes wasn't being deployed because I needed to commit first and I didn't know that (my first time deploying to eb). So, that was the problem. This solution should work now. Thanks! – Josefina Estevez Mar 30 '19 at 22:29
  • You're welcome. I fully tested the above solution and managed to get my simple Django app up and running. There were some errors in the original code I posted so I edited it, but it's optional for the health check. I was able to get my app to work by simply adding my EB URL to the ALLOWED HOSTS. I included my config as well incase it helps. It's all been fully tested and working. – Lance Mar 31 '19 at 12:07
  • 1
    As you say, at first, after commit, I've tried ALLOWED_HOSTS = ['*'] and also with my eb url and worked. Then, to improve it I did what you told me with a settings_production file and worked too :) – Josefina Estevez Apr 01 '19 at 13:53
  • 1
    thank you @JosefinaEstevez . . . i was spacing out committing my files to github . . . i think i sort of tthought the zip package was being sent from my localhost and obviously aws gets the code from repo . . . DOH!! – SmokeRaven Jul 28 '19 at 18:24