WIP roles for easy selfhosting based on ansible
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
southerntofu be3a0c1212 Better TLS handling 2 weeks ago
files Better TLS handling 2 weeks ago
handlers webserver: lint 3 months ago
tasks Better TLS handling 2 weeks ago
README.md Fix docs links 6 months ago



This service role configures a certain number of vhosts for a webserver. Features include:

  • integrated TLS/.onion support
  • IPv4/IPv6 support
  • multiple profiles (static, proxy)


This role will configure some vhosts, defined in:

  • vhosts variable, when called by another role
  • webserver.vhosts variable, when not called by another role (vhosts is empty)
  • vhost profiles within webserver variable, when not called by another role (vhosts is empty) ; reserved keywords for profile names are settings and vhosts

A vhost consists of the following arguments:

  • host: the fully qualified domain name to serve the virutalhost with
  • template: the type of vhost to configure, when not determined by a vhost profile (default: static)
  • (optional) aliases: a list of fully qualified domain namesto redirect to the host virtualhost ; in the special case that the vhost is the main server's hostname, aliases are also enabled for www. on each alias as well as www. for the hostname
  • (optional) tls: true/false to enable or disable TLS support on this vhost (default: true, unless webserver.settings.tls is false)
  • (optional) tor: true/false to enable or diable Tor .onion support on this vhost (default: true, unless webserver.settings.tor is false)
  • (optional) git: a git repository for the website source, to update automatically when the recipe is applied (submodules are supported) ; what is done with this source depends on the vhost profile

Additionally, each vhost profile may support additional settings. Please refer to the Profiles section for information on that.

Warning: When called from a profile shorthand, the vhost's template is empty, and the global variable template is used instead. TODO: Maybe we'd like to use template (or even profile) in both cases to avoid confusion?


vhost profiles are a quick way to support different kind of use-cases from a single role, as explained in the project's README. In the webserver role, some profiles are already included. They are described below, along with their specific settings:

  • static: serves a static website from a given source
    • (optional) root: a local folder for the website source (conflics with: git)
    • (optional) command: a shell command to execute from the source directory (whether root or git) ; if command is defined, files from source are only copied after that command has been run
    • (optional) default_route: the route to take when URI was not found, which will produce a 404 if not found itself, eg. /index.html for single-page applications
  • proxy: serves a simple reverse proxy to another webserver/vhost
    • to: the complete URL (including http:// or https://) to the backend server
  • zola: serves a website built with zola static-site generator

In the future, we would like to support additional profiles. In particular, contributions/patches are welcome for:

  • php profile, with configurable permissions/plugins
  • wordpress profile, with out-of-the-box caching support


Subprofiles are a special kind of profile. They enable to configure specific routes within an existing vhost, by receiving an additional route argument where the profile will be applied. route starts with a / but doesn't end with one. By convention, subprofiles are simple profiles prefixed with sub_. For example, a reverse proxy subprofile is available as sub_proxy.

Let's take an example. Reverse-proxying routes for BOSH/websocket support for the jabberserver role are defined with sub_bosh_proxy and sub_websocket_proxy profiles. The automatic configuration for a jabberserver vhost for joinjabber.org is equivalent to the following manual configuration:

    - host: "joinjabber.org"
      template: "zola"
      source: "https://codeberg.org/joinjabber/website"
    - host: "joinjabber.org"
      template: "sub_bosh_proxy"
      route: "/http-bind"
      to: "http://localhost:5280/http-bind"
    - host: "joinjabber.org"
      template: "sub_websocket_proxy"
      route: "/xmpp-websocket"
      to: "http://localhost:5280/xmpp-websocket"

Make your own profile

If you want to make your own profile, it's very easy. You simply need to create a roles/webserver/tasks/templates/foo.yml file containing Ansible instructions. If most cases, you also need to create a related template in roles/webserver/files/foo.conf file, to place in /etc/nginx/sites-enabled/ folder.

If your profile should be extensible by subprofiles, for example to serve a reverse proxy on a specific route, don't forget to include /etc/nginx/conf.d/{{ item.host }}/*.conf before your location blocks. That additional configuration folder is automatically created for you and you are free to use it or not in your profiles.

If you are making a subprofile to extend an existing profile, your profile task should create additional configuration files in /etc/nginx/conf.d/HOSTNAME/ folder, so that the main profile configuration file picks them up when starting the webserver.


The webserver role settings are defined in the configuration file, under the webserver.settings key. The following settings are available:

  • (optional) tls: whether to enable TLS by default on vhosts (default: true)
  • TODO: (optional) tor: whether to enable Tor onion services by default on vhosts (default: true)
  • TODO: (optional) http2: whether to enable HTTP2 by default on vhosts (default: true)
  • TODO: (optional): ciphers: the default cipher suite for vhosts TLS configuration


In order to interface with other roles/services, this role follows a certain number of conventions:

  • TLS certificate is generated by a tls role following a documented interface ; generated certificates are found in /etc/letsencrypt/live/HOSTNAME/{fullchain,privkey}.pem
  • Tor onion service is generated by a tor role following a documented interface ; generated hostname is found in /var/lib/tor/HOSTNAME/hostname
  • webroot of the vhost is always /var/www/HOSTNAME/, so other roles can place files in the webroot directly there (for example ACME challenges or a PGP Web Key Directory)
  • the webroot folder is not deleted automatically by any process ; if that is a concern, some garbage collection should be organized
  • when the vhost configured is the main hostname, aliases for www.hostname and www.alias (for all aliases) is automatically configured as well