I believe this situation calls for SNI, and that Cloudfront offers SNI. However, my use case doesn't really involve Cloudfront or edge caching.
Fair enough, but that is the official solution. S3 doesn't directly support SSL and custom domains.
Also, consider this:
CloudFront is not just a CDN. It's also an SSL offloader, Host: header rewriter, path prepender, geolocator, georestrictor, secure content gateway, http to https redirector, error page customizer, root page substituter, web application firewall, origin header injector, dynamic content gzipper, path-based multi-origin http request router, viewer platform identifier, DDoS mitigator, zone apex alias target... so don't get too hung up on "CDN" or on the fact that you're stacking one service in front of another -- CloudFront was designed, in large part, to complement S3. They each specialize in certain facets of storage and delivery.
https://stackoverflow.com/a/35616286/1695906
You might get the impression from that little outburst that I'm some kind of stealth evangelist for AWS, but I'm not. No affiliation. I'm just a fan of useful tools, and CloudFront is something of a swiss army knife of handy capabilities that are largely unrelated to "CDN."
So CloudFront is a viable solution, here. It allows you to use your own domain name, with an SSL cert (either one that you buy or a free one from ACM), and it optionally decouples the domain name from the bucket name, so the bucket name no longer needs to match the domain.
Additionally, if your entire site is on CloudFront, you don't necessarily need the uploads.
on the hostname -- the whole site can be behind one hostname, since CloudFront allows you to selectively route to different backends by path patterns.
CloudFront will also tend to optimize upload speeds, since the client will connect to a nearby edge and the rest of the path between client and bucket will be on AWS's managed network, rather than the public Internet.
However, you mentioned the "whitelist of hosts" issue. CloudFront has tens of thousands of IP addresses, so that part of the solution is still a bit lacking. They're public information, but that's a big list.
Still, it's a better case than S3, because AWS doesn't publish the address ranges of S3 separately, like they do with CloudFront.
But if you really don't want to go the CloudFront route, install HAProxy on a little t2.micro instance in EC2, with an Elastic IP, in the same region as the bucket. Configure it as a reverse proxy to S3, install your cert there, and point your hostname at it, and configure the proxy to rewrite the Host:
header back to the bucket name.
This, then, means you have a static IP and your vanity domain. As long as the instance is in the same region as the bucket, the only cost should be the cost of the instance, since you don't pay for bandwidth between EC2 and S3 within the same region.
I've been doing that since before CloudFront offered SNI (although, back then, the instances were m1
) for essentially the same reason... although more recently, I've got one additional reason for doing it this way. The Lua interpreter in HAProxy 1.6 can be leveraged to manipulate the S3 XML error responses by injecting a reference to an XSL stylesheet so that the browser will make them... pretty.