{ pkgs, ... }: let elementWebVersion = "1.11.59"; element-web = pkgs.fetchzip { url = "https://github.com/vector-im/element-web/releases/download/v${elementWebVersion}/element-v${elementWebVersion}.tar.gz"; sha256 = "sha256-iVTd5zWUJh9wkbKMh+5hq0ucQaLLY29w1xCLxDIdQ18="; }; elementWebSecurityHeaders = '' # Configuration best practices # See: https://github.com/vector-im/element-web/tree/develop#configuration-best-practices add_header X-Frame-Options SAMEORIGIN; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; add_header Content-Security-Policy "frame-ancestors 'self'"; add_header Strict-Transport-Security "max-age=63072000" always; ''; in { services.nginx.virtualHosts."element.nekover.se" = { forceSSL = true; enableACME = true; root = pkgs.buildEnv { name = "element-web"; paths = [ element-web ./element-web-config ]; }; listen = [{ addr = "localhost"; port = 8443; ssl = true; extraParameters = ["proxy_protocol"]; }]; # Set no-cache for the version, config and index.html # so that browsers always check for a new copy of Element Web. # NB http://your-domain/ and http://your-domain/? are also covered by this locations."= /index.html" = { extraConfig = elementWebSecurityHeaders + '' add_header Cache-Control "no-cache"; ''; }; locations."= /version" = { extraConfig = elementWebSecurityHeaders + '' add_header Cache-Control "no-cache"; ''; }; # covers config.json and config.hostname.json requests as it is prefix. locations."/config" = { extraConfig = elementWebSecurityHeaders + '' add_header Cache-Control "no-cache"; ''; }; extraConfig = elementWebSecurityHeaders + '' index index.html; # redirect server error pages to the static page /50x.html error_page 500 502 503 504 /50x.html; set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol; ''; }; }