Backend & Runtime

    Deploy Hono + Bun on a VPS

    Ultrafast web framework meets ultrafast runtime. systemd for process management, Caddy for automatic HTTPS — production-ready in ~30 minutes.

    ~30 min
    Beginner–Intermediate
    $4/mo VPS

    Prerequisites

    • A RamNode KVM VPS running Ubuntu 22.04 or 24.04
    • A non-root sudo user (or root access)
    • A domain name pointed at your VPS IP (optional but recommended for HTTPS)
    • SSH access to your server
    1

    Update the System

    Update packages
    sudo apt update && sudo apt upgrade -y
    2

    Install Bun

    Bun provides a single install script. Run it as your non-root user:

    Install Bun
    curl -fsSL https://bun.sh/install | bash

    Reload your shell environment:

    Reload PATH
    source ~/.bashrc
    # or for zsh:
    source ~/.zshrc

    Verify the install:

    Verify
    bun --version

    Note: Bun requires a 64-bit CPU with AVX2 support. All RamNode KVM instances meet this requirement.

    3

    Create Your Hono App

    If you're deploying an existing app, skip to Step 4. Otherwise, scaffold a new project:

    Scaffold project
    mkdir ~/myapp && cd ~/myapp
    bun init -y

    Install Hono:

    Install Hono
    bun add hono

    Create src/index.ts:

    src/index.ts
    import { Hono } from 'hono'
    
    const app = new Hono()
    
    app.get('/', (c) => c.text('Hello from Hono + Bun on RamNode!'))
    
    app.get('/health', (c) => c.json({ status: 'ok', timestamp: Date.now() }))
    
    export default {
      port: 3000,
      fetch: app.fetch,
    }

    Test it locally:

    Run test
    bun run src/index.ts

    Bun should confirm the server is listening on port 3000. Press Ctrl+C to stop.

    4

    Deploy Your App Files

    If pulling from a Git repo:

    Clone and install
    cd ~
    git clone https://github.com/youruser/yourrepo.git myapp
    cd myapp
    bun install

    Or upload files directly with rsync:

    Upload via rsync
    rsync -avz ./myapp/ user@your-server-ip:~/myapp/

    Then install dependencies on the server:

    Install deps
    cd ~/myapp
    bun install
    5

    Create a systemd Service

    Running your app as a systemd service keeps it alive across reboots and restarts it on failure.

    /etc/systemd/system/myapp.service
    [Unit]
    Description=Hono + Bun App
    After=network.target
    
    [Service]
    Type=simple
    User=ubuntu
    WorkingDirectory=/home/ubuntu/myapp
    ExecStart=/home/ubuntu/.bun/bin/bun run src/index.ts
    Restart=on-failure
    RestartSec=5
    StandardOutput=journal
    StandardError=journal
    SyslogIdentifier=myapp
    
    # Environment variables
    Environment=NODE_ENV=production
    Environment=PORT=3000
    
    [Install]
    WantedBy=multi-user.target

    Tip: If your app uses a .env file, add EnvironmentFile=/home/ubuntu/myapp/.env under [Service].

    Enable and start the service:

    Enable and start
    sudo systemctl daemon-reload
    sudo systemctl enable myapp
    sudo systemctl start myapp

    Check status and tail logs:

    Verify
    sudo systemctl status myapp
    sudo journalctl -u myapp -f
    6

    Install Caddy as a Reverse Proxy

    Caddy handles HTTPS automatically via Let's Encrypt:

    Install Caddy
    sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
    sudo apt update
    sudo apt install caddy
    7

    Configure Caddy

    Replace the default Caddyfile with your domain configuration:

    /etc/caddy/Caddyfile (with domain)
    yourdomain.com {
        reverse_proxy localhost:3000
    }

    If you're testing without a domain (HTTP only with IP):

    /etc/caddy/Caddyfile (IP only)
    :80 {
        reverse_proxy localhost:3000
    }

    Reload Caddy:

    Reload
    sudo systemctl reload caddy

    Caddy will automatically provision a TLS certificate for your domain via Let's Encrypt. Your app will be reachable at https://yourdomain.com within seconds.

    8

    Open the Firewall

    Allow HTTP/HTTPS
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw enable

    Verify the rules:

    Check status
    sudo ufw status
    9

    Verify the Deployment

    Test your endpoints:

    Test endpoints
    curl https://yourdomain.com
    # Expected: Hello from Hono + Bun on RamNode!
    
    curl https://yourdomain.com/health
    # Expected: {"status":"ok","timestamp":...}

    Updating Your App

    When you push new code, pull and restart:

    Deploy update
    cd ~/myapp
    git pull
    bun install          # only needed if dependencies changed
    sudo systemctl restart myapp

    Performance Notes

    Bun's HTTP server is benchmarked significantly faster than Node.js for raw throughput. On a RamNode 512MB KVM instance, a Hono + Bun app can comfortably handle thousands of concurrent requests for typical API workloads. For CPU-intensive tasks, consider scaling to a 1GB or 2GB plan.

    Monitor resources
    htop
    # or for a quick snapshot:
    sudo systemctl status myapp

    Troubleshooting

    App won't start

    Check logs with sudo journalctl -u myapp -n 50. Common causes: wrong WorkingDirectory path, missing bun binary path, or port already in use.

    Bun binary not found in systemd

    systemd uses a minimal PATH. The ExecStart line uses the full path (/home/ubuntu/.bun/bin/bun) to avoid this. Verify with which bun.

    Certificate not provisioning

    Ensure your domain's A record points to your VPS IP and port 80 is open. Caddy uses the HTTP-01 challenge which requires port 80 to be reachable.

    Port 3000 conflict

    Check what's using the port: sudo ss -tlnp | grep 3000. Update the port in both your app and the systemd Environment=PORT=3000 line.

    Next Steps

    • Add a .env file for secrets and reference it with EnvironmentFile in your service
    • Set up log rotation with logrotate for long-running services
    • Explore Hono middleware for rate limiting, JWT auth, and request logging
    • Consider Dokploy for multi-app management on your VPS