Read The Docs
  • Getting Started
    • Write Your Docs
    • Import Your Docs
  • Build Process
    • Understanding what’s going on
    • Builder Responsibility
    • Packages installed in the build environment
    • Writing your own builder
    • Deleting a stale or broken build environment
  • Read the Docs features
    • Github and Bitbucket Integration
    • Auto-updating
    • Internationalization
    • Canonical URLs
    • Versions
    • Version Control Support Matrix
    • PDF Generation
    • Search
    • Alternate Domains
  • Support
    • Getting Help
    • Backwards Incompatible Changes
  • Frequently Asked Questions
    • My project isn’t building with autodoc
    • How do I change behavior for Read the Docs?
    • I get import errors on libraries that depend on C modules
    • Can I make search engines only see one version of my docs?
    • Deleting a stale or broken build environment
    • How do I host multiple projects on one CNAME?
    • Where do I need to put my docs for RTD to find it?
    • I want to use the Blue/Default Sphinx theme
    • I want to use the Read the Docs theme locally
    • Image scaling doesn’t work in my documentation
    • I want comments in my docs
    • How do I support multiple languages of documentation?
    • Do I need to be whitelisted?
    • Does Read The Docs work well with “legible” docstrings?
  • Webhooks
    • Github
    • Bitbucket
    • Others
  • Badges
    • Status Badges
    • Project Pages
    • Style
  • Alternate Domains
    • Subdomain Support
    • CNAME Support
    • CNAME SSL
    • rtfd.org
  • Localization of Documentation
    • Single project in another language
    • Project with multiple translations
  • VCS Integration
    • GitHub
    • Bitbucket
  • Canonical URLs
    • Example
    • Enabling
    • Implementation
    • Links
  • Versions
    • How we envision versions working
    • Redirects on root URLs
  • Single Version Documentation
    • Enabling
    • Effects
  • Privacy Levels
    • Understanding the Privacy Levels
    • Project Objects
    • Version Objects
  • Installation
    • Solr (Search) Setup
    • What’s available
    • Installation with Vagrant
  • Contributing to Read the Docs
    • Tickets
    • Translations
  • Running tests
    • Continuous Integration
  • Architecture
    • Diagram
  • How we use symlinks
    • Nginx
    • Subdomains
    • CNAMEs
  • Interesting Settings
    • SLUMBER_USERNAME
    • SLUMBER_PASSWORD
    • USE_SUBDOMAIN
    • PRODUCTION_DOMAIN
    • MULTIPLE_APP_SERVERS
    • INDEX_ONLY_LATEST
    • DOCUMENT_PYQUERY_PATH
    • USE_PIP_INSTALL
  • Internationalization
    • Making Strings Localizable
    • Strings in Templates
    • Strings in Python
  • Administrative Tasks
    • Updating Localization Files
    • Compiling to MO
    • Transifex Integration
  • Read the Docs Public API
    • A basic API client using slumber
    • Example of adding a user to a project
    • API Endpoints
    • Root
    • Builds
    • Build
    • Files
    • File
    • Projects
    • Project
    • Users
    • User
    • Versions
    • Version
    • Filtering Examples
  • API
    • bookmarks
    • builds
    • doc_builder
    • core
    • projects
    • vcs_support
  • Designing Read the Docs
    • Style Catalog
    • Typekit Fonts
    • Readthedocs.org Changes
    • Sphinx Template Changes
    • Contributing
  • Read the Docs Theme
    • Contributing to the theme
    • How the Table of Contents builds
    • Other style notes
    • How do I use this locally, and on Read the Docs?
  • Sponsors of Read the Docs
    • Current sponsors
    • Past sponsors
  • Talks about Read the Docs
  • Configuration of the production servers
    • Deploying Code
    • Deploying Nginx
    • Elastic Search Setup
    • Servers
    • Site Checkout
 
Read The Docs
  • Docs »
  • How we use symlinks
  • Edit on GitHub

How we use symlinks¶

Read the Docs stays highly available by serving all documentation pages out of nginx. This means that they never hit our Python layer, meaning that they never hit out database. This reduces the total number of servers to serve a request to 1, each of which is redundant.

Nginx¶

We handle a couple of different types of requests in nginx:

  • Requests to a readthedocs.org subdomain
  • Requests to a CNAME

Subdomains¶

For subdomains this is a simple lookup. This doesn’t require symlinks, but it shows the basic logic that we need to replicate.

When a user navigates to http://pip.readthedocs.org/en/latest/, we know that they want the pip documentation. So we simply serve them the documentation:

location ~ ^/en/(.+)/(.*) {
    alias /home/docs/checkouts/readthedocs.org/user_builds/$domain/rtd-builds/$1/$2;
    error_page 404 = @fallback;
    error_page 500 = @fallback;
}

location @fallback {
    proxy_pass http://127.0.0.1:8888;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    add_header X-Deity Asgard;
}

Note

The @fallback directive is hit when we don’t find the proper file. This will cause things to hit the Python backend, so that proper action can be taken.

CNAMEs¶

CNAMEs add a bit of difficulty, because at the nginx layer we don’t know what documentation to serve. When someone requests http://docs.fabfile.org/en/latest/, we can’t look at the URL to know to serve the fabric docs.

This is where symlinks come in. When someone requests http://docs.fabfile.org/en/latest/ the first time, it hits the Python layer. In that Python layer we record that docs.fabfile.org points at fabric. When we build the fabric docs, we create a symlink for all domains that have pointed at fabric before.

So, when we get a request for docs.fabfile.org in the future, we will be able to serve it directly from nginx. In this example, $host would be docs.fabfile.org:

location ~ ^/en/(?P<doc_version>.+)/(?P<path>.*) {
    alias /home/docs/checkouts/readthedocs.org/cnames/$host/$doc_version/$path;
    error_page 404 = @fallback;
    error_page 500 = @fallback;
}

Notice that nowhere in the above path is the projects slug mentioned. It is simply there in the symlink in the cnames directory, and the docs are served from there.

Next Previous

© Copyright 2010, Eric Holscher, Charlie Leifer, Bobby Grace.

Sphinx theme provided by Read the Docs