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 everythingnanokit.yml (monorepo):
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: dockerDeploy:
nkdev up # launches all services
nkdev 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
| Concept | Description |
|---|---|
name | The project name — must be the same in all repos to share infrastructure. |
component | A unique identifier for each repo within the project. Prevents cross-repo resource deletion. |
infra.shared | Set 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# 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# In repo-auth
nkdev upThis 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# 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# In repo-billing
nkdev up[!IMPORTANT]
infra.shared: truetells Nanokit not to create or modify the Docker network and gateway. The infra-owner repo must have already runnkdev upat 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/validateThe 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:3002Multi-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):
name: my-platform
component: auth
environments:
prod:
infra:
provider: aws
region: us-east-1
# No shared: true — this repo owns the VPC and ECS clusterSecondary (repo-billing):
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 (
nkdev destroy) in a secondary repo will only remove its own services (taggednk-component: billing). The shared VPC and cluster are never touched.
State Management
| Setup | State Location |
|---|---|
| Monorepo / Local Docker | .nanokit/ in the project directory |
| Cloud provider (AWS, DO, …) | ~/.nanokit/clusters/<provider>_<project>_<env>/ |
Multi-repo with shared: true | Same ~/.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
# nanokit.yml
component: auth # Optional. Defaults to `name` if omitted.| Single-repo | Multi-repo | |
|---|---|---|
| Default | Same as name | Set explicitly per repo |
| Effect | No isolation needed | Scopes all resource ownership |
| Tag applied | nk-component: <name> | nk-component: auth etc. |
infra.shared
infra:
provider: docker
shared: true # Optional. Default: false.shared: false (default) | shared: true |
|---|---|
| Creates gateway, network, VPC | Adopts existing gateway/VPC |
| Full infrastructure owner | Service-only deployment |
| Use in infra-owner repos | Use in secondary repos |