Skip to content

Leaf

Create a separate NATS server that uses a JetStream domain, to be used as a leaf node

Initialize a local nsc config for the leaf node.

 make init-leaf-nsc
❯ tree -L2 .nsc 
.leaf
├── creds
│   └── leaf
├── keys
│   ├── A
│   ├── O
│   └── U
├── leaf
│   ├── accounts
│   └── leaf.jwt
├── nsc.conf
└── nsc.json

Start leaf node NATS server

Start the leaf node NATS server using the nsc configuration (./.leaf/nsc.conf). Note the leafnodes.remotes value that connects this server to the "local" server:

leafnodes {
  remotes = [
    {
      url: "nats://localhost:7422"
      credentials: ".nsc/creds/local/A/admin.creds"
      account: "A..."
    },
    ...
  ]
}

[!NOTE] NKey values will be different in your output.

 make leaf
❯ make leaf                              
nats-server -c leaf.conf
[27274] 2025/08/25 08:35:30.283060 [INF] Starting nats-server
[27274] 2025/08/25 08:35:30.283160 [INF]   Version:  2.11.7
[27274] 2025/08/25 08:35:30.283162 [INF]   Git:      [df44964]
[27274] 2025/08/25 08:35:30.283164 [INF]   Name:     leaf
[27274] 2025/08/25 08:35:30.283165 [INF]   Node:     ZLMV550B
[27274] 2025/08/25 08:35:30.283166 [INF]   ID:       NA7CAQ7BK3UBPNX6BALDGCCRCIFALLDPBQC43AJNX76IHMOA3TMQXLYG
[27274] 2025/08/25 08:35:30.283175 [INF] Using configuration file: leaf.conf (sha256:fcd90964b146f77d21f613fcd03f72b0843495714df49638e57ee093d53f0478)
[27274] 2025/08/25 08:35:30.283179 [INF] Trusted Operators
[27274] 2025/08/25 08:35:30.283180 [INF]   System  : ""
[27274] 2025/08/25 08:35:30.283181 [INF]   Operator: "leaf"
[27274] 2025/08/25 08:35:30.283184 [INF]   Issued  : 2025-08-25 08:25:36 -0700 PDT
[27274] 2025/08/25 08:35:30.283194 [INF]   Expires : Never
[27274] 2025/08/25 08:35:30.283586 [INF] Starting JetStream
[27274] 2025/08/25 08:35:30.283598 [WRN] Temporary storage directory used, data could be lost on system reboot
[27274] 2025/08/25 08:35:30.283859 [INF]     _ ___ _____ ___ _____ ___ ___   _   __  __
[27274] 2025/08/25 08:35:30.283863 [INF]  _ | | __|_   _/ __|_   _| _ \ __| /_\ |  \/  |
[27274] 2025/08/25 08:35:30.283865 [INF] | || | _|  | | \__ \ | | |   / _| / _ \| |\/| |
[27274] 2025/08/25 08:35:30.283866 [INF]  \__/|___| |_| |___/ |_| |_|_\___/_/ \_\_|  |_|
[27274] 2025/08/25 08:35:30.283867 [INF] 
[27274] 2025/08/25 08:35:30.283868 [INF]          https://docs.nats.io/jetstream
[27274] 2025/08/25 08:35:30.283869 [INF] 
[27274] 2025/08/25 08:35:30.283870 [INF] ---------------- JETSTREAM ----------------
[27274] 2025/08/25 08:35:30.283877 [INF]   Max Memory:      1.00 GB
[27274] 2025/08/25 08:35:30.283880 [INF]   Max Storage:     1.00 GB
[27274] 2025/08/25 08:35:30.283881 [INF]   Store Directory: "/var/folders/q3/sxmzn9xs6r90xcfzr3g5ch2m0000gn/T/jetstream"
[27274] 2025/08/25 08:35:30.283882 [INF]   Domain:          leaf
[27274] 2025/08/25 08:35:30.283883 [INF]   API Level:       1
[27274] 2025/08/25 08:35:30.283885 [INF] -------------------------------------------
[27274] 2025/08/25 08:35:30.284202 [WRN] Account fetch failed: account missing
[27274] 2025/08/25 08:35:30.284207 [WRN] Account fetch failed: account missing
[27274] 2025/08/25 08:35:30.284743 [INF] Listening for client connections on 0.0.0.0:4223
[27274] 2025/08/25 08:35:30.284873 [INF] Server is ready
[27274] 2025/08/25 08:35:30.286881 [INF] 127.0.0.1:7422 - lid:6 - Leafnode connection created for account: ABIV654V3C2AS4Y6NMZDPHVVOERHABHMBXNS2PFVSQQSGW6QIOQWR6FR/A 
[27274] 2025/08/25 08:35:30.289002 [INF] 127.0.0.1:7422 - lid:6 - JetStream using domains: local "leaf", remote ""
^C[27274] 2025/08/25 08:35:35.798395 [INF] Trapped "interrupt" signal
[27274] 2025/08/25 08:35:35.798677 [INF] Initiating Shutdown...
[27274] 2025/08/25 08:35:35.798705 [INF] Initiating JetStream Shutdown...
[27274] 2025/08/25 08:35:35.798718 [INF] JetStream Shutdown
[27274] 2025/08/25 08:35:35.798851 [INF] 127.0.0.1:7422 - lid:6 - Leafnode connection closed: Server Shutdown - Account: ABIV654V3C2AS4Y6NMZDPHVVOERHABHMBXNS2PFVSQQSGW6QIOQWR6FR/A

