# this sample config gives you a feel for how h2o can be used # and a high-security configuration for TLS and HTTP headers # see https://h2o.examp1e.net/ for detailed documentation # and h2o --help for command-line options and settings user: www pid-file: /var/run/h2o.pid # log normal access to file access-log: /var/log/h2o/access.log # send errors to syslog error-log: "| logger -i -p daemon.err -t h2o" # as of 2017-12-01 the following TLS config and headers, with # DNS CAA records and custom diffie-hellmann parameters via # `openssl dhparam -out %%PREFIX%%/etc/ssl/dhparam.pem 4096` # will get you: # A+ on https://www.ssllabs.com/ssltest/ listen: 80 listen: port: 443 ssl: # using at least TLS1.2 restricts many older devices minimum-version: TLSv1.1 dh-file: %%PREFIX%%/etc/ssl/dhparam.pem # generate your own certificates with security/acme-client certificate-file: %%PREFIX%%/etc/ssl/acme/example.org/fullchain.pem key-file: %%PREFIX%%/etc/ssl/acme/private/example.org/privkey.pem cipher-preference: server cipher-suite: ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS # A+ on https://securityheaders.io/ header.set: "x-frame-options: deny" header.set: "X-XSS-Protection: 1; mode=block" header.set: "X-Content-Type-Options: nosniff" header.set: "X-UA-Compatible: IE=Edge" header.set: "Referrer-Policy: strict-origin" header.set: "Cache-Control: no-transform" header.set: "Content-Security-Policy: default-src https:" # 6 months HSTS pinning header.set: "Strict-Transport-Security: max-age=16000000" # limit POST bodies limit-request-body: 10485760 # 10MiB file.mime.addtypes: text/plain: .log text/css: .css application/atom+xml: .xml "text/html; charset=utf-8": .html # per-host configurations hosts: # a basic fileserver www.example.org: # enable Apache-style directory listings file.dirlisting: on file.send-gzip: on paths: "/": file.dir: "/var/www/www.example.org" # a simple permanent URL redirect "/blog": redirect: status: 301 url: https://blog.example.org/ # a password-restricted url "/server-status": mruby.handler: | require "htpasswd.rb" Htpasswd.new("%%ETCDIR%%/private/htpasswd", "example.org") status: ON # redireect Lets Encrypt ACME protocol to a specific challenge directory "/.well-known/acme-challenge": file.dir: "/var/www/acme" # virtual directory layout to support serving FreeBSD packages built by poudriere pkg.example.org: paths: "/poudriere": file.dir: "%%PREFIX%%/poudriere/data/logs/bulk" "/FreeBSD:10:amd64": file.dir: "%%PREFIX%%/poudriere/data/packages/10_amd64-default/" "/FreeBSD:11:amd64": file.dir: "%%PREFIX%%/poudriere/data/packages/11_amd64-default/" # a simple ruby-powered embedded JSON API api.example.net: paths: "/ok.json": mruby.handler: | Proc.new do |env| [200, {'content-type' => 'application/json'}, ['{"status":"ok"}']] end # a websockets-aware reverse proxy ws.example.net: paths: "/": proxy.websocket: ON proxy.reverse.url: "http://localhost:1080/"