diff --git a/doc/sphinx/Makefile.am b/doc/sphinx/Makefile.am
index 8fe5dd5839..103e315c21 100644
--- a/doc/sphinx/Makefile.am
+++ b/doc/sphinx/Makefile.am
@@ -1,223 +1,224 @@
 #
 # Copyright 2003-2023 the Pacemaker project contributors
 #
 # The version control history for this file may have further details.
 #
 # This source code is licensed under the GNU General Public License version 2
 # or later (GPLv2+) WITHOUT ANY WARRANTY.
 #
 include $(top_srcdir)/mk/common.mk
 
 # Define release-related variables
 include $(top_srcdir)/mk/release.mk
 
 # Things you might want to override on the command line
 
 # Books to generate
 BOOKS		?= Clusters_from_Scratch	\
 		   Pacemaker_Administration	\
 		   Pacemaker_Development	\
 		   Pacemaker_Explained		\
 		   Pacemaker_Python_API 	\
 		   Pacemaker_Remote
 
 # Output formats to generate. Possible values:
 #  html       (multiple HTML files)
 #  dirhtml    (HTML files named index.html in multiple directories)
 #  singlehtml (a single large HTML file)
 #  text
 #  pdf
 #  epub
 #  latex
 #  linkcheck  (not actually a format; check validity of external links)
 #
 # The results will end up in <book>/_build/<format>
 BOOK_FORMATS	?= singlehtml
 
 # Set to "a4paper" or "letterpaper" if building latex format
 PAPER          ?= letterpaper
 
 # Additional options for sphinx-build
 SPHINXFLAGS	?=
 
 # toplevel rsync destination for www targets (without trailing slash)
 RSYNC_DEST	?= root@www.clusterlabs.org:/var/www/html
 
 # End of useful overrides
 
 
 # Example scheduler transition graphs
 # @TODO The original CIB XML for these is long lost. Ideally, we would recreate
 # something similar and keep those here instead of the DOTs (or use a couple of
 # scheduler regression test inputs instead), then regenerate the SVG
 # equivalents using crm_simulate and dot when making a release.
 DOTS =	$(wildcard shared/images/*.dot)
 
 # Vector sources for generated PNGs (including SVG equivalents of DOTS, created
 # manually using dot)
 SVGS =	$(wildcard shared/images/pcmk-*.svg) \
 	$(DOTS:%.dot=%.svg)
 
 # PNG images generated from SVGS
 #
 # These will not be accessible in a VPATH build, which will generate warnings
 # when building the documentation, but the make will still succeed. It is
 # nontrivial to get them working for VPATH builds and not worth the effort.
 PNGS_GENERATED	= $(SVGS:%.svg=%.png)
 
 # Original PNG image sources
 PNGS_Clusters_from_Scratch = $(wildcard Clusters_from_Scratch/images/*.png)
 PNGS_Pacemaker_Explained   = $(wildcard Pacemaker_Explained/images/*.png)
 PNGS_Pacemaker_Remote      = $(wildcard Pacemaker_Remote/images/*.png)
 
 STATIC_FILES	= $(wildcard _static/*.css)
 
 EXTRA_DIST	= $(wildcard */*.rst) $(DOTS) $(SVGS)			\
 		  $(PNGS_Clusters_from_Scratch)				\
 		  $(PNGS_Pacemaker_Explained)				\
 		  $(PNGS_Pacemaker_Remote)				\
 		  $(wildcard Pacemaker_Python_API/_templates/*rst) 	\
 		  $(STATIC_FILES)					\
 		  conf.py.in
 
 # recursive, preserve symlinks/permissions/times, verbose, compress,
 # don't cross filesystems, sparse, show progress
 RSYNC_OPTS      = -rlptvzxS --progress
 
 PACKAGE_SERIES=$(shell echo "$VERSION" | awk -F. '{ print $1"."$2 }')
 
 BOOK_RSYNC_DEST	= $(RSYNC_DEST)/$(PACKAGE)/doc/$(PACKAGE_SERIES)
 
 BOOK		= none
 
 DEPS_intro			= shared/pacemaker-intro.rst \
 				  $(PNGS_GENERATED)
 
 DEPS_Clusters_from_Scratch	= $(DEPS_intro) 		\
 				  $(PNGS_Clusters_from_Scratch)
 DEPS_Pacemaker_Administration	= $(DEPS_intro)
 DEPS_Pacemaker_Development	=
 DEPS_Pacemaker_Explained	= $(DEPS_intro) 		\
 				  $(PNGS_Pacemaker_Explained)
 DEPS_Pacemaker_Python_API 	= ../../python
 DEPS_Pacemaker_Remote		= $(PNGS_Pacemaker_Remote)
 
 if BUILD_SPHINX_DOCS
 
 INKSCAPE_CMD	= $(INKSCAPE) --export-dpi=90 -C
 
 # Pattern rule to generate PNGs from SVGs
 # (--export-png works with Inkscape <1.0, --export-filename with >=1.0;
 # create the destination directory in case this is a VPATH build)
 %.png: %.svg
 	$(AM_V_at)-$(MKDIR_P) "$(shell dirname "$@")"
 	$(AM_V_GEN) {							\
 		$(INKSCAPE_CMD) --export-png="$@" "$<" 2>/dev/null	\
 		|| $(INKSCAPE_CMD) --export-filename="$@" "$<";		\
 	} $(PCMK_quiet)
 
 # Create a book's Sphinx configuration.
 # Create the book directory in case this is a VPATH build.
 $(BOOKS:%=%/conf.py): conf.py.in
 	$(AM_V_at)-$(MKDIR_P) "$(@:%/conf.py=%)"
 	$(AM_V_GEN)sed								\
 		-e 's/%VERSION%/$(VERSION)/g'					\
 		-e 's/%BOOK_ID%/$(@:%/conf.py=%)/g'				\
 		-e 's/%BOOK_TITLE%/$(subst _, ,$(@:%/conf.py=%))/g'		\
 		-e 's#%SRC_DIR%#$(abs_srcdir)#g'				\
 		-e 's#%ABS_TOP_SRCDIR%#$(abs_top_srcdir)#g'			\
 		-e 's#%CONFIGDIR%#@CONFIGDIR@#g'				\
 		-e 's#%CRM_BLACKBOX_DIR%#@CRM_BLACKBOX_DIR@#g'			\
 		-e 's#%CRM_CONFIG_DIR%#@CRM_CONFIG_DIR@#g'			\
 		-e 's#%CRM_DAEMON_GROUP%#@CRM_DAEMON_GROUP@#g'			\
 		-e 's#%CRM_DAEMON_USER%#@CRM_DAEMON_USER@#g'			\
 		-e 's#%CRM_LOG_DIR%#@CRM_LOG_DIR@#g'				\
 		-e 's#%CRM_SCHEMA_DIRECTORY%#@CRM_SCHEMA_DIRECTORY@#g'		\
 		-e 's#%PACEMAKER_CONFIG_DIR%#@PACEMAKER_CONFIG_DIR@#g'		\
 		-e 's#%PCMK_GNUTLS_PRIORITIES%#@PCMK_GNUTLS_PRIORITIES@#g'	\
+		-e 's#%PCMK__REMOTE_SCHEMA_DIR%#@PCMK__REMOTE_SCHEMA_DIR@#g'	\
 		$(<) > "$@"
 
 $(BOOK)/_build: $(STATIC_FILES) $(BOOK)/conf.py $(DEPS_$(BOOK)) $(wildcard $(srcdir)/$(BOOK)/*.rst)
 	@echo 'Building "$(subst _, ,$(BOOK))" because of $?' $(PCMK_quiet)
 	$(AM_V_at)rm -rf "$@"
 	$(AM_V_BOOK)for format in $(BOOK_FORMATS); do			\
 		echo -e "\n * Building $$format" $(PCMK_quiet);		\
 		doctrees="doctrees";					\
 		real_format="$$format";					\
 		case "$$format" in					\
 			pdf) real_format="latex" ;;			\
 			gettext) doctrees="gettext-doctrees" ;;		\
 		esac;							\
 		$(SPHINX) -b "$$real_format" -d "$@/$$doctrees"		\
 			-c "$(builddir)/$(BOOK)"			\
 			-D latex_elements.papersize=$(PAPER)		\
 			$(SPHINXFLAGS)					\
 			"$(srcdir)/$(BOOK)" "$@/$$format"		\
 			$(PCMK_quiet);					\
 		if [ "$$format" = "pdf" ]; then				\
 			$(MAKE) $(AM_MAKEFLAGS)	-C "$@/$$format"	\
 				all-pdf;				\
 		fi;							\
 	done
 endif
 
 build-$(PACKAGE_SERIES).txt: all
 	$(AM_V_GEN)echo "Generated on `date --utc` from version $(TAG)" > "$@"
 
 .PHONY: books-upload
 books-upload: all build-$(PACKAGE_SERIES).txt
 if BUILD_SPHINX_DOCS
 	@echo "Uploading $(PACKAGE_SERIES) documentation set"
 	@for book in $(BOOKS); do 					\
 		echo " * $$book";					\
 		rsync $(RSYNC_OPTS) $(BOOK_FORMATS:%=$$book/_build/%)	\
 			"$(BOOK_RSYNC_DEST)/$$book/";			\
 	done
 	@rsync $(RSYNC_OPTS) "$(builddir)/build-$(PACKAGE_SERIES).txt"	\
 		"$(RSYNC_DEST)/$(PACKAGE)/doc"
 endif
 
 .PHONY: all-local
 all-local:
 if BUILD_SPHINX_DOCS
 	@for book in $(BOOKS); do					\
 		$(MAKE) $(AM_MAKEFLAGS) BOOK=$$book			\
 			PAPER="$(PAPER)" SPHINXFLAGS="$(SPHINXFLAGS)"	\
 			BOOK_FORMATS="$(BOOK_FORMATS)" $$book/_build;	\
 	done
 endif
 
 .PHONY: install-data-local
 install-data-local: all-local
 if BUILD_SPHINX_DOCS
 	$(AM_V_at)for book in $(BOOKS); do				\
 		for format in $(BOOK_FORMATS); do			\
 			formatdir="$$book/_build/$$format";		\
 			for f in `find "$$formatdir" -print`; do	\
 				dname="`echo $$f | sed s:_build/::`";	\
 				dloc="$(DESTDIR)/$(docdir)/$$dname";	\
 				if [ -d "$$f" ]; then			\
 					$(INSTALL) -d -m 755 "$$dloc";	\
 				else					\
 					$(INSTALL_DATA) "$$f" "$$dloc";	\
 				fi					\
 			done;						\
 		done;							\
 	done
 endif
 
 .PHONY: uninstall-local
 uninstall-local:
 if BUILD_SPHINX_DOCS
 	$(AM_V_at)for book in $(BOOKS); do		\
 		rm -rf "$(DESTDIR)/$(docdir)/$$book";	\
 	done
 endif
 
 .PHONY: clean-local
 clean-local:
 	$(AM_V_at)-rm -rf				\
 		$(BOOKS:%="$(builddir)/%/_build")	\
 		$(BOOKS:%="$(builddir)/%/conf.py")	\
 		$(BOOKS:%="$(builddir)/%/generated")	\
 		$(PNGS_GENERATED)
diff --git a/doc/sphinx/conf.py.in b/doc/sphinx/conf.py.in
index 9aac5e95d0..a921b3aad6 100644
--- a/doc/sphinx/conf.py.in
+++ b/doc/sphinx/conf.py.in
@@ -1,330 +1,331 @@
 """ Sphinx configuration for Pacemaker documentation
 """
 
 __copyright__ = "Copyright 2020-2023 the Pacemaker project contributors"
 __license__ = "GNU General Public License version 2 or later (GPLv2+) WITHOUT ANY WARRANTY"
 
 # This file is execfile()d with the current directory set to its containing dir.
 #
 # Note that not all possible configuration values are present in this
 # autogenerated file.
 #
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
 import datetime
 import os
 import sys
 
 # Variables that can be used later in this file
 authors = "the Pacemaker project contributors"
 year = datetime.datetime.now().year
 doc_license = "Creative Commons Attribution-ShareAlike International Public License"
 doc_license += " version 4.0 or later (CC-BY-SA v4.0+)"
 
 # rST markup to insert at beginning of every document; mainly used for
 #
 #   .. |<abbr>| replace:: <Full text>
 #
 # where occurrences of |<abbr>| in the rST will be substituted with <Full text>
 rst_prolog="""
 .. |CFS_DISTRO| replace:: AlmaLinux
 .. |CFS_DISTRO_VER| replace:: 9
 .. |CRM_BLACKBOX_DIR| replace:: ``%CRM_BLACKBOX_DIR%``
 .. |CRM_CONFIG_DIR| replace:: ``%CRM_CONFIG_DIR%``
 .. |CRM_DAEMON_GROUP| replace:: ``%CRM_DAEMON_GROUP%``
 .. |CRM_DAEMON_USER| replace:: ``%CRM_DAEMON_USER%``
 .. |CRM_SCHEMA_DIRECTORY| replace:: %CRM_SCHEMA_DIRECTORY%
 .. |PCMK_AUTHKEY_FILE| replace:: %PACEMAKER_CONFIG_DIR%/authkey
 .. |PCMK_CONFIG_FILE| replace:: ``%CONFIGDIR%/pacemaker``
 .. |PCMK_GNUTLS_PRIORITIES| replace:: %PCMK_GNUTLS_PRIORITIES%
 .. |PCMK_INIT_ENV_FILE| replace:: ``%PACEMAKER_CONFIG_DIR%/pcmk-init.env``
 .. |PCMK_LOG_FILE| replace:: %CRM_LOG_DIR%/pacemaker.log
 .. |PCMK_CONTAINER_LOG_FILE| replace:: ``/var/log/pcmk-init.log``
+.. |PCMK__REMOTE_SCHEMA_DIR| replace:: %PCMK__REMOTE_SCHEMA_DIR%
 .. |REMOTE_DISTRO| replace:: AlmaLinux
 .. |REMOTE_DISTRO_VER| replace:: 9
 """
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
 sys.path.insert(0, os.path.abspath('%ABS_TOP_SRCDIR%/python'))
 
 # -- General configuration -----------------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
 needs_sphinx = '1.0'
 
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
 extensions = ['sphinx.ext.autodoc',
               'sphinx.ext.autosummary']
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
 
 # The suffix of source filenames.
 source_suffix = '.rst'
 
 # The encoding of source files.
 #source_encoding = 'utf-8-sig'
 
 # The master toctree document.
 master_doc = 'index'
 
 # General information about the project.
 project = '%BOOK_ID%'
 copyright = "2009-%s %s. Released under the terms of the %s" % (year, authors, doc_license)
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # The full version, including alpha/beta/rc tags.
 release = '%VERSION%'
 # The short X.Y version.
 version = release.rsplit('.', 1)[0]
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
 #language = None
 
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:
 #today = ''
 # Else, today_fmt is used as the format for a strftime call.
 #today_fmt = '%B %d, %Y'
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
 exclude_patterns = ['_build']
 
 # The reST default role (used for this markup: `text`) to use for all documents.
 #default_role = None
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
 #add_function_parentheses = True
 
 # If true, the current module name will be prepended to all description
 # unit titles (such as .. function::).
 #add_module_names = True
 
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # output. They are ignored by default.
 #show_authors = False
 
 # The name of the Pygments (syntax highlighting) style to use.
 pygments_style = 'vs'
 
 # A list of ignored prefixes for module index sorting.
 #modindex_common_prefix = []
 
 
 # -- Options for HTML output ---------------------------------------------------
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
 html_theme = 'pyramid'
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # documentation.
 #html_theme_options = {}
 
 # Add any paths that contain custom themes here, relative to this directory.
 #html_theme_path = []
 
 html_style = 'pacemaker.css'
 
 # The name for this set of Sphinx documents.  If None, it defaults to
 # "<project> v<release> documentation".
 html_title = "%BOOK_TITLE%"
 
 # A shorter title for the navigation bar.  Default is the same as html_title.
 #html_short_title = None
 
 # The name of an image file (relative to this directory) to place at the top
 # of the sidebar.
 #html_logo = None
 
 # The name of an image file (within the static path) to use as favicon of the
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
 #html_favicon = None
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
 html_static_path = [ '%SRC_DIR%/_static' ]
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.
 #html_last_updated_fmt = '%b %d, %Y'
 
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
 #html_use_smartypants = True
 
 # Custom sidebar templates, maps document names to template names.
 #html_sidebars = {}
 
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
 #html_additional_pages = {}
 
 # If false, no module index is generated.
 #html_domain_indices = True
 
 # If false, no index is generated.
 #html_use_index = True
 
 # If true, the index is split into individual pages for each letter.
 #html_split_index = False
 
 # If true, links to the reST sources are added to the pages.
 #html_show_sourcelink = True
 
 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
 #html_show_sphinx = True
 
 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
 #html_show_copyright = True
 
 # If true, an OpenSearch description file will be output, and all pages will
 # contain a <link> tag referring to it.  The value of this option must be the
 # base URL from which the finished HTML is served.
 #html_use_opensearch = ''
 
 # This is the file name suffix for HTML files (e.g. ".xhtml").
 #html_file_suffix = None
 
 # Output file base name for HTML help builder.
 htmlhelp_basename = 'Pacemakerdoc'
 
 
 # -- Options for LaTeX output --------------------------------------------------
 
 latex_engine = "xelatex"
 
 latex_elements = {
 # The paper size ('letterpaper' or 'a4paper').
 #'papersize': 'letterpaper',
 
 # The font size ('10pt', '11pt' or '12pt').
 #'pointsize': '10pt',
 
 # Additional stuff for the LaTeX preamble.
 #'preamble': '',
 }
 
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
   ('index', '%BOOK_ID%.tex', '%BOOK_TITLE%', authors, 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
 # the title page.
 #latex_logo = None
 
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # not chapters.
 #latex_use_parts = False
 
 # If true, show page references after internal links.
 #latex_show_pagerefs = False
 
 # If true, show URL addresses after external links.
 #latex_show_urls = False
 
 # Documents to append as an appendix to all manuals.
 #latex_appendices = []
 
 # If false, no module index is generated.
 #latex_domain_indices = True
 
 
 # -- Options for manual page output --------------------------------------------
 
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 man_pages = [
     ('index', '%BOOK_ID%', 'Part of the Pacemaker documentation set', [authors], 8)
 ]
 
 # If true, show URL addresses after external links.
 #man_show_urls = False
 
 
 # -- Options for Texinfo output ------------------------------------------------
 
 # Grouping the document tree into Texinfo files. List of tuples
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
     ('index', '%BOOK_ID%', '%BOOK_TITLE%', authors, '%BOOK_TITLE%',
      'Pacemaker is an advanced, scalable high-availability cluster resource manager.',
      'Miscellaneous'),
 ]
 
 # Documents to append as an appendix to all manuals.
 #texinfo_appendices = []
 
 # If false, no module index is generated.
 #texinfo_domain_indices = True
 
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
 #texinfo_show_urls = 'footnote'
 
 
 # -- Options for Epub output ---------------------------------------------------
 
 # Bibliographic Dublin Core info.
 epub_title = '%BOOK_TITLE%'
 epub_author = authors
 epub_publisher = 'ClusterLabs.org'
 epub_copyright = copyright
 
 # The language of the text. It defaults to the language option
 # or en if the language is not set.
 #epub_language = ''
 
 # The scheme of the identifier. Typical schemes are ISBN or URL.
 epub_scheme = 'URL'
 
 # The unique identifier of the text. This can be a ISBN number
 # or the project homepage.
 epub_identifier = 'https://www.clusterlabs.org/pacemaker/doc/2.1/%BOOK_ID%/epub/%BOOK_ID%.epub'
 
 # A unique identification for the text.
 epub_uid = 'ClusterLabs.org-Pacemaker-%BOOK_ID%'
 
 # A tuple containing the cover image and cover page html template filenames.
 #epub_cover = ()
 
 # HTML files that should be inserted before the pages created by sphinx.
 # The format is a list of tuples containing the path and title.
 #epub_pre_files = []
 
 # HTML files that should be inserted after the pages created by sphinx.
 # The format is a list of tuples containing the path and title.
 #epub_post_files = []
 
 # A list of files that should not be packed into the epub file.
 epub_exclude_files = [
     '_static/doctools.js',
     '_static/jquery.js',
     '_static/searchtools.js',
     '_static/underscore.js',
     '_static/basic.css',
     '_static/websupport.js',
     'search.html',
 ]
 
 # The depth of the table of contents in toc.ncx.
 #epub_tocdepth = 3
 
 # Allow duplicate toc entries.
 #epub_tocdup = True
 
 autosummary_generate = True