blob: 4fb46c7d0179d1e5ad2219fa8a203d0434960ae3 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.12"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>libwebsockets: Notes about lwsws</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
$(document).ready(initResizable);
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectlogo"><img alt="Logo" src="libwebsockets.org-logo.png"/></td>
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">libwebsockets
</div>
<div id="projectbrief">Lightweight C library for HTML5 websockets</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.12 -->
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
initMenu('',false,false,'search.php','Search');
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('md_README_8lwsws.html','');});
</script>
<div id="doc-content">
<div class="header">
<div class="headertitle">
<div class="title">Notes about lwsws </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h1><a class="anchor" id="lwsws"></a>
Libwebsockets Web Server</h1>
<p>lwsws is an implementation of a very lightweight, ws-capable generic web server, which uses libwebsockets to implement everything underneath.</p>
<p>If you are basically implementing a standalone server with lws, you can avoid reinventing the wheel and use a debugged server including lws.</p>
<h1><a class="anchor" id="lwswsb"></a>
Build</h1>
<p>Just enable -DLWS_WITH_LWSWS=1 at cmake-time.</p>
<p>It enables libuv and plugin support automatically.</p>
<p>NOTICE on Ubuntu, the default libuv package is called "libuv-0.10". This is ancient.</p>
<p>You should replace this with libuv1 and libuv1-dev before proceeding.</p>
<h1><a class="anchor" id="lwswsc"></a>
Lwsws Configuration</h1>
<p>lwsws uses JSON config files, they're pure JSON except:</p>
<ul>
<li>'#' may be used to turn the rest of the line into a comment.</li>
<li>There's also a single substitution, if a string contains "_lws_ddir_", then that is replaced with the LWS install data directory path, eg, "/usr/share" or whatever was set when LWS was built + installed. That lets you refer to installed paths without having to change the config if your install path was different.</li>
</ul>
<p>There is a single file intended for global settings</p>
<p>/etc/lwsws/conf </p><div class="fragment"><div class="line"># these are the server global settings</div><div class="line"># stuff related to vhosts should go in one</div><div class="line"># file per vhost in ../conf.d/</div><div class="line"></div><div class="line">{</div><div class="line"> &quot;global&quot;: {</div><div class="line"> &quot;uid&quot;: &quot;48&quot;, # apache user</div><div class="line"> &quot;gid&quot;: &quot;48&quot;, # apache user</div><div class="line"> &quot;count-threads&quot;: &quot;1&quot;,</div><div class="line"> &quot;server-string&quot;: &quot;myserver v1&quot;, # returned in http headers</div><div class="line"> &quot;ws-pingpong-secs&quot;: &quot;200&quot;, # confirm idle established ws connections this often</div><div class="line"> &quot;init-ssl&quot;: &quot;yes&quot;</div><div class="line"> }</div><div class="line">}</div></div><!-- fragment --><p> and a config directory intended to take one file per vhost</p>
<p>/etc/lwsws/conf.d/warmcat.com </p><div class="fragment"><div class="line">{</div><div class="line"> &quot;vhosts&quot;: [{</div><div class="line"> &quot;name&quot;: &quot;warmcat.com&quot;,</div><div class="line"> &quot;port&quot;: &quot;443&quot;,</div><div class="line"> &quot;interface&quot;: &quot;eth0&quot;, # optional</div><div class="line"> &quot;host-ssl-key&quot;: &quot;/etc/pki/tls/private/warmcat.com.key&quot;, # if given enable ssl</div><div class="line"> &quot;host-ssl-cert&quot;: &quot;/etc/pki/tls/certs/warmcat.com.crt&quot;,</div><div class="line"> &quot;host-ssl-ca&quot;: &quot;/etc/pki/tls/certs/warmcat.com.cer&quot;,</div><div class="line"> &quot;mounts&quot;: [{ # autoserve</div><div class="line"> &quot;mountpoint&quot;: &quot;/&quot;,</div><div class="line"> &quot;origin&quot;: &quot;file:///var/www/warmcat.com&quot;,</div><div class="line"> &quot;default&quot;: &quot;index.html&quot;</div><div class="line"> }]</div><div class="line"> }]</div><div class="line">}</div></div><!-- fragment --><p> To get started quickly, an example config reproducing the old test server on port 7681, non-SSL is provided. To set it up </p><div class="fragment"><div class="line"># mkdir -p /etc/lwsws/conf.d /var/log/lwsws</div><div class="line"># cp ./lwsws/etc-lwsws-conf-EXAMPLE /etc/lwsws/conf</div><div class="line"># cp ./lwsws/etc-lwsws-conf.d-localhost-EXAMPLE /etc/lwsws/conf.d/test-server</div><div class="line"># sudo lwsws</div></div><!-- fragment --><h1><a class="anchor" id="lwsogo"></a>
Other Global Options</h1>
<ul>
<li><code>reject-service-keywords</code> allows you to return an HTTP error code and message of your choice if a keyword is found in the user agent</li>
</ul>
<div class="fragment"><div class="line">&quot;reject-service-keywords&quot;: [{</div><div class="line"> &quot;scumbot&quot;: &quot;404 Not Found&quot;</div><div class="line">}]</div></div><!-- fragment --><h1><a class="anchor" id="lwswsv"></a>
Lwsws Vhosts</h1>
<p>One server can run many vhosts, where SSL is in use SNI is used to match the connection to a vhost and its vhost-specific SSL keys during SSL negotiation.</p>
<p>Listing multiple vhosts looks something like this </p><div class="fragment"><div class="line">{</div><div class="line"> &quot;vhosts&quot;: [ {</div><div class="line"> &quot;name&quot;: &quot;localhost&quot;,</div><div class="line"> &quot;port&quot;: &quot;443&quot;,</div><div class="line"> &quot;host-ssl-key&quot;: &quot;/etc/pki/tls/private/libwebsockets.org.key&quot;,</div><div class="line"> &quot;host-ssl-cert&quot;: &quot;/etc/pki/tls/certs/libwebsockets.org.crt&quot;,</div><div class="line"> &quot;host-ssl-ca&quot;: &quot;/etc/pki/tls/certs/libwebsockets.org.cer&quot;,</div><div class="line"> &quot;mounts&quot;: [{</div><div class="line"> &quot;mountpoint&quot;: &quot;/&quot;,</div><div class="line"> &quot;origin&quot;: &quot;file:///var/www/libwebsockets.org&quot;,</div><div class="line"> &quot;default&quot;: &quot;index.html&quot;</div><div class="line"> }, {</div><div class="line"> &quot;mountpoint&quot;: &quot;/testserver&quot;,</div><div class="line"> &quot;origin&quot;: &quot;file:///usr/local/share/libwebsockets-test-server&quot;,</div><div class="line"> &quot;default&quot;: &quot;test.html&quot;</div><div class="line"> }],</div><div class="line"> # which protocols are enabled for this vhost, and optional</div><div class="line"> # vhost-specific config options for the protocol</div><div class="line"> #</div><div class="line"> &quot;ws-protocols&quot;: [{</div><div class="line"> &quot;warmcat,timezoom&quot;: {</div><div class="line"> &quot;status&quot;: &quot;ok&quot;</div><div class="line"> }</div><div class="line"> }]</div><div class="line"> },</div><div class="line"> {</div><div class="line"> &quot;name&quot;: &quot;localhost&quot;,</div><div class="line"> &quot;port&quot;: &quot;7681&quot;,</div><div class="line"> &quot;host-ssl-key&quot;: &quot;/etc/pki/tls/private/libwebsockets.org.key&quot;,</div><div class="line"> &quot;host-ssl-cert&quot;: &quot;/etc/pki/tls/certs/libwebsockets.org.crt&quot;,</div><div class="line"> &quot;host-ssl-ca&quot;: &quot;/etc/pki/tls/certs/libwebsockets.org.cer&quot;,</div><div class="line"> &quot;mounts&quot;: [{</div><div class="line"> &quot;mountpoint&quot;: &quot;/&quot;,</div><div class="line"> &quot;origin&quot;: &quot;&gt;https://localhost&quot;</div><div class="line"> }]</div><div class="line"> },</div><div class="line"> {</div><div class="line"> &quot;name&quot;: &quot;localhost&quot;,</div><div class="line"> &quot;port&quot;: &quot;80&quot;,</div><div class="line"> &quot;mounts&quot;: [{</div><div class="line"> &quot;mountpoint&quot;: &quot;/&quot;,</div><div class="line"> &quot;origin&quot;: &quot;&gt;https://localhost&quot;</div><div class="line"> }]</div><div class="line"> }</div><div class="line"></div><div class="line"> ]</div><div class="line">}</div></div><!-- fragment --><p>That sets up three vhosts all called "localhost" on ports 443 and 7681 with SSL, and port 80 without SSL but with a forced redirect to <a href="https://localhost">https://localhost</a></p>
<h1><a class="anchor" id="lwswsvn"></a>
Lwsws Vhost name and port sharing</h1>
<p>The vhost name field is used to match on incoming SNI or Host: header, so it must always be the host name used to reach the vhost externally.</p>
<ul>
<li>Vhosts may have the same name and different ports, these will each create a listening socket on the appropriate port.</li>
<li>Vhosts may also have the same port and different name: these will be treated as true vhosts on one listening socket and the active vhost decided at SSL negotiation time (via SNI) or if no SSL, then after the Host: header from the client has been parsed.</li>
</ul>
<h1><a class="anchor" id="lwswspr"></a>
Lwsws Protocols</h1>
<p>Vhosts by default have available the union of any initial protocols from context creation time, and any protocols exposed by plugins.</p>
<p>Vhosts can select which plugins they want to offer and give them per-vhost settings using this syntax </p><div class="fragment"><div class="line">&quot;ws-protocols&quot;: [{</div><div class="line"> &quot;warmcat-timezoom&quot;: {</div><div class="line"> &quot;status&quot;: &quot;ok&quot;</div><div class="line"> }</div><div class="line">}]</div></div><!-- fragment --><p>The "x":"y" parameters like "status":"ok" are made available to the protocol during its per-vhost LWS_CALLBACK_PROTOCOL_INIT ( is a pointer to a linked list of struct <a class="el" href="structlws__protocol__vhost__options.html">lws_protocol_vhost_options</a> containing the name and value pointers).</p>
<p>To indicate that a protocol should be used when no Protocol: header is sent by the client, you can use "default": "1" </p><div class="fragment"><div class="line">&quot;ws-protocols&quot;: [{</div><div class="line"> &quot;warmcat-timezoom&quot;: {</div><div class="line"> &quot;status&quot;: &quot;ok&quot;,</div><div class="line"> &quot;default&quot;: &quot;1&quot;</div><div class="line"> }</div><div class="line">}]</div></div><!-- fragment --><h1><a class="anchor" id="lwswsovo"></a>
Lwsws Other vhost options</h1>
<ul>
<li>If the three options <code>host-ssl-cert</code>, <code>host-ssl-ca</code> and <code>host-ssl-key</code> are given, then the vhost supports SSL.</li>
</ul>
<p>Each vhost may have its own certs, SNI is used during the initial connection negotiation to figure out which certs to use by the server name it's asking for from the request DNS name.</p>
<ul>
<li><code>keeplive-timeout</code> (in secs) defaults to 60 for lwsws, it may be set as a vhost option</li>
<li><code>interface</code> lets you specify which network interface to listen on, if not given listens on all</li>
<li>"`unix-socket`": "1" causes the unix socket specified in the interface option to be used instead of an INET socket</li>
<li>"`sts`": "1" causes lwsws to send a Strict Transport Security header with responses that informs the client he should never accept to connect to this address using http. This is needed to get the A+ security rating from SSL Labs for your server.</li>
<li>"`access-log`": "filepath" sets where apache-compatible access logs will be written</li>
<li><code>"enable-client-ssl"</code>: <code>"1"</code> enables the vhost's client SSL context, you will need this if you plan to create client conections on the vhost that will use SSL. You don't need it if you only want http / ws client connections.</li>
<li>"`ciphers`": "&lt;cipher list&gt;" sets the allowed list of ciphers and key exchange protocols for the vhost. The default list is restricted to only those providing PFS (Perfect Forward Secrecy) on the author's Fedora system.</li>
</ul>
<p>If you need to allow weaker ciphers,you can provide an alternative list here per-vhost.</p>
<ul>
<li>"`ecdh-curve`": "&lt;curve name&gt;" The default ecdh curve is "prime256v1", but you can override it here, per-vhost</li>
<li>"`noipv6`": "on" Disable ipv6 completely for this vhost</li>
<li>"`ipv6only`": "on" Only allow ipv6 on this vhost / "off" only allow ipv4 on this vhost</li>
<li>"`ssl-option-set`": "&lt;decimal&gt;" Sets the SSL option flag value for the vhost. It may be used multiple times and OR's the flags together.</li>
</ul>
<p>The values are derived from /usr/include/openssl/ssl.h </p><div class="fragment"><div class="line"># define SSL_OP_NO_TLSv1_1 0x10000000L</div></div><!-- fragment --><p>would equate to</p>
<div class="fragment"><div class="line">&quot;`ssl-option-set`&quot;: &quot;268435456&quot;</div></div><!-- fragment --><ul>
<li>"`ssl-option-clear'": "&lt;decimal&gt;" Clears the SSL option flag value for the vhost. It may be used multiple times and OR's the flags together.</li>
<li>"`headers':: [{ "header1": "h1value", "header2": "h2value" }]</li>
</ul>
<p>allows you to set arbitrary headers on every file served by the vhost</p>
<p>recommended vhost headers for good client security are</p>
<div class="fragment"><div class="line"> &quot;headers&quot;: [{</div><div class="line"> &quot;Content-Security-Policy&quot;: &quot;script-src &#39;self&#39;&quot;,</div><div class="line"> &quot;X-Content-Type-Options&quot;: &quot;nosniff&quot;,</div><div class="line"> &quot;X-XSS-Protection&quot;: &quot;1; mode=block&quot;,</div><div class="line"> &quot;X-Frame-Options&quot;: &quot;SAMEORIGIN&quot;</div><div class="line">}]</div></div><!-- fragment --><h1><a class="anchor" id="lwswsm"></a>
Lwsws Mounts</h1>
<p>Where mounts are given in the vhost definition, then directory contents may be auto-served if it matches the mountpoint.</p>
<p>Mount protocols are used to control what kind of translation happens</p>
<ul>
<li><a href="file://">file://</a> serve the uri using the remainder of the url past the mountpoint based on the origin directory.</li>
</ul>
<p>Eg, with this mountpoint </p><div class="fragment"><div class="line">{</div><div class="line"> &quot;mountpoint&quot;: &quot;/&quot;,</div><div class="line"> &quot;origin&quot;: &quot;file:///var/www/mysite.com&quot;,</div><div class="line"> &quot;default&quot;: &quot;/&quot;</div><div class="line">}</div></div><!-- fragment --><p> The uri /file.jpg would serve /var/www/mysite.com/file.jpg, since / matched.</p>
<ul>
<li>^http:// or ^https:// these cause any url matching the mountpoint to issue a redirect to the origin url</li>
<li>cgi:// this causes any matching url to be given to the named cgi, eg <div class="fragment"><div class="line">{</div><div class="line"> &quot;mountpoint&quot;: &quot;/git&quot;,</div><div class="line"> &quot;origin&quot;: &quot;cgi:///var/www/cgi-bin/cgit&quot;,</div><div class="line"> &quot;default&quot;: &quot;/&quot;</div><div class="line">}, {</div><div class="line"> &quot;mountpoint&quot;: &quot;/cgit-data&quot;,</div><div class="line"> &quot;origin&quot;: &quot;file:///usr/share/cgit&quot;,</div><div class="line"> &quot;default&quot;: &quot;/&quot;</div><div class="line">},</div></div><!-- fragment --> would cause the url /git/myrepo to pass "myrepo" to the cgi /var/www/cgi-bin/cgit and send the results to the client.</li>
</ul>
<h1><a class="anchor" id="lwswsomo"></a>
Lwsws Other mount options</h1>
<p>1) Some protocols may want "per-mount options" in name:value format. You can provide them using "pmo" </p><pre class="fragment"> {
"mountpoint": "/stuff",
"origin": "callback://myprotocol",
"pmo": [{
"myname": "myvalue"
}]
}
</pre><p>2) When using a cgi:// protcol origin at a mountpoint, you may also give cgi environment variables specific to the mountpoint like this </p><div class="fragment"><div class="line">{</div><div class="line"> &quot;mountpoint&quot;: &quot;/git&quot;,</div><div class="line"> &quot;origin&quot;: &quot;cgi:///var/www/cgi-bin/cgit&quot;,</div><div class="line"> &quot;default&quot;: &quot;/&quot;,</div><div class="line"> &quot;cgi-env&quot;: [{</div><div class="line"> &quot;CGIT_CONFIG&quot;: &quot;/etc/cgitrc/libwebsockets.org&quot;</div><div class="line"> }]</div><div class="line">}</div></div><!-- fragment --><p> This allows you to customize one cgi depending on the mountpoint (and / or vhost).</p>
<p>3) It's also possible to set the cgi timeout (in secs) per cgi:// mount, like this </p><div class="fragment"><div class="line">&quot;cgi-timeout&quot;: &quot;30&quot;</div></div><!-- fragment --><p> 4) <code>callback://</code> protocol may be used when defining a mount to associate a named protocol callback with the URL namespace area. For example </p><div class="fragment"><div class="line">{</div><div class="line"> &quot;mountpoint&quot;: &quot;/formtest&quot;,</div><div class="line"> &quot;origin&quot;: &quot;callback://protocol-post-demo&quot;</div><div class="line">}</div></div><!-- fragment --><p> All handling of client access to /formtest[anything] will be passed to the callback registered to the protocol "protocol-post-demo".</p>
<p>This is useful for handling POST http body content or general non-cgi http payload generation inside a plugin.</p>
<p>See the related notes in README.coding.md</p>
<p>5) Cache policy of the files in the mount can also be set. If no options are given, the content is marked uncacheable. </p><div class="fragment"><div class="line">{</div><div class="line"> &quot;mountpoint&quot;: &quot;/&quot;,</div><div class="line"> &quot;origin&quot;: &quot;file:///var/www/mysite.com&quot;,</div><div class="line"> &quot;cache-max-age&quot;: &quot;60&quot;, # seconds</div><div class="line"> &quot;cache-reuse&quot;: &quot;1&quot;, # allow reuse at client at all</div><div class="line"> &quot;cache-revalidate&quot;: &quot;1&quot;, # check it with server each time</div><div class="line"> &quot;cache-intermediaries&quot;: &quot;1&quot; # allow intermediary caches to hold</div><div class="line">}</div></div><!-- fragment --><p>6) You can also define a list of additional mimetypes per-mount </p><div class="fragment"><div class="line">&quot;extra-mimetypes&quot;: {</div><div class="line"> &quot;.zip&quot;: &quot;application/zip&quot;,</div><div class="line"> &quot;.doc&quot;: &quot;text/evil&quot;</div><div class="line"> }</div></div><!-- fragment --><p>Normally a file suffix MUST match one of the canned mimetypes or one of the extra mimetypes, or the file is not served. This adds a little bit of security because even if there is a bug somewhere and the mount dirs are circumvented, lws will not serve, eg, /etc/passwd.</p>
<p>If you provide an extra mimetype entry </p><pre class="fragment"> "*": ""
</pre><p>Then any file is served, if the mimetype was not known then it is served without a Content-Type: header.</p>
<p>7) A mount can be protected by HTTP Basic Auth. This only makes sense when using https, since otherwise the password can be sniffed.</p>
<p>You can add a <code>basic-auth</code> entry on a mount like this`</p>
<div class="fragment"><div class="line">{</div><div class="line"> &quot;mountpoint&quot;: &quot;/basic-auth&quot;,</div><div class="line"> &quot;origin&quot;: &quot;file://_lws_ddir_/libwebsockets-test-server/private&quot;,</div><div class="line"> &quot;basic-auth&quot;: &quot;/var/www/balogins-private&quot;</div><div class="line">}</div></div><!-- fragment --><p>Before serving anything, lws will signal to the browser that a username / password combination is required, and it will pop up a dialog. When the user has filled it in, lwsws checks the user:password string against the text file named in the <code>basic-auth</code> entry.</p>
<p>The file should contain user:pass one per line</p>
<div class="fragment"><div class="line">testuser:testpass</div><div class="line">myuser:hispass</div></div><!-- fragment --><p>The file should be readable by lwsws, and for a little bit of extra security not have a file suffix, so lws would reject to serve it even if it could find it on a mount.</p>
<h1><a class="anchor" id="lwswspl"></a>
Lwsws Plugins</h1>
<p>Protcols and extensions may also be provided from "plugins", these are lightweight dynamic libraries. They are scanned for at init time, and any protocols and extensions found are added to the list given at context creation time.</p>
<p>Protocols receive init (LWS_CALLBACK_PROTOCOL_INIT) and destruction (LWS_CALLBACK_PROTOCOL_DESTROY) callbacks per-vhost, and there are arrangements they can make per-vhost allocations and get hold of the correct pointer from the wsi at the callback.</p>
<p>This allows a protocol to choose to strictly segregate data on a per-vhost basis, and also allows the plugin to handle its own initialization and context storage.</p>
<p>To help that happen conveniently, there are some new apis</p>
<ul>
<li>lws_vhost_get(wsi)</li>
<li>lws_protocol_get(wsi)</li>
<li>lws_callback_on_writable_all_protocol_vhost(vhost, protocol)</li>
<li>lws_protocol_vh_priv_zalloc(vhost, protocol, size)</li>
<li>lws_protocol_vh_priv_get(vhost, protocol)</li>
</ul>
<p>dumb increment, mirror and status protocol plugins are provided as examples.</p>
<h1><a class="anchor" id="lwswsplaplp"></a>
Additional plugin search paths</h1>
<p>Packages that have their own lws plugins can install them in their own preferred dir and ask lwsws to scan there by using a config fragment like this, in its own conf.d/ file managed by the other package </p><div class="fragment"><div class="line">{</div><div class="line"> &quot;global&quot;: {</div><div class="line"> &quot;plugin-dir&quot;: &quot;/usr/local/share/coherent-timeline/plugins&quot;</div><div class="line"> }</div><div class="line">}</div></div><!-- fragment --><h1><a class="anchor" id="lwswsssp"></a>
lws-server-status plugin</h1>
<p>One provided protocol can be used to monitor the server status.</p>
<p>Enable the protocol like this on a vhost's ws-protocols section </p><div class="fragment"><div class="line">&quot;lws-server-status&quot;: {</div><div class="line"> &quot;status&quot;: &quot;ok&quot;,</div><div class="line"> &quot;update-ms&quot;: &quot;5000&quot;</div><div class="line">}</div></div><!-- fragment --><p> "update-ms" is used to control how often updated JSON is sent on a ws link.</p>
<p>And map the provided HTML into the vhost in the mounts section </p><div class="fragment"><div class="line">{</div><div class="line"> &quot;mountpoint&quot;: &quot;/server-status&quot;,</div><div class="line"> &quot;origin&quot;: &quot;file:///usr/local/share/libwebsockets-test-server/server-status&quot;,</div><div class="line"> &quot;default&quot;: &quot;server-status.html&quot;</div><div class="line">}</div></div><!-- fragment --><p> You might choose to put it on its own vhost which has "interface": "lo", so it's not externally visible.</p>
<h1><a class="anchor" id="lwswssysd"></a>
Lwsws Integration with Systemd</h1>
<p>lwsws needs a service file like this as <code>/usr/lib/systemd/system/lwsws.service</code> </p><div class="fragment"><div class="line">[Unit]</div><div class="line">Description=Libwebsockets Web Server</div><div class="line">After=syslog.target</div><div class="line"></div><div class="line">[Service]</div><div class="line">ExecStart=/usr/local/bin/lwsws</div><div class="line">StandardError=null</div><div class="line"></div><div class="line">[Install]</div><div class="line">WantedBy=multi-user.target</div></div><!-- fragment --><p>You can find this prepared in <code>./lwsws/usr-lib-systemd-system-lwsws.service</code></p>
<h1><a class="anchor" id="lwswslr"></a>
Lwsws Integration with logrotate</h1>
<p>For correct operation with logrotate, <code>/etc/logrotate.d/lwsws</code> (if that's where we're putting the logs) should contain </p><div class="fragment"><div class="line">/var/log/lwsws/*log {</div><div class="line"> copytruncate</div><div class="line"> missingok</div><div class="line"> notifempty</div><div class="line"> delaycompress</div><div class="line">}</div></div><!-- fragment --><p> You can find this prepared in <code>/lwsws/etc-logrotate.d-lwsws</code></p>
<p>Prepare the log directory like this</p>
<div class="fragment"><div class="line">sudo mkdir /var/log/lwsws</div><div class="line">sudo chmod 700 /var/log/lwsws</div></div><!-- fragment --> </div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated by
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.12 </li>
</ul>
</div>
</body>
</html>