Skip to content

Docs: update custom domains docs #9266

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jun 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@
hoverxref_domains = ["py"]
hoverxref_roles = [
"option",
"doc",
"doc", # Documentation pages
"term", # Glossary terms
]
hoverxref_role_types = {
"mod": "modal", # for Python Sphinx Domain
Expand Down
71 changes: 71 additions & 0 deletions docs/user/canonical-urls.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
Canonical URLs
==============

A `canonical URL`_
allows you to specify the preferred version of a web page to prevent duplicated content.
They are mainly used by search engines to link users to the correct
version and domain of your documentation.

If canonical URL's aren't used,
it's easy for outdated documentation to be the top search result for various pages in your documentation.
This is not a perfect solution for this problem,
but generally people finding outdated documentation is a big problem,
and this is one of the suggested ways to solve it from search engines.
Comment on lines +11 to +13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels redundant, and/or isn't adding much for the reader. Is there a specific reason worth mentioning why it isn't a great solution perhaps? If not, maybe worth skipping this sentence

Suggested change
This is not a perfect solution for this problem,
but generally people finding outdated documentation is a big problem,
and this is one of the suggested ways to solve it from search engines.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to justify why we're doing this. Users will likely be confused why this is happening if we don't explain the tradeoffs between not using canonical versions and indexing every version.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, but the sentence before describes the problem better. This sentences mostly distills down to "this is one imperfect solution to the problem we just outlined", and so sounds redundant, and isn't confident.

I'm suggesting either expanding on the problem/solution or dropping this sentence. Something like this expands on both:

Suggested change
This is not a perfect solution for this problem,
but generally people finding outdated documentation is a big problem,
and this is one of the suggested ways to solve it from search engines.
Linking to outdated documentation is confusing for your readers,
but this can be avoided by telling search engines exactly where to find your documentation.


.. _canonical URL: https://developers.google.com/search/docs/advanced/crawling/consolidate-duplicate-urls

How Read the Docs generates canonical URLs
------------------------------------------

The canonical URL takes into account:

* The default version of your project (usually "latest" or "stable").
* The canonical :doc:`custom domain </custom-domains>` if you have one,
otherwise the default :ref:`subdomain <hosting:subdomain support>` will be used.

For example, if you have a project named ``example-docs``
with a custom domain ``https://docs.example.com``,
then your documentation will be served at ``https://example-docs.readthedocs.io`` and ``https://docs.example.com``.
Without specifying a canonical URL, a search engine like Google will index both domains.

You'll want to use ``https://docs.example.com`` as your canonical domain.
This means that when Google indexes a page like ``https://example-docs.readthedocs.io/en/latest/``,
it will know that it should really point at ``https://docs.example.com/en/latest/``,
thus avoiding duplicating the content.

.. note::

If you want your custom domain to be set as the canonical, you need to set ``Canonical: This domain is the primary one where the documentation is served from`` in the :guilabel:`Admin` > :guilabel:`Domains` section of your project settings.

Implementation
--------------

The canonical URL is set in HTML with a ``link`` element.
For example, this page has a canonical URL of:

.. code-block:: html

<link rel="canonical" href="https://docs.readthedocs.io/en/stable/canonical-urls.html" />

Sphinx
~~~~~~

If you are using :doc:`Sphinx </intro/getting-started-with-sphinx>`,
Read the Docs will set the value of the html_baseurl_ setting (if isn't already set) to your canonical domain.
If you already have ``html_baseurl`` set, you need to ensure that the value is correct.

.. _html_baseurl: https://www.sphinx-doc.org/page/usage/configuration.html#confval-html_baseurl

Mkdocs
~~~~~~

For :doc:`MkDocs </intro/getting-started-with-mkdocs>` this isn't done automatically,
but you can use the site_url_ setting to set a similar value.

.. _site_url: https://www.mkdocs.org/user-guide/configuration/#site_url

.. warning::

If you change your default version or canonical domain,
you'll need to re-build all your versions in order to update their
canonical URL to the new one.
Copy link
Member

@ericholscher ericholscher May 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is bad UX :( but not much we can do but document it for now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This warning applies for both, mkdocs and sphinx, we should move it at the parent section maybe

118 changes: 118 additions & 0 deletions docs/user/custom-domains.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
Custom Domains
==============

Custom domains allow you to serve your documentation from your own domain.
This is great for maintaining a consistent brand for your documentation and application.

By default, your documentation is served from a Read the Docs :ref:`subdomain <hosting:subdomain support>` using the project's :term:`slug`:

* ``<slug>.readthedocs.io`` for |org_brand|
* ``<slug>.readthedocs-hosted.com`` for |com_brand|.

For example if you import your project and it gets the :term:`slug` ``example-docs``, it will be served from ``https://example-docs.readthedocs.io``.

.. contents:: Contents
:local:

Adding a custom domain
----------------------

To setup your custom domain, follow these steps:

#. Go the :guilabel:`Admin` tab of your project.
#. Click on :guilabel:`Domains`.
#. Enter your domain.
#. Mark the :guilabel:`Canonical` option if you want use this domain
as your :doc:`canonical domain </canonical-urls>`.
#. Click on :guilabel:`Add`.
#. At the top of the next page you'll find the value of the DNS record that you need to point your domain to.
For |org_brand| this is ``readthedocs.io``, and for :doc:`/commercial/index`
the record is in the form of ``<hash>.domains.readthedocs.com``.

.. note::

For a subdomain like ``docs.example.com`` add a CNAME record,
and for a root domain like ``example.com`` use an ANAME or ALIAS record.

By default, we provide a validated SSL certificate for the domain,
managed by `Cloudflare <https://www.cloudflare.com/>`_.
The SSL certificate issuance should happen within a few minutes,
but might take up to one hour.
See `SSL certificate issue delays`_ for more troubleshooting options.

As an example, our blog's DNS record looks like this:

.. prompt:: bash $, auto

$ dig +short CNAME blog.readthedocs.com
readthedocs.io.

.. warning::

We don't support pointing subdomains or root domains to a project using A records.
DNS A records require a static IP address and our IPs may change without notice.


Removing a custom domain
------------------------

To remove a custom domain:

#. Go the :guilabel:`Admin` tab of your project.
#. Click on :guilabel:`Domains`.
#. Click the :guilabel:`Remove` button next to the domain.
#. Click :guilabel:`Confirm` on the confirmation page.

.. warning::

Once a domain is removed,
your previous documentation domain is no longer served by Read the Docs,
and any request for it will return a 404 Not Found!

Strict Transport Security (HSTS) and other custom headers
---------------------------------------------------------

By default, we do not return a `Strict Transport Security header`_ (HSTS) for user custom domains.
This is a conscious decision as it can be misconfigured in a not easily reversible way.
For both |org_brand| and |com_brand|, HSTS and other custom headers can be set upon request.

We always return the HSTS header with a max-age of at least one year
for our own domains including ``*.readthedocs.io``, ``*.readthedocs-hosted.com``, ``readthedocs.org`` and ``readthedocs.com``.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we include HSTS on readthedocs.build for a particular reason?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guessing we just haven't done it yet.


Please contact :doc:`support` if you want to add a custom header to your domain.

.. _Strict Transport Security header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security

Multiple documentation sites as sub-folders of a domain
-------------------------------------------------------

You may host multiple documentation repositories as **sub-folders of a single domain**.
For example, ``docs.example.org/projects/repo1`` and ``docs.example.org/projects/repo2``.
This is `a way to boost the SEO of your website <https://moz.com/blog/subdomains-vs-subfolders-rel-canonical-vs-301-how-to-structure-links-optimally-for-seo-whiteboard-friday>`_.

See :doc:`subprojects` for more information.
Comment on lines +86 to +93
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this doesn't make much sense to be here, but I don't know where else to put it, maybe we should put this on the features pages as the description for subprojects?


Troubleshooting
---------------

SSL certificate issue delays
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The status of your domain validation and certificate can always be seen on the details page for your domain
under :guilabel:`Admin` > :guilabel:`Domains` > :guilabel:`YOURDOMAIN.TLD (details)`.

Domains are usually validated and a certificate issued within minutes.
However, if you setup the domain in Read the Docs without provisioning the necessary DNS changes
and then update DNS hours or days later,
this can cause a delay in validating because there is an exponential back-off in validation.

.. tip::

Loading the domain details in the Read the Docs dashboard and saving the domain again will force a revalidation.

Migrating from GitBook
~~~~~~~~~~~~~~~~~~~~~~

If your custom domain was previously used in GitBook, contact GitBook support (via live chat in their website)
to remove the domain name from their DNS Zone in order for your domain name to work with Read the Docs,
else it will always redirect to GitBook.
197 changes: 0 additions & 197 deletions docs/user/custom_domains.rst

This file was deleted.

Loading