16

How do you get aws elastic beanstalk to recognize your static assets in your flask app? I did the standard /.ebextensions/python.config couple of YAML lines a la:

option_settings:
  "aws:elasticbeanstalk:container:python:staticfiles":
    "/static/": "static/"

All of my calls to assets in templates are wrapped in "{{url_for('static', filename='img/office.jpg')}}" type things.

But no images, styles or javascript shows up on page load. Here is an example log file 404. IP - - [25/Feb/2013:21:48:13 +0000] "GET /static/css/bootstrap.css HTTP/1.1" 404 328 "http://xyz.elasticbeanstalk.com/"

Am I missing something obvious? Everything runs great on my local, just static assets dont load once i git aws.push

user1609682
  • 255
  • 2
  • 11
  • I'm having the same problem, except with bottle. I have a bunch of subfolders in /static so in bottle I have a route saying `@route('/static/:path#.+#')` and it works fine, but I can't get it to work in beanstalk. Hopefully someone has an answer for us! – Alex S Apr 29 '13 at 04:32

9 Answers9

12

It can be done also through Elastic Beanstalk Panel:

Configuration -> Software Configuration - > Static Files

and then

enter image description here

just as an alternative option

oetoni
  • 3,269
  • 5
  • 20
  • 35
  • This doesn't work. It sets the property `aws:elasticbeanstalk:container:python:staticfiles`, which is not recognized by Flask. You need to create a variable in the `aws:elasticbeanstalk:container:python` scope manually. – Myles Baker Feb 24 '20 at 04:20
  • hi @MylesBaker, maybe there are new updates but I assure you it does. The configuration is currently working on my deploys both for Flask and Node in Elastic Beanstalk – oetoni Feb 25 '20 at 09:40
  • 1
    I can confirm this is working in April 2020. I tried manually configuring my .ebextensions/helloworld.config file as other solutions suggested, but that only created additional problems. Also https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options.html#configuration-options-recommendedvalues seems to suggest the properties established in the console override those established in the config file. If you're having troubles, consider trying this solution first! (unlike me) – Luis Sosa Apr 26 '20 at 19:20
6

As of this writing, after spending many hours fighting with AWS EB's config, I gave up trying to make the static files work the way we all expect and updated my Flask app creation to:

app = Flask(__name__, static_url_path='/s')

This renders urls like /s/scripts/my-script.js and since I always use url_for('static', ...) in my code and templates, everything continued to work outside of AWS as well.

Update on 9/30/2013: I can pretty much guarantee that the staticFiles settings are completely ignored in AWS EB's Python container.

The change I suggested above has the undesirable downside of routing all static file requests through Flask (maybe, more accurately, WSGI.) That's not very hard to fix, though.

Create an Apache conig file at your project root, named app-httpd.conf:

Alias /s /opt/python/current/app/static
<Directory /opt/python/current/app/static>
Order allow,deny
Allow from all
</Directory>

This config tells Apache to take over any requests for URLs starting with /s, same prefix we chose for our static files, and serve files from our app's static folder.

Create this file at .ebextensions/custom-apache.config:

container_commands:
  add_apache_conf:
    command: "cp app-httpd.conf /etc/httpd/conf.d"

This file will be used during the app deployment and will copy the new .config file to a directory from which Apache is configure to load all .config files it sees.

