$linuxjunkies
>

Writing Technical Documentation (the Linux way)

Write and publish Linux technical documentation using Markdown, AsciiDoc, man pages, DocBook, pandoc, and MkDocs—with CI integration and practical examples.

IntermediateUbuntuDebianFedoraArch10 min readUpdated May 26, 2026

Before you start

  • Basic command-line familiarity (file editing, running commands, make)
  • Git installed and a project repository to document
  • Python 3 and pip available for MkDocs installation
  • Ruby and gem available if using asciidoctor-pdf directly

Technical documentation is a first-class deliverable, not an afterthought. The Linux ecosystem has a rich tradition of plain-text documentation formats—each with distinct strengths—and a solid toolkit for converting, publishing, and maintaining them. Whether you are shipping a man page with your CLI tool, maintaining a project wiki, or producing a multi-format manual, the right format and toolchain matters. This guide covers the practical landscape: Markdown, AsciiDoc, man pages (troff/groff), DocBook's legacy, and the modern tooling that ties it all together.

Choosing the Right Format

Each format exists for a reason. Picking the wrong one creates friction later.

FormatBest forOutput targets
MarkdownREADMEs, wikis, lightweight docs sitesHTML, PDF (via pandoc)
AsciiDocBooks, manuals, structured technical docsHTML5, PDF, EPUB, man
troff/manSystem man pagesTerminal, PostScript
DocBook XMLEnterprise documentation, standards bodiesHTML, PDF, man, EPUB
reStructuredTextPython projects, Sphinx-based docsHTML, PDF, man

For new projects, Markdown handles simple needs and AsciiDoc handles complex ones. Use troff only when you are writing man pages directly; everyone else should generate them from a higher-level format.

Markdown: Fast, Portable, and Everywhere

Markdown is the lingua franca of project documentation. Every major code forge renders it natively. Keep files in a docs/ directory alongside your source code.

Install CommonMark-compliant tooling

# Debian/Ubuntu
sudo apt install pandoc cmark

# Fedora/RHEL
sudo dnf install pandoc cmark

# Arch
sudo pacman -S pandoc cmark

Use CommonMark syntax rather than GitHub-Flavored Markdown when portability matters. Avoid raw HTML inside Markdown if the document will be processed by multiple renderers.

Linting Markdown

markdownlint-cli2 catches heading hierarchy errors, trailing whitespace, and inconsistent list style—the bugs that break rendered output silently.

npm install -g markdownlint-cli2
markdownlint-cli2 "docs/**/*.md"

AsciiDoc: Markdown Grown Up

AsciiDoc supports cross-references, includes, admonitions, tables with spanning cells, and conditional content—features Markdown simply does not have. The reference implementation is Asciidoctor, written in Ruby.

Install Asciidoctor

# Debian/Ubuntu
sudo apt install asciidoctor

# Fedora/RHEL
sudo dnf install asciidoctor

# Arch
sudo pacman -S asciidoctor

# Any distro, via RubyGems (latest version)
gem install asciidoctor asciidoctor-pdf

A minimal AsciiDoc document

cat > myproject.adoc <<'EOF'
= My Project Manual
Author Name <[email protected]>
v1.0, 2024-06-01
:toc:
:source-highlighter: rouge

== Installation

Clone the repository and run the installer.

[source,bash]
----
git clone https://example.com/myproject
cd myproject && sudo make install
----

== Configuration

See <<advanced,Advanced Options>> for tuning.

[[advanced]]
== Advanced Options

TBD.
EOF
# Render to HTML5
asciidoctor myproject.adoc

# Render to PDF
asciidoctor-pdf myproject.adoc

The :toc: attribute auto-generates a table of contents. Cross-references like <<advanced,Advanced Options>> are validated at build time—broken links fail loudly, unlike Markdown.

Writing Man Pages

Man pages use troff macros, specifically the mdoc (BSD-style, preferred for new pages) or man macro set. Writing raw troff is tedious. Use Asciidoctor or pandoc to generate them instead.

Generate a man page from AsciiDoc

cat > mytool.1.adoc <<'EOF'
= mytool(1)
Author Name
:doctype: manpage
:manmanual: User Commands
:mansource: mytool 1.0

== NAME

mytool - frobnicate the widgets

== SYNOPSIS

*mytool* [_OPTIONS_] _FILE_...

== DESCRIPTION

Processes each _FILE_ and applies widget frobnicating.

== OPTIONS

*-v*, *--verbose*::
  Print verbose output.

== EXIT STATUS

*0*:: Success.
*1*:: General error.

== SEE ALSO

*grep*(1), *sed*(1)
EOF

asciidoctor -b manpage mytool.1.adoc -o mytool.1
# Verify it renders correctly
man ./mytool.1

Install the man page system-wide

sudo install -Dm644 mytool.1 /usr/local/share/man/man1/mytool.1
sudo mandb

Section numbers matter: 1 = user commands, 5 = file formats, 8 = sysadmin commands. Place the generated file in the matching manN/ directory.

DocBook: The Heritage Format

