W
Wasp2d ago
Zuck

CSP Header Issue with Railway Deployment - Need Help with blob: URLs

Hey Wasp team! I'm deploying to Railway using wasp deploy railway and running into a Content-Security-Policy issue. Problem: • When users drag/drop images into my canvas app, browser creates blob: URLs • Railway's edge proxy serves the client with a default CSP that blocks blob: URLs • Error: Refused to load the image 'blob:https://...' because it violates the following Content Security Policy directive: "img-src 'self' data: https: *" What I've discovered: • Railway deploys the client from .wasp/build/web-app/build as static files • It uses Caddy web server with a default Caddyfile • The server CSP middleware in serverSetup.ts only applies to API routes, not the client HTML What I'm trying: • Created a custom Caddyfile with the correct CSP header (including blob: in img-src) • Copied it to public/Caddyfile so it gets included in the build output • Railway should detect and use it instead of generating a default one Questions: 1. Is there an official/recommended way to customize HTTP headers for the Railway client deployment? 2. Should the server's CSP middleware also apply to serving the client HTML, or is separating them expected? 3. Any best practices for handling blob: URLs with Wasp + Railway? The custom Caddyfile approach seems to work based on Railway's build logs, but wondering if there's a cleaner solution I'm missing! Thanks! 🐝
5 Replies
kapa.ai
kapa.ai2d ago
Hi @Zuck. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Great questions! Here’s what the Wasp documentation and related sources say regarding your situation: 1. Is there an official/recommended way to customize HTTP headers for the Railway client deployment? There is no official Wasp documentation describing a built-in or recommended way to customize HTTP headers (like CSP) for the static client deployment on Railway. The docs focus on deploying the client as static files, typically using gostatic or similar, and do not mention customizing HTTP headers or Caddyfile for the client. The server-side middleware configuration (e.g., for CSP) only applies to API routes handled by the Express server, not to static client files served by Railway’s static hosting or Caddy/gostatic containers. Your approach of providing a custom Caddyfile is not documented in the official Wasp guides, but if Railway’s build system picks it up, it’s a valid workaround based on Railway’s own behavior, not Wasp’s deployment process itselfDeploying the Client. 2. Should the server's CSP middleware also apply to serving the client HTML, or is separating them expected? Separation is expected. Wasp’s middleware configuration (including CSP via Helmet) is applied to the Express server, which handles API routes and server-side logic. The static client (frontend) is served separately—often by a static file server or container (like gostatic or Caddy)—and is not affected by the server’s middleware. This is by design and is reflected in the deployment guides, which treat server and client as separate deployable units with their own environments and configurationsConfiguring Middleware. 3. Any best practices for handling blob: URLs with Wasp + Railway? There are no Wasp-specific best practices documented for handling blob: URLs in CSP for Railway deployments. The issue you’re facing is a result of the static file server’s default CSP, not Wasp itself. The best practice in this context is to ensure your static file server (Caddy, gostatic, etc.) is configured to allow blob: in the relevant CSP directives (e.g., img-src). Your approach of providing a custom Caddyfile is appropriate given the current tooling and deployment flow. If you automate client deployment (as in the provided shell script), you may want to ensure your custom Caddyfile is copied into the build output each time, since .wasp/build/web-app is regenerated on each buildDeploying the Client. --- Summary:
- There’s no official Wasp mechanism for customizing HTTP headers for the static client on Railway; your Caddyfile workaround is valid. - Server middleware (CSP) only affects API routes, not static client files—separation is expected. - For blob: URLs, ensure your static file server’s CSP allows them; your current approach is the best available given the docs. If you’d like to see more streamlined support for this in Wasp, consider opening a feature request or sharing your solution with the community! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @Zuck, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
Zuck
ZuckOP2d ago
@kapa.ai SOLUTION: Custom Caddyfile for Railway Deployment Problem: Railway's default CSP blocks blob: URLs needed for drag/drop image handling. Fix: Create a custom Caddyfile that Railway will use instead of its default. Step 1: Create public/Caddyfile in your Wasp project root: caddyfile :{$PORT} { root * /app file_server # Set Content-Security-Policy header with blob: support for drag/drop images header { Content-Security-Policy "default-src 'self'; img-src 'self' data: https: blob: *; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; font-src 'self' data: https:; connect-src 'self' https: wss: ws:; frame-src 'self' https:; media-src 'self' https: blob:; object-src 'none'; base-uri 'self'; form-action 'self';" X-Content-Type-Options "nosniff" X-Frame-Options "SAMEORIGIN" Referrer-Policy "strict-origin-when-cross-origin" } encode gzip try_files {path} /index.html } Step 2: Deploy normally: bash wasp deploy railway deploy <your-project-name> Why this works: • Wasp copies public/ contents to the build output • Railway detects the custom Caddyfile and uses it instead of generating a default • The CSP header now includes blob: in img-src and media-src Verify: Check the client build logs for ↳ Using custom Caddyfile: Caddyfile ────────────────────────────────────────── root cause: Railway uses Caddy to serve the client as static files, and its default CSP doesn't include blob: support. The server's CSP middleware in serverSetup.ts only applies to API routes, not the client HTML.
kapa.ai
kapa.ai2d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Your solution—using a custom Caddyfile to set the Content-Security-Policy (CSP) for Railway static client deployments—is a practical and effective workaround, given the current state of Wasp and Railway integration. Key points confirmed by the knowledge sources: - Wasp copies the contents of the public/ directory into the build output for the client, which means placing a Caddyfile there will include it in the deployed static files. This aligns with your approach and is supported by the deployment process described in the docsDeploying the Client. - Railway uses a static file server (like Caddy or gostatic) to serve the client build. The CSP headers set by the Express server (via middleware in serverSetup.ts) only apply to API routes, not to the static client HTML. This separation is expected and documentedConfiguring Middleware. - There is no official Wasp mechanism for customizing HTTP headers for the static client deployment on Railway. Your method of providing a custom Caddyfile is not documented as an official feature, but it is a valid and effective solution given how Railway handles static hosting. Summary:
Your solution is correct and aligns with the current Wasp and Railway deployment flow. Placing a custom Caddyfile in the public/ directory ensures that Railway uses your specified CSP, including blob: support for drag-and-drop images. This is the best available approach based on the official documentation and community discussions. If you want to automate this further, ensure your deployment scripts always copy the Caddyfile into the correct location after each build, since .wasp/build/web-app is regenerated on every buildDeploying the Client. If you’d like to see more streamlined support for this in Wasp, consider opening a feature request or sharing your solution with the community! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @Zuck, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
Zuck
ZuckOP2d ago
Would be nice to have a cleaner solution for this btw!
Filip
Filip2d ago
Hey @Zuck, this was a very clever solution but it does have a problem: You're exposing your Caddyfile for anyone on the web to see, which is a security concern. It's not a huge problem but it's always best not to expose internal code to strangers 🙂 The problem you encountered is, at its core: How do I get railway to accept blob URLs when deploying a static site? I suggest you go to Railway's discord and find this out, no need to mention Wasp or anything - it's a general problem and they will understand it immediately. I've read the docs and can't think of anything better than what you did. Once you know "the way" to serve blobs with railway, come back here and I'll see how we can make Wasp play along with that

Did you find this page helpful?