kdwarn

Codeberg Mastodon Feeds

Hosting Rust crate documentation with Nginx

April 21, 2024

coding, rust, docs, nginx | permalink

I didn't come across a guide on how to do this with an online search (but hey, online search is a dumpster fire like most things on the internet nowadays), so thought I'd write up something quick to help others looking to host their own crate documentation. It's quite easy if you're already familiar with nginx. Here I'll be using the work project I did this for as an example. The source is available at https://github.com/dvrpc/traffic-counts; it contains a library and binary program.

Let's start locally. Clone that repo or use one of your own and then use cargo, that wonderful tool, to create the html documentation: cargo doc --no-deps --open. --no-deps excludes documentation for any dependencies; leave it off if you want them. --open opens the documentation in your browser. (For more information on creating Rust documentation, see the docs on cargo doc and rustdoc.)

cargo defaults to opening the library documentation when there is both a library and a binary, but you can easily get to the binary docs from the sidebar. Let's examine the URL we'll need to replicate. For this project, for me, the address is file:///home/kris/dvrpc/traffic-counts/traffic-counts/target/doc/traffic_counts/index.html. The binary docs are at file:///home/kris/dvrpc/traffic-counts/traffic-counts/target/doc/import/index.html. What follows target/doc/ is the important part. (That's the default location, but it's configurable.)

There is no page above those; going to file:///home/kris/dvrpc/traffic-counts/traffic-counts/target/doc/ will give you the directory index. However, as you can see by visiting that directory, there are all kinds of things there that need to be included. So, we'll make the contents of that entire directory accessible, and, though not necessary, redirect from the bare /doc path to the library's documentation.

Now go to the server (Debian for me). I cloned the repo to /opt, cd'd into /opt/traffic-counts, and ran cargo doc --no-deps. The library's index.html is located at /opt/traffic-counts/target/doc/traffic_counts/index.html. For the binary documentation, it's ...doc/import/index.html.

And finally, here are the nginx header directives, in a jinja2 template, that allow you to then serve these static files. {{ docs_url }} is the root path you want them hosted at, e.g. use "/traffic-counts/docs" for http://example.com/traffic-counts/docs. Don't forget to reload nginx after you add this to your configuration.

# Traffic Counts documentation

# Make everything at target/doc available.
location {{ docs_url }} {
    alias /opt/traffic-counts/target/doc;
}

# There is no top-level index, so redirect it to the library crate
# with the trailing slash
location = {{ docs_url }}/ {
    return 301 $scheme://$http_host{{docs_url }}/traffic_counts/index.html;
}
# and without the trailing slash
location = {{ docs_url }} {
    return 301 $scheme://$http_host{{docs_url }}/traffic_counts/index.html;
}

In the return (redirect) statements, I use $scheme://$http_host so that it'll work in both production and development environments. Particularly useful is $http_host, which will include the port with a localhost address.