App Deployment·6 min read·

Running Production Bun Microservices with Systemd and Caddy

Deploy high-throughput TypeScript microservices with the Bun runtime on Ubuntu 24.04, securing processes with systemd sandboxing and Caddy.

NB

Netbay Infrastructure Team

Netbay Engineering

On this page

Bun has rapidly grown from an experimental JavaScript toolchain into a battle-tested, high-performance production runtime. Built on Apple's WebKit JavaScriptCore engine rather than Google's V8, Bun executes TypeScript natively without transpilation passes, starts up in milliseconds, and provides built-in HTTP server primitives capable of handling over 100,000 requests per second on a single multi-core instance.

Running Bun in production requires pairing it with systemd process supervision for automatic restart on crash, strict Linux namespace sandboxing, and Caddy as an automated TLS reverse proxy binding directly to Unix Domain Sockets.

Why Unix Domain Sockets Beat Localhost TCP

When reverse proxying web traffic from an edge proxy like Caddy or Nginx to an application service running on the same host, developers almost universally default to binding a local TCP port (e.g. 127.0.0.1:3000). While functional, this routing forces the Linux kernel to traverse the entire network stack:

  • Memory allocations for socket buffers.
  • TCP checksum calculations and handshake roundtrips.
  • Ephemeral port exhaustion under heavy concurrent load (TIME_WAIT socket accumulation).

Unix Domain Sockets (UDS) bypass the network layer completely. Communication occurs via memory buffers managed directly inside the kernel Virtual File System (VFS). This slashes inter-process communication latency by 30-40% while eliminating port scanning and port conflict vectors.

Installing Bun on Ubuntu 24.04

Install the official Bun binary directly into a shared system path for access across system users:

bash
# Install Bun globally
sudo apt-get update
sudo apt-get install -y unzip curl
curl -fsSL https://bun.sh/install | bash

# Move binary to system PATH
sudo mv ~/.bun/bin/bun /usr/local/bin/bun
sudo chmod +x /usr/local/bin/bun

# Verify version
bun --version

Create a dedicated system user www-bun with no login shell to run the application process:

bash
sudo useradd -r -s /usr/sbin/nologin -d /srv/bun-app www-bun
sudo mkdir -p /srv/bun-app
sudo chown -R www-bun:www-bun /srv/bun-app

Writing a Native Bun Microservice

Bun includes a fast built-in HTTP server. Instead of binding to a TCP port, bind directly to a Unix Domain Socket to bypass Linux network stack overhead and eliminate port collision risks:

typescript
// /srv/bun-app/server.ts
import { serve } from "bun";
import { unlinkSync, existsSync } from "node:fs";

const socketPath = "/run/bun-app/server.sock";

// Clean up stale socket file if it exists
if (existsSync(socketPath)) {
  unlinkSync(socketPath);
}

const server = serve({
  unix: socketPath,
  fetch(req) {
    const url = new URL(req.url);

    if (url.pathname === "/health") {
      return new Response(JSON.stringify({ status: "healthy", uptime: process.uptime() }), {
        headers: { "Content-Type": "application/json" },
      });
    }

    if (url.pathname === "/api/compute") {
      // Simulate fast CPU-bound JSON work
      return Response.json({
        engine: "Bun JavaScriptCore",
        timestamp: Date.now(),
        worker_id: process.pid,
      });
    }

    return new Response("Not Found", { status: 404 });
  },
});

console.log("Bun production microservice listening on unix:" + socketPath);
Expand
Bun Production Microservice
Bun Runtime Performance and Execution

Sandboxing with Systemd

Create a hardened systemd unit file at /etc/systemd/system/bun-app.service. Use systemd's RuntimeDirectory directive to automatically create the /run/bun-app directory with proper ownership:

ini
# /etc/systemd/system/bun-app.service
[Unit]
Description=Bun Production Microservice
After=network.target

[Service]
Type=simple
User=www-bun
Group=www-bun
WorkingDirectory=/srv/bun-app
RuntimeDirectory=bun-app
RuntimeDirectoryMode=0755
ExecStart=/usr/local/bin/bun run server.ts
Restart=always
RestartSec=2s
LimitNOFILE=65535

# Linux process sandboxing controls
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
NoNewPrivileges=true
ProtectKernelTunables=true
ProtectControlGroups=true

[Install]
WantedBy=multi-user.target

Reload systemd and start the Bun service:

bash
sudo systemctl daemon-reload
sudo systemctl enable --now bun-app
sudo systemctl status bun-app
ls -la /run/bun-app/server.sock

Reverse Proxying with Caddy

Caddy provides automatic HTTPS with Let's Encrypt and native HTTP/3 support. Configure Caddy to proxy incoming requests to the Unix socket:

caddy
# /etc/caddy/Caddyfile
api.example.com {
    reverse_proxy unix//run/bun-app/server.sock {
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
    }

    encode zstd gzip
    log {
        output file /var/log/caddy/bun_access.log
    }
}

Reload Caddy:

bash
sudo systemctl reload caddy
Bun Microservice Architecture with Unix Socket & Caddy Public Edge (Caddy) - Port 443 TLS (HTTP/3) - Automatic Let's Encrypt - Zstandard compression - DDoS filtering edge Lucknow DC01 Unix Domain Socket - /run/bun-app/server.sock - Zero TCP overhead - In-kernel memory pipe - High-Speed SSD backed Microsecond IPC Bun Runtime (JSC) - Native TypeScript exec - Fast startup (<10ms) - Systemd sandboxing - Low memory footprint Intel Xeon Platinum Unix domain sockets eliminate network protocol latency between Caddy and the Bun worker
Modern JavaScript Runtime Architecture and Production Best Practices
YouTube

Verification and Benchmark Testing

Query the endpoint to verify socket communication and benchmark latency:

bash
# Verify health endpoint over HTTPS
curl -I https://api.example.com/health

# Benchmark throughput directly against unix socket
curl --unix-socket /run/bun-app/server.sock http://localhost/api/compute

Bun combines rapid developer ergonomics with elite runtime performance for modern backend microservices.

Deploy Bun-powered microservices on Netbay Linux VPS in under 60 seconds with High-Speed SSD in Lucknow DC01 — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance