---
title: "Go SDK — Bare metal"
description: "Lease and manage bare-metal hosts with the Metalhost Go SDK — browse, quote, create, power, ISO library, and release."
url: "https://metalhost.net/docs/developers/guides/sdk-bare-metal"
---

# Go SDK — Bare metal

Whole-host leases use `BareMetalServiceClient` (`baremetalv1connect`). Unlike VMs, create returns the instance directly — no operation poll for the initial lease (provisioning state is on the instance). Bandwidth is **unlimited** — not metered under the VM transfer allowance.

## Browse and quote

```
bm := baremetalv1connect.NewBareMetalServiceClient(httpClient, base)
offers, err := bm.ListAvailableBareMetal(ctx, connect.NewRequest(
    &baremetalv1.ListAvailableBareMetalRequest{PageSize: 50},
))
```

`ListBareMetalInventory` returns the full fleet (available + leased) — public, unauthenticated for specs/pricing only.

```
quote, err := bm.QuoteBareMetal(ctx, connect.NewRequest(
    &baremetalv1.QuoteBareMetalRequest{
        HostName:    "hosts/dal-r740-01",
        BillingMode: computev1.BillingMode_MONTHLY_1,
    },
))
```

Monthly terms show `dueNowMinor` — wallet must cover it at create.

## Lease a host

```
resp, err := bm.CreateBareMetalInstance(ctx, connect.NewRequest(
    &baremetalv1.CreateBareMetalInstanceRequest{
        Name:        "bare-metal-instances/my-box",
        ProjectName: "projects/my-app",
        HostName:    "hosts/dal-r740-01",
        BillingMode: computev1.BillingMode_MONTHLY_1,
        Autorenew:   true,
        OsImage:     "ubuntu-24-04",
        Hostname:    "my-box",
        LinuxUsername: "ubuntu",
        SshKeyNames: []string{"projects/my-app/ssh-keys/laptop"},
        PublicIpv4PrefixLen: 32,
    },
))
inst := resp.Msg.GetInstance()
```

### CreateBareMetalInstanceRequest fields

| Field | Description |
| --- | --- |
| `name` | `bare-metal-instances/{slug}` |
| `hostName` | `hosts/{slug}` from ListAvailableBareMetal |
| `billingMode` | `HOURLY` or `MONTHLY_*` |
| `autorenew` | Monthly only — renew at term end |
| `osImage` | Catalog id; omit for BYO OS |
| `customImageUrl` | Overrides catalog image |
| `linuxUsername` / `sshKeyNames` | Managed install access |
| `userData` | Raw cloud-init; empty → SSH-only seed |
| `publicIpv4PrefixLen` | 32 (1 IP) through 28 (16 IPs). Default 32. |

> **powered off still bills**
>
> `SetBareMetalPower` off does not stop billing — you lease the hardware until `ReleaseBareMetalInstance`.

## Get and list

```
bm.GetBareMetalInstance(ctx, connect.NewRequest(
    &baremetalv1.GetBareMetalInstanceRequest{Name: name},
))
bm.ListBareMetalInstances(ctx, connect.NewRequest(
    &baremetalv1.ListBareMetalInstancesRequest{ProjectName: project},
))
```

## Power and console

```
bm.SetBareMetalPower(ctx, connect.NewRequest(&baremetalv1.SetBareMetalPowerRequest{
    Name:   "bare-metal-instances/my-box",
    Action: baremetalv1.BareMetalPowerAction_BARE_METAL_POWER_ACTION_REBOOT,
}))
```

`GetBareMetalConsoleURL` — short-lived KVM websocket URL + `vnc_password`. Connect within 60s.

`EnterBareMetalRescueMode` / `ExitBareMetalRescueMode` — reboots into/out of rescue.

## Reinstall

`ReinstallBareMetal` — wipes OS disk, keeps lease and IPv4 block. Returns operation for managed reinstalls.

## Renew and release

```
bm.RenewBareMetalNow(ctx, connect.NewRequest(
    &baremetalv1.RenewBareMetalNowRequest{Name: name},
))
bm.ReleaseBareMetalInstance(ctx, connect.NewRequest(
    &baremetalv1.ReleaseBareMetalInstanceRequest{
        Name: "bare-metal-instances/my-box",
    },
))
```

Mid-term prepaid release returns `FailedPrecondition` until the commitment ends.

## ISO library (BYO OS)

Org-scoped — shared across projects. Quota-limited (default 5 ready ISOs).

```
upload, err := bm.CreateBareMetalISOUploadURL(ctx, connect.NewRequest(
    &baremetalv1.CreateBareMetalISOUploadURLRequest{
        DisplayName: "proxmox-8.iso",
        SizeBytes:   fileSize,
    },
))
// PUT the ISO bytes to upload.GetUploadUrl(), then poll ListBareMetalISOs until READY
```

Or `CreateBareMetalISOFromURL` for HTTPS import. `ListBareMetalISOs`, `DeleteBareMetalISO`.

Attach and boot from console workflow:

```
bm.AttachBareMetalISO(ctx, connect.NewRequest(&baremetalv1.AttachBareMetalISORequest{
    InstanceName: "bare-metal-instances/my-box",
    ObjectKey:    "orgs/my-org/isos/proxmox-8.iso",
}))
bm.SetBareMetalBootDevice(ctx, connect.NewRequest(&baremetalv1.SetBareMetalBootDeviceRequest{
    Name:   "bare-metal-instances/my-box",
    Device: baremetalv1.BareMetalBootDevice_BARE_METAL_BOOT_DEVICE_CDROM,
}))
```

`GetBareMetalVirtualMedia` — current mount state. `DetachBareMetalISO` — eject.

## What's next

- [Dashboard — Lease bare metal](https://metalhost.net/docs/dashboard/guides/bare-metal-lease.md)
- [CLI → Bare metal](https://metalhost.net/docs/developers/guides/cli-bare-metal.md)
- [API reference](https://metalhost.net/docs/developers/api.md)