sergiopereira
  • 2,026
  • 2
  • 23
  • 31
  • [What is the relationship between `.ebextensions/*.config` files and `.elasticbeanstalk/optionsettings.*` files](http://stackoverflow.com/q/27907203/656912)? – orome Jan 12 '15 at 17:09
  • The **.elasticbeanstalk** directory, as far as I understand, keeps local settings for your project. These settings are used by the `eb` command line tools, including when you run `git aws.push`. I personally stopped using these tools and wrote my own scripts using their API. In my case, for Python, I use the Boto package. The stuff in **.ebextensions** are included with your app when it's deployed or updated. It contains settings or commands that will be executed in your app servers upon deployment. – sergiopereira Jan 12 '15 at 22:19
  • @sergiopereira Thank you, your comment about the problems with the `staticfiles` settings helped me solve my issue. – Myles Baker Feb 24 '20 at 04:24
6

4+ years later, I'm able to get static files working using:

(file: .ebextensions/WHATEVER_NAME.config)

option_settings:
  - namespace: aws:elasticbeanstalk:container:python
    option_name: StaticFiles
    value: /static/=PATH/FROM/MY/APP/BASE/DIR/TO/STATIC/DIR/

...in my case, this was

    value: /static/=distrib/static/

I found that changing my

app = Flask(__name__)

to

app = Flask(__name__, static_url_path='/static')

was neither necessary nor sufficient. When I only set static_url_path but not StaticFiles, it didn't work; when I set StaticFiles but not static_url_path, it worked fine.

<sarcasm>Elastic Beanstalk is super straightforward and well documented!</sarcasm>

Ben Wheeler
  • 6,788
  • 2
  • 45
  • 55
  • I needed to read this answer a few times before it made sense, but this is the correct answer. As @sergiopereira stated, the "staticfiles settings are completely ignored in AWS EB's Python container." – Myles Baker Feb 24 '20 at 04:22
  • This worked for me based on your answer aws:elasticbeanstalk:environment:proxy:staticfiles: /static: static – ChrisDanger May 08 '23 at 18:41
1

I spent a goodly amount of time trying to figure this out and sort through these suggestions. I've made comments on the answers that were still relevant in 2020. Here's the TL;DR of the solution I encountered:

  • The static files section in the Modify Software screen under the Configuration left navigation pane on the Elastic Beanstalk UI sets the property aws:elasticbeanstalk:container:python:staticfiles. This configuration does not map to the static_url_path which Flask needs to find the static assets.
  • The correct property to set is StaticFiles, which can be set by adding a .config file to the .ebextensions directory.

Read more here.

Myles Baker
  • 3,600
  • 2
  • 19
  • 25
0

A strange thing that I found to solve this issue was editing my .gitignore file. It had included removing the /dist folders, and that included the dist folders that my CSS was generated into. So the css files were actually missing when I deployed.

Hope this may help anyone who might be in the same boat.

nycynik
  • 7,371
  • 8
  • 62
  • 87
0

This problem baffled me for a bit because it worked locally. No need to change config. I change line 1 to line 2 in my html file and it worked. Keep static folder in root directory and also keep config at /static/:/static/.

 1 <link rel="stylesheet" href={{url_for('static',filename='style.css')}}/>

2 <link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='style.css') }}">

may be the quotes around the href.

zachary
  • 108
  • 1
  • 9
0

I tried Myles Baker's solution, but did not work as upon deployment I received the error -

ERROR   Invalid option specification (Namespace: 'aws:elasticbeanstalk:container:python', OptionName: 'StaticFiles')

I ended up using the following code in my .ebextensions/WHATEVER_NAME.config -

option_settings:
  aws:elasticbeanstalk:environment:proxy:staticfiles:
    /html: statichtml
    /images: staticimages

Which is a straight copy/paste from here - https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environment-cfg-staticfiles.html

VectorVictor
  • 820
  • 8
  • 17
0

This worked for me:

option_settings:
  aws:elasticbeanstalk:application:environment:
    PYTHONPATH: "/var/app/current:$PYTHONPATH"
  aws:elasticbeanstalk:environment:proxy:staticfiles:
    /static: static
ChrisDanger
  • 1,071
  • 11
  • 10
-1

I had a similar problem where, strangely enough, all files from static/img/ were being served, but anything in static/css/ or static/js/ were simply not being served.

To fix this I opened .elasticbeanstalk/optionsettings.app-env from the root directory of the Flask source and edited this block of code to be

[aws:elasticbeanstalk:container:python]
NumProcesses=1
NumThreads=15
StaticFiles=/static/.*=
WSGIPath=application.py

[aws:elasticbeanstalk:container:python:staticfiles]

Note that StaticFiles actually takes a regular expression, so in /static/.* the .* allows for any path after /static/

ajrenold
  • 69
  • 1
  • 4