{"id":22801689,"url":"https://github.com/pojntfx/go-nbd","last_synced_at":"2025-04-05T11:10:07.511Z","repository":{"id":108919323,"uuid":"604359802","full_name":"pojntfx/go-nbd","owner":"pojntfx","description":"Pure Go NBD server and client library.","archived":false,"fork":false,"pushed_at":"2024-07-30T23:28:42.000Z","size":1409,"stargazers_count":367,"open_issues_count":3,"forks_count":19,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-29T10:06:17.388Z","etag":null,"topics":["golang","nbd","nbd-client","nbd-server"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pojntfx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-20T22:27:13.000Z","updated_at":"2025-03-29T04:42:54.000Z","dependencies_parsed_at":"2024-07-31T02:48:26.732Z","dependency_job_id":"38065e06-5408-458b-b333-8c8e5478228f","html_url":"https://github.com/pojntfx/go-nbd","commit_stats":{"total_commits":85,"total_committers":3,"mean_commits":"28.333333333333332","dds":0.02352941176470591,"last_synced_commit":"2d78be2564f3835178508cb61c0a84d562f80364"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pojntfx%2Fgo-nbd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pojntfx%2Fgo-nbd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pojntfx%2Fgo-nbd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pojntfx%2Fgo-nbd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pojntfx","download_url":"https://codeload.github.com/pojntfx/go-nbd/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247325693,"owners_count":20920714,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["golang","nbd","nbd-client","nbd-server"],"created_at":"2024-12-12T08:12:26.572Z","updated_at":"2025-04-05T11:10:07.493Z","avatar_url":"https://github.com/pojntfx.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg alt=\"Project icon\" style=\"vertical-align: middle;\" src=\"./docs/icon.svg\" width=\"128\" height=\"128\" align=\"left\"\u003e\n\n# go-nbd\n\nPure Go NBD server and client library.\n\n\u003cbr/\u003e\n\n[![hydrun CI](https://github.com/pojntfx/go-nbd/actions/workflows/hydrun.yaml/badge.svg)](https://github.com/pojntfx/go-nbd/actions/workflows/hydrun.yaml)\n![Go Version](https://img.shields.io/badge/go%20version-%3E=1.20-61CFDD.svg)\n[![Go Reference](https://pkg.go.dev/badge/github.com/pojntfx/go-nbd.svg)](https://pkg.go.dev/github.com/pojntfx/go-nbd)\n[![Matrix](https://img.shields.io/matrix/go-nbd:matrix.org)](https://matrix.to/#/#go-nbd:matrix.org?via=matrix.org)\n\n## Overview\n\ngo-nbd is a lean NBD server and client library supporting the baseline protocol.\n\nIt enables you to:\n\n- **Build NBD servers and clients in Go:** Develop Network Block Device servers and clients using the efficient and easy-to-understand Go programming language, without having to fallback to CGo.\n- **Expose any `io.ReadWriter` as a block device:** Effortlessly turn a file, byte slice, S3 bucket or other `io.ReadWriter` into a fully-fledged block device.\n- **Bridge with legacy services:** If you need to make your application's dynamic data available to a legacy system, providing a NBD interface can be the perfect solution.\n\n## Installation\n\nYou can add go-nbd to your Go project by running the following:\n\n```shell\n$ go get github.com/pojntfx/go-nbd/...@latest\n```\n\n## Tutorial\n\n\u003e TL;DR: Define a backend, expose it with a server, connect a block device with the client and setup/mount the filesystem.\n\n### 1. Define a Backend\n\nFirst, define a backend; it should conform to this simple interface:\n\n```go\ntype Backend interface {\n\tReadAt(p []byte, off int64) (n int, err error)\n\tWriteAt(p []byte, off int64) (n int, err error)\n\tSize() (int64, error)\n\tSync() error\n}\n```\n\nA simple file-based backend could look like this:\n\n```go\n// server/main.go\n\ntype FileBackend struct {\n\tfile *os.File\n\tlock sync.RWMutex\n}\n\nfunc NewFileBackend(file *os.File) *FileBackend {\n\treturn \u0026FileBackend{file, sync.RWMutex{}}\n}\n\nfunc (b *FileBackend) ReadAt(p []byte, off int64) (n int, err error) {\n\tb.lock.RLock()\n\n\tn, err = b.file.ReadAt(p, off)\n\n\tb.lock.RUnlock()\n\n\treturn\n}\n\nfunc (b *FileBackend) WriteAt(p []byte, off int64) (n int, err error) {\n\tb.lock.Lock()\n\n\tn, err = b.file.WriteAt(p, off)\n\n\tb.lock.Unlock()\n\n\treturn\n}\n\nfunc (b *FileBackend) Size() (int64, error) {\n\tstat, err := b.file.Stat()\n\tif err != nil {\n\t\treturn -1, err\n\t}\n\n\treturn stat.Size(), nil\n}\n\nfunc (b *FileBackend) Sync() error {\n\treturn b.file.Sync()\n}\n```\n\nSee [pkg/backend](./pkg/backend) for more backend examples.\n\n### 2. Expose the Backend With a Server\n\nNext, create the backend and expose it with a server:\n\n```go\n// server/main.go\n\nb := NewFileBackend(f)\n\nfor {\n\tconn, err := l.Accept()\n\tif err != nil {\n\t\tcontinue\n\t}\n\n\tgo func() {\n\t\tif err := server.Handle(\n\t\t\tconn,\n\t\t\t[]server.Export{\n\t\t\t\t{\n\t\t\t\t\tName:        *name,\n\t\t\t\t\tDescription: *description,\n\t\t\t\t\tBackend:     b,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\u0026server.Options{\n\t\t\t\tReadOnly:           *readOnly,\n\t\t\t\tMinimumBlockSize:   uint32(*minimumBlockSize),\n\t\t\t\tPreferredBlockSize: uint32(*preferredBlockSize),\n\t\t\t\tMaximumBlockSize:   uint32(*maximumBlockSize),\n\t\t\t}); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}()\n}\n```\n\nSee [cmd/go-nbd-example-server-file/main.go](./cmd/go-nbd-example-server-file/main.go) for the full example.\n\n### 3. Connect to the Server with a Client\n\nIn a new `main` package, connect to the server by creating a client; note that you'll have to `modprobe nbd` and run the command as `root`:\n\n```go\n// client/main.go\n\nif err := client.Connect(conn, f, \u0026client.Options{\n\tExportName: *name,\n\tBlockSize:  uint32(*blockSize),\n}); err != nil {\n\tpanic(err)\n}\n```\n\nSee [cmd/go-nbd-example-client/main.go](./cmd/go-nbd-example-client/main.go) for the full example.\n\n### 4. Setup and Mount the Filesystem\n\nLastly, create a filesystem on the block device and mount it:\n\n```shell\n$ sudo mkfs.ext4 /dev/nbd0\n$ sudo mkdir -p /mnt\n$ sudo mount -t ext4 /dev/nbd0 /mnt\n```\n\nYou should now be able to use the mounted filesystem by navigating to `/mnt`.\n\n🚀 That's it! We can't wait to see what you're going to build with go-nbd.\n\n## Examples\n\nTo make getting started with go-nbd easier, take a look at the following examples:\n\n- [NBD File Server](./cmd/go-nbd-example-server-file/main.go)\n- [NBD Memory Server](./cmd/go-nbd-example-server-memory/main.go)\n- [NBD Client](./cmd/go-nbd-example-client/main.go)\n\n## Acknowledgements\n\n- [abligh/gonbdserver](https://github.com/abligh/gonbdserver/) provided the initial inspiration for this project.\n- [NetworkBlockDevice/nbd](https://github.com/NetworkBlockDevice/nbd/blob/master/doc/proto.md) provided the NBD protocol documentation.\n\n## Contributing\n\nTo contribute, please use the [GitHub flow](https://guides.github.com/introduction/flow/) and follow our [Code of Conduct](./CODE_OF_CONDUCT.md).\n\nTo build and start a development version of one of the examples locally, run the following:\n\n```shell\n$ git clone https://github.com/pojntfx/go-nbd.git\n$ cd go-nbd\n$ mkdir -p out \u0026\u0026 rm -f out/disk.img \u0026\u0026 truncate -s 10G out/disk.img \u0026\u0026 go run ./cmd/go-nbd-example-server-file --file out/disk.img\n$ go run ./cmd/go-nbd-example-server-memory\n\n# With the C NBD client\n$ sudo umount ~/Downloads/mnt; sudo nbd-client -d /dev/nbd1 \u0026\u0026 echo 'NBD starting' | sudo tee /dev/kmsg \u0026\u0026 sudo nbd-client -N default localhost 10809 /dev/nbd1\n\n# With the Go NBD client\n$ sudo umount ~/Downloads/mnt; go build -o /tmp/go-nbd-example-client ./cmd/go-nbd-example-client/ \u0026\u0026 sudo /tmp/go-nbd-example-client --file /dev/nbd1\n\n$ sudo mkfs.ext4 /dev/nbd1\n$ sync -f ~/Downloads/mnt; sudo umount ~/Downloads/mnt; sudo rm -rf ~/Downloads/mnt \u0026\u0026 sudo mkdir -p ~/Downloads/mnt \u0026\u0026 sudo mount -t ext4 /dev/nbd1 ~/Downloads/mnt \u0026\u0026 sudo chown -R \"${USER}\" ~/Downloads/mnt\n```\n\nHave any questions or need help? Chat with us [on Matrix](https://matrix.to/#/#go-nbd:matrix.org?via=matrix.org)!\n\n## License\n\ngo-nbd (c) 2024 Felicitas Pojtinger and contributors\n\nSPDX-License-Identifier: Apache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpojntfx%2Fgo-nbd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpojntfx%2Fgo-nbd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpojntfx%2Fgo-nbd/lists"}