Skip to content

Run icemap.app on Bun instead of Node + pnpm - #8

Merged
ralyodio merged 3 commits into
masterfrom
bun-runtime
Oct 1, 2026
Merged

ralyodio merged 3 commits into
masterfrom
bun-runtime

Conversation

@ralyodio

@ralyodio ralyodio commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Part of the fleet Node -> Bun migration.

What changes

  • Image (apps/web/Dockerfile, the path dev2's compose builds): deps and build on oven/bun:1.4.0-alpine; runtime is alpine:3.24 with Bun's musl binary copied in, so /api/media/upload keeps exactly the ffmpeg 8.1.2 and ImageMagick 7.1.2 prod runs today (oven/bun:*-alpine is Alpine 3.22 with ffmpeg 6.1; Debian slim doubled the image to 1 GB). Runs bun apps/web/server.js (Next standalone) as uid 1000, adds a HEALTHCHECK, and declares the two NEXT_PUBLIC_* build args dev2 passes (the three Railway-era ones stay declared).
  • Package manager: Bun workspaces replace pnpm-workspace.yaml. bun.lock is migrated from pnpm-lock.yaml, and all 740 package versions match. bunfig.toml uses the hoisted linker so the Socket patch postinstall still finds fast-xml-parser, which it cannot do in Bun's isolated layout. The image installs with --ignore-scripts: socket-patch has no musl build and the image never had .socket/ anyway, bcrypt ships a musl prebuild, and sharp, esbuild and unrs-resolver use platform packages.
  • next.config.ts pins outputFileTracingRoot to the workspace root.
  • CI (new ci.yml): lint, typecheck, bun test, build, boot the standalone server under Bun and render /_next/image (sharp). bun audit runs as a non-blocking job. The first test (src/lib/time.test.ts) is written with node:test.
  • The pre-commit hook and the README now use bun.

Verified from the commit

I built the image from git archive HEAD with a compose file shaped like dev2's (same build args, env_file, 1 GiB limit) and compared it with https://icemap.app:

  • Every page returns 200 with the same title and visible text. Only chunk hashes differ. /api/posts/recent, /api/posts/nearby (PostGIS rpc), /api/donate/coins, the post and comments APIs, /sw.js, /manifest.json and the Supabase storage proxy /api/media/... (including a 206 range request) are byte-identical.
  • /_next/image output is byte-identical for both a public PNG and a storage JPEG, so sharp works under Bun.
  • bcrypt runs on the musl prebuild: hash/compare works, and an admin login with a wrong password takes the same ~0.29 s bcrypt path and returns 401, as it does on prod.
  • The upload route's exact magick and ffmpeg commands run through Bun's child_process.exec and produce 1440x1080 JPEG and H.264 Main 1280x720 + AAC. A 20 MB multipart body is parsed and rejected with 400.
  • Docker health reached healthy, docker stop took 0.5 s, the logs are clean, and the container used 57 MiB at idle. The image is 431 MB, down from 522 MB.

deploy-dev2.yml is untouched.

🤖 Generated with Claude Code

ralyodio and others added 3 commits October 1, 2026 13:09
- Image: oven/bun:1.4.0-slim, `bun apps/web/server.js` (Next standalone),
  same Dockerfile path dev2's compose builds; ffmpeg + ImageMagick 7 from
  Debian for media uploads. Declares the two NEXT_PUBLIC_* build args
  dev2 passes; adds a HEALTHCHECK.
- Bun workspaces replace pnpm-workspace.yaml; bun.lock migrated from
  pnpm-lock.yaml with every version kept. Hoisted linker so the Socket
  patch postinstall still finds fast-xml-parser.
- next.config pins outputFileTracingRoot to the workspace root.
- CI: lint, typecheck, bun test, build, boot the standalone server under
  Bun and render /_next/image (sharp); bun audit (non-blocking).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

ThreatCrush Security Scan

3 finding(s)

HIGH/CRITICAL: 1 | LOW: 2

Severity Rule Location
HIGH js-ssrf-outbound-request apps/web/src/app/api/media/[...path]/route.ts:28
LOW secret-generic-credential packages/supabase/supabase/config.toml:271
LOW secret-generic-credential packages/supabase/supabase/config.toml:303

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit cafd676 into master Oct 1, 2026
5 of 6 checks passed
@ralyodio
ralyodio deleted the bun-runtime branch October 1, 2026 13:17
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.

1 participant