Introduction
A server is not necessary to use Fossil, but a server does help in collaborating with peers. A Fossil server also works well as a complete website for a project. For example, the complete 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.
Overview
There are basically four ways to set up a Fossil server:Each of these can serve either a single repository, or a directory hierarchy containing many repositories with names ending in ".fossil".
- A stand-alone server
- Using inetd or xinetd or stunnel
- CGI
- SCGI (a.k.a. SimpleCGI)
Standalone server
The easiest way to set up a Fossil server is to use either the server or the ui commands:
- fossil server REPOSITORY
- fossil ui REPOSITORY
The REPOSITORY argument is either the name of the repository file, or a directory containing many repositories. Both of these commands start a Fossil server, usually on TCP port 8080, though a higher numbered port might also be used 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. The difference between "ui" and "server" is that "ui" will also start a web browser and point it to the URL mentioned above, and the "ui" command binds to the loopback IP address (127.0.0.1) only so that the "ui" command cannot be used to serve content to a different machine.
If one of the commands above is run from within an open checkout, then the REPOSITORY argument can be omitted and the checkout is used as the repository.
Both commands have additional command-line options that can be used to refine their behavior. See the online documentation for an overview.
Fossil as an inetd/xinetd or stunnel service
A Fossil server can be launched on-demand by inetd or xinetd using the fossil http command. To launch Fossil from inetd, modify your inetd configuration file (typically "/etc/inetd.conf") to contain a line something like this:
In this example, you are telling "inetd" that when an incoming connection appears on TCP port "80", that it should launch the binary "/usr/bin/fossil" program 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.80 stream tcp nowait.1000 root /usr/bin/fossil /usr/bin/fossil http /home/fossil/repo.fossilIf 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:
and use the symbolic name ('fossil' in this example) instead of the numeral ('12345') in inetd.conf. For details, see the relevant section in your system's documentation, e.g. the FreeBSD Handbook in case you use FreeBSD.fossil 12345/tcp #fossil serverIf your system is running xinetd, then the configuration is likely to be in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". An xinetd configuration file will appear like this:
service http { port = 80 socket_type = stream wait = no user = root server = /usr/bin/fossil server_args = http /home/fossil/repos/ }The xinetd example above has Fossil configured to serve multiple repositories, contained under the "/home/fossil/repos/" directory.
In both cases notice that Fossil was launched as root. This is not required, but if it is done, then Fossil will automatically put itself into a chroot jail for the user who owns the fossil repository before reading any information off of the wire.
Inetd or xinetd must be enabled, and must be (re)started whenever their configuration changes - consult your system's documentation for details.
Stunnel version 5 is an inetd-like process that accepts and decodes SSL-encrypted connections. Fossil can be run directly from stunnel in a manner similar to inetd and xinetd. This can be used to provide a secure link to a Fossil project. The configuration needed to get stunnel5 to invoke Fossil is very similar to the inetd and xinetd examples shown above. The relevant parts of an stunnel configuration might look something like the following:
See the stunnel5 documentation for further details about the /etc/stunnel/stunnel.conf configuration file. Note that the fossil http command should include the --https option to let Fossil know to use "https" instead of "http" as the scheme on generated hyperlinks.[https] accept = www.ubercool-project.org:443 TIMEOUTclose = 0 exec = /usr/bin/fossil execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --httpsUsing inetd or xinetd or stunnel is a more complex setup than the "standalone" server, 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 and therefore may not normally be available to lower-priced "shared" servers on the internet.
Fossil as CGI
A Fossil server can also be run from an ordinary web server as a CGI program. This feature allows Fossil to be seamlessly integrated into a larger website. CGI is how the self-hosting fossil repositories are implemented.
To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory of your web server and having content like this:
#!/usr/bin/fossil repository: /home/fossil/repo.fossilAs always, adjust your paths appropriately. It may be necessary to set permissions properly, or to modify an ".htaccess" file or make other server-specific changes. Consult the documentation for your particular web server. In particular, 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, and ALL directories leading up to it must be readable by the process which executes the CGI.
- ALL directories leading to the CGI script must also be readable and the CGI script itself 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 administrator).
- The repository file AND the directory containing it must be writable by the same account which executes the Fossil binary (again, this might differ from the WWW user). The directory needs to be writable so that sqlite can write its journal files.
- Fossil must be able to create temporary files, the default directory for which depends on the OS. When the CGI process is operating within a chroot, ensure that this directory exists and is readable/writeable by the user who executes the Fossil binary.
Once the 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: http://mydomain.org/cgi-bin/repo (assuming the "repo" script is accessible under "cgi-bin", which would be a typical deployment on Apache for instance).
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: http://mydomain.org/cgi-bin/repo/XYZ will serve up the repository "/home/fossil/repos/XYZ.fossil" (if it exists).
Additional options available to the CGI script are documented in the source code. As of 2017-07-02, the available options are described at main.c lines 1777 through 1824.
Fossil as SCGI
The fossil server command, described above as a way of starting a stand-alone web server, can also be used for SCGI. Simply add the --scgi command-line option and the stand-alone server will interpret and respond to the SimpleCGI or SCGI protocol rather than raw HTTP. This can be used in combination with a webserver (such as Nginx) that does not support CGI. A typical Nginx configuration to support SCGI with Fossil would look something like this:
location /demo_project/ { include scgi_params; scgi_pass localhost:9000; scgi_param SCRIPT_NAME "/demo_project"; scgi_param HTTPS "on"; }Note that Fossil requires the SCRIPT_NAME variable in order to function properly, but Nginx does not provide this variable by default. So it is necessary to provide the SCRIPT_NAME parameter in the configuration. Failure to do this will cause Fossil to return an error.
All of the features of the stand-alone server mode described above, 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.
For security, it is probably a good idea to add the --localhost option to the fossil server command to prevent Fossil from accepting off-site connections. And one might want to specify the listening TCP port number, rather than letting Fossil choose one for itself, just to avoid ambiguity. A typical command to start a Fossil SCGI server would be something like this:
fossil server $REPOSITORY --scgi --localhost --port 9000
Securing a repository with SSL
Using either CGI or SCGI, it is trivial to use SSL to secure the server. Simply set up the Fossil CGI scripts etc. as above, but modify the Apache (or IIS, etc.) server to require SSL (that is, a URL with "https://") in order to access the CGI script directory. This may also be accomplished (on Apache, at least) using appropriate ".htaccess" rules.
If you are using "inetd" to serve your repository, then you simply need to add "/usr/bin/stunnel" (perhaps on a different path, depending on your setup) before the command line to launch Fossil.
At this stage, the standalone server (e.g. "fossil server") does not support SSL.
For more information, see Using SSL with Fossil.
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:
Both of these load-control mechanisms are turned off by default, but they are recommended for high-traffic sites.
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.
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 webserver.
To activate the server load control feature visit the /Admin/Access setup page in the administrative web interface and 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-host 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:
The second form is especially useful for changing the maximum load average simultaneously on a large number of repositories.fossil set max-loadavg 1.5 fossil all set max-loadavg 1.5Note 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 filesystem. 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:
The /home/www/proc pathname should be adjusted so that the "/proc" component is in the root of the chroot jail, of course.chroot_jail_proc /home/www/proc proc ro 0 0To 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.