Relayd and headers

Because httpd can't manage headers itself, you can put relayd "before" httpd. It helps add headers or modify others.

As you can guess, relayd is included in base installation.

Visit this link to test your website headers.

Relayd configuration

Edit /etc/relayd.conf to configure relayd. Inside, add the following lines as example :

http protocol "http" {
  match request header remove "Proxy"
  match response header set "X-Xss-Protection" value "1; mode=block"
  return error
  pass
}
relay "www" {
  listen on 192.0.2.2 port 80
  protocol "http"
  forward to 127.0.0.1 port 80
}

Those lines means :

That's why you must edit httpd configuration accodingly :

# httpd's configuration
listen on localhost port 80

To sum up, things goes like this now :

1. A client ask to see your website and knocks at port 80.

2. relayd modify a few headers and redirect to httpd which still serve the website.

Dont forget to reload relayd and httpd:

# rcctl enable relayd
# rcctl restart httpd
# rcctl start relayd

Notice logs will show incoming connections from 127.0.0.1 (relayd local address). You may want to use "forwarded" log format for httpd :

log style forwarded

You can find a configuration example at the end of this documentation.

TLS / https

Find below an example to add TLS support to relayd. There are a few things to take care of about certificates and keys.

http protocol "https" {
  match request header remove "Proxy"
  match response header set "X-Xss-Protection" value "1; mode=block"
  return error
  pass
  tls keypair athome.tld
  tls keypair here.tld
}
relay "tlsforward" {
  listen on 192.0.2.2 port 443 tls
  protocol "https"
  forward with tls to 127.0.0.1 port 443
}

Look at the lines starting with "tls keypair". They define the certificate and keys to use for TLS. In the above example, two certificates for two different domains are used, you can add as much as you have certificates to use.

However, thos certificates MUST be stored with the appropriate filename in the correct location :

/etc/ssl/private/athome.tld.key
/etc/ssl/athome.tld.crt

Make sure /etc/ssl/athome.tld.crt is the "full chain".

This means you should have such configuration in acme-client configuration :

domain athome.tld {
    domain key "/etc/ssl/private/athome.tld.key"
    domain certificate "/etc/ssl/athome.tld-cert.crt"
    domain chain certificate "/etc/ssl/athome.tld-chain.crt"
    domain full chain certificate "/etc/ssl/athome.tld.crt"
    sign with letsencrypt
}

This way, relayd will automatically pick up the right certificate.

Renew certificates

Remember to reload relayd after certificate renewal :

/usr/sbin/acme-client -v athome.tld && \
    /usr/sbin/rcctl reload relayd

IPv6

If you want to add ipv6 support with relayd, it is obviously possible.

First, make sure you set the local address in "/etc/hosts" :

127.0.0.1 localhost
::1 localhost

You can now use "localhost" to refer to both ipv4 or ipv6 local depending on context.

Now add two entries in relayd configuration:

relay "http" {
        listen on $ext_ip4 port 80
        protocol "http"
        forward to 127.0.0.1 port 80
}
relay "http6" {
        listen on $ext_ip6 port 80
        protocol "http"
        forward to ::1 port 80
}

httpd's configuration will make use of "localhost" so it's simpler :

listen on localhost port 80

Deal with headers

Security headers

You can set a few headers to improve your website security. It's mostly useful if you host huge webapps, not really for static websites.

match request header remove "Proxy"
match response header set "X-Xss-Protection" value "1; mode=block"
match response header set "Frame-Options" value "SAMEORIGIN"
match response header set "X-Frame-Options" value "SAMEORIGIN"
match response header set "X-Robots-Tag" value "index,nofollow"
match response header set "X-Permitted-Cross-Domain-Policies" value "none"
match response header set "X-Download-Options" value "noopen"
match response header set "X-Content-Type-Options" value "nosniff"
match response header set "Permissions-Policy" value "interest-cohort=()"

If you only host one domain, add :

match response header set "Access-Control-Allow-Origin" value "athome.tld"

Learn more

Optimize client cache and bandwidth usage

You should consider to tune up th amount of request a client should make each time he checks on your website. As example, you can specify to keep in cache files such as pictures, stylesheets or fonts for a few days before asking again.

In "protocol" section, just before "pass" keyword, add :

match request path "/*.css" tag "CACHE"
match request path "/*.js" tag "CACHE"
match request path "/*.atom" tag "CACHE"
match request path "/*.rss" tag "CACHE"
match request path "/*.xml" tag "CACHE"
match request path "/*.jpg" tag "CACHE"
match request path "/*.png" tag "CACHE"
match request path "/*.svg" tag "CACHE"
match request path "/*.gif" tag "CACHE"
match request path "/*.ico" tag "CACHE"
match response tagged "CACHE" header set "Cache-Control" value "max-age=1814400"

Everytime a client ask for a file ending with ".css" or ".js" or ".atom" (...), relayd tag the resquest with "CACHE". At last we add a header to increase cache to 21 days to requests with this tag.

Set default encoding

Following the same scheme, you can specify the default encoding according to file extension :

match request path "/*.html" tag "UTF8"
match request path "*/" tag "UTF8"
match response tagged "UTF8" header set "Content-Type" value "text/html;charset=UTF-8"

About tags

Understand you can't set multiple tags at once. If you want to apply the two above headers (cache-control and content-type), you must do it separately since relayd configuration is processed in order :

match request path "/*.html" tag "CACHE"
match response tagged "CACHE" header set "Cache-Control" value "max-age=1814400"
match request path "/*.html" tag "UTF8"
match response tagged "UTF8" header set "Content-Type" value "text/html;charset=UTF-8"