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
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.,
- 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?
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?
@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.
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
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
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?Would be nice to have a cleaner solution for this btw!
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