No Server Required
Fossil does not require a central server. Data sharing and synchronization can be entirely peer-to-peer. Fossil uses conflict-free replicated data types to ensure that (in the limit) all participating peers see the exact same content.
But, A Server Can Be Useful
Fossil does not require a server, but a server does make collaboration easier. A Fossil server also works well as a complete website for a project. For example, the https://www.fossil-scm.org/ website, including the page you are now reading, is just a Fossil server displaying the content of the self-hosting repository for Fossil.This article is a guide for setting up your own Fossil server.
See "How CGI Works In Fossil" for background information on the underlying CGI technology. See "The Fossil Sync Protocol" for information on the wire protocol used for client/server communication.
Methods
There are basically four ways to set up a Fossil server:
- Socket activation: inetd, xinetd, stunnel...
- Stand-alone HTTP server
- SCGI
- CGI
The HTTP and SCGI options also allow for various sorts of reverse proxying: Apache, nginx, HAProxy, stunnel (proxy mode), IIS...
Regardless of the method you choose, all can serve either a single repository or a directory hierarchy containing many repositories with names ending in ".fossil".
We've broken the configuration for each method out into a series of sub-articles, some of which are OS-specific:
Fossil Front-End Program | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
Host OS | none | inetd | xinetd | stunnel | CGI | SCGI | nginx | Apache | IIS | OS service |
Any | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
Debian/Ubuntu | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
Windows | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
Where there is a check mark in the "Any" row, the method for that is generic enough that it works across OSes that Fossil is known to work on. The check marks below that usually just link to this generic documentation.There are several widely-deployed socket activation schemes besides the inetd, xinetd, and stunnel schemes with documents linked above: Apple’s launchd, Linux’s systemd, Solaris’ SMF, etc. We would welcome contributions to cover these as well. We also welcome contributions to fill gaps (❌) in the table above.
Standalone HTTP server
This is the easiest way to set up a Fossil server. It's covered in a separate article.
Serving via inetd
See this article.
Serving via CGI
See this article.
Serving via SCGI
See this article.
CGI Server Extensions
In addition to serving Fossil repositories via CGI, Fossil can itself launch other programs via CGI to implement server extensions. Do not confuse these two concepts. This extension mechanism works regardless of the method above you choose to serve your Fossil repository.
Securing a repository with TLS
Fossil's built-in HTTP server (e.g. "fossil server") does not support TLS, but there are multiple ways to protect your Fossil server with TLS. All of this is covered in a separate document, Using TLS-Encrypted Communications with Fossil.
The Fossil Chroot Jail
If you run Fossil as root in any mode that serves data on the network, and you're running it on Unix or a compatible OS, Fossil will drop itself into a chroot jail shortly after starting up. It will drop its root privileges once it's done everything that requires root access; most commonly, you run Fossil as root to allow it to bind to TCP port 80 for HTTP service, since normal users are restricted to ports 1024 and up on OSes where this behavior occurs.Fossil uses the owner of the Fossil repository file as its new user ID when dropping root privileges.
When this happens, Fossil needs to have all of its dependencies inside the chroot jail. There are several things you typically need in order to make things work properly:
- the repository file(s)
- /dev/null — create it with mknod(8) inside the jail directory
- /dev/urandom — ditto
- any shared libraries your fossil binary is linked to, such as /lib/libssl.so; consider building Fossil as a static binary to avoid this
Fossil does all of this in order to protect the host OS. There is no way to bypass it, on purpose.
Managing Server Load
A Fossil server is very efficient and normally presents a very light load on the server. The Fossil self-hosting server is a 1/24th slice VM at Linode.com hosting 65 other repositories in addition to Fossil (and including some very high-traffic sites such as http://www.sqlite.org and http://system.data.sqlite.org) and it has a typical load of 0.05 to 0.1. A single HTTP request to Fossil normally takes less than 10 milliseconds of CPU time to complete, so requests can be arriving at a continuous rate of 20 or more per second, and the CPU can still be mostly idle.However, there are some Fossil web pages that can consume large amounts of CPU time, especially on repositories with a large number of files or with long revision histories. High CPU usage pages include /zip, /tarball, /annotate and others. On very large repositories, these commands can take 15 seconds or more of CPU time. If these kinds of requests arrive too quickly, the load average on the server can grow dramatically, making the server unresponsive.
Fossil provides two capabilities to help avoid server overload problems due to excessive requests to expensive pages:
An optional cache is available that remembers the 10 most recently requested /zip or /tarball pages and returns the precomputed answer if the same page is requested again.
Page requests can be configured to fail with a "503 Server Overload" HTTP error if an expensive request is received while the host load average is too high.
Both of these load-control mechanisms are turned off by default, but they are recommended for high-traffic sites.
The webpage cache is activated using the fossil cache init command-line on the server. Add a -R option to specify the specific repository for which to enable caching. If running this command as root, be sure to "chown" the cache database (which is a separate file in the same directory and with the same name as the repository but with the suffix changed to ".cache") to give it write permission for the userid of the web server.
To activate the server load control feature visit the Admin → Access setup page in the administrative web interface; in the "Server Load Average Limit" box enter the load average threshold above which "503 Server Overload" replies will be issued for expensive requests. On the self-hosting Fossil server, that value is set to 1.5, but you could easily set it higher on a multi-core server.
The maximum load average can also be set on the command line using commands like this:
fossil set max-loadavg 1.5 fossil all set max-loadavg 1.5The second form is especially useful for changing the maximum load average simultaneously on a large number of repositories.
Note that this load-average limiting feature is only available on operating systems that support the "getloadavg()" API. Most modern Unix systems have this interface, but Windows does not, so the feature will not work on Windows. Note also that Linux implements "getloadavg()" by accessing the "/proc/loadavg" file in the "proc" virtual file system. If you are running a Fossil instance inside a chroot() jail on Linux, you will need to make the "/proc" file system available inside that jail in order for this feature to work. On the self-hosting Fossil repositories, this was accomplished by adding a line to the "/etc/fstab" file that looks like:
chroot_jail_proc /home/www/proc proc ro 0 0The /home/www/proc pathname should be adjusted so that the "/proc" component is in the root of the chroot jail, of course.
To see if the load-average limiter is functional, visit the /test_env page of the server to view the current load average. If the value for the load average is greater than zero, that means that it is possible to activate the load-average limiter on that repository. If the load average shows exactly "0.0", then that means that Fossil is unable to find the load average (either because it is in a chroot() jail without /proc access, or because it is running on a system that does not support "getloadavg()") and so the load-average limiter will not function.