multifile(1)            FreeBSD General Commands Manual           multifile(1)

     multifile - multiplexing file server

     multifile -t <tlsconfigfile> -r <rootdir> [-u <user> -o <ocspfile>]

     Multifile is a multiplexing file server with Transport Layer Security.
     Mutifile delivers up to 255 multiplexed streams of file and local socket
     server content per connection.

     Multifile exchanges data with clients in frames of up to 65535 bytes.
     Frames begin with a 2-byte payload-length header.  A minimal client is
     included in the source distribution.

     A companion library, libmultifile(3), provides functions to aid the
     writing of blocking multifile clients.

     Another library, multiserve(3), makes it easy to write socket servers
     that work with multifile.

     When a client connects to multifile, multifile greets the client with a
     frame containing a line of UTF-8 text that advertises multifile's version
     and the maximum number of simultaneous requests multifile is configured
     to service per connection (the value of the -n option).  The values are
     separated by a colon (UTF-8 58).  The text is zero-terminated.  The
     advertisment has the following form:


     After they read the advertisement, clients send request frames.

     A client requests up to 255 (or the value of the -n option) resources in
     a request frame.  A request frame consists of UTF-8 UNIX paths separated
     by newlines and terminated with a zero byte.


     Components of paths must be separated by virgules (UTF-8 47).  Multiple
     contiguous virgules are not an error in a path.  Multiple virgules are
     collapsed into a single virgule by the kernel and have been since at
     least UNIX Version 6 of 1975.

     Paths must begin with a virgule or the UTF-8 represententation of 1 to 3
     numbers separated by colons.  Paths cannot begin with a full-stop "."
     (UTF-8 46).

     A path that begins with a virgule is an unconditional request.  If the
     path describes a file, multifile returns the data in the file in one or
     more response frames.  If the path describes a directory, multifile
     returns a content listing for the directory.  If the path describes a
     local socket, multifile returns data read from the socket.

     The path for a file or directory cannot contain a question mark "?"
     (UTF-8 63).

     If the path for a socket contains a question mark, the portion before the
     question mark is interpreted as the path to the socket, and the portion
     after the question mark is interpreted as the parameter string for the
     request.  Multifile writes the parameter string to the socket before
     reading the response.  The parameter string is always less than 64KiB in
     size.  The socket server reads its end of the socket until it returns
     EOF.  The server returns whatever stream of bytes it wants to return, and
     multifile frames and delivers the data.  The socket server terminates its
     response by closing the connection.

     A path that begins with numbers is a conditional request.  Multifile
     ignores the conditions for a socket path.

     The first number is a time value expressed as the number of seconds since
     the UNIX epoch (00:00:00 January 1, 1970 UTC).  The server only returns
     data for the requested entity if its modification time is more recent
     than the time value.

     The second number is optional.  If present, it must be separated from the
     time value by a colon: ":" (UTF-8 58).  The second number is an offset
     into the file.  The server returns data for the file starting from the
     offset byte.  The first byte in a file is numbered 0.  This value is
     ignored with directory requests.

     The third number is optional.  It cannot be present unless the offset is
     present.  If the third number is present, it must be separated from the
     offset by a colon.  The third number is a byte count.  The server
     delivers at most the byte count number of bytes from the file.  A request
     with a byte count of 0 is identical to a request with no count.  This
     value is ignored with directory requests.

     If a client wants to request a range of bytes unconditionally, the client
     specifies a time value of 0.  If a client wants to request multiple
     ranges from the same file, the client prefixes each range to a separate

     Response data are delivered in multiplexed frames.

     The first byte of response frames is an unsigned numerical response ID.
     The value of this number corresponds to the ordinal position of a path in
     its request frame.  The stream of response frames is terminated with a
     frame with a response ID of 0.

     In the first response frame for a request, the remaining bytes subsequent
     to the response ID are the response header.  A response header is UTF-8
     text describing the number of data bytes to be delivered and the last
     modification time expressed in seconds since the UNIX epoch.  The two
     values are separated by a colon.  The text is zero-terminated.  A non-
     zero count indicates that multifile will deliver data for that request.

     o   If the count is zero and the time is zero, the server could not
         access the requested entity.  Multifile delivers no further response
         frames for the path.

     o   If the count is zero and the time is non-zero, the conditions of a
         file or directory request could not be satisfied, or the file is
         empty.  Multifile delivers no further response frames for the path.

     o   If the count is non-zero and the time is non-zero, a file request is
         successful and the file's data are delivered in subsequent response

     o   If the count is non-zero and the time is zero, the path is a socket
         or a directory path.  Either multifile successfully connected to the
         socket, or multifile successfully opened the directory.  The count is
         inaccurate and should be ignored.  The length of the response data is
         not known in advance.  It may be zero.

     In response frames subsequent to the first for a request, the remaining
     bytes subsequent to the response ID are response data.  Multifile
     delivers empty frames for files and sockets that have data pending but
     are not ready to be read.

     The data returned for directory requests consists of lines of newline
     terminated UTF-8 text.  The first line contains the directory name and
     its modification time separated by a colon.  Each subsequent line
     consists of a directory entry's name, its size, and the entry's last
     modification time.  The three values are separated by colons.  The name
     is appended with a virgule if the named entity is a directory.  The name
     is appended with a plus sign (UTF-8 43) if the named entity is a socket.
     The directory listing is zero-terminated.

     A client can send request frames while it receives response frames.  The
     response IDs for the new requests are the same as they would be if all
     the active requests had been concatenated into one oversized request
     frame.  If a client submits more than 255 requests (see the -n option)
     before receiving a terminator frame, the excess requests are discarded.
     Note that each request path must fit entirely inside one request frame.
     Paths cannot be split across frames.

     Piggybacked requests enable the creation of fast and slow lanes so that
     clients do not have to wait for large resources to be delivered before
     requesting smaller resources.

     If a client does not receive response frames for new requests before
     receving the terminator frame, piggybacking did not occur.  Multifile
     delivered the response stream in its entirety before processing the new
     requests.  Multifile delivers the new requests in a new response stream.

     If a client wants to stop all or part of a response stream, the client
     sends a stop frame.  Then the client continues reading response frames
     until it reads the terminator frame.  Stopped responses cannot be

     A stop frame consists of a series of stop pairs.  A stop pair consists of
     a UTF-8 full-stop character "." (UTF-8 46) followed by the UTF-8
     representation of a number.  The number must correspond to the ordinal
     position of a path in its request frame.  A stop frame must be zero-

     A zero in a stop pair stops the entire response stream.  Negative numbers
     are ignored.

     Multifile closes idle connections every 20 seconds regardless of how long
     the associated clients have been connected.  An idle connection is one
     that is not delivering response data.

     By default, FreeBSD limits each process to a low number of maximum
     simultaneously open descriptors.  This places a limit on the number of
     connections multifile may multiplex.  Set these values at the command-
     line with the "sysctl" utility.  Enable them permanently by placing these
     lines in /etc/sysctl.conf on the host machine.  Your system will complain
     about these values if it lacks resources.


     Multifile writes its pid into /var/run/ if it can (ie., it
     is started as root).  You stop multifile with a SIGTERM.

     A rc.d script is installed in /usr/local/etc/rc.d/.  Add the following
     lines to /etc/rc.conf to start multifile on system boot.  Replace the
     items in brackets with values appropriate for your system.  These are the
     minimal set of options you should start with.  The available options are
     described in full at the end of this manual page.

     multifile_flags="-t <tls-config-file> -r <server-root> -u <user>"

     Start, stop, or restart multifile, or determine if it is running with the
     following commands.

     /usr/local/etc/rc.d/multifile start
     /usr/local/etc/rc.d/multifile stop
     /usr/local/etc/rc.d/multifile restart
     /usr/local/etc/rc.d/multifile status

     If you do not want multifile started on system start, set


     and use the following commands.

     /usr/local/etc/rc.d/multifile forcestart
     /usr/local/etc/rc.d/multifile forcestop
     /usr/local/etc/rc.d/multifile forcerestart
     /usr/local/etc/rc.d/multifile forcestatus

     The following command line options are recognized.  The -t and -r options
     are mandatory.  The rest are optional.

     -r  The -r option specifies the root directory of the server. The server
         invokes chdir(2) and chroot(2) on the value of this option before
         changing to the user and group specified by the -u and -g options.

         For maximum performance, serve files from a tmpfs(5) in-memory
         filesystem.  Create a mount point directory with mkdir(1).  Then, as
         root, create and mount the in-memory filesystem with:

         mount -t tmpfs tmpfs <mount point>

         Copy the files you wish to serve into into the mount point.  Pass the
         mount point or a directory that contains the mount point as the
         argument to -r.  The filesystem is not persistent between system
         starts, but you can easily craft a shell script wrapper around
         multifile to mount the tmpfs and copy over the applicable files on
         server start.  Note that if your files change, you must also copy the
         files to a persistent filesystem before unmounting, or you will lose
         the changes.

     -p  The -p option specifies the port to listen on.  This defaults to
         8000.  To bind to a port lower than 1024, the server must be started
         as root.

     -i  By default, multifile accepts connections on all interfaces it can
         find capable of IPv4 or IPv6.  The -i option limits the server to
         accepting connections from a specified interface.  Pass the IP
         address of the desired interface as argument.

     -m  By default, multifile maintains no more than 1024 simultaneous
         connections.  The -m option changes this value.

     -n  By default, multifile will service no more than 255 active requests
         per connection.  The -n option lowers this value.  Note that when
         multifile has 255 active requests for a connection, multifile can
         queue almost 17MiB of data for the connection at any one time.


     -g  The -u and the -g options are used to specify the user and group for
         the server.  If the server starts as an unprivileged user and group,
         then these options must be set to the user and group.  For multifile
         to change to a different user and group, it must be started as root.
         Both values default to "nobody".

         multifile restarts on receipt of SIGSEGV or SIGBUS.

         If multifile starts as root and changes user and group, multifile
         will be unable to restart if the server is not executable by the user
         or group.

         multifile will be unable to perform the operations that require root
         privileges after restart unless you turn on the setuid bit of the
         server (chmod +s).

     -x  The -x option prevents multifile from becoming a daemon and writing
         its pidfile to /var/run/.  multifile runs in the foreground.

     -o  The -o option specifies the fully qualified path to a file containing
         an OCSP response to be stapled to the TLS handshake.  To schedule
         at(1) jobs to fetch OCSP responses, follow the instructions in
         multifile_ocsp in the source distribution.

     -t  The -t option specifies the fully qualified path to the TLS
         configuration file.  The file must contain 3 lines of text.  The
         first line is the fully qualified path to the file holding the server
         key in PEM format. The second line is the password for the key.  This
         line can be blank if there is no password.  The third line is the
         fully qualified path to the file containing the certificate chain in
         PEM format.

         Multifile supports TLS 1.2 and TLS 1.3 with this cipher set:


     James Bailie <>

                               Wed Jul 10, 2019