Hako
Explanation

Port Allocation

Understanding how Hako manages deterministic port assignment.

Hako manages network isolation by assigning unique port ranges to each branch. This approach allows multiple versions of the same project to run simultaneously without manual configuration.

The Problem

Development environments often rely on fixed ports. When a developer needs to switch between branches or run multiple branches at once, port conflicts occur. Manually reconfiguring ports for each branch is tedious and error-prone.

Design Goals

The port allocation system follows three core principles:

  • Deterministic: The same branch always receives the same port range.
  • Collision-resistant: Different branches and projects should not overlap.
  • Decentralized: No central server is required to coordinate assignments.

The Algorithm

Hako uses a SHA256 hash of the repository path and branch name to determine the base port. This hash is mapped to a range between 40000 and 59999.

The range is divided into 100-port blocks. SHA256 provides a uniform distribution across these blocks, minimizing the chance of initial collisions. The selected range sits above the standard ephemeral range and below most well-known services.

Collision Handling

Hako verifies port availability before finalizing an assignment. It checks a local registry at ~/.hako/ports.json and uses lsof to detect external processes.

If a collision is detected, Hako probes the next available 100-port block. It attempts up to 100 probes before failing. The registry tracks Hako-managed environments, while lsof catches services started outside of Hako.

Port Offsets

Services within an environment receive sequential ports starting from the base. The first variable is assigned base+0, the second base+1, and so on. This simple mapping makes port assignments predictable and easy to debug.

Registry Management

Hako maintains a persistent JSON registry at ~/.hako/ports.json. In bare mode, Hako writes to this registry to reserve ports. In Docker mode, Hako reads the registry to ensure it doesn't conflict with bare-mode services. Docker Compose manages its own state through project names, so Hako only needs to provide the environment variables.

Locking Mechanism

Hako uses directory-based locking with mkdir to prevent race conditions during port allocation. This choice ensures compatibility with macOS, where flock behavior can vary. The locking mechanism ensures that two Hako processes don't attempt to claim the same port block simultaneously.

See Also

ops.origin: Masakiro Corp.

On this page