Documentation Hub Setup

Overview

This runbook documents the implementation of the Domus Digitalis multi-repository documentation hub using Antora. The architecture follows a hub-spoke model that scales to any number of component repositories while maintaining a unified site with cross-component navigation and search.

Architecture

Hub-Spoke Model

Component Repository Purpose

Hub

domus-docs

Orchestration only. No content. Contains playbook, branding, diagrams, build tooling.

Spoke

domus-infra-ops

Infrastructure operations, architecture, services, runbooks, recovery procedures.

Spoke

domus-ise-linux

Linux EAP-TLS deployment methodology, PKI, ISE configuration.

Spoke

domus-netapi-docs

Network automation CLI documentation (85+ pages).

Spoke

domus-secrets-ops

Secrets management with dsec/SOPS/age.

Design Principles

Separation of Concerns

Hub handles orchestration; spokes own their content.

Scalability

Add new components without modifying existing repositories.

Independence

Each component can build and test in isolation.

Consistency

Unified branding, search, and navigation across all components.

Parameterization

All values as attributes - no hardcoded content anywhere.

Repository Structure

Hub Repository (domus-docs)

domus-docs/
├── antora-playbook.yml           # CI playbook (GitHub URLs)
├── antora-playbook-local.yml     # Local dev playbook (filesystem paths)
├── Makefile                      # Build automation
├── package.json                  # Node.js dependencies
├── diagrams/                     # Architecture diagrams
│   ├── hub-spoke-architecture.d2
│   └── hub-spoke-architecture.svg
├── supplemental-ui/              # UI customizations
│   ├── css/custom.css
│   └── partials/header-content.hbs
└── .github/workflows/
    └── deploy.yml                # GitHub Pages deployment

Spoke Repository Structure

Each spoke follows the standard Antora component layout:

component-repo/
├── Makefile                      # Local build automation
├── README.adoc                   # Repository documentation
├── runbooks/                     # Standalone runbooks (symlinked)
└── docs/asciidoc/
    ├── antora.yml                # Component descriptor (100+ attributes)
    ├── antora-playbook.yml       # Local standalone build
    └── modules/ROOT/
        ├── nav.adoc              # Navigation structure
        ├── pages/                # AsciiDoc content
        │   ├── index.adoc
        │   ├── architecture/
        │   ├── services/
        │   ├── runbooks/         # Symlinks to root runbooks
        │   └── ...
        ├── partials/
        │   └── diagrams/         # Parameterized diagram templates
        ├── images/
        │   └── diagrams/         # Rendered SVG diagrams
        └── examples/             # Code examples

Makefile Implementation

The Makefile provides unified build automation for both development and CI/CD.

Hub Makefile Targets

# Configuration
PLAYBOOK := antora-playbook.yml
PLAYBOOK_LOCAL := antora-playbook-local.yml
BUILD_DIR := build/site
DIAGRAM_DIR := diagrams

# Default target (uses local paths for development)
all: diagrams local

# Local build (filesystem paths - fast development)
local: $(PLAYBOOK_LOCAL)
	npx antora $(PLAYBOOK_LOCAL)

# CI build (GitHub URLs - requires credentials)
site: $(PLAYBOOK)
	npx antora $(PLAYBOOK)

# Serve locally on port 8000
serve: diagrams local
	cd $(BUILD_DIR) && python3 -m http.server 8000

# Diagram rendering (d2, mermaid, graphviz)
diagrams: diagrams-d2 diagrams-mermaid diagrams-graphviz

