Skip to content

Multi-Repo & Shared Clusters

Nanokit supports two project architectures: Monorepo (single nanokit.yml for all services) and Multi-Repo (each application lives in its own repository but shares a common cluster).


Monorepo (Default)

A monorepo places all services under one nanokit.yml. This is the default and simplest setup.

my-platform/
├── apps/
│   ├── auth/         # Auth microservice
│   ├── billing/      # Billing microservice
│   └── api/          # API gateway
├── packages/
│   └── shared/
└── nanokit.yml       # ← single config for everything

nanokit.yml (monorepo):

yaml
name: my-platform
version: "1"

services:
  auth:
    runtime: node
    path: ./apps/auth
    expose: 3001
    host: auth.my-platform.localhost

  billing:
    runtime: node
    path: ./apps/billing
    expose: 3002
    host: billing.my-platform.localhost

  api:
    runtime: node
    path: ./apps/api
    expose: 3000
    host: my-platform.localhost

environments:
  local:
    infra:
      provider: docker

Deploy:

bash
nkapp up              # launches all services
nkapp up auth         # launches only the auth service

Tip. In a monorepo, all services share the same gateway, Docker network, and state file. Cross-service communication uses internal container DNS (e.g., nk-my-platform-local-auth).


Multi-Repo

In a multi-repo setup, each application repository has its own nanokit.yml but all repos share a common Nanokit cluster (Docker daemon on a VPS, or the same ECS/VPC on AWS).

Key Concepts

ConceptDescription
nameThe project name — must be the same in all repos to share infrastructure.
componentA unique identifier for each repo within the project. Prevents cross-repo resource deletion.
infra.sharedSet to true in secondary repos. Tells Nanokit to adopt existing infrastructure instead of creating it.

How it Works

┌────────────────────────────────────────────────┐
│           Cluster: "my-platform" / local        │
│                                                 │
│  ┌──────────────────┐  ┌──────────────────┐    │
│  │  repo-auth       │  │  repo-billing    │    │
│  │  component: auth │  │  component: bill │    │
│  │                  │  │                  │    │
│  │  [nk-auth-svc]   │  │  [nk-bill-svc]   │    │
│  └──────────────────┘  └──────────────────┘    │
│                                                 │
│  [Shared Gateway]  ←  auto-discovers both       │
└────────────────────────────────────────────────┘

The Nanokit Reconciler uses the nk-component Docker/AWS tag to scope ownership: each repo only creates, updates, or deletes containers that belong to its own component.

Step-by-Step Setup

1. Infra Owner Repo

One repository is designated as the infrastructure owner. It provisions the cluster, gateway, and shared networking.

repo-infra/          ← or repo-auth if it's the "main" app
└── nanokit.yml
yaml
# repo-auth / nanokit.yml
name: my-platform        # ← shared project name
component: auth          # ← this repo's component ID

services:
  auth:
    runtime: node
    path: .
    expose: 3001
    host: auth.my-platform.localhost

environments:
  local:
    infra:
      provider: docker         # no shared: true here — this repo OWNS infra
bash
# In repo-auth
nkapp up

This creates the Docker network, Caddy gateway, and the auth containers.


2. Secondary Repos

Secondary repos add component and infra.shared: true.

repo-billing/
└── nanokit.yml
yaml
# repo-billing / nanokit.yml
name: my-platform        # ← same project name as repo-auth
component: billing       # ← different component ID

services:
  billing:
    runtime: node
    path: .
    expose: 3002
    host: billing.my-platform.localhost

environments:
  local:
    infra:
      provider: docker
      shared: true         # ← adopts existing gateway/network, does NOT create one
bash
# In repo-billing
nkapp up

Important.infra.shared: true tells Nanokit not to create or modify the Docker network and gateway. The infra-owner repo must have already run nkapp up at least once.


Cross-Service Communication

Services from different repos can communicate directly over the shared Docker network using container DNS names:

# From billing service → call auth
http://nk-my-platform-local-auth:3001/validate

# Or via the exposed host (through the gateway)
http://auth.my-platform.localhost/validate

The shared Caddy gateway auto-discovers all components and routes correctly:

auth.my-platform.localhost    → nk-my-platform-local-auth:3001
billing.my-platform.localhost → nk-my-platform-local-billing:3002

Multi-Repo on AWS (ECS / Fargate)

The same pattern applies to cloud deployments. The infra-owner repo creates the VPC, NLB, and ECS cluster. Secondary repos attach their services to the existing cluster.

Infra-owner (repo-auth):

yaml
name: my-platform
component: auth

environments:
  prod:
    infra:
      provider: aws
      region: us-east-1
      # No shared: true — this repo owns the VPC and ECS cluster

Secondary (repo-billing):

yaml
name: my-platform
component: billing

environments:
  prod:
    infra:
      provider: aws
      region: us-east-1
      shared: true    # ← adopts VPC/NLB/Cluster created by repo-auth

Warning. Destroy operations (nkapp destroy) in a secondary repo will only remove its own services (tagged nk-component: billing). The shared VPC and cluster are never touched.


State Management

SetupState Location
Monorepo / Local Docker.nanokit/ in the project directory
Cloud provider (AWS, DO, …)~/.nanokit/clusters/<provider>_<project>_<env>/
Multi-repo with shared: trueSame ~/.nanokit/clusters/ directory, shared across repos

The global state store ensures all repos working on the same cluster have a consistent view of deployed resources.


Reference: component and shared Fields

component

yaml
# nanokit.yml
component: auth   # Optional. Defaults to `name` if omitted.
Single-repoMulti-repo
DefaultSame as nameSet explicitly per repo
EffectNo isolation neededScopes all resource ownership
Tag appliednk-component: <name>nk-component: auth etc.

infra.shared

yaml
infra:
  provider: docker
  shared: true  # Optional. Default: false.
shared: false (default)shared: true
Creates gateway, network, VPCAdopts existing gateway/VPC
Full infrastructure ownerService-only deployment
Use in infra-owner reposUse in secondary repos