Quick Start

Get Ze running with two BGP peers in under 5 minutes.

Build

git clone https://github.com/ze-software/ze.git
cd ze
make build    # produces bin/ze, bin/ze-test, bin/ze-chaos

Requires Go 1.26+ on a macOS or Linux development host. Windows is not a supported development platform.

Or: go install

To just get a ze binary without cloning the repo, go install with the same build tags make build uses:

go install -tags 'ze_core ze_distro ze_gnmi ze_grpc ze_isis ze_ldp ze_lg ze_mcp ze_ospf ze_rest ze_rsvpte ze_ssh ze_telemetry ze_web' codeberg.org/thomas-mangin/ze/cmd/ze@latest

This tracks the module's default branch (development version), not a tagged release -- there are no tagged releases yet.

Initialize

Ze runs an SSH server on localhost for CLI access (ze cli, ze show, ze signal). This keeps the control plane authenticated even in multi-user environments. Set up credentials once:

bin/ze init

This prompts for username, password, SSH host (default 127.0.0.1), port (default 2222), and node name (default: hostname). Credentials are stored locally with bcrypt-hashed passwords. For scripting (later fields fall back to their defaults):

echo -e "admin\nsecret" | bin/ze init

Running ze init a second time will refuse with error: database already exists. To reinitialize, use --force -- this backs up the old database as database.zefs.replaced-<date> before creating a new one:

bin/ze signal stop             # stop daemon first
bin/ze init --force            # prompts for confirmation, then backs up and reinitializes

Minimal Config

Save as example.conf:

plugin {
    internal rib {
        use bgp-rib
    }
}

bgp {
    router-id 10.0.0.1

    peer test-peer {
        connection {
            remote {
                ip 10.0.0.2
            }
            local {
                ip 10.0.0.1
            }
        }

        session {
            asn {
                local 65000
                remote 65001
            }
            family {
                ipv4/unicast {
                    prefix {
                        maximum 1000000
                    }
                }
            }
        }

        process rib {
            receive [ state ]
            send [ update ]
        }

        update {
            attribute {
                origin igp
                next-hop 10.0.0.1
            }
            nlri {
                ipv4/unicast add 192.168.1.0/24
            }
        }
    }
}

Validate

bin/ze config validate example.conf

Expected output:

configuration valid: example.conf

Start

bin/ze example.conf

Ze logs to stderr. You should see something like:

level=INFO  msg="hub ready" subsystem=hub plugins=1 peers=1 listen=":179"
level=INFO  msg="peer connecting" subsystem=bgp.reactor peer=test-peer address=10.0.0.2

Silence means the default log level (warn) has nothing to report -- that's normal. To see all activity:

bin/ze -d example.conf        # debug logging

Verify

In another terminal:

# Check daemon is running
bin/ze status

# List peers
bin/ze cli -c "show bgp peer list"

# Show peer details
bin/ze cli -c "show bgp peer test-peer detail"

# Watch live events
bin/ze cli -c "monitor bgp"

Test Without a Real Peer

Use the built-in test peer to accept any BGP session:

# Terminal 1: start a sink peer (accepts sessions, replies keepalive)
bin/ze-test peer --mode sink --port 1179 --asn 65001

# Terminal 2: start ze with config pointing to localhost:1179
bin/ze example-local.conf

Where example-local.conf is the config above with the peer's connection block pointed at the local sink, so ze dials 127.0.0.1:1179 instead of 10.0.0.2:

        connection {
            remote {
                ip 127.0.0.1
                port 1179
            }
            local {
                ip 127.0.0.1
            }
        }

The sink's --asn 65001 matches the peer's session { asn { remote 65001 } }.

Stop

bin/ze signal stop             # graceful shutdown
bin/ze signal restart          # graceful restart (preserves routes via GR)

Next Steps