summaryrefslogtreecommitdiff
path: root/www/server/any
diff options
context:
space:
mode:
authorcashmere <cashmere@autistici.org>2026-09-04 09:05:24 +0200
committercashmere <cashmere@autistici.org>2026-09-04 09:05:24 +0200
commit4f49b16079b27d7ce633619e4cddfdf2bffbc952 (patch)
treec296c1e7f3c3e2f6859c6d3a1b1b208779b89679 /www/server/any
downloadrelic-master.tar.gz
initial commitHEADmaster
Diffstat (limited to 'www/server/any')
-rw-r--r--www/server/any/althttpd.md42
-rw-r--r--www/server/any/cgi.md117
-rw-r--r--www/server/any/http-over-ssh.md173
-rw-r--r--www/server/any/index.md11
-rw-r--r--www/server/any/inetd.md52
-rw-r--r--www/server/any/none.md56
-rw-r--r--www/server/any/scgi.md72
-rw-r--r--www/server/any/stunnel.md81
-rw-r--r--www/server/any/xinetd.md27
9 files changed, 631 insertions, 0 deletions
diff --git a/www/server/any/althttpd.md b/www/server/any/althttpd.md
new file mode 100644
index 0000000..7797103
--- /dev/null
+++ b/www/server/any/althttpd.md
@@ -0,0 +1,42 @@
+# Serving via althttpd
+
+[Althttpd][althttpd]
+is a light-weight web server that has been used to implement the SQLite and
+Fossil websites for well over a decade. Althttpd strives for simplicity,
+security, ease of configuration, and low resource usage.
+
+To set up a Fossil server as CGI on a host running the althttpd web
+server, follow these steps.
+<ol>
+<li>Get the althttpd webserver running on the host. This is easily
+done by following the [althttpd documentation][althttpd].
+
+<li>Create a CGI script for your Fossil repository. The script will
+be typically be two lines of code that look something like this:
+
+~~~
+ #!/usr/bin/fossil
+ repository: /home/yourlogin/fossils/project.fossil
+~~~
+
+Modify the filenames to conform to your system, of course. The
+CGI script accepts [other options][cgi] besides the
+repository:" line. You can add in other options as you desire,
+but the single "repository:" line is normally all that is needed
+to get started.
+
+<li>Make the CGI script executable.
+
+<li>Verify that the fossil repository file and the directory that contains
+the repository are both writable by whatever user the web server is
+running and.
+</ol>
+
+And you are done. Visit the URL that corresponds to the CGI script
+you created to start using your Fossil server.
+
+*[Return to the top-level Fossil server article.](../)*
+
+
+[althttpd]: https://sqlite.org/althttpd/
+[cgi]: ../../cgi.wiki
diff --git a/www/server/any/cgi.md b/www/server/any/cgi.md
new file mode 100644
index 0000000..79ede92
--- /dev/null
+++ b/www/server/any/cgi.md
@@ -0,0 +1,117 @@
+# Serving via CGI
+
+A Fossil server can be run from most ordinary web servers as a CGI
+program. This feature allows Fossil to seamlessly integrate into a
+larger website. The [self-hosting Fossil repository web
+site](../../selfhost.wiki) is implemented using CGI. See the
+[How CGI Works](../../aboutcgi.wiki) page for background information
+on the CGI protocol.
+
+To run Fossil as CGI, create a CGI script (here called "repo") in the
+CGI directory of your web server with content like this:
+
+ #!/usr/bin/fossil
+ repository: /home/fossil/repo.fossil
+
+Adjust the paths appropriately. It may be necessary to set certain
+permissions on this file or to modify an `.htaccess` file or make other
+server-specific changes. Consult the documentation for your particular
+web server. The following permissions are *normally* required, but,
+again, may be different for a particular configuration:
+
+* The Fossil binary (`/usr/bin/fossil` in the example above)
+ must be readable/executable.
+
+* *All* directories leading up to the Fossil binary must be readable
+ by the process which executes the CGI.
+
+* The CGI script must be executable for the user under which it will
+ run, which often differs from the one running the web server.
+ Consult your site's documentation or the web server’s system
+ administrator.
+
+* *All* directories leading to the CGI script must be readable by the
+ web server.
+
+* The repository file *and* the directory containing it must be
+ writable by the same account which executes the Fossil binary.
+ (This might differ from the user the web server normally runs
+ under.) The directory holding the repository file(s) needs to be
+ writable so that SQLite can write its journal files. When using
+ another access control system, such as AppArmor or SELinux, it may
+ be necessary to explicitly permit that account to read and write
+ the necessary files. Also verify a possible _systemd_ sandboxing of
+ the web server service, especially the combination of _ProtectSystem_,
+ _ProtectHome_, and _ReadWriteDirectories_/_ReadWritePaths_.
+
+* Fossil must be able to create temporary files in a
+ [directory that varies by host OS](../../env-opts.md#temp). When the
+ CGI process is operating [within a chroot](../../chroot.md),
+ ensure that this directory exists and is readable/writeable by the
+ user who executes the Fossil binary.
+
+Once the CGI script is set up correctly, and assuming your server is
+also set correctly, you should be able to access your repository with a
+URL like: <b>http://mydomain.org/cgi-bin/repo</b> This is assuming you
+are running a web server like Apache that uses a “`cgi-bin`” directory
+for scripts like our “`repo`” example.
+
+To serve multiple repositories from a directory using CGI, use the
+"directory:" tag in the CGI script rather than "repository:". You
+might also want to add a "notfound:" tag to tell where to redirect if
+the particular repository requested by the URL is not found:
+
+ #!/usr/bin/fossil
+ directory: /home/fossil/repos
+ notfound: http://url-to-go-to-if-repo-not-found/
+
+Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
+will serve up the repository `/home/fossil/repos/XYZ.fossil` if it
+exists.
+
+Additional options available to the CGI script are [documented
+separately](../../cgi.wiki).
+
+#### CGI with Apache behind an Nginx proxy
+
+For the case where the Fossil repositories live on a computer, itself behind
+an Internet-facing machine that employs Nginx to reverse proxy HTTP(S) requests
+and take care of the TLS part of the connections in a transparent manner for
+the downstream web servers, the CGI parameter `HTTPS=on` might not be set.
+However, Fossil in CGI mode needs it in order to generate the correct links.
+
+Apache can be instructed to pass this parameter further to the CGI scripts for
+TLS connections with a stanza like
+
+ SetEnvIf X-Forwarded-Proto "https" HTTPS=on
+
+in its config file section for CGI, provided that
+
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+has been be added in the relevant proxying section of the Nginx config file.
+
+*[Return to the top-level Fossil server article.](../)*
+
+#### Apache mod_cgi and `CONTENT_LENGTH`
+
+At some point in its 2.4.x family, Apache's `mod_cgi` stopped relaying
+the Content-Length header in the HTTP reply from CGIs back to clients.
+However, Fossil clients prior to 2024-04-17 depended on seeing the
+Content-Length header and were unable to handle HTTP replies without
+one. The change in Apache behavior caused "fossil clone" and "fossil
+sync" to stop working. There are two possible fixes to this problem:
+
+ 1. Restore legacy behavior in Apache by adding
+ the following to the Apache configuration, scoped to the `<Directory>`
+ entry or entries in which fossil is being served via CGI:
+ <blockquote><pre>
+ &lt;Directory ...&gt;
+ SetEnv ap_trust_cgilike_cl "yes"
+ &lt;/Directory&gt;
+ </pre></blockquote>
+
+ 2. Upgrade your Fossil client to any trunk check-in after 2024-04-17,
+ as Fossil was upgraded to be able to deal with the missing
+ Content-Length field by
+ [check-in a8e33fb161f45b65](/info/a8e33fb161f45b65).
diff --git a/www/server/any/http-over-ssh.md b/www/server/any/http-over-ssh.md
new file mode 100644
index 0000000..8bc6fdb
--- /dev/null
+++ b/www/server/any/http-over-ssh.md
@@ -0,0 +1,173 @@
+# Forcing Use of Fossil’s RBAC over SSH
+
+Andy Bradford posted a [clever solution][sshfc] to the problem of
+Fossil’s RBAC system [being ignored](../../caps/#webonly) over `ssh://`
+URLs: use OpenSSH’s `ForceCommand` feature to route the sync transfer
+protocol data over `fossil http` rather than `fossil test-http`.
+
+The setup for this is complicated, but it’s a worthy option when you
+need encrypted communications between the client and server, you already
+have SSH set up, and [the HTTPS alternative](../../ssl.wiki) is
+unworkable for some reason.
+
+
+## 1. Force remote Fossil access through a wrapper script <a id="sshd"></a>
+
+Put something like the following into the `sshd_config` file on the
+Fossil repository server:
+
+``` ssh-config
+Match Group fossil
+ X11Forwarding no
+ AllowTcpForwarding no
+ AllowAgentForwarding no
+ ForceCommand /home/fossil/bin/wrapper
+```
+
+This file is usually found in `/etc/ssh`, but some OSes put it
+elsewhere.
+
+The first line presumes that we will put all users who need to use our
+Fossil repositories into the `fossil` group, as we will do
+[below](#perms). You could instead say something like:
+
+``` ssh-config
+Match User alice,bob,carol,dave
+```
+
+You have to list the users allowed to use Fossil in this case because
+your system likely has a system administrator that uses SSH for remote
+shell access, so you want to *exclude* that user from the list. For the
+same reason, you don’t want to put the `ForceCommand` directive outside
+a `Match` block of some sort.
+
+You could instead list the exceptions:
+
+``` ssh-config
+Match User !evi
+```
+
+This would permit only [Evi the System Administrator][evi] to bypass this
+mechanism.
+
+[evi]: https://en.wikipedia.org/wiki/Evi_Nemeth
+
+If you have a user that needs both interactive SSH shell access *and*
+Fossil access, exclude that user from the `Match` rule and use Fossil’s
+normal `ssh://` URL scheme for those cases. This user will bypass the
+Fossil RBAC, but they effectively have Setup capability on those
+repositories anyway by having full read/write access to the DB files via
+the shell.
+
+
+## 2. Rewrite the sync command with that wrapper <a id="wrapper"></a>
+
+When Fossil syncs over SSH, it attempts to launch a remote Fossil
+instance with certain parameters in order to set up the HTTP-based sync
+protocol over that SSH tunnel. We need to preserve some of this command
+and rewrite other parts to make this work.
+
+Here is a simpler variant of Andy’s original wrapper script:
+
+``` sh
+#!/bin/bash
+set -- $SSH_ORIGINAL_COMMAND
+while [ $# -gt 1 ] ; do shift ; done
+export REMOTE_USER="$USER"
+ROOT=/home/fossil
+exec "$ROOT/bin/fossil" http "$ROOT/museum/$(/bin/basename "$1")"
+```
+
+The substantive changes are:
+
+1. Move the command rewriting bits to the start.
+
+2. Be explicit about executable paths. You might extend this idea by
+ using chroot, BSD jails, Linux containers, etc.
+
+3. Restrict the Fossil repositories to a single flat subdirectory under
+ the `fossil` user’s home directory. This scheme is easier to secure
+ than one allowing subdirectories, since you’d need to take care of
+ `../` and such to prevent a sandbox escape.
+
+4. Don’t take the user name via the SSH command; to this author’s mind,
+ the user should not get to override their Fossil user name on the
+ remote server, as that permits impersonation. The identity you
+ present to the SSH server must be the same identity that the Fossil
+ repository you’re working with knows you by. Since the users
+ selected by “`Match`” block above are dedicated to using only Fossil
+ in this setup, this restriction shouldn’t present a practical problem.
+
+The script’s shebang line assumes `/bin/sh` is POSIX-compliant, but that
+is not the case everywhere. If the script fails to run on your system,
+try changing this line to point at `bash`, `dash`, `ksh`, or `zsh`. Also
+check the absolute paths for local correctness: is `/bin/basename`
+installed on your system, for example?
+
+Under this scheme, you clone with a command like:
+
+ $ fossil clone ssh://HOST/repo.fossil
+
+This will clone the remote `/home/fossil/museum/repo.fossil` repository
+to your local machine under the same name and open it into a “`repo/`”
+subdirectory. Notice that we didn’t have to give the `museum/` part of
+the path: it’s implicit per point #3 above.
+
+This presumes your local user name matches the remote user name. Unlike
+with `http[s]://` URLs, you don’t have to provide the `USER@` part to
+get authenticated access
+since this scheme doesn’t permit anonymous cloning. Only
+if these two user names are different do you need to add the `USER@` bit to the
+URL.
+
+
+## 3. Set permissions <a id="perms"></a>
+
+This scheme assumes that the users covered by the `Match` rule can read
+the wrapper script from where you placed it and execute it, and that
+they have read/write access on the directory where the Fossil
+repositories are stored.
+
+You can achieve all of this on a Linux box with:
+
+``` shell
+sudo adduser fossil
+for u in alice bob carol dave ; do
+ sudo adduser $u
+ sudo gpasswd -a fossil $u
+done
+sudo -i -u fossil
+chmod 710 .
+mkdir -m 750 bin
+mkdir -m 770 museum
+ln -s /usr/local/bin/fossil bin
+```
+
+You then need to copy the Fossil repositories into `~fossil/museum` and
+make them readable and writable by group `fossil`. These repositories
+presumably already have Fossil users configured, with the necessary
+[user capabilities](../../caps/), the point of this article being to
+show you how to make Fossil-over-SSH pay attention to those caps.
+
+You must also permit use of `REMOTE_USER` on each shared repository.
+Fossil only pays attention to this environment variable in certain
+contexts, of which “`fossil http`” is not one. Run this command against
+each repo to allow that:
+
+``` shell
+echo "INSERT OR REPLACE INTO config VALUES ('remote_user_ok',1,strftime('%s','now'));" |
+fossil sql -R museum/repo.fossil
+```
+
+Now you can configure SSH authentication for each user. Since Fossil’s
+password-saving feature doesn’t work in this case, I suggest setting up
+SSH keys via `~USER/.ssh/authorized_keys` since the SSH authentication
+occurs on each sync, which Fossil’s default-enabled autosync setting
+makes frequent.
+
+Equivalent commands for other OSes should be readily discerned from the
+script above.
+
+[sshfc]: forum:/forumpost/0d7d6c3df41fcdfd
+
+<div style="height:50em" id="this-space-intentionally-left-blank"></div>
diff --git a/www/server/any/index.md b/www/server/any/index.md
new file mode 100644
index 0000000..ccf2d94
--- /dev/null
+++ b/www/server/any/index.md
@@ -0,0 +1,11 @@
+# Portable Fossil Service Options
+
+- [Fossil as a standalone HTTP server](./none.md)
+- [SCGI under your web server of choice](./scgi.md)
+- [CGI under your web server of choice](./cgi.md)
+- [CGI under `althttpd`](./althttpd.md)
+- [Behind `stunnel` to get TLS encryption](./stunnel.md)
+- [`inetd`](./inetd.md)
+- [`xinetd`](./xinetd.md)
+
+*[Return to the top-level Fossil server article.](../)*
diff --git a/www/server/any/inetd.md b/www/server/any/inetd.md
new file mode 100644
index 0000000..35766c7
--- /dev/null
+++ b/www/server/any/inetd.md
@@ -0,0 +1,52 @@
+# Serving via inetd
+
+A Fossil server can be launched on-demand by `inetd` by using the
+[`fossil http`](/help/http) command. To do so, add a line like the
+following to its configuration file, typically `/etc/inetd.conf`:
+
+ 80 stream tcp nowait.1000 root /usr/bin/fossil /usr/bin/fossil http /home/fossil/repo.fossil
+
+In this example, you are telling `inetd` that when an incoming
+connection appears on TCP port 80 that it should launch the program
+`/usr/bin/fossil` with the arguments shown. Obviously you will need to
+modify the pathnames for your particular setup. The final argument is
+either the name of the fossil repository to be served or a directory
+containing multiple repositories.
+
+If you use a non-standard TCP port on systems where the port
+specification must be a symbolic name and cannot be numeric, add the
+desired name and port to `/etc/services`. For example, if you want your
+Fossil server running on TCP port 12345 instead of 80, you will need to
+add:
+
+ fossil 12345/tcp # fossil server
+
+and use the symbolic name “`fossil`” instead of the numeric TCP port
+number (“12345” in the above example) in `inetd.conf`.
+
+Notice that we configured `inetd` to launch Fossil as root. See the
+top-level section on “[The Fossil Chroot
+Jail](../../chroot.md)” for the consequences of this and
+alternatives to it.
+
+You can instead configure `inetd` to bind to a higher-numbered TCP port,
+allowing Fossil to be run as a normal user. In that case, Fossil will
+not put itself into a chroot jail, because it assumes you have set up
+file permissions and such on the server appropriate for that user.
+
+The `inetd` daemon must be enabled for this to work, and it must be
+restarted whenever its configuration file changes.
+
+This is a more complicated method than the [standalone HTTP server
+method](./none.md), but it has the advantage of only using system
+resources when an actual connection is attempted. If no one ever
+connects to that port, a Fossil server will not (automatically) run. It
+has the disadvantage of requiring "root" access, which may not be
+available to you, either due to local IT policy or because of
+restrictions at your shared Internet hosting service.
+
+For further details, see the relevant section in your system's
+documentation. The FreeBSD Handbook covers `inetd` in [this
+chapter](https://www.freebsd.org/doc/en/books/handbook/network-inetd.html).
+
+*[Return to the top-level Fossil server article.](../)*
diff --git a/www/server/any/none.md b/www/server/any/none.md
new file mode 100644
index 0000000..2208091
--- /dev/null
+++ b/www/server/any/none.md
@@ -0,0 +1,56 @@
+# Standalone HTTP Server
+
+The easiest way to set up a Fossil server is to use either the
+[`server`](/help/server) or [`ui`](/help/ui) command:
+
+* **fossil server** _REPOSITORY_
+* **fossil ui** _REPOSITORY_
+
+The _REPOSITORY_ argument is either the name of the repository file or a
+directory containing many repositories named “`*.fossil`”. Both of these
+commands start a Fossil server, usually on TCP port 8080, though a
+higher numbered port will be used instead if 8080 is already occupied.
+
+You can access these using URLs of the form **http://localhost:8080/**,
+or if _REPOSITORY_ is a directory, URLs of the form
+**http://localhost:8080/**_repo_**/** where _repo_ is the base name of
+the repository file without the “`.fossil`” suffix.
+
+There are several key differences between “`ui`” and “`server`”:
+
+* “`ui`” always binds the server to the loopback IP address (127.0.0.1)
+ so that it cannot serve to other machines.
+
+* Anyone who visits this URL is treated as the all-powerful Setup
+ user, which is why the first difference exists.
+
+* “`ui`” launches a local web browser pointed at this URL.
+
+You can omit the _REPOSITORY_ argument if you run one of the above
+commands from within a Fossil checkout directory to serve that
+repository:
+
+ $ fossil ui # or...
+ $ fossil server
+
+You can abbreviate Fossil sub-commands as long as they are unambiguous.
+“`server`” can currently be as short as “`ser`”.
+
+You can serve a directory containing multiple `*.fossil` files like so:
+
+ $ fossil server --port 9000 --repolist /path/to/repo/dir
+
+As a security precaution, when the “`server`” or
+“`ui`” commands are run as `root` Fossil will drop into
+a [chroot](../../chroot.md) with the directory where the repository is located
+as the new root of the filesystem.
+
+There is an [example script](/file/tools/fslsrv) in the Fossil
+distribution that wraps `fossil server` to produce more complicated
+effects. Feel free to take it, study it, and modify it to suit your
+local needs.
+
+See the [online documentation](/help/server) for more information on the
+options and arguments you can give to these commands.
+
+*[Return to the top-level Fossil server article.](../)*
diff --git a/www/server/any/scgi.md b/www/server/any/scgi.md
new file mode 100644
index 0000000..4c02158
--- /dev/null
+++ b/www/server/any/scgi.md
@@ -0,0 +1,72 @@
+# Serving via SCGI
+
+There is an alternative to running Fossil as a [standalone HTTP
+server](./none.md), which is to run it in SimpleCGI (a.k.a. SCGI) mode,
+which uses the same [`fossil server`](/help/server) command as for HTTP
+service. Simply add the `--scgi` command-line option and the stand-alone
+server will speak the SCGI protocol rather than raw HTTP.
+
+This can be used with a web server such as [nginx](http://nginx.org)
+which does not support [Fossil’s CGI mode](./cgi.md).
+
+A basic nginx configuration to support SCGI with Fossil looks like this:
+
+ location /code/ {
+ include scgi_params;
+ scgi_param SCRIPT_NAME "/code";
+ scgi_pass localhost:9000;
+ }
+
+The `scgi_params` file comes with nginx, and it simply translates nginx
+internal variables to `scgi_param` directives to create SCGI environment
+variables for the proxied program; in this case, Fossil. Our explicit
+`scgi_param` call to define `SCRIPT_NAME` adds one more variable to this
+set, which is necessary for this configuration to work properly, because
+our repo isn’t at the root of the URL hierarchy. Without it, when Fossil
+generates absolute URLs, they’ll be missing the `/code` part at the
+start, which will typically cause [404 errors][404].
+
+The final directive simply tells nginx to proxy all calls to URLs under
+`/code` down to an SCGI program on TCP port 9000. We can temporarily
+set Fossil up as a server on that port like so:
+
+ $ fossil server /path/to/repo.fossil --scgi --localhost --port 9000 &
+
+The `--scgi` option switches Fossil into SCGI mode from its default,
+which is [stand-alone HTTP server mode](./none.md). All of the other
+options discussed in that linked document — such as the ability to serve
+a directory full of Fossil repositories rather than just a single
+repository — work the same way in SCGI mode.
+
+The `--localhost` option is simply good security: we’re using nginx to
+expose Fossil service to the outside world, so there is no good reason
+to allow outsiders to contact this Fossil SCGI server directly.
+
+Giving an explicit non-default TCP port number via `--port` is a good
+idea to avoid conflicts with use of Fossil’s default TCP service port,
+8080, which may conflict with local uses of `fossil ui` and such.
+
+We characterized the SCGI service start command above as “temporary”
+because running Fossil in the background like that means it won’t start
+back up on a reboot of the server. A simple solution to that is to add
+that command to `/etc/rc.local` on systems that have it. However, you
+might want to consider setting Fossil up as an OS service instead, so
+that you get the benefits of the platform’s service management
+framework:
+
+* [Linux (systemd)](../debian/service.md)
+* [Windows service](../windows/service.md)
+* [macOS (launchd)](../macos/service.md)
+* [xinetd](../any/xinetd.md)
+* [inetd](../any/inetd.md)
+
+We go into more detail on nginx service setup with Fossil in our
+[Debian/Ubuntu specific guide](../debian/nginx.md), which also
+gets you TLS service.
+
+Similarly, our [OpenBSD specific guide](../openbsd/fastcgi.md) details how
+to setup a Fossil server using httpd and FastCGI on OpenBSD.
+
+*[Return to the top-level Fossil server article.](../)*
+
+[404]: https://en.wikipedia.org/wiki/HTTP_404
diff --git a/www/server/any/stunnel.md b/www/server/any/stunnel.md
new file mode 100644
index 0000000..c8824a7
--- /dev/null
+++ b/www/server/any/stunnel.md
@@ -0,0 +1,81 @@
+# Serving via stunnel
+
+[`stunnel`](https://www.stunnel.org/) is a TLS/SSL proxy for programs
+that themselves serve only via HTTP, such as Fossil. (Fossil *can* speak
+HTTPS, but only as a client.) `stunnel` decodes the HTTPS data from the
+outside world as HTTP before passing it to Fossil, and it encodes the
+HTTP replies from Fossil as HTTPS before sending them to the remote host
+that made the request.
+
+You can run `stunnel` in one of two modes: socket listener — much like
+in our [`inetd` doc](./inetd.md) — and as an HTTP reverse proxy. We’ll
+cover both cases here, separately.
+
+
+## <a id="sa"></a>Socket Activation
+
+The following `stunnel.conf` configuration configures it to run Fossil
+in socket listener mode, launching Fossil only when an HTTPS hit comes
+in, then shutting it back down as soon as the transaction is complete:
+
+```dosini
+ [fossil]
+ accept = 443
+ TIMEOUTclose = 0
+ exec = /usr/bin/fossil
+ execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https
+ cert = /etc/letsencrypt/live/ubercool-project.org/fullchain.pem
+ key = /etc/letsencrypt/live/ubercool-project.org/privkey.pem
+ ciphers = ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES128-SHA:DES-CBC3-SHA
+ options = CIPHER_SERVER_PREFERENCE
+```
+
+This configuration shows the TLS certificate generated by the [Let’s
+Encrypt](https://letsencrypt.org) [Certbot](https://certbot.eff.org) in
+[certonly mode](https://certbot.eff.org/lets-encrypt/debianbuster-other).
+There are other ways to get TLS certificates, but this is a popular and
+free option.
+
+You will need to adjust the site names and paths in this example. Where
+this file goes varies by OS type, so check the man pages on your system
+to find out where it should be locally.
+
+See the `stunnel` documentation for further details about this
+configuration file.
+
+It is important that the [`fossil http`](/help/http) command in that
+configuration include the `--https` option to let Fossil know to use
+“`https://`” instead of “`http://`” in generated hyperlinks.
+
+
+
+## <a id="proxy"></a>Reverse Proxy
+
+You can instead have Fossil running in the background in [standalone
+HTTP server mode](./none.md), bound to a high random TCP port number on
+localhost via the `--localhost` and `--port` flags, then configure
+`stunnel` to reverse proxy public HTTPS connections down to it via HTTP.
+
+The configuration is the same as the above except that you drop the
+`exec` and `execargs` directives and add this instead:
+
+```dosini
+ connect = 9000
+```
+
+That tells `stunnel` to connect to an already-running process listening
+on the given TCP port number.
+
+There are a few advantages to this mode:
+
+1. At the cost of some server memory and a tiny bit of idle CPU time,
+ Fossil remains running so that hits can be served a smidge faster
+ than in socket listener mode, where the Fossil binary has to be
+ loaded and re-initialized on each HTTPS hit.
+
+2. The socket listener mode doesn’t work on all platforms that
+ `stunnel` runs on, particularly [on Windows](../windows/stunnel.md).
+
+*[Return to the top-level Fossil server article.](../)*
+
+<div style="height:50em" id="this-space-intentionally-left-blank"></div>
diff --git a/www/server/any/xinetd.md b/www/server/any/xinetd.md
new file mode 100644
index 0000000..9e93502
--- /dev/null
+++ b/www/server/any/xinetd.md
@@ -0,0 +1,27 @@
+# Serving via xinetd
+
+Some operating systems have replaced the old Unix `inetd` daemon with
+`xinetd`, which has a similar mission but with a very different
+configuration file format.
+
+The typical configuration file is either `/etc/xinetd.conf` or a subfile
+in the `/etc/xinetd.d` directory. You need a configuration something
+like this for Fossil:
+
+ service http
+ {
+ port = 80
+ socket_type = stream
+ wait = no
+ user = root
+ server = /usr/bin/fossil
+ server_args = http /home/fossil/repos/
+ }
+
+This example configures Fossil to serve multiple repositories under the
+`/home/fossil/repos/` directory.
+
+Beyond this, see the general commentary in our article on [the `inetd`
+method](./inetd.md) as they also apply to service via `xinetd`.
+
+*[Return to the top-level Fossil server article.](../)*