### Install nbdkit Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Installs nbdkit after compilation. This command typically requires root privileges. ```bash make install ``` -------------------------------- ### Python Plugin Example (ramdisk.py) Source: https://context7.com/nbdkit/nbdkit/llms.txt Example of a Python plugin for an in-memory read/write disk. It defines configuration, open, get_size, pread, pwrite, zero, and flush callbacks. ```APIDOC ## Writing a Python plugin Python plugins set `API_VERSION = 2` and define module-level functions matching the plugin callbacks. ```python # ramdisk.py — in-memory read/write disk # Run: nbdkit -fv python ramdisk.py size=67108864 import nbdkit import errno API_VERSION = 2 disk = bytearray(0) def config(key, value): global disk if key == "size": disk = bytearray(int(value)) else: nbdkit.debug("ignored parameter %s=%s" % (key, value)) def config_complete(): if len(disk) == 0: raise Exception("size parameter is required") def open(readonly): nbdkit.debug("open: readonly=%d tls=%r" % (readonly, nbdkit.is_tls())) return {} # per-connection handle (any Python object) def get_size(h): return len(disk) def pread(h, buf, offset, flags): end = offset + len(buf) buf[:] = disk[offset:end] def pwrite(h, buf, offset, flags): end = offset + len(buf) disk[offset:end] = buf def zero(h, count, offset, flags): if flags & nbdkit.FLAG_MAY_TRIM: disk[offset:offset + count] = bytearray(count) else: nbdkit.set_error(errno.EOPNOTSUPP) raise Exception("trim not permitted") def flush(h, flags): pass # in-memory, nothing to flush # Connect: # guestfish --format=raw -a nbd://localhost ``` ``` -------------------------------- ### Install Cross-compilation Prerequisites on Fedora/RHEL Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Installs the necessary mingw-w64 toolchain and build tools for cross-compiling nbdkit on Fedora or RHEL systems. ```bash dnf install -y mingw64-{gcc,dlfcn,winpthreads,gnutls} dnf install -y autoconf automake libtool make ``` -------------------------------- ### Start TLS-required server Source: https://context7.com/nbdkit/nbdkit/llms.txt Start an nbdkit server that requires TLS. Certificate files must be present in the specified directory. ```bash nbdkit --tls=require \ --tls-certificates=/etc/nbdkit/certs \ file disk.img ``` -------------------------------- ### Inspect a plugin with nbdinfo in captive mode Source: https://context7.com/nbdkit/nbdkit/llms.txt Use nbdkit with `--run` to start a plugin and then inspect it using nbdinfo. The `$uri` variable is available within the `--run` command. ```bash nbdkit file disk.img --run 'nbdinfo "$uri"' ``` -------------------------------- ### Start TLS server with Pre-Shared Key (PSK) Source: https://context7.com/nbdkit/nbdkit/llms.txt Start an nbdkit server using TLS with a pre-shared key (PSK) for authentication. A PSK file mapping usernames to keys is required. ```bash echo "alice:$(openssl rand -hex 32)" > /etc/nbdkit/keys.psk bdkit --tls=require --tls-psk=/etc/nbdkit/keys.psk file disk.img ``` -------------------------------- ### Run nbdkit with Memory Plugin on Linux Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Demonstrates running the cross-compiled nbdkit server with the memory plugin on Linux using Wine, without requiring installation. ```bash ./nbdkit.exe -f -v memory 1G ``` -------------------------------- ### nbdkit Built-in Filters Examples Source: https://context7.com/nbdkit/nbdkit/llms.txt Demonstrates stacking and usage of various built-in nbdkit filters for common tasks like copy-on-write, offsetting, error injection, rate limiting, compression, partitioning, read-only enforcement, logging, resizing, and combining filters. ```bash # Copy-on-write: all writes go to a temporary overlay, discarded on exit nbdkit --filter=cow file disk.img # COW with read-caching into the overlay nbdkit --filter=cow file disk.img cow-on-read=true # Offset + range window into a larger image nbdkit --filter=offset file disk.img offset=512 range=1G # Inject random errors and delays for client resilience testing nbdkit --filter=error --filter=delay memory 100M \ error-rate=5% rdelay=10ms wdelay=10ms # Rate-limit bandwidth to 10 MiB/s read, 5 MiB/s write nbdkit --filter=rate file disk.img rate=10M wrate=5M # Compress/decompress on-the-fly (serve an xz file as raw block device) nbdkit --filter=xz file disk.img.xz # Expose only partition 2 nbdkit --filter=partition file disk.img partition=2 # Enforce read-only regardless of plugin capability nbdkit --filter=readonly file disk.img # Log all I/O to a file for debugging nbdkit --filter=log file disk.img logfile=/tmp/nbd.log # Resize the export (truncate or extend with zeroes) nbdkit --filter=truncate memory 1G truncate=500M # Stack multiple filters: partition → xz → file nbdkit --filter=partition --filter=xz file disk.img.xz partition=1 ``` -------------------------------- ### Python Plugin Example: Ramdisk Source: https://context7.com/nbdkit/nbdkit/llms.txt Example of an in-memory read/write disk plugin in Python. Requires setting API_VERSION = 2 and defining module-level functions for callbacks. The 'size' parameter is mandatory. ```python # ramdisk.py — in-memory read/write disk # Run: nbdkit -fv python ramdisk.py size=67108864 import nbdkit import errno API_VERSION = 2 disk = bytearray(0) def config(key, value): global disk if key == "size": disk = bytearray(int(value)) else: nbdkit.debug("ignored parameter %s=%s" % (key, value)) def config_complete(): if len(disk) == 0: raise Exception("size parameter is required") def open(readonly): nbdkit.debug("open: readonly=%d tls=%r" % (readonly, nbdkit.is_tls())) return {} # per-connection handle (any Python object) def get_size(h): return len(disk) def pread(h, buf, offset, flags): end = offset + len(buf) buf[:] = disk[offset:end] def pwrite(h, buf, offset, flags): end = offset + len(buf) disk[offset:end] = buf def zero(h, count, offset, flags): if flags & nbdkit.FLAG_MAY_TRIM: disk[offset:offset + count] = bytearray(count) else: nbdkit.set_error(errno.EOPNOTSUPP) raise Exception("trim not permitted") def flush(h, flags): pass # in-memory, nothing to flush # Connect: # guestfish --format=raw -a nbd://localhost ``` -------------------------------- ### Client connects with libnbd/nbdinfo using TLS Source: https://context7.com/nbdkit/nbdkit/llms.txt Examples of how a client can connect to an nbdkit server using TLS, either with standard certificates or PSK authentication. ```bash nbdinfo nbds://localhost ``` ```bash nbdinfo "nbds://alice@localhost?tls-psk-file=/etc/nbdkit/keys.psk" ``` -------------------------------- ### Get Interactive Help for nbdkit Plugin Source: https://context7.com/nbdkit/nbdkit/llms.txt Command to display interactive help for a specific nbdkit plugin's parameters. ```bash # Interactive help for a plugin's parameters bdkit --help file ``` -------------------------------- ### Enabling and Testing Systemd Socket Activation Source: https://context7.com/nbdkit/nbdkit/llms.txt Commands to enable and start the nbdkit systemd socket and test the connection using nbdinfo. ```bash systemctl enable --now nbdkit.socket # Test: bdinfo nbd://localhost ``` -------------------------------- ### Minimal Read/Write In-Memory C Plugin Source: https://context7.com/nbdkit/nbdkit/llms.txt This C plugin provides a basic in-memory disk image with read and write capabilities. It requires the `NBDKIT_API_VERSION`, includes necessary headers, defines a disk size, and implements core callbacks for loading, unloading, opening, getting size, reading, writing, and flushing. ```c #define NBDKIT_API_VERSION 2 #include #include #include #include #define DISK_SIZE (64 * 1024 * 1024) /* 64 MiB */ static unsigned char *disk; #define THREAD_MODEL NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS static void myplugin_load (void) { disk = calloc (DISK_SIZE, 1); } static void myplugin_unload (void) { free (disk); } static void * myplugin_open (int readonly) { return NBDKIT_HANDLE_NOT_NEEDED; } static int64_t myplugin_get_size (void *handle) { return DISK_SIZE; } static int myplugin_pread (void *handle, void *buf, uint32_t count, uint64_t offset, uint32_t flags) { memcpy (buf, disk + offset, count); return 0; } static int myplugin_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset, uint32_t flags) { memcpy (disk + offset, buf, count); /* If NBDKIT_FLAG_FUA is set we must flush to persistent storage here */ return 0; } static int myplugin_flush (void *handle, uint32_t flags) { /* Nothing to flush for in-memory storage */ return 0; } static struct nbdkit_plugin plugin = { .name = "myplugin", .longname = "My Example Plugin", .description = "64 MiB in-memory read/write disk", .load = myplugin_load, .unload = myplugin_unload, .open = myplugin_open, .get_size = myplugin_get_size, .pread = myplugin_pread, .pwrite = myplugin_pwrite, .flush = myplugin_flush, .errno_is_preserved = 1, }; NBDKIT_REGISTER_PLUGIN (plugin) /* * Build and run: * gcc -fPIC -shared myplugin.c -o myplugin.so * nbdkit -fv ./myplugin.so * # connect: guestfish --format=raw -a nbd://localhost */ ``` -------------------------------- ### Configure nbdkit on macOS Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Build configuration for nbdkit on macOS, specifying include and library paths for MacPorts. Assumes MacPorts is installed. ```bash ./configure --enable-gcc-warnings --disable-perl \ CFLAGS="-g -O2 -I/opt/local/include" \ LDFLAGS="-L/opt/local/lib" ``` -------------------------------- ### Systemd Socket Activation Configuration Source: https://context7.com/nbdkit/nbdkit/llms.txt Configuration files for enabling nbdkit with systemd socket activation, allowing it to start only when a client connects. Includes socket and service unit files. ```ini # /etc/systemd/system/nbdkit.socket [Unit] Description=nbdkit NBD server socket [Socket] ListenStream=10809 Accept=no [Install] WantedBy=sockets.target ``` ```ini # /etc/systemd/system/nbdkit.service [Unit] Description=nbdkit NBD server Requires=nbdkit.socket [Service] ExecStart=/usr/sbin/nbdkit --tls=require file /srv/disk.img StandardInput=socket # Socket activation: nbdkit detects LISTEN_FDS automatically ``` -------------------------------- ### Configure Python Version for nbdkit Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Specify a particular Python version during configuration if multiple versions are installed. Requires nbdkit >= 1.16 and Python >= 3.6. ```bash ./configure PYTHON=/usr/bin/python3.8 ``` -------------------------------- ### Format and populate memory disk with guestfish in captive mode Source: https://context7.com/nbdkit/nbdkit/llms.txt Use nbdkit with the memory plugin and `--run` to create a memory disk, then format and populate it using guestfish. The `$uri` variable is available for guestfish. ```bash nbdkit memory 2G --run ' guestfish --format=raw -a "$uri" -i < #include #include static char *filename = NULL; static int port = 0; static int myplugin_config (const char *key, const char *value) { if (strcmp (key, "file") == 0) { free (filename); filename = strdup (value); return 0; } else if (strcmp (key, "port") == 0) { if (nbdkit_parse_int ("port", value, &port) == -1) return -1; return 0; } nbdkit_error ("unknown parameter: %s", key); return -1; } static int myplugin_config_complete (void) { if (filename == NULL) { nbdkit_error ("the 'file' parameter is required"); return -1; } return 0; } /* Magic config key: bare positional argument is treated as 'file=...' */ static struct nbdkit_plugin plugin = { .name = "myplugin", .magic_config_key = "file", .config = myplugin_config, .config_complete = myplugin_config_complete, .config_help = "file= Path to disk image (required)\n" "port= Optional port number", /* ... other callbacks ... */ }; NBDKIT_REGISTER_PLUGIN (plugin) /* * Usage: * nbdkit ./myplugin.so disk.img # magic key * nbdkit ./myplugin.so file=disk.img # explicit key * nbdkit ./myplugin.so file=disk.img port=8080 */ ``` -------------------------------- ### Run captive qemu with memory plugin Source: https://context7.com/nbdkit/nbdkit/llms.txt Run nbdkit with the memory plugin and a captive qemu process using the NBD URI. ```bash nbdkit memory 2G --run 'qemu-system-x86_64 -drive file="$uri",if=virtio' ``` -------------------------------- ### Serve ISO 9660 image from a directory Source: https://context7.com/nbdkit/nbdkit/llms.txt Create an ISO 9660 image from the contents of a directory. ```bash nbdkit iso mydir/ ``` -------------------------------- ### Show plugin capabilities Source: https://context7.com/nbdkit/nbdkit/llms.txt Display the capabilities and options of a specific plugin, in this case, the 'memory' plugin. ```bash nbdkit memory --dump-plugin ``` -------------------------------- ### Serve a null device Source: https://context7.com/nbdkit/nbdkit/llms.txt Create a null device that reads as zeroes and discards writes. Specify the size. ```bash nbdkit null 1G ``` -------------------------------- ### Serve over Unix socket with guestfish Source: https://context7.com/nbdkit/nbdkit/llms.txt Serve a disk image over a Unix domain socket and run guestfish captively. nbdkit is automatically killed when guestfish exits. ```bash nbdkit file disk.img --run 'guestfish --format=raw -a "$uri" -i' ``` -------------------------------- ### Run nbdkit, connect client, and unmount in captive mode Source: https://context7.com/nbdkit/nbdkit/llms.txt Demonstrates running nbdkit, connecting an nbd-client, performing operations, and unmounting within a single `--run` command. The `$port` variable is used to connect to the NBD server. ```bash nbdkit file disk.img --run ' nbd-client localhost $port /dev/nbd0 mount /dev/nbd0p1 /mnt # ... do work ... umount /mnt nbd-client -d /dev/nbd0 ' ``` -------------------------------- ### Inspect nbdkit Build Configuration Source: https://context7.com/nbdkit/nbdkit/llms.txt Command to display compile-time options, paths, and enabled features for nbdkit. ```bash # Show all compile-time options (paths, enabled features, TLS support, etc.) bdkit --dump-config # Output includes: # version=1.46.0 # libdir=/usr/lib64/nbdkit # plugindir=/usr/lib64/nbdkit/plugins # filterdir=/usr/lib64/nbdkit/filters # has_tls=yes ``` -------------------------------- ### Dump compile-time configuration Source: https://context7.com/nbdkit/nbdkit/llms.txt Display the compile-time configuration options of the nbdkit binary. ```bash nbdkit --dump-config ``` -------------------------------- ### Serve a pattern-filled disk Source: https://context7.com/nbdkit/nbdkit/llms.txt Create a disk image filled with a repeating pattern, useful for testing. ```bash nbdkit pattern size=1G ``` -------------------------------- ### Configure nbdkit for Development with GCC Warnings and Valgrind Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Enables GCC warnings and Valgrind support during configuration for development purposes. Requires valgrind and development headers. ```bash ./configure --enable-gcc-warnings --enable-valgrind ``` -------------------------------- ### Serve specific partition with compression Source: https://context7.com/nbdkit/nbdkit/llms.txt Serve only partition 1 from a compressed image file. Filters are stacked from left to right. ```bash nbdkit --filter=partition --filter=xz file disk.img.xz partition=1 ``` -------------------------------- ### Build Container Image with Podman Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/ci/README.rst Use this command to build a container image for a specific Linux distribution. Replace 'fedora-rawhide' with your desired distribution file name. This image can then be used to run tests. ```shell podman build -f ci/containers/fedora-rawhide.Dockerfile -t nbdkit-fedora-rawhide ``` -------------------------------- ### Serve on-demand disk Source: https://context7.com/nbdkit/nbdkit/llms.txt Create a disk image on-demand per client connection with a specified size. ```bash nbdkit ondemand size=1G ``` -------------------------------- ### Run Container with Bind Mount and User Mapping Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/ci/README.rst Execute commands within a container, mounting the current directory as '/repo' and setting it as the working directory. This ensures changes are visible locally and vice-versa. The command runs under a user with the same UID as the host user. ```shell podman run -it --rm --userns=keep-id -v .:/repo:z -w /repo nbdkit-fedora-rawhide bash ``` -------------------------------- ### Run nbdkit with Memory Plugin on Windows Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Runs the nbdkit server on a Windows system using the memory plugin. Ensure the necessary DLLs and firewall rules are in place. ```bash nbdkit.exe -f -v nbdkit-memory-plugin.dll 1G ``` -------------------------------- ### C Plugin Data Serving Callbacks Source: https://context7.com/nbdkit/nbdkit/llms.txt Implement .pread, .pwrite, .flush, .trim, and .zero callbacks for core data I/O. The plugin only needs to perform I/O as nbdkit handles bounds-checking. ```c #define NBDKIT_API_VERSION 2 #include #include #include #include static int fd = -1; static int myplugin_pread (void *handle, void *buf, uint32_t count, uint64_t offset, uint32_t flags) { ssize_t n = pread (fd, buf, count, (off_t) offset); if (n == -1) { nbdkit_error ("pread: %m"); return -1; } return 0; } static int myplugin_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset, uint32_t flags) { ssize_t n = pwrite (fd, buf, count, (off_t) offset); if (n == -1) { nbdkit_error ("pwrite: %m"); return -1; } if (flags & NBDKIT_FLAG_FUA) { if (fdatasync (fd) == -1) { nbdkit_error ("fdatasync: %m"); return -1; } } return 0; } static int myplugin_flush (void *handle, uint32_t flags) { if (fdatasync (fd) == -1) { nbdkit_error ("fdatasync: %m"); return -1; } return 0; } static int myplugin_trim (void *handle, uint32_t count, uint64_t offset, uint32_t flags) { #ifdef FALLOC_FL_PUNCH_HOLE if (fallocate (fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, (off_t) offset, (off_t) count) == -1) { nbdkit_error ("fallocate (trim): %m"); return -1; } return 0; #else nbdkit_set_error (EOPNOTSUPP); return -1; #endif } static int myplugin_zero (void *handle, uint32_t count, uint64_t offset, uint32_t flags) { if (flags & NBDKIT_FLAG_FAST_ZERO) { /* Report quickly if we cannot do this faster than pwrite */ nbdkit_set_error (EOPNOTSUPP); return -1; } /* ... write zeroes ... */ return 0; } ``` -------------------------------- ### Run Container with Bind Mount and User Mapping (Docker) Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/ci/README.rst An alternative to the podman command, this uses 'docker run' to achieve the same result: executing commands within a container with the current directory bind-mounted and set as the working directory. It also maps the user ID. ```shell docker run -it --rm --user $UID:$UID -v $PWD:/repo:z -w /repo nbdkit-fedora-rawhide bash ``` -------------------------------- ### Run nbdkit from Source Directory Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Execute nbdkit and its plugins directly from the compiled source directory using the top-level wrapper script. ```bash $ ./nbdkit example1 -f -v ./server/nbdkit ./plugins/example1/.libs/nbdkit-example1-plugin.so -f -v [etc] ``` -------------------------------- ### Go RAMDisk Plugin Source: https://context7.com/nbdkit/nbdkit/llms.txt Implements an in-memory disk plugin for nbdkit. Requires the 'size' parameter during configuration. The disk is initialized when GetReady is called. ```go // ramdisk.go — in-memory disk in Go // Run: nbdkit -fv golang ramdisk.so size=67108864 package main import ( "C" "libguestfs.org/nbdkit" "strconv" "unsafe" ) var pluginName = "ramdisk" type RAMDiskPlugin struct{ nbdkit.Plugin } type RAMDiskConnection struct{ nbdkit.Connection } var size uint64 var disk []byte func (p *RAMDiskPlugin) Config(key, value string) error { if key == "size" { var err error size, err = strconv.ParseUint(value, 0, 64) return err } return nbdkit.PluginError{Errmsg: "unknown parameter"} } func (p *RAMDiskPlugin) ConfigComplete() error { if size == 0 { return nbdkit.PluginError{Errmsg: "size parameter is required"} } return nil } func (p *RAMDiskPlugin) GetReady() error { disk = make([]byte, size) return nil } func (p *RAMDiskPlugin) Open(readonly bool) (nbdkit.ConnectionInterface, error) { return &RAMDiskConnection{}, nil } func (c *RAMDiskConnection) GetSize() (uint64, error) { return size, nil } func (c *RAMDiskConnection) CanWrite() (bool, error) { return true, nil } func (c *RAMDiskConnection) PRead(buf []byte, offset uint64, flags uint32) error { copy(buf, disk[offset:int(offset)+len(buf)]) return nil } func (c *RAMDiskConnection) PWrite(buf []byte, offset uint64, flags uint32) error { copy(disk[offset:int(offset)+len(buf)], buf) return nil } //export plugin_init func plugin_init() unsafe.Pointer { return nbdkit.PluginInitialize(pluginName, &RAMDiskPlugin{}) } func main() {} ``` -------------------------------- ### Serve floppy disk image from a directory Source: https://context7.com/nbdkit/nbdkit/llms.txt Create a floppy disk image from the contents of a directory. ```bash nbdkit floppy mydir/ ``` -------------------------------- ### Configure and Build nbdkit for Windows Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Configures the nbdkit build for Windows cross-compilation and initiates the build process. Assumes autoreconf has been run if building from git. ```bash autoreconf -i # when building from git mingw64-configure --disable-ocaml --disable-perl make ``` -------------------------------- ### Run nbdkit Benchmarks Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Executes the nbdkit benchmark suite. ```bash make bench ``` -------------------------------- ### Serve torrent Source: https://context7.com/nbdkit/nbdkit/llms.txt Serve a disk image from a torrent file. Requires libtorrent-rasterbar. ```bash nbdkit torrent file.torrent ``` -------------------------------- ### Run nbdkit Test Suite Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Executes the nbdkit test suite. Check 'tests/*.log' for details on failures. ```bash make check ``` -------------------------------- ### Serve a sparse in-memory RAM disk Source: https://context7.com/nbdkit/nbdkit/llms.txt Create a sparse in-memory RAM disk of a specified size. ```bash nbdkit memory 1G ``` -------------------------------- ### stdin/stdout mode (inetd) Source: https://context7.com/nbdkit/nbdkit/llms.txt Run nbdkit in inetd mode, using standard input and output for communication. ```bash nbdkit -s file disk.img ``` -------------------------------- ### Benchmark null plugin with fio in captive mode Source: https://context7.com/nbdkit/nbdkit/llms.txt Benchmark a null plugin using fio in captive mode. The `$uri` variable is exported for fio to use. ```bash nbdkit -f null 10G --run 'export uri; fio --filename="$uri" \ --name=randread --rw=randread --bs=4k --iodepth=32 --numjobs=4' ``` -------------------------------- ### Serve a local file Source: https://context7.com/nbdkit/nbdkit/llms.txt Serve a local file as an NBD export. Supports directory exports since version 1.44. ```bash nbdkit file disk.img ``` ```bash nbdkit file dir=/srv/disks/ ``` -------------------------------- ### Inspect nbdkit Plugin Details Source: https://context7.com/nbdkit/nbdkit/llms.txt Command to show detailed information about a specific nbdkit plugin, including its capabilities and thread model. ```bash # Show detailed information about a plugin bdkit file --dump-plugin # Output includes: # name=file # version=1.46.0 # thread_model=serialize_requests # max_thread_model=parallel # has_pwrite=1 # has_trim=1 # has_zero=1 # has_extents=1 ``` -------------------------------- ### Test nbdkit with Valgrind Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Runs the test suite with Valgrind enabled to detect memory errors and leaks. Requires nbdkit to be configured with --enable-valgrind. ```bash make check-valgrind ``` -------------------------------- ### Configure OCaml Warnings for nbdkit Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Enable OCaml warnings and treat them as errors during configuration. Intended for developers. ```bash ./configure OCAMLOPTFLAGS="-warn-error +A-3" ``` -------------------------------- ### Add NBDKit Dependency Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/plugins/rust/README.md To use the nbdkit crate, add it to your Cargo.toml file. ```toml [dependencies] nbdkit = "0.1.0" ``` -------------------------------- ### Serve a raw disk image Source: https://context7.com/nbdkit/nbdkit/llms.txt Serve a raw disk image file on the default NBD port (10809). ```bash nbdkit file disk.img ``` -------------------------------- ### Construct arbitrary disk contents inline Source: https://context7.com/nbdkit/nbdkit/llms.txt Use the data plugin to construct arbitrary disk contents inline using hexadecimal byte sequences. ```bash nbdkit data ' ( 0x55 0xAA )*2048 ' ``` -------------------------------- ### Daemonize and record PID Source: https://context7.com/nbdkit/nbdkit/llms.txt Run nbdkit as a daemon in the background and record its process ID (PID) to a file. ```bash nbdkit -P /run/nbdkit.pid file disk.img ``` -------------------------------- ### Serve read-only with TLS Source: https://context7.com/nbdkit/nbdkit/llms.txt Serve a disk image in read-only mode, requiring TLS for secure connections. ```bash nbdkit --tls=require -r file disk.img ``` -------------------------------- ### TLS with certificates Source: https://context7.com/nbdkit/nbdkit/llms.txt Configure nbdkit to require TLS, specifying the directory for certificates and enabling peer verification. ```bash nbdkit --tls=require \ --tls-certificates=/etc/nbdkit/certs \ --tls-verify-peer \ file disk.img ``` -------------------------------- ### Log to file Source: https://context7.com/nbdkit/nbdkit/llms.txt Configure nbdkit to write log messages to a specified file. ```bash nbdkit --log=/var/log/nbdkit.log file disk.img ``` -------------------------------- ### Copy compressed image using nbdcopy in captive mode Source: https://context7.com/nbdkit/nbdkit/llms.txt Use nbdkit with the xz filter and `--run` to copy a compressed image to a new raw file using nbdcopy. The `$uri` variable provides the NBD URI. ```bash nbdkit --filter=xz file disk.img.xz \ --run 'nbdcopy "$uri" output.img' ``` -------------------------------- ### Test nbdkit-vddk-plugin with VDDK Library Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Tests the nbdkit-vddk-plugin against the proprietary VDDK library. Specify the directory containing the library. ```bash make check-vddk vddkdir=vmware-vix-disklib-distrib ``` -------------------------------- ### Configure nbdkit for Downstream Packaging Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Configure nbdkit with extra distribution-specific information for downstream packagers. This aids in troubleshooting. ```bash ./configure --with-extra='...' ``` -------------------------------- ### Print NBD URI Source: https://context7.com/nbdkit/nbdkit/llms.txt Print the NBD URI of the running server, useful for clients to connect. ```bash nbdkit -U /tmp/sock --print-uri null ``` -------------------------------- ### Log to syslog Source: https://context7.com/nbdkit/nbdkit/llms.txt Configure nbdkit to send log messages to syslog. ```bash nbdkit --log=syslog file disk.img ``` -------------------------------- ### Implement NBDKit Server in Rust Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/plugins/rust/README.md Implement the `nbdkit::Server` trait and register your plugin using `nbdkit::plugin!` to create an NBD server in Rust. ```rust use nbdkit::* #[derive(Default)] struct MyPlugin { // ... } impl Server for MyPlugin { // ... } plugin!(MyPlugin {write_at, trim, ...}); ``` -------------------------------- ### Inline shell plugin for RAM disk Source: https://context7.com/nbdkit/nbdkit/llms.txt Serve a 1 MiB RAM disk using an inline shell script. The script handles 'get_size' and 'pread' commands. ```bash nbdkit sh - <<'EOF' case "$1" in get_size) echo 1M ;; pread) dd if=/dev/zero count=$3 iflag=count_bytes ;; *) exit 2 ;; esac EOF ``` -------------------------------- ### Test Cross-compiled nbdkit Server on Linux Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Tests the functionality of the cross-compiled nbdkit Windows executable on a Linux system, typically using Wine. It dumps the configuration of the server. ```bash ./nbdkit.exe --dump-config ``` -------------------------------- ### Compile nbdkit with Address Sanitizer (ASAN) Source: https://gitlab.com/nbdkit/nbdkit/-/blob/master/README.md Compiles nbdkit using clang and Address Sanitizer for detecting memory errors. Disables linker script and Golang support. Requires clang. ```bash ./configure CC=clang CXX=clang++ \ CFLAGS="-O0 -g -fsanitize=address -fno-omit-frame-pointer" \ --disable-linker-script \ --disable-golang make clean make ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0" make check ``` -------------------------------- ### Proxy to another NBD server Source: https://context7.com/nbdkit/nbdkit/llms.txt Connect to another NBD server and proxy requests to it using the nbd plugin. ```bash nbdkit nbd uri=nbd://remote.example.com ``` -------------------------------- ### Shell Script Plugin for nbdkit Source: https://context7.com/nbdkit/nbdkit/llms.txt This shell script acts as an nbdkit plugin to serve a local file over NBD. It handles various nbdkit callbacks like config, open, get_size, pread, pwrite, and trim. Ensure the script has execute permissions and is called correctly by nbdkit. ```bash #!/usr/bin/env bash # file-plugin.sh — serve a local file over NBD # Run: nbdkit -fv sh file-plugin.sh disk.img # # Exit codes: 0=OK 1=Error 2=method missing 3=false # Ensure we are called from nbdkit if [ ! -d "$tmpdir" ] || [ -z "$1" ]; then echo "$0: must be run from nbdkit" >&2; exit 1 fi f=$tmpdir/backing case "$1" in magic_config_key) echo "file" ;; config) [ "$2" = "file" ] || { echo "unknown param $2" >&2; exit 1; } [ -r "$3" ] || { echo "cannot read $3" >&2; exit 1; } ln -sf "$(realpath "$3")" "$f" ;; config_complete) [ -L "$f" ] || { echo "file parameter missing" >&2; exit 1; } ;; thread_model) echo parallel ;; open) # Print a per-connection handle (a temp directory path) mktemp -d "$tmpdir/handle-XXXXXX" ;; get_size) stat -L -c '%s' "$f" || exit 1 ;; pread) # $2=handle $3=count $4=offset dd iflag=skip_bytes,count_bytes skip=$4 count=$3 if="$f" || exit 1 ;; pwrite) # stdin holds the data to write dd oflag=seek_bytes conv=notrunc seek=$4 of="$f" || exit 1 ;; can_write) ;; # exit 0 = true trim) fallocate -p -o $4 -l $3 -n "$f" || exit 1 ;; can_trim) fallocate --help >/dev/null 2>&1 || exit 3 ;; flush) sync "$f" ;; can_flush) ;; *) exit 2 ;; esac exit 0 ``` -------------------------------- ### nbdkit Helper API Functions Source: https://context7.com/nbdkit/nbdkit/llms.txt Demonstrates various helper functions available in nbdkit for parsing sizes, booleans, and delays, as well as for error reporting, debugging, and managing exports. These functions are useful within plugin or filter callbacks. ```c #define NBDKIT_API_VERSION 2 #include #include static void demo_helpers (const char *size_str, const char *bool_str, const char *delay_str) { int64_t bytes; int flag; struct timespec ts; /* Parse a size like "1G", "512M", "4096" */ bytes = nbdkit_parse_size (size_str); /* returns -1 on error */ /* Parse a boolean like "true", "yes", "on", "1", "false", "0" */ if (nbdkit_parse_bool (bool_str, &flag) == -1) { nbdkit_error ("invalid boolean: %s", bool_str); } /* Parse a delay/duration like "100ms", "2s", "1min" */ if (nbdkit_parse_delay (delay_str, &ts) == -1) { nbdkit_error ("invalid delay: %s", delay_str); } /* Sleep interruptibly (honours shutdown) */ nbdkit_nanosleep (ts.tv_sec, ts.tv_nsec); /* Print debug message (only visible with -v) */ nbdkit_debug ("size=%%" PRId64 " flag=%%d", bytes, flag); /* Report an error to the client */ nbdkit_error ("something went wrong: %%m"); /* Set a specific errno for the error response */ nbdkit_set_error (ENOSPC); /* Get export name requested by the client */ const char *export = nbdkit_export_name (); /* Check if client completed TLS handshake */ int tls = nbdkit_is_tls (); /* Get client address (AF_INET, AF_INET6, AF_UNIX) */ /* nbdkit_peer_name (3) — see man page */ /* Intern a dynamically-built string for use as a const char * return value */ const char *s = nbdkit_printf_intern ("export-%%d", 42); /* Request shutdown from within a plugin */ nbdkit_shutdown (); } ``` -------------------------------- ### Exit with parent process Source: https://context7.com/nbdkit/nbdkit/llms.txt Configure nbdkit to exit automatically when its parent process dies, useful for managed environments. ```bash nbdkit --exit-with-parent file disk.img & ``` -------------------------------- ### C Plugin Core Callbacks Source: https://context7.com/nbdkit/nbdkit/llms.txt Core data-serving callbacks for C plugins: pread, pwrite, flush, trim, and zero. These functions handle I/O operations, with nbdkit ensuring bounds-checking. ```APIDOC ## Plugin callback: `.pread` / `.pwrite` / `.flush` / `.trim` / `.zero` The core data-serving callbacks. nbdkit guarantees bounds-checking; the plugin only needs to do I/O. ```c #define NBDKIT_API_VERSION 2 #include #include #include #include static int fd = -1; static int myplugin_pread (void *handle, void *buf, uint32_t count, uint64_t offset, uint32_t flags) { ssize_t n = pread (fd, buf, count, (off_t) offset); if (n == -1) { nbdkit_error ("pread: %m"); return -1; } return 0; } static int myplugin_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset, uint32_t flags) { ssize_t n = pwrite (fd, buf, count, (off_t) offset); if (n == -1) { nbdkit_error ("pwrite: %m"); return -1; } if (flags & NBDKIT_FLAG_FUA) { if (fdatasync (fd) == -1) { nbdkit_error ("fdatasync: %m"); return -1; } } return 0; } static int myplugin_flush (void *handle, uint32_t flags) { if (fdatasync (fd) == -1) { nbdkit_error ("fdatasync: %m"); return -1; } return 0; } static int myplugin_trim (void *handle, uint32_t count, uint64_t offset, uint32_t flags) { #ifdef FALLOC_FL_PUNCH_HOLE if (fallocate (fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, (off_t) offset, (off_t) count) == -1) { nbdkit_error ("fallocate (trim): %m"); return -1; } return 0; #else nbdkit_set_error (EOPNOTSUPP); return -1; #endif } static int myplugin_zero (void *handle, uint32_t count, uint64_t offset, uint32_t flags) { if (flags & NBDKIT_FLAG_FAST_ZERO) { /* Report quickly if we cannot do this faster than pwrite */ nbdkit_set_error (EOPNOTSUPP); return -1; } /* ... write zeroes ... */ return 0; } ``` ``` -------------------------------- ### Privilege drop Source: https://context7.com/nbdkit/nbdkit/llms.txt Drop privileges after startup, running as a specified user and group for security. ```bash nbdkit -u nobody -g nogroup file disk.img ``` -------------------------------- ### Enable nbdkit Plugin-Specific Tracing Source: https://context7.com/nbdkit/nbdkit/llms.txt Command to enable debug flags for plugin-specific tracing in nbdkit. ```bash # Debug flags for plugin-specific tracing bdkit -f -v -D file.zero=1 file disk.img ```