New to Voyager? Please start here.


HTTP Strict Transport Security (HSTS) is a web security policy mechanism which helps to protect websites against protocol downgrade attacks and cookie hijacking. It allows web servers to declare that web browsers (or other complying user agents) should only interact with it using secure HTTPS connections, and never via the insecure HTTP protocol. HSTS is an IETF standards track protocol and is specified in RFC 6797.

The HSTS Policy is communicated by the server to the user agent via an HTTPS response header field named “Strict-Transport-Security”. HSTS Policy specifies a period of time during which the user agent should only access the server in a secure fashion.

Voyager can insert HSTS headers in http response if configured via following ingress annotations:

  • If false disables HSTS. By default HSTS is enabled.
  • If true enables HSTS preload.
  • If true HSTS rule applies to all of the site’s sub domains.
  • Specifies the time (in seconds) the browser should connect to the server using the HTTPS connection. You can also specify time with units such as “300ms”, “-1.5h” or “2h45m”. Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”. Default value is 15768000 (6 months).

Ingress example

First create a test-server and expose it via service:

$ kubectl run test-server
deployment "test-server" created

$ kubectl expose deployment test-server --type=LoadBalancer --port=80 --target-port=8080
service "test-server" exposed

Then create required tls-certificates:

$ ./onessl-linux-amd64 create ca-cert
Wrote ca certificates in  /home/appscode

$ ./onessl-linux-amd64 create server-cert tls
Wrote server certificates in  /home/appscode

$ kubectl create secret tls tls-secret --key tls.key --cert tls.crt
secret "tls-secret" created

Now create the ingress with HSTS annotations:

$ kubectl apply -f test-ingress.yaml

kind: Ingress
  name: test-ingress
  namespace: default
  annotations: "true" "true" "true" "100"
  - secretName: tls-secret
    - voyager.appscode.test
  - host: voyager.appscode.test
      - path: /foo
          serviceName: test-server
          servicePort: 80

Generated haproxy.cfg:

# HAProxy configuration generated by
	stats socket /tmp/haproxy
	server-state-file global
	server-state-base /var/state/haproxy/
	# log using a syslog socket
	log /dev/log local0 info
	log /dev/log local0 notice
	tune.ssl.default-dh-param 2048
	log global
	option dontlognull
	option http-server-close
	# Timeout values
	timeout client 50s
	timeout client-fin 50s
	timeout connect 50s
	timeout server 50s
	timeout tunnel 50s
	# Configure error files
	# default traffic mode is http
	# mode is overwritten in case of tcp services
	mode http
frontend http-0_0_0_0-80
	bind *:80
	mode http
	option httplog
	option forwardfor
	acl is_proxy_https hdr(X-Forwarded-Proto) https
	acl acl_voyager.appscode.test hdr(host) -i voyager.appscode.test
	acl acl_voyager.appscode.test hdr(host) -i voyager.appscode.test:80
	acl acl_voyager.appscode.test:foo path_beg /foo
	redirect scheme https code 308 if ! is_proxy_https acl_voyager.appscode.test acl_voyager.appscode.test:foo
frontend http-0_0_0_0-443
	bind *:443  ssl no-sslv3 no-tlsv10 no-tls-tickets crt /etc/ssl/private/haproxy/tls/  alpn http/1.1
	# Mark all cookies as secure
	rsprep ^Set-Cookie:\ (.*) Set-Cookie:\ \1;\ Secure
	# Add the HSTS header with a 6 month default max-age
	http-response set-header Strict-Transport-Security max-age=100;\ preload;\ includeSubDomains
	mode http
	option httplog
	option forwardfor
	acl is_proxy_https hdr(X-Forwarded-Proto) https
	acl acl_voyager.appscode.test hdr(host) -i voyager.appscode.test
	acl acl_voyager.appscode.test hdr(host) -i voyager.appscode.test:443
	acl acl_voyager.appscode.test:foo path_beg /foo
	use_backend test-server.default:80 if acl_voyager.appscode.test acl_voyager.appscode.test:foo
backend test-server.default:80
	server pod-test-server-68ddc845cd-tpq7d

Get url for offshoot voyager service:

$ kubectl get service voyager-test-ingress
NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
voyager-test-ingress   LoadBalancer   <pending>     443:32273/TCP,80:31129/TCP   21m

$ minikube service --url voyager-test-ingress

Applying the annotation in ingress will have the following effects, will add the HSTS Header in the response.

$ curl -v -k -H 'Host: voyager.appscode.test'

*   Trying
* Connected to ( port 32273 (#0)
* found 148 certificates in /etc/ssl/certs/ca-certificates.crt
* found 597 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
* 	 server certificate verification SKIPPED
* 	 server certificate status verification SKIPPED
* 	 common name: tls (does not match '')
* 	 server certificate expiration date OK
* 	 server certificate activation date OK
* 	 certificate public key: RSA
* 	 certificate version: #3
* 	 subject: CN=tls
* 	 start date: Tue, 13 Feb 2018 09:14:08 GMT
* 	 expire date: Wed, 13 Feb 2019 09:14:15 GMT
* 	 issuer: CN=ca
* 	 compression: NULL
* ALPN, server accepted to use http/1.1
> GET /foo HTTP/1.1
> Host: voyager.appscode.test
> User-Agent: curl/7.47.0
> Accept: */*
< HTTP/1.1 200 OK
< Date: Tue, 13 Feb 2018 11:42:02 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Server: echoserver
< Strict-Transport-Security: max-age=100; preload; includeSubDomains

Hostname: test-server-68ddc845cd-tpq7d

Pod Information:
	-no pod information available-

Server values:
	server_version=nginx: 1.13.3 - lua: 10008

Request Information:
	real path=/foo

Request Headers:

Request Body:
	-no body in request-

* Connection #0 to host left intact

Take your team where it needs to go.

Create your cluster in minutes. Our team is here to help and would be happy to chat with you.