DocBook is XML-based and verbose by design. Most projects have moved away from writing DocBook directly, but it remains important as an intermediate format. Pandoc can read and write it; the Linux Documentation Project and many enterprise systems still produce DocBook. You will encounter it when maintaining legacy documentation or integrating with publishing pipelines that use DITA or DocBook stylesheets.

# Convert AsciiDoc to DocBook 5 XML
asciidoctor -b docbook5 myproject.adoc -o myproject.xml

# Convert DocBook XML to HTML using xsltproc and the docbook-xsl stylesheets
sudo apt install xsltproc docbook-xsl   # Debian/Ubuntu
xsltproc /usr/share/xml/docbook/stylesheet/nwalsh/current/html/docbook.xsl \
  myproject.xml > myproject.html

For new projects, treat DocBook as an output target, not an authoring format.

Pandoc: The Universal Converter

Pandoc converts between over 40 formats. It is the practical glue between authoring formats and output targets.

# Markdown → PDF (requires a LaTeX engine)
sudo apt install texlive-latex-base texlive-fonts-recommended  # Debian/Ubuntu
pandoc README.md -o README.pdf

# Markdown → man page
pandoc README.md -s -t man -o README.1

# Markdown → EPUB
pandoc docs/*.md -o manual.epub --metadata title="My Manual"

# AsciiDoc → HTML (pandoc reads AsciiDoc since 2.11)
pandoc myproject.adoc -f asciidoc -t html5 -o myproject.html

Use a Makefile or shell script to codify your build steps so that anyone checking out the repository can reproduce the docs with a single command.

cat > Makefile <<'EOF'
.PHONY: docs clean

docs:
	asciidoctor myproject.adoc
	asciidoctor -b manpage mytool.1.adoc -o mytool.1

clean:
	rm -f myproject.html mytool.1
EOF

MkDocs: Static Documentation Sites

MkDocs takes a directory of Markdown files and a YAML config and produces a navigable static site. It is the standard choice for project documentation hosted on GitHub Pages or any static host.

Install and initialize

pip install mkdocs mkdocs-material
mkdocs new myproject-docs
cd myproject-docs

The mkdocs-material theme is the de-facto standard: it is accessible, responsive, and has built-in search. Edit mkdocs.yml:

cat > mkdocs.yml <<'EOF'
site_name: My Project
theme:
  name: material
nav:
  - Home: index.md
  - Installation: install.md
  - Configuration: config.md
  - Reference: reference.md
EOF
# Local live-reload server
mkdocs serve

# Build static output to site/
mkdocs build

# Deploy to GitHub Pages
mkdocs gh-deploy

Verification and CI Integration

Documentation that is not tested drifts. Add a CI step that builds your docs on every commit.

# .github/workflows/docs.yml skeleton (GitHub Actions)
cat > .github/workflows/docs.yml <<'EOF'
name: Docs
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: sudo apt-get install -y asciidoctor pandoc
      - run: make docs
      - run: pip install mkdocs mkdocs-material && mkdocs build --strict
EOF

The --strict flag makes MkDocs fail on warnings, including broken internal links. Treat documentation build failures the same as test failures.

Troubleshooting

  • Pandoc PDF fails with LaTeX errors — Install texlive-xetex and pass --pdf-engine=xelatex. The default pdflatex engine does not handle Unicode well.
  • Man page renders with literal asterisks — You have not compiled with -b manpage; you are viewing the raw AsciiDoc source. Re-run the correct Asciidoctor command.
  • MkDocs broken links in --strict mode — Internal links in MkDocs must use the file path (../config.md), not the rendered URL. Fix the link, not the strict flag.
  • asciidoctor-pdf missing fonts — Run gem install rouge and ensure the Noto font family is installed, or switch to the default theme which uses bundled fonts.
  • mandb reports "whatis parse error" — The NAME section of a man page must be exactly one line in the format name - description with no markup. Fix the AsciiDoc source in the == NAME block.
tested on:Ubuntu 24.04Fedora 40Arch rollingDebian 12

Frequently asked questions

Should I write man pages in raw troff or generate them?
Generate them. Writing raw troff is error-prone and hard to maintain. Use Asciidoctor with doctype: manpage or pandoc's man output target; both produce correct, portable troff output.
Is DocBook still relevant for new projects?
Rarely as an authoring format, but yes as an intermediate or output format. Many enterprise publishing pipelines, the Linux Documentation Project, and DITA-based toolchains still consume DocBook XML, so knowing how to produce it from AsciiDoc or pandoc is useful.
What is the difference between Asciidoc and AsciiDoc?
AsciiDoc is the format; Asciidoctor is the current reference implementation in Ruby. The older Python-based 'asciidoc' processor still exists in some package repos but is largely unmaintained—use Asciidoctor for all new work.
Can MkDocs produce PDF output?
Not natively. Use mkdocs-with-pdf (a third-party plugin) or build PDF separately via pandoc or Asciidoctor and link to it as a downloadable artifact from your MkDocs site.
How do I handle documentation for multiple versions of a project?
Use mike, the MkDocs versioning plugin, which deploys each version to a separate subdirectory on your docs host and maintains a version switcher in the UI. For AsciiDoc-based projects, use the :revnumber: attribute and maintain version branches in git.

Related guides