diff --git a/Dockerfile b/Dockerfile index 91e325c..21ccace 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,6 +20,7 @@ RUN bun run build FROM nginx:alpine-slim AS prod +COPY nginx.conf /etc/nginx/conf.d/default.conf COPY --from=builder /app/builder/dist/watch-list/browser /usr/share/nginx/html EXPOSE 80 diff --git a/angular.json b/angular.json index 91e40c3..0094e88 100644 --- a/angular.json +++ b/angular.json @@ -39,6 +39,14 @@ }, "configurations": { "production": { + "optimization": { + "scripts": true, + "styles": { + "minify": true, + "inlineCritical": false + }, + "fonts": true + }, "budgets": [ { "type": "initial", diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..9bc5bd6 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,31 @@ +# Production server for the Docker image (copied to +# /etc/nginx/conf.d/default.conf in the Dockerfile). +# +# The Content-Security-Policy here must stay in sync with the fallback +# in src/index.html (GitHub Pages cannot send custom HTTP headers, so the meta +# tag is its only enforcement). If the inline theme script in index.html +# changes, recompute its sha256 and update script-src in both places. +# +# Policy notes: +# - img-src allows blob:/data:/https: (IndexedDB posters via object URLs, +# inline SVG placeholder, TMDB/MyAnimeList/AniList CDN posters). +# - connect-src enumerates the API + image origins the app fetches from +# (poster save uses fetch() on image CDN URLs, so those need connect-src). +# - style-src 'unsafe-inline' is required: Angular injects component styles +# at runtime. No external stylesheets are used. +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; form-action 'self'; object-src 'none'; frame-ancestors 'none'; script-src 'self' 'sha256-MEU5LmGgErYBNZ8qIkvEKZWSLfoRWEtbAbW+YA5ToCE='; style-src 'self' 'unsafe-inline'; img-src 'self' blob: data: https:; connect-src 'self' https://api.themoviedb.org https://api.jikan.moe https://graphql.anilist.co https://image.tmdb.org https://cdn.myanimelist.net https://s4.anilist.co; font-src 'self' data:; manifest-src 'self'; worker-src 'self'" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "DENY" always; + add_header Referrer-Policy "no-referrer" always; + + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/src/index.html b/src/index.html index 80ffada..8a153da 100644 --- a/src/index.html +++ b/src/index.html @@ -2,6 +2,15 @@
+ + +