I am trying to send HTTP response headers from Apache on an Amazon Linux 2 AMI EC2 instance. I had originally tried to do this in httpd.conf and tried a few variations...


Header always set X-Frame-Options "SAMEORIGIN"

But the header is not set. So I figured maybe they're reset somewhere down the line, but at least .htaccess should be able to set them, so I tried a couple of variations...


Header set ApacheFoo ApacheBar
Header add Strict-Transport-Security "max-age=31104000; includeSubdomains"

But again, neither of these headers are set.

However, if I use PHP to set the headers, it works fine...


header("phpfoo: phpbar");
die(print_r(headers_list(), 1));

I have the phpfoo: phpbar header showing up in Chrome's DevTools, but none of the ones set directly in Apache have been set.

The .htaccess solution works fine on my own local Windows+Apache setup, but not on AWS, so I'm assuming the issue is specific to it and am wondering if there are any quirks specific to this platform that I need to know about?

More info

Headers module is definitely loaded. If I run sudo httpd -S (I have to use sudo to run this command or there is a permission issue to do with accessing a .pem file required for SSL, Apache starts fine so I assume this is not an issue if imbued with its permissions), this is the output (host specific info replaced with asterisks):

VirtualHost configuration:
*:80                   *.com (/etc/httpd/conf/httpd.conf:44)
*:443                  is a NameVirtualHost
         default server ip-*-*-*-*.us-east-2.compute.internal (/etc/httpd/conf.d/ssl.conf:56)
         port 443 namevhost ip-*-*-*-*.us-east-2.compute.internal (/etc/httpd/conf.d/ssl.conf:56)
         port 443 namevhost *.com (/etc/httpd/conf/httpd-le-ssl.conf:2)
                 alias www.*.com
ServerRoot: "/etc/httpd"
Main DocumentRoot: "/var/www/html"
Main ErrorLog: "/etc/httpd/logs/error_log"
Mutex authdigest-opaque: using_defaults
Mutex watchdog-callback: using_defaults
Mutex proxy-balancer-shm: using_defaults
Mutex rewrite-map: using_defaults
Mutex ssl-stapling-refresh: using_defaults
Mutex authdigest-client: using_defaults
Mutex lua-ivm-shm: using_defaults
Mutex ssl-stapling: using_defaults
Mutex proxy: using_defaults
Mutex authn-socache: using_defaults
Mutex ssl-cache: using_defaults
Mutex default: dir="/run/httpd/" mechanism=default
Mutex mpm-accept: using_defaults
Mutex cache-socache: using_defaults
PidFile: "/run/httpd/httpd.pid"
User: name="apache" id=48
Group: name="apache" id=48
  • I have tested this on web hosting provided by SiteGround and it works fine. The issue is clearly specific to AWS. I'm really disappointed that amidst all the complexity of the service, something so simple and necessary in providing a secure web service seems simply impossible to do. – Deji Sep 7 '18 at 21:22
  • Do you have another AWS service sitting in front of your EC2 instance (CloudFront, Load Balancer, etc.). I have had zero problems setting up HTTPS, HTTP/2, etc. on AWS. Look into your Apache configuration. Everything starts with a correct SSL implementation and you don't have one. Fix that first. – John Hanley Sep 9 '18 at 17:41
  • @JohnHanley I had no problems in setting up the things you mentioned either. Everything was running fine on Amazon Linux 2, SSL, HTTP/2, etc., just not the Apache headers module - almost as if it was specifically blocked on that instance. There was nothing wrong with the SSL implementation. As I say in my reply, using a different instance (Ubuntu), everything works fine, including Apache headers. So nothing is wrong with AWS, just Amazon Linux 2 (or perhaps just the particular instance I was running, but I'd find that hard to understand). I'm guessing you were not not running Amazon Linux 2? – Deji Sep 9 '18 at 20:11
  • Yes, I use both Amazon Linux and Amazon Linux 2 - except for Amazon EMR, I only use Amazon Linux 2 these days. You are using AWS EC2 domain names in your SSL configuration. There is no way that you have an SSL certificate that ends in us-east-2.compute.internal. Until you have a correct SSL configuration .... – John Hanley Sep 9 '18 at 20:34
  • @JohnHanley What? That is not the domain name nor the SSL certificate, that's the private DNS, the internal hostname that is on every instance and never changes... the SSL certificate was via LetsEncrypt, completely irrelevant to that address. – Deji Sep 9 '18 at 22:09

My best and only answer so far is: give up on Amazon Linux 2.

After trying and failing to set up an Nginx reverse proxy on it in the hopes it could set the headers and work around the issue (Amazon Linux 2 seems to lack the required make utilities to build mod_rpaf - this was the final straw), I created a new instance using Ubuntu and started a lengthy process of setting everything I had set up on Amazon Linux 2, however it was relatively easier and less confusing on Ubuntu and there were a lot more helpful tutorials to work with in general.

In the end I ended up being able to add Nginx into the stack as a bonus, having it reverse proxy to Apache, and there's now no issue setting headers in Apache at all.

To others having this problem, or considering using AWS to run an Apache web server, my advice from this experience is: do not use Amazon Linux 2!

Not only does setting headers from Apache simply not seem to work (which is key to enabling some modern security features that don't depend on PHP working all the time), but in general everything is much easier and more flexible using an Ubuntu build. There aren't good AWS docs for the Ubuntu build, but the rest of the internet has you covered and you can apply the AWS-specific parts (security groups, elastic IP and route 53) of the Amazon Linux 2 tutorial to it.

  • Amazon Linux 2 seems to have stopped .htaccess from working, also. Hmm. There must be another way around this. – Django Reinhardt Jun 12 '20 at 0:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.