Skip to main content

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.lockb file (Bun's binary lockfile)
  • bunfig.toml (Bun configuration file)
  • .bun-version for 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

  1. Detection: Finds bun.lockb or bunfig.toml and identifies as Bun project
  2. Version Selection:
    • Checks BUN_VERSION environment variable
    • Checks .bun-version file
    • Checks engines.bun in package.json
    • Falls back to latest Bun version
  3. Runtime Installation:
    • Downloads official Bun binary from bun.sh
    • Installs to /opt/flux-tools/bun
    • Sets up PATH environment variables
  4. Dependencies: Runs bun install
  5. Build: Runs bun run build if build script exists (optional - Bun runs TypeScript natively!)
  6. Start: Executes bun run start or 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

VariableDescriptionDefault
BUN_VERSIONBun version to installAuto-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 push event

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:

  1. A start script in package.json:
{
"scripts": {
"start": "bun run index.ts"
}
}
  1. Or a common entry point file: index.ts, index.js, src/index.ts, main.ts, server.ts, or app.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

  1. Native TypeScript: Skip build steps when possible - Bun runs TypeScript natively
  2. Bun.serve API: For maximum performance, use Bun's native server API instead of Express
  3. Dependency Caching: Dependencies are cached based on bun.lockb hash
  4. Health Checks: Implement /health endpoint for faster deployment verification
  5. Hot Module Reloading: Use bun --hot in 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

Next Steps