Back to articles
Technology Insight

Building a Self-Hosted Private API Testing Environment: Deploying Bruno Server on an Independent Docker VPS

June 3, 2026

Introduction: The Shift Toward Private API Testing Infrastructure

In the modern software development lifecycle, API testing and collaboration tools are indispensable. For years, teams have relied on SaaS platforms like Postman or Insomnia to share collections, environment variables, and documentation. However, recent shifts in pricing models, forced cloud synchronization policies, and data privacy concerns have forced enterprise architects and engineering leads to reconsider their tooling strategy.

Data leaks involving sensitive API keys, staging URLs, and proprietary payloads are a major risk vector. To mitigate these security threats while maintaining development velocity, building an in-house, self-hosted API testing environment is the optimal solution. This article provides an enterprise-grade blueprint for deploying Bruno Server on an independent Docker-enabled Virtual Private Server (VPS), establishing a secure, private, and cost-effective testing infrastructure for your engineering team.


Why Bruno and Docker? The Architectural Advantages

Before diving into the technical implementation, it is crucial to understand why the combination of Bruno and Docker offers a superior alternative to traditional SaaS solutions.

1. The Git-Friendly Philosophy of Bruno

Unlike legacy API clients that store collections in proprietary JSON blobs or opaque cloud databases, Bruno stores collections directly in a plain-text folder structure using a markup language called Bru. Because collections are just files, they can reside within your application's Git repository. This design enables seamless version control, code reviews, and conflict resolution using standard Git workflows.

2. Centralized Collaboration via Bruno Server

While the Bruno desktop application works perfectly for individual developers using Git, larger teams often require a centralized hub for real-time collaboration, environment synchronization, and centralized access management. Bruno Server acts as this centralized backend, allowing teams to sync collections securely without relying on third-party cloud infrastructure.

3. Docker for Isolated, Portable Deployment

By containerizing Bruno Server and its dependencies, you abstract away OS-level discrepancies. Docker ensures that your testing environment behaves identically whether it is running on a staging VPS, an on-premise server, or a local machine. It simplifies backup, scaling, and migration processes significantly.


Prerequisites and Environment Setup

To follow this guide, ensure your infrastructure meets the following baseline requirements:

  • VPS Instance: A Linux-based VPS (Ubuntu 22.04 LTS or newer recommended) with at least 2 vCPUs, 2GB RAM, and 20GB SSD storage.
  • Network: A dedicated public IP address with firewall permissions configured to allow traffic on ports 80, 443, and your designated Bruno port (e.g., 5173 or 3000).
  • Domain Name: A fully qualified domain name (FQDN) pointing to your VPS IP address (e.g., bruno.company.com) for SSL termination.
  • Software: Docker Engine (v24.0+) and Docker Compose (v2.0+) installed on the host machine.
Security Note: Never run your API testing server entirely open to the public internet without an SSL/TLS layer and strict firewall rules. The environment will handle sensitive authorization headers and API tokens.

Step-by-Step Deployment Guide

We will configure Bruno Server using a multi-container Docker Compose setup. This architecture includes the Bruno Server application, a PostgreSQL database for persistent storage, and an Nginx Reverse Proxy with Let's Encrypt for automatic SSL management.

Step 1: Directory Structure Alignment

Connect to your VPS via SSH and establish a structured directory layout for your deployment configuration and volume persistence:mkdir -p /opt/bruno-server/{config,data,database} cd /opt/bruno-server

Step 2: Configuring the Docker Compose Manifest

Create a docker-compose.yml file within the directory. This file defines the orchestration between the application layer and the database layer.

version: '3.8'

services:
  bruno-db:
    image: postgres:15-alpine
    container_name: bruno-postgres
    restart: always
    environment:
      POSTGRES_DB: bruno_db
      POSTGRES_USER: bruno_admin
      POSTGRES_PASSWORD: SuperSecurePassword123!
    volumes:
      - ./database:/var/lib/postgresql/data
    networks:
      - bruno-network

  bruno-server:
    image: usebruno/bruno-server:latest
    container_name: bruno-backend
    restart: always
    depends_on:
      - bruno-db
    environment:
      - PORT=3000
      - DB_HOST=bruno-db
      - DB_PORT=5432
      - DB_NAME=bruno_db
      - DB_USER=bruno_admin
      - DB_PASSWORD=SuperSecurePassword123!
      - JWT_SECRET=YourUltraSecretJWTKey987!
      - DISABLE_SIGNUP=false
    ports:
      - "127.0.0.1:3000:3000"
    networks:
      - bruno-network

networks:
  bruno-network:
    driver: bridge

Note: Modify the POSTGRES_PASSWORD and JWT_SECRET to strong, unique strings before executing the deployment. Setting DISABLE_SIGNUP=false is necessary for initial admin creation, but should be toggled to true afterward to prevent unauthorized user registrations.

Step 3: Implementing Reverse Proxy and SSL Termination

To secure transmission data, deploy an Nginx instance or a specialized reverse proxy like Traefik or Caddy. Below is an example Nginx server block configuration to handle incoming traffic and upgrade connections securely:server { listen 80; server_name bruno.company.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name bruno.company.com; ssl_certificate /etc/letsencrypt/live/[bruno.company.com/fullchain.pem](https://bruno.company.com/fullchain.pem); ssl_certificate_key /etc/letsencrypt/live/[bruno.company.com/privkey.pem](https://bruno.company.com/privkey.pem); location / { proxy_pass [http://127.0.0.1:3000](http://127.0.0.1:3000); proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }

Step 4: Launching the Infrastructure

Validate your configuration and initiate the containers in detached mode:docker compose up -d

Verify that all services are executing successfully by inspecting the container states:docker compose ps


Connecting the Bruno Desktop Client

Once your server is running and accessible via HTTPS, establishing a connection from your local workstation is straightforward:

  • Launch the Bruno Desktop Application on your machine.
  • Navigate to the collection preferences or click on the "Cloud Sync / Collaboration" icon in the sidebar.
  • Select Self-Hosted Server as your provider.
  • Input your custom domain URL (e.g., [https://bruno.company.com](https://bruno.company.com)).
  • Create your primary administrative account, log in, and establish your workspace teams.

  • Enterprise Best Practices for Private API Environments

    Deploying the infrastructure is only the first step. To ensure maximum availability, compliance, and security, adhere to these operational guidelines:

    • Automated Database Backups: Implement a daily cron job on the VPS that executes pg_dump within the PostgreSQL container and uploads the encrypted snapshots to an isolated object storage bucket (e.g., AWS S3 or Cloudflare R2).
    • Disable Open Registration: Once your core engineering team has created their accounts, update the DISABLE_SIGNUP environment variable to true in your docker-compose.yml and run docker compose up -d to apply changes. This prevents external entities from creating accounts on your endpoint.
    • Restrict Network Perimeter: If your team utilizes a corporate VPN, configure your VPS firewall (UFW) to only accept incoming traffic on port 443 from your VPN gateway IP addresses.

    Conclusion

    Transitioning to a self-hosted Bruno Server environment provides your organization with absolute autonomy over its API testing workflows, data security, and operational overhead. By leveraging Docker and an independent VPS, you eliminate external SaaS dependencies, guarantee data privacy, and maintain a lightweight, lightning-fast development cycle integrated perfectly with standard Git governance. Take control of your development ecosystem today by deploying your own private API testing testing gateway.

    Building a Self-Hosted Private API Testing Environment: Deploying Bruno Server on an Independent Docker VPS | DPTCloud