Serving files to the interwebs via AWS S3 and/or CloudFront is super convenient for most cases. You can even hide them behind a CNAME so it looks like you're your own capable web host. However, one nagging feature lack is the ability to upload a root certificate and serve said files via HTTPS. Without this, your users' browsers will display an annoying SSL Certificate error when using that super friendly CNAMEed URL.
Insert s3-edge.
This is a simple app which sits between S3 and your users. Push this war to a service like Elastic Beanstalk, a service which does allow you to specify your own certificate, and voila! You now have CNAME friendly HTTPS with the simplicity of S3 file management. Isn't that easy?
Use s3-edge in one of two ways: stand-alone or as part of your larger clojure/ring web application.
Pull the source and build a war. s3-edge uses leiningen so be sure you have that installed first.
$ git clone https://github.com/ndimiduk/s3-edge.git
$ cd s3-edge
$ lein deps, ring uberwar
Note: building the war appears to compile and execute the code! This causes an exception to be thrown because you likely don't have the environment properly configured in your shell. This is a known issue; please don't be alarmed.
You can now upload the newly created
s3-edge-1.0.0-standalone.war
to EBS or wherever else
you'd find it useful.
s3-edge expects to be deployed to Elastic Beanstalk and so looks for
configuration in a specific place. It looks for AWS access credentials
in the System properties AWS_SECRET_KEY_ID
and
AWS_SECRET_KEY
. It looks for the name of the bucket from
which to serve content in the most intuitively named property
PARAM1
. These are easily set in your EBS environment
configuration. For everyone else, you can likely launch your servlet
container with the JAVA_OPTS
environment variable
defining these values,
ie. JAVA_OPTS="-DPARAM1=my-bucket-name"
.
s3-edge defines the ring.middleware.s3
namespace which
exports the wrap-s3
function. Use it just like you would
wrap-file
. To use the middleware, include it as a
dependency in your leiningen project:
:dependencies [[s3-edge "1.0.0"]]
It accepts an option map which respects the following keys:
- :bucket-name name of the bucket to check for objects. Defaults to
the system property specified by
PARAM1
- :access-key-id the AWS access key id to use for S3
interaction. Defaults to the system property specified by
AWS_ACCESS_KEY_ID
- :secret-key the AWS secret key to use for S3 interaction. Defaults
to the system property specified by
AWS_SECRET_KEY
- s3-edge does its best to pass along appropriate headers. Basically, if it's available in the s3 client library API it's passed through.
- File streams opened from s3 are passed directly into the response. This may do things like consume lots of memory if you're not kicking those responses back right away.
Copyright (C) 2011 Nick Dimiduk
Distributed under the Eclipse Public License, the same as Clojure.