Create clones of streams from the self-managed cluster into the leaf node

The streams in the leaf node will use “limits” retention policies, which is required for sourcing/mirroring. Interest and work queue policies are not supported when sourcing/mirroring.

 cd ./tf/leaf
❯ terraform apply -auto-approve  # or `terraform plan -out plan.out` and `terraform apply plan.out`
jetstream_stream.QUEUE: Refreshing state... [id=JETSTREAM_STREAM_QUEUE]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # jetstream_stream.QUEUE will be created
  + resource "jetstream_stream" "QUEUE" {
      + ack                     = true
      + allow_direct            = true
      + allow_msg_ttl           = false
      + allow_rollup_hdrs       = false
      + compression             = "none"
      + deny_delete             = false
      + deny_purge              = false
      + discard                 = "old"
      + discard_new_per_subject = false
      + duplicate_window        = 120
      + id                      = (known after apply)
      + max_age                 = 86400
      + max_bytes               = 10485760
      + max_consumers           = -1
      + max_msg_size            = -1
      + max_msgs                = 1024
      + max_msgs_per_subject    = -1
      + name                    = "QUEUE"
      + replicas                = 1
      + retention               = "limits"
      + storage                 = "file"
      + subjects                = [
          + "QUEUE.>",
        ]
    }

Plan: 1 to add, 0 to change, 0 to destroy.
jetstream_stream.QUEUE: Creating...
jetstream_stream.QUEUE: Creation complete after 0s [id=JETSTREAM_STREAM_QUEUE]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

View the created stream.

 nats --server nats://localhost:4223 --creds ../../.leaf/creds/leaf/A/leaf.creds stream report 
Obtaining Stream stats

╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮
│                                            Stream Report                                            │
├────────┬─────────┬───────────┬───────────┬──────────┬───────┬──────┬─────────┬───────────┬──────────┤
│ Stream  Storage  Placement  Consumers  Messages  Bytes  Lost  Deleted  API Level  Replicas │
├────────┼─────────┼───────────┼───────────┼──────────┼───────┼──────┼─────────┼───────────┼──────────┤
│ QUEUE   File                0          0         0 B    0     0        0                   │
╰────────┴─────────┴───────────┴───────────┴──────────┴───────┴──────┴─────────┴───────────┴──────────╯