Go SDK for BoxLite — an embeddable virtual machine runtime for secure, isolated code execution.
go get github.com/boxlite-ai/boxlite/sdks/go
go run github.com/boxlite-ai/boxlite/sdks/go/cmd/setupRequires Go 1.24+ with CGO enabled. The setup step downloads the prebuilt native library and header into the module directory in your Go module cache (one-time). Set GITHUB_TOKEN to avoid API rate limits.
package main
import (
"context"
"fmt"
"log"
boxlite "github.com/boxlite-ai/boxlite/sdks/go"
)
func main() {
rt, err := boxlite.NewRuntime(
boxlite.WithImageRegistry(boxlite.ImageRegistry{
Host: "registry.example.com",
Auth: boxlite.ImageRegistryAuth{
Username: "user",
Password: "password",
},
}),
)
if err != nil {
log.Fatal(err)
}
defer rt.Close()
ctx := context.Background()
box, err := rt.Create(ctx, "alpine:latest",
boxlite.WithName("my-box"),
boxlite.WithCPUs(1),
boxlite.WithMemory(512),
boxlite.WithNetwork(boxlite.NetworkSpec{
Outbound: boxlite.OutboundNetworkSpec{
Mode: boxlite.NetworkModeEnabled,
AllowNet: []string{"api.openai.com"},
},
}),
boxlite.WithSecret(boxlite.Secret{
Name: "openai",
Value: "sk-...",
Hosts: []string{"api.openai.com"},
}),
)
if err != nil {
log.Fatal(err)
}
if err := box.Start(ctx); err != nil {
log.Fatal(err)
}
fmt.Println("Box started successfully!")
}archivePath, err := box.Export(ctx, "/var/lib/my-app/archives")
if err != nil {
log.Fatal(err)
}
// An empty name uses the same unnamed-box behavior as Create without
// WithName. The imported box receives a new ID and starts stopped.
restored, err := rt.Import(ctx, archivePath, "")
if err != nil {
log.Fatal(err)
}
defer restored.Close()A local runtime treats the archive as trusted because local applications own both the runtime and archive. A REST runtime uploads the file and relies on the server's untrusted-upload policy.
Export and Import never delete the archive. The caller owns its retention and must explicitly remove it when it is no longer needed.
ctx := context.Background()
images, err := rt.Images()
if err != nil {
log.Fatal(err)
}
defer images.Close()
pull, err := images.Pull(ctx, "alpine:latest")
if err != nil {
log.Fatal(err)
}
fmt.Println(pull.Reference, pull.ConfigDigest, pull.LayerCount)
cached, err := images.List(ctx)
if err != nil {
log.Fatal(err)
}
for _, image := range cached {
fmt.Println(image.Repository, image.Tag, image.ID)
}-
WithNetwork(boxlite.NetworkSpec{Outbound: boxlite.OutboundNetworkSpec{Mode: boxlite.NetworkModeEnabled, AllowNet: []string{"api.openai.com"}}})restricts outbound traffic while keeping networking enabled. -
WithNetwork(boxlite.NetworkSpec{Outbound: boxlite.OutboundNetworkSpec{Mode: boxlite.NetworkModeDisabled}})disables the guest network interface entirely. -
WithNetwork(boxlite.NetworkSpec{Inbound: boxlite.InboundNetworkSpec{Mode: boxlite.NetworkModeDisabled}})keeps the box private. The two directions are independent. -
The deprecated flat fields
NetworkSpec{Mode, AllowNet}still configure the outbound direction. Setting them together withOutboundis rejected when the options are built.NetworkInfo.ModeandNetworkInfo.AllowNetlikewise remain readable as views ontoNetworkInfo.Outbound. -
WithPort(boxlite.PortSpec{Guest: 3000})publishes TCP locally on an OS-selected host port; after checkingBoxInfo.Network != nil, read the concrete binding fromNetwork.PublishedPorts. -
A nil
PublishedPortsslice means the current handle does not know the bindings; a non-nil empty slice means there are no active publications.Box.Info,Runtime.GetInfo, andRuntime.ListInfouse callback-backed runtime operations and honor context cancellation. -
WithSecret(boxlite.Secret{...})configures host-side HTTP(S) secret substitution;Placeholderdefaults to<BOXLITE_SECRET:{Name}>. -
Container capabilities live under advanced options:
advanced, err := boxlite.NewAdvancedBoxOptions() if err != nil { log.Fatal(err) } defer advanced.Close() if err := advanced.SetCapabilities(boxlite.ContainerCapabilities{ Add: []string{"NET_ADMIN"}, Drop: []string{"NET_RAW"}, }); err != nil { log.Fatal(err) } box, err := runtime.Create(ctx, "alpine:latest", boxlite.WithAdvancedOptions(advanced))
Port publication is local-only. Remote runtimes reject it with guidance to use
the existing network tunnel API. Each tunnel handle is one-shot.
OCI EXPOSE metadata does not publish ports.
The same route workflow works with local and remote runtimes:
box.Network() (*Network, error)returns box-scoped network operations.network.Tunnel(ctx, port) (*BoxTunnel, error)prepares a one-shot tunnel.TCPListenAddress(host, port)andUnixListenAddress(path)return validated standardnet.Addrvalues fortunnel.Forward(ctx, addr). The returnedTunnelForwarderhasAddr() net.Addr,Wait(ctx) error, and repeatableClose() error; canceling a wait context does not close the listener.tunnel.URI() (string, error)returns the public URL of a remotely served tunnel, or an empty string for a local one.tunnel.Connect(ctx) (net.Conn, error)consumes the prepared connection.
Choose Connect or Forward; a forwarder prepares fresh tunnels for later
clients. This differs from WithPort, which creates a persistent,
local-only host listener that accepts repeated connections.
Build from source (requires Rust toolchain):
# From the project root
make dev:go
# Run tests
cd sdks/go && go test -tags boxlite_dev -v ./...Apache-2.0