95 lines
3.8 KiB
Nix
95 lines
3.8 KiB
Nix
{ config, pkgs, ... }:
|
|
|
|
let
|
|
elementAdminVersion = "0.1.10";
|
|
elementAdmin = pkgs.stdenv.mkDerivation (finalAttrs: {
|
|
pname = "element-admin";
|
|
version = elementAdminVersion;
|
|
|
|
src = pkgs.fetchzip {
|
|
url = "https://github.com/element-hq/element-admin/archive/refs/tags/v${elementAdminVersion}.zip";
|
|
sha256 = "sha256-dh7tmzAaTfKB9FuOVhLHpOIsTZK1qMvNq16HeObHOqI=";
|
|
};
|
|
|
|
nativeBuildInputs = [
|
|
pkgs.nodejs
|
|
pkgs.pnpm.configHook
|
|
];
|
|
|
|
pnpmDeps = pkgs.pnpm.fetchDeps {
|
|
inherit (finalAttrs) pname version src;
|
|
fetcherVersion = 2;
|
|
hash = "sha256-S/MdfUv6q+PaAKWYHxVY80BcpL81dOfpPVhNxEPQVE4=";
|
|
};
|
|
|
|
buildPhase = ''
|
|
pnpm build
|
|
'';
|
|
|
|
installPhase = ''
|
|
cp -a dist $out
|
|
'';
|
|
});
|
|
in
|
|
{
|
|
services.nginx.virtualHosts."element-admin.nekover.se" = {
|
|
forceSSL = true;
|
|
enableACME = true;
|
|
|
|
listen = [{
|
|
addr = "localhost";
|
|
port = 8443;
|
|
ssl = true;
|
|
extraParameters = ["proxy_protocol"];
|
|
}];
|
|
|
|
root = elementAdmin;
|
|
|
|
locations."/assets" = {
|
|
extraConfig = ''
|
|
expires 1y;
|
|
add_header Cache-Control "public, max-age=31536000, immutable";
|
|
# Security headers.
|
|
add_header X-Frame-Options "DENY" always;
|
|
add_header X-XSS-Protection "1; mode=block" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' blob: data:; font-src 'self'; connect-src *; object-src 'none'; media-src 'self'; child-src 'none'; worker-src 'self'; manifest-src 'self';" always;
|
|
add_header Permissions-Policy "geolocation=(), camera=(), microphone=(), payment=(), usb=(), magnetometer=(), accelerometer=(), gyroscope=()" always;
|
|
'';
|
|
};
|
|
|
|
locations."/" = {
|
|
index = "/index.html";
|
|
tryFiles = "$uri $uri/ /";
|
|
extraConfig = ''
|
|
# Security headers.
|
|
add_header X-Frame-Options "DENY" always;
|
|
add_header X-XSS-Protection "1; mode=block" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' blob: data:; font-src 'self'; connect-src *; object-src 'none'; media-src 'self'; child-src 'none'; worker-src 'self'; manifest-src 'self';" always;
|
|
add_header Permissions-Policy "geolocation=(), camera=(), microphone=(), payment=(), usb=(), magnetometer=(), accelerometer=(), gyroscope=()" always;
|
|
'';
|
|
};
|
|
|
|
extraConfig = ''
|
|
# Security headers.
|
|
add_header X-Frame-Options "DENY" always;
|
|
add_header X-XSS-Protection "1; mode=block" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' blob: data:; font-src 'self'; connect-src *; object-src 'none'; media-src 'self'; child-src 'none'; worker-src 'self'; manifest-src 'self';" always;
|
|
add_header Permissions-Policy "geolocation=(), camera=(), microphone=(), payment=(), usb=(), magnetometer=(), accelerometer=(), gyroscope=()" always;
|
|
|
|
# Make use of the ngx_http_realip_module to set the $remote_addr and
|
|
# $remote_port to the client address and client port, when using proxy
|
|
# protocol.
|
|
# First set our proxy protocol proxy as trusted.
|
|
set_real_ip_from 127.0.0.1;
|
|
# Then tell the realip_module to get the addreses from the proxy protocol
|
|
# header.
|
|
real_ip_header proxy_protocol;
|
|
'';
|
|
};
|
|
}
|