diagrams-d2:
	@for f in $(DIAGRAM_DIR)/*.d2; do \
		d2 "$$f" "$${f%.d2}.svg"; \
	done

# Clean build artifacts
clean:
	rm -rf $(BUILD_DIR) .cache

Key Design Decisions

Dual Playbooks

antora-playbook.yml uses GitHub URLs for CI/CD. antora-playbook-local.yml uses filesystem paths for fast local development.

Automatic Diagram Rendering

Diagrams are rendered from source (d2/mmd/dot) to SVG before site build. This keeps diagram source in version control while generating optimized output.

Symlinked Runbooks

Runbooks live at project root for standalone PDF export. Symlinks in pages/runbooks/ make them available to Antora. Edit once, available everywhere.

Playbook Configuration

Local Development Playbook

site:
  title: Domus Digitalis
  url: https://docs.domusdigitalis.dev
  start_page: infra-ops::index.adoc

content:
  sources:
    # Local filesystem paths for fast iteration
    - url: /path/to/domus-infra-ops
      branches: HEAD
      start_path: docs/asciidoc
    - url: /path/to/domus-ise-linux
      branches: HEAD
      start_path: docs/asciidoc

ui:
  bundle:
    url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable
    snapshot: true
  supplemental_files: ./supplemental-ui

asciidoc:
  extensions:
    - '@asciidoctor/tabs'

output:
  dir: ./build/site
  clean: true

CI/CD Playbook

For GitHub Actions, component repos are checked out locally:

content:
  sources:
    - url: ./components/domus-infra-ops
      branches: HEAD
      start_path: docs/asciidoc

Attribute Parameterization

Component antora.yml

Each spoke defines 100+ attributes for complete parameterization:

name: infra-ops
title: Infrastructure Operations
version: '2026'

asciidoc:
  attributes:
    # Domain configuration
    domain: inside.domusdigitalis.dev

    # Infrastructure hosts
    ise-01-hostname: ise-01.inside.domusdigitalis.dev
    ise-01-ip: 10.50.1.20

    # Vault PKI
    vault-addr: http://127.0.0.1:8200
    vault-pki-root: pki
    vault-server-role: domus-server

    # Network
    vlan-mgmt: 100
    subnet-mgmt: 10.50.100.0/24

    # Paths
    byod-cert-dir: /home/ansible/byod-certs

Usage in Content

Reference attributes anywhere in AsciiDoc:

Connect to the ISE admin interface at `{ise-pan-hostname}`.

The certificate is stored at `{byod-cert-dir}/device.crt`.

Vault server: `{vault-addr}`

Parameterized Diagrams

Create diagram templates with attribute substitution:

[d2,target=vault-architecture,subs=attributes+]
....
vault: HashiCorp Vault {
  addr: {vault-addr}
}
ise: {ise-pan-hostname}
vault -> ise: issues certs
....

Cross-Component Linking

Link between components using qualified xrefs:

// From infra-ops, link to ise-linux
See xref:prj-ise-home-linux::02-pki/vault-byod-enrollment.adoc[BYOD Enrollment].

// From ise-linux, link to infra-ops
See xref:infra-ops::runbooks/pki-strategy.adoc[PKI Strategy].

GitHub Pages Deployment

Workflow Configuration

The deployment workflow:

  1. Checks out hub repository

  2. Checks out component repositories

  3. Builds unified site with Antora

  4. Deploys to GitHub Pages

jobs:
  build:
    steps:
      - uses: actions/checkout@v4
      - uses: actions/checkout@v4
        with:
          repository: EvanusModestus/domus-infra-ops
          path: components/domus-infra-ops
          token: ${{ secrets.REPO_ACCESS_TOKEN }}
      # ... build and deploy

Required Configuration

  1. Create Personal Access Token with repo scope

  2. Add REPO_ACCESS_TOKEN secret to domus-docs repository

  3. Enable GitHub Pages in repository settings (Source: GitHub Actions)

Build Commands

Command Description

make

Build diagrams + unified site (local)

make site

Build using GitHub URLs (CI)

make serve

Build and serve on localhost:8000

make diagrams

Render all diagrams to SVG

make clean

Remove build artifacts

make check-deps

Verify required tools

Adding a New Component

  1. Create new repository with Antora structure:

    mkdir -p docs/asciidoc/modules/ROOT/{pages,partials,images}
  2. Create antora.yml with component name and attributes

  3. Add navigation in modules/ROOT/nav.adoc

  4. Add to hub playbook:

    content:
      sources:
        # ... existing sources ...
        - url: https://github.com/EvanusModestus/new-component
          branches: main
          start_path: docs/asciidoc
  5. Update deployment workflow to checkout new component

  6. Rebuild: make

Troubleshooting

Missing xref targets

Ensure xref paths are correct for Antora:

// Wrong - relative path
xref:disaster-recovery.adoc[]

// Correct - from pages directory
xref:runbooks/disaster-recovery.adoc[]

// Cross-component
xref:component-name::path/to/page.adoc[]

Build fails on private repos

For CI builds with private repos:

  1. Create PAT with repo scope

  2. Add as REPO_ACCESS_TOKEN secret

  3. Use token: ${{ secrets.REPO_ACCESS_TOKEN }} in checkout action

Diagram not rendering

Ensure diagram tools are installed:

make check-deps