Skip to content

Add AWS Lambda deployment target#87

Open
busla wants to merge 7 commits into
ClickHouse:mainfrom
aproorg:feat/lambda-deploy-target
Open

Add AWS Lambda deployment target#87
busla wants to merge 7 commits into
ClickHouse:mainfrom
aproorg:feat/lambda-deploy-target

Conversation

@busla

@busla busla commented Jun 23, 2026

Copy link
Copy Markdown

What

Adds lambda.ts, a serverless entry point for running the admin panel as a single AWS Lambda. The handler detects the incoming event shape and supports both:

The same Lambda serves both the server routes and the static client assets, so no CDN or S3 bucket is required — the deployed zip is self-contained.

Why

The panel currently ships only the long-running server.ts / Docker deployment. This adds a zero-infrastructure serverless option for teams that prefer to run it as a Lambda.

Usage

bun run build:lambda     # outputs dist/lambda/{index.mjs, client/}

Zip the contents of dist/lambda/ and deploy with handler index.handler on a Node.js runtime. Set the runtime environment variables used by the Docker deployment (SESSION_SECRET, VITE_API_BASE_URL, ADMIN_SSO_*, SESSION_COOKIE_SECURE, VITE_BASE_PATH, etc.). A GET /health route returns 200 ok for health checks.

Changes

  • lambda.ts — the handler:
    • detects ALB (requestContext.elb) vs. payload-2.0 events and replies in the matching format (statusDescription + multiValueHeaders for ALB; headers + cookies[] for HTTP API)
    • builds a Web Request from the event and delegates dynamic routes to the existing fetch handler
    • serves dist/client assets directly (immutable caching, gzip for compressible types, path-traversal guarded)
    • honors VITE_BASE_PATH: serves assets only under the prefix and redirects the bare base path to its trailing-slash form, matching server.ts
    • applies the same security headers as server.ts (CSP report-only/enforced, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, HSTS in production) to text/html responses
  • package.jsonbuild:lambda script bundles handler + client into dist/lambda/.
  • tsconfig.json — excludes lambda.ts (consistent with server.ts; it imports the built server bundle).
  • README.md — documents both deployment paths and their caveats.

Notes

  • Static serving from a Lambda is for simplicity, not a production ideal — in production you would normally front it with a CDN (or S3 + CloudFront) serving dist/client directly. The inline serving keeps the deploy to a single self-contained zip.
  • ALB targets: enable multi-value headers on the target group so multiple Set-Cookie headers survive; ALB caps responses at 1 MB (gzip keeps assets under it).
  • The Prometheus /metrics endpoint is not exposed by the Lambda — pull-model metrics don't fit Lambda's ephemeral instances; use CloudWatch / a push exporter instead.
  • No new runtime dependencies.

Add lambda.ts, a serverless entry point for running the admin panel as a
single AWS Lambda behind a Function URL or API Gateway HTTP API (payload
format 2.0). The handler serves both server routes and the static client
assets itself, so no CDN or S3 bucket is required.

- `build:lambda` bundles the handler + client into `dist/lambda/`
- README documents the serverless deployment path
- `GET /health` returns 200 for load-balancer health checks

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@CLAassistant

CLAassistant commented Jun 23, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Comment thread lambda.ts
Comment thread lambda.ts
Detect the incoming event shape and reply in the matching format:
ELB event (statusDescription + multiValueHeaders) for ALB targets, and
payload format 2.0 (headers + cookies[]) for Function URLs / HTTP API.
Document both deployment paths in the README, including the ALB target
group's multi-value-headers requirement and 1 MB response cap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread lambda.ts
busla and others added 3 commits June 23, 2026 12:45
Mirror server.ts: assets live on disk without the base prefix, so strip
VITE_BASE_PATH before the static lookup while still handing the app the
original request (its router is configured with the base path). Without
this, /<base>/assets/* requests skipped the static branch and 404'd.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…duction-ideal

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread lambda.ts
The pull-model /metrics endpoint is a server.ts feature; in-process counters
don't fit Lambda's ephemeral instances. Narrow the env-var list to the ones
that actually apply and point to CloudWatch for Lambda metrics.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 3 potential issues.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 03c7652. Configure here.

Comment thread lambda.ts
Comment thread lambda.ts
Comment thread lambda.ts
Bring the Lambda handler to parity with the long-running server.ts:

- apply security headers (CSP report-only/enforced, X-Frame-Options,
  X-Content-Type-Options, Referrer-Policy, HSTS in prod) to text/html
  responses
- only serve static assets under VITE_BASE_PATH (not at the unprefixed
  path) when a base path is configured
- redirect the bare base path to its trailing-slash form (302)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants