Back to articles
Technology Insight

Building a Private Docker Image Builder Server with Standalone BuildKit on Low-Spec VPS

June 3, 2026

Introduction

In modern cloud-native development, continuous integration and continuous deployment (CI/CD) pipelines heavily rely on containerizing applications. Typically, teams lean on standard Docker Daemons (dockerd) or heavy cloud-managed services to build their Docker images. However, for startups, small-to-medium enterprises (SMEs), and independent developers, maintaining a full-scale CI/CD runner or paying for premium managed image builders can quickly become cost-prohibitive.

Running a standard Docker daemon on a low-spec Virtual Private Server (VPS)—such as one with 1 vCPU and 1GB or 2GB of RAM—often leads to stability issues. The Docker daemon carries significant architectural overhead, managing container runtimes, networking layers, and volume storage volumes that are entirely unnecessary if your sole objective is to build images, not run them. This is where BuildKit steps in as a game-changer.

By isolating BuildKit as a standalone tool, you can transform a budget VPS into a highly efficient, secure, and blazing-fast private image builder server. This technical guide explores the architectural advantages of standalone BuildKit and provides a step-by-step blueprint for setting up your own production-ready builder server.

Why Standalone BuildKit for Low-Spec Hardware?

Originally introduced as part of Docker 18.06, BuildKit is the next-generation container image building engine developed under the Moby Project. It was designed from the ground up to replace the legacy Docker builder, addressing critical bottlenecks in performance, security, and extensibility.

When decoupled from the traditional Docker daemon, BuildKit operates via buildkitd, a lightweight daemon dedicated exclusively to executing multi-stage build definitions. Here is why it excels on low-spec hardware:

  • Minimal Memory Footprint: Without the burden of managing live container lifecycles, virtual networks, and complex storage drivers, buildkitd consumes a fraction of the RAM required by a full Docker daemon.
  • Concurrent Execution and Parallelism: BuildKit features a low-level builder engine that constructs a directed acyclic graph (DAG) of the build stages. It automatically parallelizes independent build stages, significantly reducing compilation time on limited CPU resources.
  • Advanced Cache Management: Unlike traditional builders that rely on local image layers for caching, BuildKit supports remote cache backends (such as inline cache, registry cache, or local directory cache export/import), maximizing cache hits even if the VPS disk space is restricted.
  • Rootless Execution Support: BuildKit can be run entirely without root privileges, mitigating security risks inherent to exposing a Docker daemon socket over network interfaces.
Key Takeaway: Standalone BuildKit treats image creation as a pure data-transformation function rather than a runtime execution environment, making it perfect for resource-constrained architectures.

Prerequisites and Environment Layout

Before proceeding with the deployment, ensure your environment meets the following baseline criteria:

  • Target VPS: A minimal Linux distribution (Ubuntu 24.04 LTS or Debian 12 recommended) with at least 1 vCPU, 1GB RAM, and 20GB of SSD storage.
  • Network: Static public IP address with firewall configurations allowing secure SSH and TLS-encrypted custom TCP access.
  • Local/Client Machine: A development machine or CI/CD runner with the buildctl CLI tool installed.

Step-by-Step Implementation Guide

Step 1: Install Standalone BuildKit on the VPS

First, establish an SSH connection to your low-spec VPS and update your package lists. Since BuildKit binaries are self-contained, we will fetch the latest official release directly from the GitHub repository.

Execute the following commands to download and extract the BuildKit binaries:

sudo apt update && sudo apt upgrade -y
curl -sSL [https://github.com/moby/buildkit/releases/download/v0.19.0/buildkit-v0.19.0.linux-amd64.tar.gz](https://github.com/moby/buildkit/releases/download/v0.19.0/buildkit-v0.19.0.linux-amd64.tar.gz) -o buildkit.tar.gz
sudo tar -C /usr/local -xzf buildkit.tar.gz
rm buildkit.tar.gz

Verify the installation by checking the version of the daemon:

buildkitd --version

Step 2: Configuring systemd for Reliability

To ensure that the BuildKit service starts automatically upon system boot and gracefully recovers from unexpected out-of-memory (OOM) events, we must manage it using systemd.

Create a service configuration file at /etc/systemd/system/buildkit.service with the following structural layout:

[Unit]
Description=BuildKit
Documentation=[https://github.com/moby/buildkit](https://github.com/moby/buildkit)
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/buildkitd --addr tcp://0.0.0.0:1234
Restart=always
RestartSec=5
Delegate=yes
KillMode=process

[Install]
WantedBy=multi-user.target

Note: Exposing the daemon on 0.0.0.0:1234 without encryption or strict firewalls is highly insecure. In the next steps, we will secure this transport layer using mTLS.

Reload the systemd manager configuration, enable, and start the service:

sudo systemctl daemon-reload
sudo systemctl enable --now buildkit
sudo systemctl status buildkit

Step 3: Securing the Connection via mutual TLS (mTLS)

Because the BuildKit server will accept build instructions from remote development machines or CI runners, safeguarding the transport layer is non-negotiable. Mutual TLS (mTLS) ensures that only authorized clients possessing valid cryptographic certificates can communicate with your build server.

You can generate these certificates using utilities like openssl or cfssl. You will need to generate three distinct sets of certificates:

  1. Certificate Authority (CA): The root trusted certificate used to sign both server and client pairs.
  2. Server Certificates: Configured with the VPS's public IP address or domain name as a Subject Alternative Name (SAN).
  3. Client Certificates: Generated for your local machine or CI system to authenticate against the server.

Once generated, update your /etc/buildkit/buildkitd.toml configuration file to enforce TLS verification:

[grpc]
  address = ["tcp://0.0.0.0:1234"]
  [grpc.tls]
    cert = "/etc/buildkit/certs/server.crt"
    key = "/etc/buildkit/certs/server.key"
    ca = "/etc/buildkit/certs/ca.crt"

Modify the ExecStart directive in your systemd service file to point to this configuration: ExecStart=/usr/local/bin/buildkitd --config /etc/buildkit/buildkitd.toml, then restart the service.

Executing Remote Builds Using buildctl

With the server securely operating, configure your local client machine to interact with the remote standalone builder. The official client CLI tool is buildctl.

To execute a build from a local directory containing a standard Dockerfile, invoke the build controller by explicitly defining the remote address and passing the required mTLS credentials:

buildctl --addr tcp://:1234 \
  --tlscacert=ca.crt --tlscert=client.crt --tlskey=client.key \
  build \
  --frontend=dockerfile.v0 \
  --local context=. \
  --local dockerfile=. \
  --output type=image,name=[private-registry.com/my-app:latest,push=true](https://private-registry.com/my-app:latest,push=true)

In this workflow, the local context is streamed efficiently to the remote VPS, where BuildKit constructs the layers step-by-step and immediately pushes the compiled layers to your private registry without storing massive image archives on the local disk of your small VPS.

Optimizing BuildKit for Constrained Hardware

To maximize performance and prevent OOM faults on lower tier infrastructure, implement these strict garbage collection (GC) and caching optimizations within your buildkitd.toml config:

[worker.oci]
  enabled = true
  gckeepstorage = 10000 # Keep up to 10GB of cache max

  [[worker.oci.gcpolicy]]
    keepBytes = 5120000000 # 5GB
    keepDuration = 172800 # 48 hours
    filters = ["type==source.local", "type==exec.cachemount"]

  [[worker.oci.gcpolicy]]
    all = true
    keepBytes = 10240000000 # 10GB

This strategic layout guarantees that BuildKit actively prunes old intermediate layers, maintaining a predictable disk space ceiling and ensuring your low-spec server never runs out of storage space unexpectedly during intensive compilations.

Conclusion

Transitioning from a heavy, generic Docker setup to a dedicated, standalone BuildKit infrastructure is an elegant optimization for cloud engineering teams. By shedding the runtime baggage of standard container engines, you gain fine-grained control over caching, reduce processing overhead, and successfully transform a low-spec VPS into a production-grade CI/CD building workhorse. This tailored approach allows you to achieve fast, automated image builds while maintaining a lean cloud architecture and minimal infrastructure costs.

Building a Private Docker Image Builder Server with Standalone BuildKit on Low-Spec VPS | DPTCloud