2024-07-24 18:21:03 +05:30
|
|
|
server {
|
2024-08-23 12:56:03 +02:00
|
|
|
listen 80;
|
|
|
|
|
listen [::]:80;
|
|
|
|
|
|
2026-09-13 00:56:23 -04:00
|
|
|
# ── Gitea #95 / #44 — shipped image had no security headers at all.
|
|
|
|
|
# `always` so these are sent on error responses too, not just 200s.
|
|
|
|
|
#
|
|
|
|
|
# Content-Security-Policy, directive by directive:
|
|
|
|
|
# default-src 'self' baseline: same-origin unless a directive below opens it up
|
|
|
|
|
# script-src 'self' 'wasm-unsafe-eval'
|
|
|
|
|
# app code is same-origin only; 'wasm-unsafe-eval' is required
|
|
|
|
|
# for the wasm modules used for E2EE crypto and audio denoise
|
|
|
|
|
# style-src 'self' 'unsafe-inline'
|
|
|
|
|
# vanilla-extract (the app's CSS-in-JS) emits inline <style>,
|
|
|
|
|
# so 'unsafe-inline' is required — no remote stylesheets needed
|
|
|
|
|
# img-src * data: blob: avatars/media/previews come from whichever homeserver or
|
|
|
|
|
# media repo the user points the client at — not knowable
|
|
|
|
|
# ahead of time — plus data: URIs and blob: for local previews
|
|
|
|
|
# media-src * blob: same reasoning as img-src, for audio/video attachments
|
|
|
|
|
# connect-src * the Matrix homeserver is user-chosen at runtime, so this
|
|
|
|
|
# can't be pinned to a fixed origin
|
|
|
|
|
# worker-src 'self' blob: service worker + blob: web workers (crypto/denoise) are
|
|
|
|
|
# same-origin or created from in-memory blobs, never remote
|
|
|
|
|
# frame-src ... the rich link-preview embeds in
|
|
|
|
|
# src/app/utils/videoEmbed.ts, one entry per provider:
|
|
|
|
|
# YouTube, Vimeo, Dailymotion, Streamable, Twitch, Spotify,
|
|
|
|
|
# SoundCloud, Apple Music, Tidal, Mixcloud, Deezer,
|
|
|
|
|
# Instagram, Reddit, Bluesky, Loom, Kick, TikTok, Steam —
|
|
|
|
|
# plus 'self' (no first-party iframes today, cheap to allow)
|
|
|
|
|
# object-src 'none' no <object>/<embed> plugin content is used anywhere
|
|
|
|
|
# base-uri 'self' blocks a <base> tag injection from redirecting relative URLs
|
|
|
|
|
# frame-ancestors 'none' this app must never be framed by another site (clickjacking)
|
|
|
|
|
#
|
|
|
|
|
# Shipped config — verify against chat.lotusguild.org's live headers before
|
|
|
|
|
# enabling this in the production nginx config; this file is currently only
|
|
|
|
|
# exercised by the CI `docker` smoke-test job, not by the live deploy path.
|
|
|
|
|
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src * data: blob:; media-src * blob:; connect-src *; worker-src 'self' blob:; frame-src 'self' https://www.youtube-nocookie.com https://player.vimeo.com https://geo.dailymotion.com https://streamable.com https://clips.twitch.tv https://player.twitch.tv https://open.spotify.com https://w.soundcloud.com https://embed.music.apple.com https://embed.tidal.com https://www.mixcloud.com https://widget.deezer.com https://www.instagram.com https://embed.reddit.com https://embed.bsky.app https://www.loom.com https://player.kick.com https://www.tiktok.com https://store.steampowered.com; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" always;
|
|
|
|
|
add_header Referrer-Policy "no-referrer" always;
|
|
|
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
|
|
|
|
2024-07-24 18:21:03 +05:30
|
|
|
location / {
|
2024-08-23 12:56:03 +02:00
|
|
|
root /usr/share/nginx/html;
|
2024-07-24 18:21:03 +05:30
|
|
|
|
2024-08-23 12:56:03 +02:00
|
|
|
rewrite ^/config.json$ /config.json break;
|
2024-07-24 18:21:03 +05:30
|
|
|
rewrite ^/manifest.json$ /manifest.json break;
|
|
|
|
|
|
2024-09-07 21:45:55 +08:00
|
|
|
rewrite ^/sw.js$ /sw.js break;
|
2024-07-24 18:21:03 +05:30
|
|
|
rewrite ^/pdf.worker.min.js$ /pdf.worker.min.js break;
|
|
|
|
|
|
|
|
|
|
rewrite ^/public/(.*)$ /public/$1 break;
|
|
|
|
|
rewrite ^/assets/(.*)$ /assets/$1 break;
|
|
|
|
|
|
|
|
|
|
rewrite ^(.+)$ /index.html break;
|
2024-08-23 12:56:03 +02:00
|
|
|
}
|
|
|
|
|
}
|