- Added new npm scripts for production testing with Content Security Policy: `dev:prod` and `preview:prod`. - Updated README.md to include detailed instructions for development, production testing, and a pre-deployment checklist to ensure security settings are verified before deployment.
58 lines
2.1 KiB
JavaScript
58 lines
2.1 KiB
JavaScript
// Load environment variables from .env file first
|
|
import dotenv from 'dotenv';
|
|
dotenv.config();
|
|
|
|
import express from 'express';
|
|
import compression from 'compression';
|
|
import { handler } from './dist/server/entry.mjs';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
const app = express();
|
|
const PORT = process.env.PORT || 3000;
|
|
|
|
// Enable gzip/brotli compression
|
|
app.use(compression());
|
|
|
|
// Set minimal secure headers for SSR responses
|
|
app.use((req, res, next) => {
|
|
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
|
|
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
|
|
res.setHeader('Cross-Origin-Embedder-Policy', 'credentialless');
|
|
// Gate SSR CSP to avoid breaking inline scripts unless explicitly enabled
|
|
if (process.env.ENABLE_SSR_CSP === '1') {
|
|
res.setHeader(
|
|
'Content-Security-Policy',
|
|
"default-src 'self' https://365devnet.eu https://*.365devnet.eu; " +
|
|
"script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval' https://chat.365devnet.eu; " +
|
|
"style-src 'self' 'unsafe-inline'; " +
|
|
"img-src 'self' data: https: blob:; " +
|
|
"font-src 'self' data:; " +
|
|
"connect-src 'self' https://365devnet.eu https://*.365devnet.eu https://chat.365devnet.eu https://git.365devnet.eu wss://chat.365devnet.eu; " +
|
|
"frame-src 'self' https://chat.365devnet.eu; " +
|
|
"frame-ancestors 'none'; " +
|
|
"base-uri 'self'; " +
|
|
"form-action 'self'"
|
|
);
|
|
}
|
|
next();
|
|
});
|
|
|
|
// Serve static assets from the dist/client directory
|
|
app.use(express.static(path.join(__dirname, 'dist/client')));
|
|
|
|
// Handle all SSR requests with Astro's handler
|
|
app.all('*', handler);
|
|
|
|
app.listen(PORT, () => {
|
|
const isProduction = process.env.NODE_ENV === 'production';
|
|
const domain = isProduction ? '365devnet.eu' : `localhost:${PORT}`;
|
|
const protocol = isProduction ? 'https' : 'http';
|
|
|
|
console.log(`Server running with compression on ${protocol}://${domain}`);
|
|
if (!isProduction) {
|
|
console.log(`Development server accessible at http://localhost:${PORT}`);
|
|
}
|
|
});
|