.\" -*- mode: troff; coding: utf-8 -*-
.\" Automatically generated by Podwrapper::Man 1.47.8 (Pod::Simple 3.47)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>.
.ie n \{\
.    ds C` ""
.    ds C' ""
'br\}
.el\{\
.    ds C`
.    ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.\"
.\" If the F register is >0, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD.  Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{\
.    if \nF \{\
.        de IX
.        tm Index:\\$1\t\\n%\t"\\$2"
..
.        if !\nF==2 \{\
.            nr % 0
.            nr F 2
.        \}
.    \}
.\}
.rr rF
.\"
.\" Required to disable full justification in groff 1.23.0.
.if n .ds AD l
.\" ========================================================================
.\"
.IX Title "nbdkit-curl-plugin 1"
.TH nbdkit-curl-plugin 1 2026-04-25 nbdkit-1.47.8 NBDKIT
.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH NAME
nbdkit\-curl\-plugin \- nbdkit curl plugin (HTTP, FTP and other protocols)
.SH SYNOPSIS
.IX Header "SYNOPSIS"
.Vb 1
\& nbdkit \-r curl [url=]http://example.com/disk.img
.Ve
.SH DESCRIPTION
.IX Header "DESCRIPTION"
\&\f(CW\*(C`nbdkit\-curl\-plugin\*(C'\fR is a plugin for \fBnbdkit\fR\|(1) which turns content
served over HTTP, FTP, and more, into a Network Block Device.  It uses
a library called libcurl (also known as cURL) to read data from URLs.
The exact list of protocols that libcurl can handle depends on how it
was compiled, but most versions will handle HTTP, HTTPS, FTP, FTPS and
more (see: \f(CW\*(C`curl\ \-V\*(C'\fR).
.PP
\&\fBNote:\fR This plugin supports writes.  However for HTTP, you may not
want nbdkit to issue PUT requests to the remote server (which probably
doesn\*(Aqt understand them).  To force nbdkit to use a readonly
connection, pass the \fI\-r\fR flag.  Using the \fI\-r\fR flag also enables
NBD multi\-conn, which usually performs much better (if the client
supports it).
.PP
Although this plugin can access SFTP (ie. SSH) servers, it is much
better to use \fBnbdkit\-ssh\-plugin\fR\|(1).  This plugin can be used to
access \f(CW\*(C`file:///\*(C'\fR URLs, but you should use \fBnbdkit\-file\-plugin\fR\|(1)
instead.
.SH EXAMPLE
.IX Header "EXAMPLE"
.Vb 1
\& nbdkit \-r curl http://example.com/disk.img
.Ve
.PP
serves the remote disk image as NBD on TCP port 10809 (to control
ports and protocols used to serve NBD see \fBnbdkit\fR\|(1)).
.SH PARAMETERS
.IX Header "PARAMETERS"
.IP \fBcainfo=\fRFILENAME 4
.IX Item "cainfo=FILENAME"
(nbdkit ≥ 1.18)
.Sp
Configure CA bundle for libcurl. See \fBCURLOPT_CAINFO\fR\|(3) for details.
.Sp
Pass empty string in order to not use the default certificate store
that libcurl is compiled with.
.IP \fBcapath=\fRPATH 4
.IX Item "capath=PATH"
(nbdkit ≥ 1.18)
.Sp
Set CA certificates directory location for libcurl. See
\&\fBCURLOPT_CAPATH\fR\|(3) for more information.
.IP \fBconnections=\fRN 4
.IX Item "connections=N"
(nbdkit ≥ 1.34)
.Sp
Open up to \f(CW\*(C`N\*(C'\fR connections to the web server.  The default is 16.
Connections are shared between all NBD clients, so you may wish to
increase this if you expect many simultaneous NBD clients (or a single
client using many multi\-conn connections).
.Sp
See "NBD CONNECTIONS AND CURL HANDLES" below.
.IP \fBcookie=\fRCOOKIE 4
.IX Item "cookie=COOKIE"
.PD 0
.IP \fBcookie=+\fRFILENAME 4
.IX Item "cookie=+FILENAME"
.IP \fBcookie=\-\fR 4
.IX Item "cookie=-"
.IP \fBcookie=\-\fRFD 4
.IX Item "cookie=-FD"
.PD
(nbdkit ≥ 1.12)
.Sp
Set a cookie in the request header when connecting to the remote
server.
.Sp
A typical example is:
.Sp
.Vb 1
\& cookie=\*(Aqvmware_soap_session="52a01262\-bf93\-ccce\-d379\-8dabb3e55560"\*(Aq
.Ve
.Sp
This option can be used at most once.  It only works for HTTP and
HTTPS transports.  To set multiple cookies you must concatenate them
yourself, eg:
.Sp
.Vb 1
\& cookie=\*(Aqname1=content1; name2=content2\*(Aq
.Ve
.Sp
See \fBCURLOPT_COOKIE\fR\|(3) for more information about this.  The format
is quite strict and must consist of \f(CW\*(C`key=value\*(C'\fR, each cookie
separated by exactly \f(CW";\ "\fR (semicolon and space).
.Sp
If the cookie is used for authentication then passing it on the
command line is not secure on shared machines.  Use the alternate
\&\f(CW\*(C`+FILENAME\*(C'\fR syntax to pass it in a file, \f(CW\*(C`\-\*(C'\fR to read the cookie
interactively, or \f(CW\*(C`\-FD\*(C'\fR to read it from a file descriptor.
.IP \fBcookiefile=\fR 4
.IX Item "cookiefile="
(nbdkit ≥ 1.26)
.Sp
Enable cookie processing (eg. when following redirects), starting with
an empty list of cookies.  This is equivalent to calling
\&\fBCURLOPT_COOKIEFILE\fR\|(3) with an empty string.
.IP \fBcookiefile=\fRFILENAME 4
.IX Item "cookiefile=FILENAME"
(nbdkit ≥ 1.26)
.Sp
Enable cookie processing (eg. when following redirects), prepopulating
cookies from the given file.  The file can contain cookies in any
format supported by curl, see \fBCURLOPT_COOKIEFILE\fR\|(3).  Cookies sent
by the server are not saved when nbdkit exits.
.IP \fBcookiejar=\fRFILENAME 4
.IX Item "cookiejar=FILENAME"
(nbdkit ≥ 1.26)
.Sp
Enable cookie processing (eg. when following redirects), prepopulating
cookies from the given file, and writing server cookies back to the
file when the NBD handle is closed.  The file can contain cookies in
any format supported by curl, see \fBCURLOPT_COOKIEJAR\fR\|(3).
.Sp
There is some advice on the internet telling you to set this to
\&\fI/dev/null\fR, but you \fBshould not\fR do this because it can corrupt
\&\fI/dev/null\fR.  If you don\*(Aqt want a cookiejar, omit this option.  If
you want to enable cookie processing without updating a permanent
cookiejar, use the \f(CW\*(C`cookiefile=\*(C'\fR option instead.
.IP \fBcookie\-script=\fRSCRIPT 4
.IX Item "cookie-script=SCRIPT"
.PD 0
.IP \fBcookie\-script\-renew=\fRSECS 4
.IX Item "cookie-script-renew=SECS"
.PD
(nbdkit ≥ 1.22, not Windows)
.Sp
Run \f(CW\*(C`SCRIPT\*(C'\fR (a command or shell script fragment) to generate the
HTTP/HTTPS cookies.  \f(CW\*(C`cookie\-script\*(C'\fR cannot be used with \f(CW\*(C`cookie\*(C'\fR.
See "HEADER AND COOKIE SCRIPTS" below.
.IP \fBfollowlocation=false\fR 4
.IX Item "followlocation=false"
(nbdkit ≥ 1.26)
.Sp
Do not follow redirects from the server.  The default is true (follow
redirects).
.Sp
You can follow redirects but avoid redirecting to a less secure
protocol (eg. HTTPS redirecting to FTP) by using the \f(CW\*(C`protocols\*(C'\fR
parameter instead.
.IP \fBheader=\fRHEADER 4
.IX Item "header=HEADER"
(nbdkit ≥ 1.22)
.Sp
For HTTP/HTTPS, send a custom header, or remove a header that curl has
added.  To add a custom header:
.Sp
.Vb 1
\& header=\*(AqX\-My\-Name: John Doe\*(Aq
.Ve
.Sp
To remove a header that curl has added, add the header followed by a
colon and no value:
.Sp
.Vb 1
\& header=\*(AqUser\-Agent:\*(Aq
.Ve
.Sp
To add a custom header that has no value, you have to use a semicolon
instead of colon.  This adds an \f(CW\*(C`X\-Empty:\*(C'\fR header with no value:
.Sp
.Vb 1
\& header=\*(AqX\-Empty;\*(Aq
.Ve
.Sp
See \fBCURLOPT_HTTPHEADER\fR\|(3).  You can use this option multiple times
in order to add several headers.  Note this sends the header in all
requests, even when following a redirect, which can cause headers
(eg. containing sensitive authorization information) to be sent to
hosts other than the one originally requested.
.IP \fBheader\-script=\fRSCRIPT 4
.IX Item "header-script=SCRIPT"
.PD 0
.IP \fBheader\-script\-renew=\fRSECS 4
.IX Item "header-script-renew=SECS"
.PD
(nbdkit ≥ 1.22, not Windows)
.Sp
Run \f(CW\*(C`SCRIPT\*(C'\fR (a command or shell script fragment) to generate the
HTTP/HTTPS headers.  \f(CW\*(C`header\-script\*(C'\fR cannot be used with \f(CW\*(C`header\*(C'\fR.
See "HEADER AND COOKIE SCRIPTS" below.
.IP \fBhttp\-version=none\fR 4
.IX Item "http-version=none"
.PD 0
.IP \fBhttp\-version=1.0\fR 4
.IX Item "http-version=1.0"
.IP \fBhttp\-version=1.1\fR 4
.IX Item "http-version=1.1"
.IP \fBhttp\-version=2.0\fR 4
.IX Item "http-version=2.0"
.IP \fBhttp\-version=2TLS\fR 4
.IX Item "http-version=2TLS"
.IP \fBhttp\-version=2\-prior\-knowledge\fR 4
.IX Item "http-version=2-prior-knowledge"
.IP \fBhttp\-version=3\fR 4
.IX Item "http-version=3"
.IP \fBhttp\-version=3only\fR 4
.IX Item "http-version=3only"
.PD
(nbdkit ≥ 1.34)
.Sp
Force curl to use a particular HTTP protocol.  The default is \f(CW\*(C`none\*(C'\fR
meaning curl will negotiate the best protocol with the server.  The
other settings are mainly for testing.  See \fBCURLOPT_HTTP_VERSION\fR\|(3)
for details.
.IP \fBipresolve=any\fR 4
.IX Item "ipresolve=any"
.PD 0
.IP \fBipresolve=v4\fR 4
.IX Item "ipresolve=v4"
.IP \fBipresolve=v6\fR 4
.IX Item "ipresolve=v6"
.PD
(nbdkit ≥ 1.36)
.Sp
Force curl to use only IPv4 (\f(CW\*(C`ipresolve=v4\*(C'\fR), only IPv6
(\f(CW\*(C`ipresolve=v6\*(C'\fR) or any IP version supported by your system
(\f(CW\*(C`ipresolve=any\*(C'\fR).  The default is \f(CW\*(C`any\*(C'\fR.  See
\&\fBCURLOPT_IPRESOLVE\fR\|(3).
.IP \fBpassword=\fRPASSWORD 4
.IX Item "password=PASSWORD"
Set the password to use when connecting to the remote server.
.Sp
Note that passing this on the command line is not secure on shared
machines.
.IP \fBpassword=\-\fR 4
.IX Item "password=-"
Ask for the password (interactively) when nbdkit starts up.
.IP \fBpassword=+\fRFILENAME 4
.IX Item "password=+FILENAME"
Read the password from the named file.  This is a secure method
to supply a password, as long as you set the permissions on the file
appropriately.
.IP \fBpassword=\-\fRFD 4
.IX Item "password=-FD"
Read the password from file descriptor number \f(CW\*(C`FD\*(C'\fR, inherited from
the parent process when nbdkit starts up.  This is also a secure
method to supply a password.
.IP \fBprotocols=\fRPROTO,PROTO,... 4
.IX Item "protocols=PROTO,PROTO,..."
(nbdkit ≥ 1.12)
.Sp
Limit the protocols that are allowed in the URL.  Use this option for
extra security if the URL comes from an untrusted source and you want
to avoid security issues in the more obscure protocols that curl
supports.  (See qemu CVE\-2013\-0249 for an example of a security bug
introduced by allowing unrestricted protocols).
.Sp
For example if you only intend HTTP and HTTPS URLs to be used, then
add this parameter: \f(CW\*(C`protocols=http,https\*(C'\fR
.Sp
This restriction also applies if the plugin follows a redirect to
another protocol (eg. you start with an \f(CW\*(C`https://\*(C'\fR URL which the
server redirects to \f(CW\*(C`ftp://\*(C'\fR).  To prevent redirects altogether see
the \f(CW\*(C`followlocation\*(C'\fR parameter.
.Sp
The value of this parameter is a comma\-separated list of protocols,
for example \f(CW\*(C`protocols=https\*(C'\fR, or \f(CW\*(C`protocols=http,https\*(C'\fR, or
\&\f(CW\*(C`protocols=file,ftp,gopher\*(C'\fR.  For a list of known protocols, see the
libcurl manual (\fBCURLOPT_PROTOCOLS_STR\fR\|(3)), and in nbdkit\ ≥\ 1.40
the output of:
.Sp
.Vb 1
\& nbdkit curl \-\-dump\-plugin
.Ve
.Sp
The default is to allow any protocol.
.IP \fBproxy=\fRPROXY 4
.IX Item "proxy=PROXY"
(nbdkit ≥ 1.20)
.Sp
Set the proxy.  See \fBCURLOPT_PROXY\fR\|(3).
.IP \fBproxy\-cainfo=\fRFILENAME 4
.IX Item "proxy-cainfo=FILENAME"
.PD 0
.IP \fBproxy\-capath=\fRPATH 4
.IX Item "proxy-capath=PATH"
.PD
(nbdkit ≥ 1.44)
.Sp
Set the CA bundle and CA certificates directory location for the
proxy. See \fBCURLOPT_PROXY_CAINFO\fR\|(3) and \fBCURLOPT_PROXY_CAPATH\fR\|(3)
for more information.
.IP \fBproxy\-password=\fRPASSWORD 4
.IX Item "proxy-password=PASSWORD"
.PD 0
.IP \fBproxy\-password=\-\fR 4
.IX Item "proxy-password=-"
.IP \fBproxy\-password=+\fRFILENAME 4
.IX Item "proxy-password=+FILENAME"
.IP \fBproxy\-password=\-\fRFD 4
.IX Item "proxy-password=-FD"
.IP \fBproxy\-user=\fRUSERNAME 4
.IX Item "proxy-user=USERNAME"
.PD
(nbdkit ≥ 1.12)
.Sp
Set the proxy username and password.
.IP \fBresolve=\fRHOST\fB:\fRPORT\fB:\fRADDRESS 4
.IX Item "resolve=HOST:PORT:ADDRESS"
Provide custom host name to IP address resolution.  You can supply
this option as many times as needed.  See \fBCURLOPT_RESOLVE\fR\|(3) for
the full details of this option.
.IP \fBsslverify=false\fR 4
.IX Item "sslverify=false"
Don\*(Aqt verify the SSL certificate of the remote host.
.IP \fBssl\-cipher\-list=\fRCIPHER[:CIPHER...] 4
.IX Item "ssl-cipher-list=CIPHER[:CIPHER...]"
.PD 0
.IP \fBssl\-version=default\fR 4
.IX Item "ssl-version=default"
.IP \fBssl\-version=tlsv1\fR 4
.IX Item "ssl-version=tlsv1"
.IP \fBssl\-version=sslv2\fR 4
.IX Item "ssl-version=sslv2"
.IP \fBssl\-version=sslv3\fR 4
.IX Item "ssl-version=sslv3"
.IP \fBssl\-version=tlsv1.0\fR 4
.IX Item "ssl-version=tlsv1.0"
.IP \fBssl\-version=tlsv1.1\fR 4
.IX Item "ssl-version=tlsv1.1"
.IP \fBssl\-version=tlsv1.2\fR 4
.IX Item "ssl-version=tlsv1.2"
.IP \fBssl\-version=tlsv1.3\fR 4
.IX Item "ssl-version=tlsv1.3"
.IP \fBssl\-version=max\-default\fR 4
.IX Item "ssl-version=max-default"
.IP \fBssl\-version=max\-tlsv1.0\fR 4
.IX Item "ssl-version=max-tlsv1.0"
.IP \fBssl\-version=max\-tlsv1.1\fR 4
.IX Item "ssl-version=max-tlsv1.1"
.IP \fBssl\-version=max\-tlsv1.2\fR 4
.IX Item "ssl-version=max-tlsv1.2"
.IP \fBssl\-version=max\-tlsv1.3\fR 4
.IX Item "ssl-version=max-tlsv1.3"
.PD
Set the SSL ciphers and TLS version.  For further information see
\&\fBCURLOPT_SSL_CIPHER_LIST\fR\|(3) and \fBCURLOPT_SSLVERSION\fR\|(3).
.IP \fBtcp\-keepalive=true\fR 4
.IX Item "tcp-keepalive=true"
(nbdkit ≥ 1.20)
.Sp
Enable TCP keepalives.
.IP \fBtcp\-nodelay=false\fR 4
.IX Item "tcp-nodelay=false"
(nbdkit ≥ 1.20)
.Sp
Enable Nagle’s algorithm.  Small writes on the network socket will not
be sent immediately but will be held in a local buffer and coalesced
if possible.  This is more efficient for the network but can cause
increased latency.
.Sp
The default (in libcurl ≥ 7.50.2) is that Nagle’s algorithm is
disabled for better latency at the expense of network efficiency.
.Sp
See \fBCURLOPT_TCP_NODELAY\fR\|(3).
.IP \fBtimeout=\fRSECS 4
.IX Item "timeout=SECS"
Set the timeout for requests.
.IP \fBtimeout=0\fR 4
.IX Item "timeout=0"
Use the default libcurl timeout for requests.
.IP \fBtls13\-ciphers=\fRCIPHER[:CIPHER...] 4
.IX Item "tls13-ciphers=CIPHER[:CIPHER...]"
Select TLSv1.3 ciphers available.  See \fBCURLOPT_TLS13_CIPHERS\fR\|(3) and
https://curl.se/docs/ssl\-ciphers.html
.IP \fBunix\-socket\-path=\fRPATH 4
.IX Item "unix-socket-path=PATH"
(nbdkit ≥ 1.10)
.Sp
Instead of using a TCP connection, connect to the server over the
named Unix domain socket.  See \fBCURLOPT_UNIX_SOCKET_PATH\fR\|(3).
.IP [\fBurl=\fR]URL 4
.IX Item "[url=]URL"
The URL of the remote disk image.  This is passed to libcurl directly
via \fBCURLOPT_URL\fR\|(3).
.Sp
This parameter is required.
.Sp
\&\f(CW\*(C`url=\*(C'\fR prefix may be omitted in most cases.
See "Magic parameters" in \fBnbdkit\fR\|(1).
.IP \fBuser=\fRUSERNAME 4
.IX Item "user=USERNAME"
Set the username to use when connecting to the remote server.  This
may also be set in the URL (eg. \f(CW\*(C`http://foo@example.com/disk.img\*(C'\fR)
.IP \fBuser\-agent=\fRUSER\-AGENT 4
.IX Item "user-agent=USER-AGENT"
(nbdkit ≥ 1.22)
.Sp
Send user\-agent header when using HTTP or HTTPS.  The default is no
user\-agent header.
.SH "NBD CONNECTIONS AND CURL HANDLES"
.IX Header "NBD CONNECTIONS AND CURL HANDLES"
nbdkit ≤ 1.32 used a simple model where a new NBD connection would
create a new libcurl handle.  Since a libcurl handle maintains a small
cache of connections, this meant that the number of HTTP connections
would be a small multiple of the number of incoming NBD connections
and the total would not be limited (assuming \f(CW\*(C`http:\*(C'\fR or \f(CW\*(C`https:\*(C'\fR
URL).
.PP
nbdkit 1.34 changed to using a fixed pool of libcurl handles shared
across all NBD connections.  You can control the maximum number of
curl handles in the pool with the \f(CW\*(C`connections\*(C'\fR parameter (default
4).  Since each curl handle maintains a small cache of connections,
this meant that the number of HTTP connections would be a small
multiple of the \f(CW\*(C`connections\*(C'\fR parameter.  If there are more than 4
incoming NBD connections, they will contend for the libcurl handles,
unless you adjust \f(CW\*(C`connections\*(C'\fR.
.PP
nbdkit ≥ 1.36 changed again to use a curl multi handle
(\fBlibcurl\-multi\fR\|(3)).  Now the \f(CW\*(C`connections\*(C'\fR parameter controls the
maximum number of HTTP connections made to the remote server
(\fBCURLMOPT_MAX_TOTAL_CONNECTIONS\fR\|(3)).  This is more efficient
especially with HTTP/2 and HTTP/3, where each HTTP connection can
contain a very large number of streams (typically up to 100)
multiplexed over one connection.  The default for \f(CW\*(C`connections\*(C'\fR was
raised to 16.
.SH "HEADER AND COOKIE SCRIPTS"
.IX Header "HEADER AND COOKIE SCRIPTS"
While the \f(CW\*(C`header\*(C'\fR and \f(CW\*(C`cookie\*(C'\fR parameters can be used to specify
static headers and cookies which are used in every HTTP/HTTPS request,
the alternate \f(CW\*(C`header\-script\*(C'\fR and \f(CW\*(C`cookie\-script\*(C'\fR parameters can be
used to run an external script or program to generate headers and/or
cookies.  This is particularly useful to access services which require
an authorization token.  In addition the \f(CW\*(C`header\-script\-renew\*(C'\fR and
\&\f(CW\*(C`cookie\-script\-renew\*(C'\fR parameters allow you to renew the authorization
token by rerunning the script periodically.
.PP
\&\f(CW\*(C`header\-script\*(C'\fR is incompatible with \f(CW\*(C`header\*(C'\fR, and \f(CW\*(C`cookie\-script\*(C'\fR
is incompatible with \f(CW\*(C`cookie\*(C'\fR.
.SS "Header script"
.IX Subsection "Header script"
The header script should print zero or more HTTP headers, each line of
output in the same format as the \f(CW\*(C`header\*(C'\fR parameter.  The headers
printed by the script are passed to \fBCURLOPT_HTTPHEADER\fR\|(3).
.PP
In the following example, an imaginary web service requires
authentication using a token fetched from a separate login server.
The token expires after 60 seconds, so we also tell the plugin that it
must renew the token (by re\-running the script) if more than 50
seconds have elapsed since the last request:
.PP
.Vb 7
\& nbdkit curl https://service.example.com/disk.img \e
\&        header\-script=\*(Aq
\&          printf "Authorization: Bearer "
\&          curl \-s \-X POST https://auth.example.com/login |
\&               jq \-r .token
\&        \*(Aq \e
\&        header\-script\-renew=50
.Ve
.SS "Cookie script"
.IX Subsection "Cookie script"
The cookie script should print a single line in the same format as the
\&\f(CW\*(C`cookie\*(C'\fR parameter.  This is passed to \fBCURLOPT_COOKIE\fR\|(3).
.SS "Header and cookie script shell variables"
.IX Subsection "Header and cookie script shell variables"
Within the \f(CW\*(C`header\-script\*(C'\fR and \f(CW\*(C`cookie\-script\*(C'\fR the following shell
variables are available:
.ie n .IP $iteration 4
.el .IP \f(CW$iteration\fR 4
.IX Item "$iteration"
The number of times that the script has been called.  The first time
the script is called this contains \f(CW0\fR.
.ie n .IP $url 4
.el .IP \f(CW$url\fR 4
.IX Item "$url"
The URL as passed to the plugin.
.SS "Example: VMware ESXi cookies"
.IX Subsection "Example: VMware ESXi cookies"
VMware ESXi’s web server can expose both VMDK and raw format disk
images, but requires you to log in using HTTP Basic Authentication.
While you can use the \f(CW\*(C`user\*(C'\fR and \f(CW\*(C`password\*(C'\fR parameters to send HTTP
Basic Authentication headers in every request, tests have shown that
it is faster to accept the cookie which the server returns and send
that instead.  (It is not clear why it is faster, but one theory is
that VMware has to do a more expensive username and password check
each time.)
.PP
The web server can be accessed as below.  Since the cookie expires
after a certain period of time, we use \f(CW\*(C`cookie\-script\-renew\*(C'\fR, and
because the server uses a self\-signed certificate we must use
\&\fI\-\-insecure\fR and \f(CW\*(C`sslverify=false\*(C'\fR.
.PP
.Vb 5
\& SERVER=esx.example.com
\& DCPATH=data
\& DS=datastore1
\& GUEST=guest\-name
\& URL="https://$SERVER/folder/$GUEST/$GUEST\-flat.vmdk?dcPath=$DCPATH&dsName=$DS"
\&
\& nbdkit curl "$URL" \e
\&        cookie\-script=\*(Aq
\&            curl \-\-head \-s \-\-insecure \-u root:password "$url" |
\&                 sed \-ne "{ s/^Set\-Cookie: \e([^;]*\e);.*/\e1/ip }"
\&        \*(Aq \e
\&        cookie\-script\-renew=500 \e
\&        sslverify=false
.Ve
.SS "Example: Docker Hub authorization tokens"
.IX Subsection "Example: Docker Hub authorization tokens"
Accessing objects like container layers from Docker Hub requires that
you first fetch an authorization token, even for anonymous access.
These tokens expire after about 5 minutes (300 seconds) so must be
periodically renewed.
.PP
You will need this authorization script (\fI/tmp/auth.sh\fR):
.PP
.Vb 4
\& #!/bin/sh \-
\& IMAGE=library/fedora
\& curl \-s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$IMAGE:pull" |
\&      jq \-r .token
.Ve
.PP
You will also need this script to get the blobSum of the layer
(\fI/tmp/blobsum.sh\fR):
.PP
.Vb 6
\& #!/bin/sh \-
\& TOKEN=\`/tmp/auth.sh\`
\& IMAGE=library/fedora
\& curl \-s \-X GET \-H "Authorization: Bearer $TOKEN" \e
\&      "https://registry\-1.docker.io/v2/$IMAGE/manifests/latest" |
\&      jq \-r \*(Aq.fsLayers[0].blobSum\*(Aq
.Ve
.PP
Both scripts must be executable, and both can be run on their own to
check they are working.  To run nbdkit:
.PP
.Vb 3
\& IMAGE=library/fedora
\& BLOBSUM=\`/tmp/blobsum.sh\`
\& URL="https://registry\-1.docker.io/v2/$IMAGE/blobs/$BLOBSUM"
\&
\& nbdkit curl "$URL" \e
\&        header\-script=\*(Aq printf "Authorization: Bearer "; /tmp/auth.sh \*(Aq \e
\&        header\-script\-renew=200 \e
\&        \-\-filter=gzip
.Ve
.PP
Note that this exposes a tar file over NBD.  See also
\&\fBnbdkit\-tar\-filter\fR\|(1).
.SH "DEBUG FLAGS"
.IX Header "DEBUG FLAGS"
.IP "\fB\-D curl.scripts=1\fR" 4
.IX Item "-D curl.scripts=1"
This prints out the headers and cookies generated by the
\&\f(CW\*(C`header\-script\*(C'\fR and \f(CW\*(C`cookie\-script\*(C'\fR options, which can be useful
when debugging these scripts.
.IP "\fB\-D curl.times=1\fR" 4
.IX Item "-D curl.times=1"
This prints out additional information about the total time taken to
do name resolution, connect to the remote server, etc.  The
information is printed in the debug output before nbdkit exits.  The
output will look like:
.Sp
.Vb 8
\& nbdkit: debug: times (\-D curl.times=1):
\& nbdkit: debug: name resolution               :    0.128442 s
\& nbdkit: debug: connection                    :    4.945213 s
\& nbdkit: debug: SSL negotiation               :    4.291362 s
\& nbdkit: debug: pretransfer                   :    0.104137 s
\& nbdkit: debug: first byte received           :   56.115269 s
\& nbdkit: debug: data transfer                 :  222.633831 s
\& nbdkit: debug: redirection time              :    0.000000 s
.Ve
.Sp
The cumulative time taken to perform each step is shown (summed across
all HTTP connections).  The redirection time is the total time taken
doing HTTP redirections.  For further information see
"TIMES" in \fBcurl_easy_getinfo\fR\|(3).
.IP "\fB\-D curl.verbose=1\fR" 4
.IX Item "-D curl.verbose=1"
This enables very verbose curl debugging.  See \fBCURLOPT_VERBOSE\fR\|(3).
This is mainly useful if you suspect there is a bug inside libcurl
itself.
.IP "\fB\-D curl.verbose.ids=1\fR" 4
.IX Item "-D curl.verbose.ids=1"
This enhances \f(CW\*(C`\-D curl.verbose=1\*(C'\fR by printing connection and transfer
IDs next to each debug message.  As this has some overhead it is not
enabled by default.
.SH FILES
.IX Header "FILES"
.ie n .IP \fR\fI$plugindir\fR\fI/nbdkit\-curl\-plugin.so\fR 4
.el .IP \fR\f(CI$plugindir\fR\fI/nbdkit\-curl\-plugin.so\fR 4
.IX Item "$plugindir/nbdkit-curl-plugin.so"
The plugin.
.Sp
Use \f(CW\*(C`nbdkit \-\-dump\-config\*(C'\fR to find the location of \f(CW$plugindir\fR.
.SH VERSION
.IX Header "VERSION"
\&\f(CW\*(C`nbdkit\-curl\-plugin\*(C'\fR first appeared in nbdkit 1.2.
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fBcurl\fR\|(1),
\&\fBlibcurl\fR\|(3),
\&\fBCURLOPT_CAINFO\fR\|(3),
\&\fBCURLOPT_CAPATH\fR\|(3),
\&\fBCURLOPT_COOKIE\fR\|(3),
\&\fBCURLOPT_COOKIEFILE\fR\|(3),
\&\fBCURLOPT_COOKIEJAR\fR\|(3),
\&\fBCURLOPT_FOLLOWLOCATION\fR\|(3),
\&\fBCURLOPT_HTTPHEADER\fR\|(3),
\&\fBCURLOPT_IPRESOLVE\fR\|(3),
\&\fBCURLOPT_PROXY\fR\|(3),
\&\fBCURLOPT_PROXY_CAINFO\fR\|(3),
\&\fBCURLOPT_PROXY_CAPATH\fR\|(3),
\&\fBCURLOPT_RESOLVE\fR\|(3),
\&\fBCURLOPT_SSL_CIPHER_LIST\fR\|(3),
\&\fBCURLOPT_SSLVERSION\fR\|(3),
\&\fBCURLOPT_TCP_KEEPALIVE\fR\|(3),
\&\fBCURLOPT_TCP_NODELAY\fR\|(3),
\&\fBCURLOPT_TLS13_CIPHERS\fR\|(3),
\&\fBCURLOPT_URL\fR\|(3),
\&\fBCURLOPT_UNIX_SOCKET_PATH\fR\|(3),
\&\fBCURLOPT_USERAGENT\fR\|(3),
\&\fBCURLOPT_VERBOSE\fR\|(3),
\&\fBnbdkit\fR\|(1),
\&\fBnbdkit\-extentlist\-filter\fR\|(1),
\&\fBnbdkit\-file\-plugin\fR\|(1),
\&\fBnbdkit\-nfs\-plugin\fR\|(1),
\&\fBnbdkit\-retry\-filter\fR\|(1),
\&\fBnbdkit\-retry\-request\-filter\fR\|(1),
\&\fBnbdkit\-ssh\-plugin\fR\|(1),
\&\fBnbdkit\-torrent\-plugin\fR\|(1),
\&\fBnbdkit\-plugin\fR\|(3),
http://curl.haxx.se,
https://curl.se/docs/ssl\-ciphers.html
.SH AUTHORS
.IX Header "AUTHORS"
Richard W.M. Jones
.PP
Parts derived from Alexander Graf\*(Aqs "QEMU Block driver for CURL images".
.SH COPYRIGHT
.IX Header "COPYRIGHT"
Copyright Red Hat
.SH LICENSE
.IX Header "LICENSE"
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
.IP \(bu 4
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
.IP \(bu 4
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
.IP \(bu 4
Neither the name of Red Hat nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
.PP
THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS \*(Aq\*(AqAS IS\*(Aq\*(Aq AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
