-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathCaddyfile
More file actions
138 lines (121 loc) · 4.56 KB
/
Copy pathCaddyfile
File metadata and controls
138 lines (121 loc) · 4.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
{
admin off
}
:{$PORT:80} {
# Overridable root so the config can be tested locally against ./dist.
root * {$SITE_ROOT:/srv}
# Gzip compression
encode gzip
# Security headers
header {
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
X-XSS-Protection "1; mode=block"
}
# Keep /typedoc/ out of search indexes. A robots.txt Disallow cannot be used
# because it hides the page from crawlers before they can see a noindex.
header /typedoc/* X-Robots-Tag "noindex"
# CORS for *.rivet.dev subdomains to fetch changelog.json
@cors_preflight {
path /changelog.json
method OPTIONS
header_regexp Origin ^https://.*\.rivet\.dev$
}
handle @cors_preflight {
header Access-Control-Allow-Origin {header.Origin}
header Access-Control-Allow-Methods "GET, OPTIONS"
header Access-Control-Allow-Headers "Content-Type"
respond 204
}
@cors_json {
path /changelog.json
header_regexp Origin ^https://.*\.rivet\.dev$
}
header @cors_json Access-Control-Allow-Origin {header.Origin}
# Cache static assets aggressively (Astro outputs to _astro/)
@static {
path /_astro/* *.js *.css *.png *.jpg *.jpeg *.gif *.ico *.svg *.woff *.woff2 *.ttf *.eot
}
header @static Cache-Control "public, max-age=31536000, immutable"
# HTML documents always revalidate. Pages are served at clean URLs (`/`,
# `/docs/`), so matching only *.html left them with no Cache-Control at
# all and browsers heuristically cached them off Last-Modified. After a
# deploy, that stale HTML requests the previous build's hashed chunks,
# which 404. no-cache (rather than no-store) keeps revalidation to cheap
# 304s and lets Astro's hover-prefetch still use the HTTP cache. The
# header directive runs before try_files, so the matcher must cover the
# original directory-style paths, not the rewritten {path}/index.html.
@html {
path *.html */ /
}
header @html Cache-Control "no-cache"
# www -> apex. Railway terminates TLS upstream, so always redirect to https.
# Only takes effect when www.rivet.dev is attached to the Railway service.
@www {
host www.rivet.dev
not path /mcp /mcp/
}
redir @www https://rivet.dev{uri} 301
# The former apex landing route now lives in the docs. Keep this redirect
# host-aware: an unconditional /mcp redirect would intercept the MCP service
# endpoint on mcp.rivet.dev before its reverse-proxy handler runs.
@mcpDocsPage {
not host mcp.rivet.dev
path /mcp /mcp/
}
redir @mcpDocsPage https://rivet.dev/docs/mcp/{http.request.uri.prefixed_query} 301
# mcp.rivet.dev redirects its root to the canonical docs page while the MCP
# server keeps every route it owns, which are proxied to MCP_UPSTREAM. A
# blanket host redirect is not possible: https://mcp.rivet.dev/mcp is the
# endpoint clients connect to. Only takes effect when mcp.rivet.dev is
# attached to the Railway service and MCP_UPSTREAM is set.
@mcpHost host mcp.rivet.dev
handle @mcpHost {
@mcpService path /mcp /mcp/* /.well-known/oauth-protected-resource /health /ready
handle @mcpService {
reverse_proxy {$MCP_UPSTREAM}
}
handle / {
redir https://rivet.dev/docs/mcp/{http.request.uri.prefixed_query} 301
}
# The service routes above are the only content this host serves; the rest
# of the site keeps one canonical home.
handle {
redir https://rivet.dev{uri} 301
}
}
# Real HTTP 301s for legacy/moved URLs. Generated from redirects.mjs by
# scripts/generate-caddy-redirects.mjs. The import path resolves relative to
# this Caddyfile, so it works both locally and in-container.
import redirects.caddy
# /path -> /path/ only when the directory index actually exists. File-like
# paths (/llms.txt, /rss/feed.xml, assets) never match, and unknown paths
# fall through to a clean 404 instead of a 301 -> 404 chain.
@needsSlash {
not path */
not path /health
file {path}/index.html
}
redir @needsSlash {path}/{http.request.uri.prefixed_query} 301
# Health check endpoint
handle /health {
respond "healthy" 200
}
# Main site handler - Astro static export with directory index
handle {
try_files {path} {path}/ {path}/index.html
file_server
}
# Custom 404 page
handle_errors {
# The immutable header set for @static paths has already been applied
# to the response by the time file_server errors, so without this
# override a 404 for a hashed asset is cached for a year by the CDN
# and by browsers. Anyone who caught such a 404 during a deploy window
# then replays it forever, and island hydration (header, footer) dies
# on the failed import. Error responses must never be cached.
header Cache-Control "no-store"
rewrite * /404.html
file_server
}
}