diff --git a/data/deployments/admin/common.yaml b/data/deployments/admin/common.yaml index b0ffbe3f..0f002480 100644 --- a/data/deployments/admin/common.yaml +++ b/data/deployments/admin/common.yaml @@ -1,17 +1,18 @@ swh::deploy::environment: admin swh::deploy::reverse_proxy::services: - hedgedoc swh::postgresql::shared_buffers: 4GB swh::deploy::hedgedoc::reverse_proxy::backend_http_host: bardo.internal.admin.swh.network swh::deploy::hedgedoc::reverse_proxy::backend_http_port: "3000" +swh::deploy::hedgedoc::reverse_proxy::websocket_support: true swh::deploy::hedgedoc::base_url: hedgedoc.softwareheritage.org swh::deploy::hedgedoc::vhost::letsencrypt_cert: hedgedoc hitch::frontend: "[*]:443" hitch::proxy_support: true varnish::http_port: 80 diff --git a/site-modules/profile/manifests/swh/deploy/reverse_proxy.pp b/site-modules/profile/manifests/swh/deploy/reverse_proxy.pp index 9e2886d4..6242f4a9 100644 --- a/site-modules/profile/manifests/swh/deploy/reverse_proxy.pp +++ b/site-modules/profile/manifests/swh/deploy/reverse_proxy.pp @@ -1,94 +1,99 @@ # Reverse proxy to expose staging services # https://forge.softwareheritage.org/T2747 class profile::swh::deploy::reverse_proxy { include ::profile::hitch include ::profile::varnish $service_names = lookup('swh::deploy::reverse_proxy::services') $varnish_http_port = lookup('varnish::http_port') each($service_names) |$service_name| { # Retrieve certificate name $cert_name = lookup("swh::deploy::${service_name}::vhost::letsencrypt_cert") $backend_http_host = lookup("swh::deploy::${service_name}::reverse_proxy::backend_http_host") $backend_http_port = lookup("swh::deploy::${service_name}::reverse_proxy::backend_http_port") + $websocket_support = lookup({ + "name" => "swh::deploy::${service_name}::reverse_proxy::websocket_support", + "default_value" => false, + }) # Retrieve the list of vhosts $vhosts = lookup('letsencrypt::certificates')[$cert_name]['domains'] if $swh_hostname['fqdn'] in $vhosts { $vhost_name = $swh_hostname['fqdn'] } else { $vhost_name = $vhosts[0] } # Compute aliases, removing the main vhost from the list $vhost_aliases = delete($vhosts, $vhost_name) realize(::Profile::Hitch::Ssl_cert[$cert_name]) ::profile::varnish::vhost {$vhost_name: aliases => $vhost_aliases, backend_name => $service_name, backend_http_host => $backend_http_host, backend_http_port => $backend_http_port, hsts_max_age => lookup('strict_transport_security::max_age'), + websocket_support => $websocket_support, } $icinga_checks_file = lookup('icinga2::exported_checks::filename') # icinga alerts @@::icinga2::object::service {"${service_name} http redirect on ${::fqdn}": service_name => "swh ${service_name} http redirect", import => ['generic-service'], host_name => $::fqdn, check_command => 'http', vars => { http_address => $vhost_name, http_vhost => $vhost_name, http_port => $varnish_http_port, http_uri => '/', }, target => $icinga_checks_file, tag => 'icinga2::exported', } $vhost_ssl_port = lookup('apache::https_port') # $vhost_ssl_protocol = lookup('swh::deploy::webapp::vhost::ssl_protocol') # $vhost_ssl_honorcipherorder = lookup('swh::deploy::webapp::vhost::ssl_honorcipherorder') # $vhost_ssl_cipher = lookup('swh::deploy::webapp::vhost::ssl_cipher') @@::icinga2::object::service {"swh-${service_name} https on ${::fqdn}": service_name => "swh ${service_name}", import => ['generic-service'], host_name => $::fqdn, check_command => 'http', vars => { http_address => $vhost_name, http_vhost => $vhost_name, http_port => $vhost_ssl_port, http_ssl => true, http_sni => true, http_uri => '/', http_onredirect => sticky }, target => $icinga_checks_file, tag => 'icinga2::exported', } @@::icinga2::object::service {"swh-${service_name} https certificate ${::fqdn}": service_name => "swh ${service_name} https certificate", import => ['generic-service'], host_name => $::fqdn, check_command => 'http', vars => { http_address => $vhost_name, http_vhost => $vhost_name, http_port => $vhost_ssl_port, http_ssl => true, http_sni => true, http_certificate => 15, }, target => $icinga_checks_file, tag => 'icinga2::exported', } } } diff --git a/site-modules/profile/manifests/varnish/vhost.pp b/site-modules/profile/manifests/varnish/vhost.pp index 88a96c7d..840f6c49 100644 --- a/site-modules/profile/manifests/varnish/vhost.pp +++ b/site-modules/profile/manifests/varnish/vhost.pp @@ -1,24 +1,25 @@ # Virtual host definition for varnish define profile::varnish::vhost ( String $servername = $title, String $order = '50', Array[String] $aliases = [], String $backend_name, String $backend_http_host, String $backend_http_port, + Boolean $websocket_support = false, Optional[String] $vcl_recv_extra = undef, Optional[String] $vcl_deliver_extra = undef, Variant[Undef, String, Integer[1]] $hsts_max_age = undef, ) { ::profile::varnish::vcl_include {$backend_name: order => '01', content => template('profile/varnish/backend.vcl.erb'), } ::profile::varnish::vcl_include {"vhost_${servername}": order => $order, content => template('profile/varnish/vhost.vcl.erb'), } } diff --git a/site-modules/profile/templates/varnish/vhost.vcl.erb b/site-modules/profile/templates/varnish/vhost.vcl.erb index 505bcc68..73370978 100644 --- a/site-modules/profile/templates/varnish/vhost.vcl.erb +++ b/site-modules/profile/templates/varnish/vhost.vcl.erb @@ -1,44 +1,59 @@ # vhost_<%= @servername %>.vcl # # Settings for the <%= @servername %> vhost # # File managed by puppet. All modifications will be lost. sub vcl_recv { if ( <% @aliases.each do |alias_| -%> req.http.host ~ "^(?i)<%= Regexp.escape(alias_) %>(:[0-9]+)?$" || <% end -%> req.http.host ~ "^(?i)<%= Regexp.escape(@servername) %>(:[0-9]+)?$" ) { if (std.port(server.ip) == <%= scope['::profile::varnish::http_port'] %>) { set req.http.x-redir = "https://" + req.http.host + req.url; return(synth(850, "Moved permanently")); } else { +<% if @websocket_support -%> + if (req.http.upgrade ~ "(?i)websocket") { + return (pipe); + } +<% end -%> + set req.http.X-Forwarded-Proto = "https"; set req.backend_hint = <%= @backend_name %>; } <% if @vcl_recv_extra -%> <%= @vcl_recv_extra %> <% end -%> } } +<% if @websocket_support -%> +sub vcl_pipe { + if (req.http.upgrade) { + set bereq.http.upgrade = req.http.upgrade; + set bereq.http.connection = req.http.connection; + } +} + +<% end -%> <% if @hsts_max_age or @vcl_deliver_extra -%> sub vcl_deliver { if ( <% @aliases.each do |alias_| -%> req.http.host ~ "^(?i)<%= Regexp.escape(alias_) %>(:[0-9]+)?$" || <% end -%> req.http.host ~ "^(?i)<%= Regexp.escape(@servername) %>(:[0-9]+)?$" ) { <% if @hsts_max_age -%> if (std.port(server.ip) != <%= scope['::profile::varnish::http_port'] %>) { set resp.http.Strict-Transport-Security = "max-age=<%= @hsts_max_age %>;"; } <% end -%> <% if @vcl_deliver_extra -%> <%= @vcl_deliver_extra %> <% end -%> } } <% end -%>