Deploying Bun Applications
This comprehensive guide covers everything you need to know about deploying Bun applications via Deploy with Git, from simple Elysia APIs to complex applications using Hono, or even Node.js-compatible frameworks running on Bun.
Overview
Deploy with Git automatically detects Bun applications by looking for:
bun.lockbfile (Bun's binary lockfile)bunfig.toml(Bun configuration file).bun-versionfor version specification (optional)
Basic Bun Deployment
Simple Elysia API
docker run -d \
--name elysia-api \
-e GIT_REPO_URL=https://github.com/your-username/elysia-api \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest
What Happens Automatically
- Detection: Finds
bun.lockborbunfig.tomland identifies as Bun project - Version Selection:
- Checks
BUN_VERSIONenvironment variable - Checks
.bun-versionfile - Checks
engines.bunin package.json - Falls back to latest Bun version
- Checks
- Runtime Installation:
- Downloads official Bun binary from bun.sh
- Installs to
/opt/flux-tools/bun - Sets up PATH environment variables
- Dependencies: Runs
bun install - Build: Runs
bun run buildif build script exists (optional - Bun runs TypeScript natively!) - Start: Executes
bun run startor detected entry point
Framework-Specific Guides
Elysia Framework
Elysia is a Bun-native web framework designed for ergonomics and performance. Deploy with Git automatically detects and optimizes Elysia applications:
docker run -d \
--name elysia-rest-api \
-e GIT_REPO_URL=https://github.com/your-username/elysia-api \
-e APP_PORT=3000 \
-e BUN_VERSION=1.0.25 \
-p 3000:3000 \
runonflux/orbit:latest
Example index.ts:
import { Elysia } from 'elysia';
const app = new Elysia();
const port = process.env.APP_PORT || 3000;
app.get('/health', () => ({
status: 'healthy',
runtime: 'bun',
framework: 'elysia'
}));
app.get('/', () => ({
message: 'Hello from Elysia!',
runtime: `Bun ${Bun.version}`
}));
app.listen(port, () => {
console.log(`🦊 Elysia is running on port ${port}`);
});
Key Features:
- Native TypeScript support (no transpilation needed)
- Type safety with end-to-end type inference
- High performance with Bun's optimizations
Hono Framework
Hono is an ultra-fast web framework that works great with Bun:
docker run -d \
--name hono-api \
-e GIT_REPO_URL=https://github.com/your-username/hono-api \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest
Example index.ts:
import { Hono } from 'hono';
const app = new Hono();
const port = Number(process.env.APP_PORT) || 3000;
app.get('/health', (c) => {
return c.json({ status: 'healthy', runtime: 'bun' });
});
app.get('/', (c) => {
return c.json({
message: 'Hello from Hono!',
runtime: `Bun ${Bun.version}`
});
});
export default {
port,
fetch: app.fetch,
};
console.log(`Hono is running on port ${port}`);
Express on Bun
Bun is compatible with Node.js frameworks like Express:
docker run -d \
--name express-bun \
-e GIT_REPO_URL=https://github.com/your-username/express-app \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest
Example:
import express from 'express';
const app = express();
const port = process.env.APP_PORT || 3000;
app.get('/health', (req, res) => {
res.json({ status: 'healthy', runtime: 'bun' });
});
app.get('/', (req, res) => {
res.json({ message: 'Express running on Bun!' });
});
app.listen(port, () => {
console.log(`Express on Bun listening on port ${port}`);
});
Next.js on Bun
Bun can run Next.js applications:
docker run -d \
--name nextjs-bun \
-e GIT_REPO_URL=https://github.com/your-username/nextjs-app \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest
Note: Ensure your package.json has a start script:
{
"scripts": {
"build": "next build",
"start": "next start"
}
}
Version Management
Specify Bun Version
Option 1: Environment Variable
docker run -d \
-e GIT_REPO_URL=https://github.com/your-username/bun-app \
-e APP_PORT=3000 \
-e BUN_VERSION=1.0.25 \
-p 3000:3000 \
runonflux/orbit:latest
Option 2: .bun-version File
1.0.25
Option 3: package.json Engines
{
"name": "my-bun-app",
"engines": {
"bun": ">=1.0.0"
}
}
Native TypeScript Execution
One of Bun's killer features is native TypeScript execution - no build step required!
TypeScript Without Build
docker run -d \
--name ts-api \
-e GIT_REPO_URL=https://github.com/your-username/typescript-api \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest
Your index.ts runs directly without transpilation:
interface ApiResponse {
message: string;
timestamp: Date;
}
const response: ApiResponse = {
message: 'TypeScript running natively!',
timestamp: new Date()
};
console.log(response);
When to Use Build Scripts
Use a build script when you need:
- Asset bundling for frontend applications
- Code minification for production
- Special build optimizations
{
"scripts": {
"build": "bun build ./src/index.ts --outdir ./dist --target bun",
"start": "bun run ./dist/index.js"
}
}
Environment Variables
Bun-Specific Variables
| Variable | Description | Default |
|---|---|---|
BUN_VERSION | Bun version to install | Auto-detected or latest |
Common Application Variables
docker run -d \
--name bun-api \
-e GIT_REPO_URL=https://github.com/your-username/bun-api \
-e APP_PORT=3000 \
-e BUN_VERSION=1.0.25 \
-e DATABASE_URL=postgres://user:pass@db:5432/mydb \
-e JWT_SECRET=your-secret-key \
-e LOG_LEVEL=info \
-p 3000:3000 \
runonflux/orbit:latest
Advanced Scenarios
Monorepo - Deploy Specific Package
docker run -d \
--name bun-auth-service \
-e GIT_REPO_URL=https://github.com/your-username/monorepo \
-e PROJECT_PATH=packages/auth \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest
Private Repository
docker run -d \
--name private-bun-api \
-e GIT_REPO_URL=https://github.com/your-username/private-api \
-e GIT_TOKEN=ghp_your_personal_access_token \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest
With Deployment Hooks
Create pre-deploy.sh in your repository root:
#!/bin/bash
# Check Bun runtime before deployment
echo "Checking Bun runtime..."
bun --version
# Run tests
echo "Running tests..."
bun test
Create post-deploy.sh:
#!/bin/bash
# Health check after deployment
echo "Performing health check..."
curl -f http://localhost:$APP_PORT/health || exit 1
echo "Deployment successful!"
docker run -d \
--name bun-api-with-hooks \
-e GIT_REPO_URL=https://github.com/your-username/bun-api \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest
CI/CD Integration
Automatic Deployment with Webhooks
docker run -d \
--name bun-api \
-e GIT_REPO_URL=https://github.com/your-username/bun-api \
-e APP_PORT=3000 \
-e WEBHOOK_SECRET=my-secret-phrase \
-p 3000:3000 \
-p 9001:9001 \
runonflux/orbit:latest
Configure GitHub Webhook:
- Payload URL:
https://your-app-9001.app.runonflux.io/webhook - Content type:
application/json - Secret:
my-secret-phrase - Events: Just the
pushevent
Polling for Updates
docker run -d \
--name bun-api \
-e GIT_REPO_URL=https://github.com/your-username/bun-api \
-e APP_PORT=3000 \
-e POLLING_INTERVAL=300 \
-p 3000:3000 \
runonflux/orbit:latest
Troubleshooting
Bun Not Detected
Problem: Application detected as Node.js instead of Bun
Solution: Ensure you have bun.lockb in your repository:
# Generate bun.lockb
bun install
git add bun.lockb
git commit -m "Add bun.lockb for Bun detection"
Entry Point Not Found
Problem: "No entry point found for Bun application"
Solution: Ensure you have either:
- A
startscript in package.json:
{
"scripts": {
"start": "bun run index.ts"
}
}
- Or a common entry point file:
index.ts,index.js,src/index.ts,main.ts,server.ts, orapp.ts
Port Binding Issues
Problem: Application not accessible
Solution: Ensure your Bun application binds to 0.0.0.0 (not localhost):
// Good: Accessible from outside container
app.listen(port, '0.0.0.0', () => {
console.log(`Server running on port ${port}`);
});
// Also good (default in most frameworks)
app.listen(port);
TypeScript Type Errors
Problem: TypeScript compilation errors even though Bun runs TS natively
Solution: Bun runs TypeScript without strict type checking. For development, fix type errors locally:
# Check types locally before pushing
bun run tsc --noEmit
Add to package.json:
{
"scripts": {
"typecheck": "tsc --noEmit",
"start": "bun run index.ts"
}
}
Dependencies Not Installing
Problem: bun install fails
Solution: Check for bunfig.toml configuration issues or try clearing Bun cache:
# In pre-deploy.sh
bun pm cache rm
bun install
Performance Tips
- Native TypeScript: Skip build steps when possible - Bun runs TypeScript natively
- Bun.serve API: For maximum performance, use Bun's native server API instead of Express
- Dependency Caching: Dependencies are cached based on bun.lockb hash
- Health Checks: Implement
/healthendpoint for faster deployment verification - Hot Module Reloading: Use
bun --hotin development (not needed in production)
Bun-Native APIs
Bun provides high-performance native APIs:
Bun.serve (High Performance)
const server = Bun.serve({
port: process.env.APP_PORT || 3000,
fetch(req) {
const url = new URL(req.url);
if (url.pathname === '/health') {
return new Response(JSON.stringify({ status: 'healthy' }), {
headers: { 'Content-Type': 'application/json' }
});
}
return new Response('Hello from Bun.serve!');
},
});
console.log(`Server running on port ${server.port}`);
File I/O with Bun.file
// Fast file reading
const file = Bun.file('data.json');
const data = await file.json();
// Fast file writing
await Bun.write('output.json', JSON.stringify(data));
SQLite with Bun
import { Database } from 'bun:sqlite';
const db = new Database('mydb.sqlite');
const query = db.query('SELECT * FROM users WHERE id = ?');
const user = query.get(1);
Example Repository Structure
my-bun-api/
├── package.json # Dependencies and scripts
├── bun.lockb # Bun lockfile (binary format)
├── .bun-version # Optional: Pin Bun version
├── bunfig.toml # Optional: Bun configuration
├── tsconfig.json # TypeScript configuration
├── index.ts # Application entry point
├── pre-deploy.sh # Optional: Pre-deployment hook
├── post-deploy.sh # Optional: Post-deployment hook
├── src/
│ ├── routes/
│ │ ├── users.ts
│ │ └── auth.ts
│ ├── models/
│ │ └── user.ts
│ └── middleware/
│ └── auth.ts
└── test/
└── api.test.ts