---
title: "Go SDK — Storage"
description: "Block disks and NFS file shares with the Metalhost Go SDK — create, attach, resize, and delete."
url: "https://metalhost.net/docs/developers/guides/sdk-storage"
---

# Go SDK — Storage

Persistent storage uses `StorageServiceClient`. Block disks are RWO volumes; file shares are RWX NFS exports mountable from multiple VMs in the same project and datacenter.

## Block disks

### Create

```
storage := storagev1connect.NewStorageServiceClient(httpClient, base)
resp, err := storage.CreateDisk(ctx, connect.NewRequest(&storagev1.CreateDiskRequest{
    Parent: "projects/my-app",
    Disk: &storagev1.Disk{
        DatacenterName: "datacenters/us-dal-1",
        SizeGib:        100,
        StorageClass:   "nvme",
        DisplayName:    "data-1",
        // NetworkName: defaults to project's default network in that DC
    },
}))
diskName := resp.Msg.GetDisk().GetName()
```

| Constraint | Value |
| --- | --- |
| Size | 1–1024 GiB |
| Storage class | `nvme` |
| Datacenter | Immutable after create |

### States

`PROVISIONING` → `AVAILABLE` → `ATTACHED` → `AVAILABLE` (detach) → `DELETING`

### List and delete

```
storage.ListDisks(ctx, connect.NewRequest(&storagev1.ListDisksRequest{
    ProjectName: project, PageSize: 100,
}))
storage.DeleteDisk(ctx, connect.NewRequest(&storagev1.DeleteDiskRequest{Name: diskName}))
```

Delete fails while `ATTACHED` — detach first.

### Attach, detach, resize

VM must be `RUNNING` for hot attach/detach:

```
storage.AttachDisk(ctx, connect.NewRequest(&storagev1.AttachDiskRequest{
    DiskName: diskName,
    VmName:   "projects/my-app/virtual-machines/web-1",
}))
storage.DetachDisk(ctx, connect.NewRequest(&storagev1.DetachDiskRequest{DiskName: diskName}))
storage.ResizeDisk(ctx, connect.NewRequest(&storagev1.ResizeDiskRequest{
    DiskName: diskName, NewSizeGib: 200,
}))
```

Resize is grow-only — no shrink.

> **boot disk vs data disk**
>
> VM create provisions a boot disk tied to the VM lifecycle. This service is for **data disks** that survive across VMs.

## Backups and automatic schedules (SDK v1.1.0)

`CreateSnapshot`, `GetSnapshot`, `ListSnapshots` and `DeleteSnapshot` manage single-disk backups. Restore with `CreateDiskRequest.FromSnapshot` and a stable `DiskId`. Wait for READY before restoring into a new disk in the same project, network and datacenter.

`CreateSnapshotSchedule`, `ListSnapshotSchedules`, `UpdateSnapshotSchedule` and `DeleteSnapshotSchedule` manage automatic captures. Set `Enabled: true` explicitly on create, supply UTC times and keep-N retention, and use an explicit `FieldMask` for updates. Set an `Idempotency-Key` header on create requests and reuse it only for identical retries.

See the [released backup API guide](https://github.com/AES-Services/metalhost-sdk/blob/v1.1.0/docs/BACKUPS.md) for whole-VM manifests, consistency, retry rules, and billing. These APIs require backend v1.0.67 or later.

## File shares

```
resp, err := storage.CreateFileShare(ctx, connect.NewRequest(&storagev1.CreateFileShareRequest{
    ProjectName:    "projects/my-app",
    DatacenterName: "datacenters/us-dal-1",
    SizeGib:        500,
    DisplayName:    "shared-data",
}))
share := resp.Msg.GetFileShare()
// share.GetMountCommand() — NFSv4 mount line for VMs in same project + DC
```

| Constraint | Value |
| --- | --- |
| Size | 1–10240 GiB |
| Storage class | `cephfs-rwx` |
| Mount | Same project + datacenter only |

```
storage.ListFileShares(ctx, connect.NewRequest(&storagev1.ListFileSharesRequest{ProjectName: project}))
storage.DeleteFileShare(ctx, connect.NewRequest(&storagev1.DeleteFileShareRequest{Name: shareName}))
```

## What's next

- [Dashboard — Storage](https://metalhost.net/docs/dashboard/guides/storage.md)
- [Go SDK — VMs](https://metalhost.net/docs/developers/guides/sdk-vms.md) — attach disks to running VMs
- [CLI → Storage](https://metalhost.net/docs/developers/guides/cli-storage.md)
