- Recommended: verify with mongosh
+ Insert and read your first document
- This is the fastest shared validation path after either install
- option because it confirms authentication, TLS, and a working
- endpoint before you add editor or driver setup. If you already
- know your target workflow, you can skip this and continue directly
- with VS Code or a driver quick start.
+ Install mongosh separately for the shell walkthrough below, or
+ use your preferred language or editor. Each guide connects to
+ the instance you already created and verifies an insert and read.
+ Sample data is optional.
params.has(key)) ? "packages" : "docker");
+ // Recover to the method the link asked for, so a stale package link stays on packages.
+ const fail = (error: string): SelectionResult => ({
+ selection: null,
+ error,
+ recovery: { ...defaultInstallSelection, method: method === "packages" ? "packages" : "docker" },
+ });
+ if (installQueryKeys.some((key) => params.getAll(key).length > 1)) {
+ return fail("This link contains conflicting install choices. Choose your settings below.");
+ }
+ if (method !== "packages" && method !== "docker") {
+ return fail("This install method is not supported. Choose Docker or Linux packages.");
+ }
+ const packages = parsePackageSelection(params);
+ if (typeof packages === "string") {
+ // Docker does not use package choices, so a stale one must not block it.
+ return method === "docker"
+ ? { selection: defaultInstallSelection, error: null }
+ : fail(packages);
+ }
+ return { selection: { method, packages }, error: null };
+}
+
+function parsePackageSelection(params: URLSearchParams): PackageSelection | string {
+ const family = params.get("family") ?? "apt";
+ const pg = params.get("pg") ?? "18";
+ const arch = params.get("arch") ?? "auto";
+ const target = params.get("target") ?? (family === "rpm" ? "rocky9" : "ubuntu24");
+
+ if (pg !== "17" && pg !== "18") {
+ return "Linux packages are available for PostgreSQL 17 and 18. Choose a supported version.";
+ }
+ if (family === "apt") {
+ if (!isAptTarget(target) || !aptTargetPgVersions[target].includes(pg)) {
+ return "This APT target is not supported. Choose Ubuntu 24.04.";
+ }
+ if (arch !== "auto" && arch !== "amd64" && arch !== "arm64") {
+ return "Choose automatic architecture, amd64, or arm64 for APT.";
+ }
+ return { family, target, arch, pg };
+ }
+ if (family === "rpm") {
+ if (!isRpmTarget(target) || !rpmServesFullStack(target, pg)) {
+ return "This RPM target is not supported. Choose an EL9 distribution below.";
+ }
+ if (arch !== "auto" && arch !== "x86_64" && arch !== "aarch64") {
+ return "Choose automatic architecture, x86_64, or aarch64 for RPM.";
+ }
+ return { family, target, arch, pg };
+ }
+ return "This package format is not supported. Choose an available Linux distribution.";
+}
+
+export function installSelectionQuery(selection: InstallSelection): string {
+ const { family, target, pg, arch } = selection.packages;
+ return new URLSearchParams({ method: selection.method, family, target, pg, arch }).toString();
+}
+
+// Docker links stay short, but keep non-default package choices so switching back restores them.
+export function installSelectionUrlQuery(selection: InstallSelection): string {
+ const { family, target, pg, arch } = selection.packages;
+ const defaults = defaultInstallSelection.packages;
+ const packagesChanged = family !== defaults.family || target !== defaults.target
+ || pg !== defaults.pg || arch !== defaults.arch;
+ return selection.method === "docker" && !packagesChanged ? "method=docker" : installSelectionQuery(selection);
+}
+
+export function selectInstallTarget(selection: InstallSelection, target: string): SelectionResult {
+ const params = new URLSearchParams(installSelectionQuery(selection));
+ const family = isAptTarget(target) ? "apt" : isRpmTarget(target) ? "rpm" : null;
+ if (!family) {
+ return {
+ selection: null,
+ error: "This distribution is not supported. Choose a listed Linux distribution.",
+ recovery: { ...defaultInstallSelection, method: selection.method },
+ };
+ }
+ const previousArch = selection.packages.arch;
+ const arch = previousArch === "auto"
+ ? "auto"
+ : previousArch === "arm64" || previousArch === "aarch64"
+ ? family === "apt" ? "arm64" : "aarch64"
+ : family === "apt" ? "amd64" : "x86_64";
+ params.set("family", family);
+ params.set("target", target);
+ params.set("arch", arch);
+ return parseInstallSelection(params.toString());
+}
+
+export function releaseHasPackages(release: ReleaseInfo, selection: PackageSelection): boolean {
+ const names = release.assetNames;
+ const has = (pattern: RegExp) => names.some((name) => pattern.test(name));
+ const { pg, arch, family } = selection;
+ if (family === "apt") {
+ const arches = arch === "auto" ? ["amd64", "arm64"] : [arch];
+ return [`documentdb-${pg}`, "documentdb-common", "documentdb-postgresql-tools"].every(
+ (name) => has(new RegExp(`^ubuntu24\\.04-${name}_[^_]+_all\\.deb$`)),
+ ) && arches.every((value) =>
+ has(new RegExp(`^ubuntu24\\.04-documentdb-gateway_[^_]+_${value}\\.deb$`)) &&
+ has(new RegExp(`^ubuntu24\\.04-postgresql-${pg}-documentdb_[^_]+_${value}\\.deb$`)),
+ );
+ }
+ const arches = arch === "auto" ? ["x86_64", "aarch64"] : [arch];
+ return [`documentdb-${pg}`, "documentdb-common", "documentdb-postgresql-tools"].every(
+ (name) => has(new RegExp(`^${name}-[0-9][^.]*\\..*\\.noarch\\.rpm$`)),
+ ) && arches.every((value) =>
+ has(new RegExp(`^documentdb-gateway-.*\\.el9\\.${value}\\.rpm$`)) &&
+ has(new RegExp(`^rhel9-postgresql${pg}-documentdb-.*\\.el9\\.${value}\\.rpm$`)),
+ );
+}
diff --git a/app/lib/releaseInfo.ts b/app/lib/releaseInfo.ts
index 948c748..2b5ac11 100644
--- a/app/lib/releaseInfo.ts
+++ b/app/lib/releaseInfo.ts
@@ -34,10 +34,7 @@ export type ReleaseInfo = {
assetNames: readonly string[];
};
-// Used until the fetch resolves, and permanently if it fails. A stale-but-valid
-// page is much better than a blank one, so this is a real release rather than a
-// placeholder. Keep it in step with the newest release; the drift check in CI
-// fails the build when it falls behind release-info.json.
+// A reference release, not evidence of current repository availability.
export const FALLBACK_RELEASE: ReleaseInfo = {
tagName: "v0.117-0",
aptVersion: "0.117-0",
@@ -77,24 +74,17 @@ function firstMatch(names: readonly string[], pattern: RegExp): string | null {
return null;
}
-/**
- * Derives the display versions from a release-info.json payload.
- *
- * Each field falls back independently: a release that stops shipping one
- * package shape must not blank out the versions that are still present.
- */
export function parseReleaseInfo(payload: unknown): ReleaseInfo {
if (!payload || typeof payload !== "object") {
- return FALLBACK_RELEASE;
+ throw new Error("The repository returned invalid release metadata.");
}
const raw = payload as RawReleaseInfo;
const names = assetNamesOf(raw);
-
- const tagName = typeof raw.tag_name === "string" ? raw.tag_name : FALLBACK_RELEASE.tagName;
- const releaseUrl =
- typeof raw.html_url === "string"
- ? raw.html_url
- : `https://github.com/documentdb/documentdb/releases/tag/${tagName}`;
+ if (typeof raw.tag_name !== "string" || !/^v\d+\.\d+[.-]\d+(?:[.-][a-zA-Z0-9]+)*$/.test(raw.tag_name)) {
+ throw new Error("The repository returned an invalid release tag.");
+ }
+ const tagName = raw.tag_name;
+ const releaseUrl = `https://github.com/documentdb/documentdb/releases/tag/${tagName}`;
// The extension keeps the control-file form (0.117-0) on DEB, while RPM
// splits it into Version/Release and renders 0.117.0-1.el9. Everything else
@@ -102,22 +92,22 @@ export function parseReleaseInfo(payload: unknown): ReleaseInfo {
// cannot claim a shape the release does not contain.
const aptVersion =
firstMatch(names, /^ubuntu[\d.]+-postgresql-\d+-documentdb_([^_]+)_/) ??
- firstMatch(names, /^deb\d+-postgresql-\d+-documentdb_([^_]+)_/) ??
- FALLBACK_RELEASE.aptVersion;
+ firstMatch(names, /^deb\d+-postgresql-\d+-documentdb_([^_]+)_/);
const rpmVersion =
- firstMatch(names, /^rhel\d+-postgresql\d+-documentdb-(.+)\.(?:x86_64|aarch64)\.rpm$/) ??
- FALLBACK_RELEASE.rpmVersion;
+ firstMatch(names, /^rhel\d+-postgresql\d+-documentdb-(.+)\.(?:x86_64|aarch64)\.rpm$/);
const metaVersion =
firstMatch(names, /^ubuntu[\d.]+-documentdb_([^_]+)_all\.deb$/) ??
- firstMatch(names, /^documentdb-(\d+\.\d+\.\d+)-\d+\.noarch\.rpm$/) ??
- FALLBACK_RELEASE.metaVersion;
+ firstMatch(names, /^documentdb-(\d+\.\d+\.\d+)-\d+\.noarch\.rpm$/);
// e.g. documentdb-0.117.0-1.noarch.rpm -> 0.117.0-1
const metaRpmVersion =
- firstMatch(names, /^documentdb-(\d+\.\d+\.\d+-\d+)\.noarch\.rpm$/) ??
- FALLBACK_RELEASE.metaRpmVersion;
+ firstMatch(names, /^documentdb-(\d+\.\d+\.\d+-\d+)\.noarch\.rpm$/);
+
+ if (!aptVersion || !rpmVersion || !metaVersion || !metaRpmVersion) {
+ throw new Error("The repository release metadata does not contain the expected package versions.");
+ }
return {
tagName,
@@ -130,37 +120,56 @@ export function parseReleaseInfo(payload: unknown): ReleaseInfo {
};
}
-/**
- * Reads the mirrored release description published alongside the packages.
- *
- * Returns the fallback synchronously so the first paint is always correct-ish,
- * then swaps in the live values. The site is a static export, so this has to
- * happen in the browser; NEXT_PUBLIC_BASE_PATH is the one base-path value Next
- * keeps in the client bundle.
- */
-export function useReleaseInfo(): ReleaseInfo {
- const [release, setRelease] = useState
(FALLBACK_RELEASE);
+export type ReleaseState = {
+ release: ReleaseInfo;
+ status: "loading" | "live" | "fallback";
+ error: string | null;
+};
+
+export function useReleaseInfo(): ReleaseState {
+ const [state, setState] = useState({
+ release: FALLBACK_RELEASE,
+ status: "loading",
+ error: null,
+ });
useEffect(() => {
let cancelled = false;
const basePath = process.env.NEXT_PUBLIC_BASE_PATH ?? "";
+ const controller = new AbortController();
+ const timeout = window.setTimeout(() => controller.abort(), 15000);
- fetch(`${basePath}/packages/release-info.json`)
- .then((response) => (response.ok ? response.json() : Promise.reject(response.status)))
+ fetch(`${basePath}/packages/release-info.json`, { signal: controller.signal })
+ .then((response) => {
+ if (!response.ok) {
+ throw new Error(`Release metadata is unavailable (HTTP ${response.status}).`);
+ }
+ return response.json();
+ })
.then((payload) => {
if (!cancelled) {
- setRelease(parseReleaseInfo(payload));
+ setState({ release: parseReleaseInfo(payload), status: "live", error: null });
+ }
+ })
+ .catch((error: unknown) => {
+ if (!cancelled) {
+ setState({
+ release: FALLBACK_RELEASE,
+ status: "fallback",
+ error: error instanceof Error && error.name !== "AbortError"
+ ? error.message
+ : "The release metadata request timed out.",
+ });
}
})
- .catch(() => {
- // Keep the fallback: an unreachable or malformed feed must not empty
- // the install commands the page exists to show.
- });
+ .finally(() => window.clearTimeout(timeout));
return () => {
cancelled = true;
+ window.clearTimeout(timeout);
+ controller.abort();
};
}, []);
- return release;
+ return state;
}
diff --git a/app/packages/layout.tsx b/app/packages/layout.tsx
index 051d8c3..c81a967 100644
--- a/app/packages/layout.tsx
+++ b/app/packages/layout.tsx
@@ -2,11 +2,11 @@ import { getMetadata } from "../services/metadataService";
// The packages page is a client component, so its metadata lives here.
export const metadata = getMetadata({
- title: "Download DocumentDB - Docker, APT, and RPM Packages",
+ title: "Install DocumentDB - Docker and Linux Packages",
description:
- "Run DocumentDB with Docker or install the full stack from GPG-signed repositories for Ubuntu 24.04 and EL9, including Rocky-family systems and registered RHEL. Build other targets from source.",
+ "Run DocumentDB with Docker on Linux, macOS, or Windows, or install Linux packages on Ubuntu 24.04 or RHEL/Rocky 9 with apt or dnf. Linux packages are pre-GA and for fresh installs.",
path: "/packages/",
- extraKeywords: ["download", "install", "Docker", "APT", "RPM", "Debian", "Ubuntu", "RHEL"],
+ extraKeywords: ["install", "Linux", "APT", "RPM", "dnf", "Ubuntu", "RHEL", "Rocky Linux", "Docker"],
});
export default function PackagesLayout({
diff --git a/app/packages/page.tsx b/app/packages/page.tsx
index a56a7cc..af8a58f 100644
--- a/app/packages/page.tsx
+++ b/app/packages/page.tsx
@@ -1,28 +1,32 @@
"use client";
import Link from "next/link";
-import { useEffect, useState } from "react";
+import { useSearchParams } from "next/navigation";
+import { Suspense, useEffect, useState } from "react";
import CommandSnippet from "../components/CommandSnippet";
import {
- aptTargetPgVersions,
aptTargetLabels,
- aptServesFullStack,
+ aptTargetPgVersions,
buildAptInstallCommand,
buildRpmInstallCommand,
buildSetupCommand,
- rpmServesFullStack,
- type AptArch,
- type AptDistro,
- type AptPgVersion,
- type RpmArch,
- type RpmDistro,
- type RpmPgVersion,
rpmTargetLabels,
} from "../lib/packageInstall";
+import {
+ defaultInstallSelection,
+ installQueryKeys,
+ installSelectionQuery,
+ installSelectionUrlQuery,
+ parseInstallSelection,
+ releaseHasPackages,
+ selectInstallTarget,
+ type SelectionResult,
+} from "../lib/installSelection";
import { useReleaseInfo } from "../lib/releaseInfo";
-
-type InstallMethod = "docker" | "packages";
-type PackageFamily = "apt" | "rpm";
+import {
+ documentdbVsCodeExtensionMarketplaceUrl,
+ documentdbVsCodeLocalQuickStartDeepLink,
+} from "../services/externalLinks";
const dockerCommand = `docker run -dt --name documentdb \\
-p 127.0.0.1:10260:10260 \\
@@ -30,694 +34,465 @@ const dockerCommand = `docker run -dt --name documentdb \\
--username '' \\
--password ''`;
+const dockerReadyCommand = `until docker logs documentdb 2>&1 | grep -q "=== DocumentDB is ready ==="; do sleep 2; done`;
+
+const firstQuery = `use quickstart
+db.orders.insertOne({ item: "widget", qty: 5 })
+db.orders.find({ item: "widget" })`;
+
const nextGuides = [
- {
- title: "Getting started",
- description: "See the full setup flow and choose the guide that fits your environment.",
- href: "/docs/getting-started",
- },
- {
- title: "Python Quick Start",
- description: "Install PyMongo and connect to your local DocumentDB instance.",
- href: "/docs/getting-started/python-setup",
- },
- {
- title: "Node.js Quick Start",
- description: "Use the Node.js driver and run your first queries locally.",
- href: "/docs/getting-started/nodejs-setup",
- },
- {
- title: "Visual Studio Code Quick Start",
- description: "Connect through the VS Code extension for a guided local workflow.",
- href: "/docs/getting-started/vscode-quickstart",
- },
+ { title: "Python", description: "Connect with PyMongo.", href: "/docs/getting-started/python-setup" },
+ { title: "Node.js", description: "Use the MongoDB Node.js driver.", href: "/docs/getting-started/nodejs-setup" },
+ { title: "Visual Studio Code", description: "Explore your data in the editor.", href: "/docs/getting-started/vscode-quickstart" },
] as const;
-const allReleasesUrl = "https://github.com/documentdb/documentdb/releases";
-
-// The v0.116-0 packaging redesign replaced the single extension package with
-// this set. Listed here so the page explains what an install actually brings
-// in, instead of naming one package and silently pulling four more.
const packageRoles = [
- {
- name: "documentdb / documentdb-N",
- role: "Meta and per-major stand-alone package. Pins PostgreSQL and owns the systemd lifecycle.",
- },
- {
- name: "postgresql-N-documentdb",
- role: "The PostgreSQL extension itself (files only).",
- },
- {
- name: "documentdb-gateway",
- role: "Wire-protocol runtime that serves the MongoDB-compatible endpoint.",
- },
- {
- name: "documentdb-postgresql-tools",
- role: "Administrator helpers: documentdb-tune, documentdb-createcluster, documentdb-register-gateway, documentdb-gateway-admin.",
- },
- {
- name: "documentdb-common",
- role: "Shared payload: documentdb-setup, the systemd units, helper scripts and sample data.",
- },
+ { name: "documentdb-N", role: "The complete stack for PostgreSQL major N. Owns that instance's service lifecycle." },
+ { name: "postgresql-N-documentdb", role: "PostgreSQL extension files. RPM uses postgresqlN-documentdb." },
+ { name: "documentdb-gateway", role: "The MongoDB-compatible wire-protocol runtime." },
+ { name: "documentdb-postgresql-tools", role: "Tools for configuration, gateway registration, and user administration." },
+ { name: "documentdb-common", role: "The shared setup wizard, service templates, helpers, and optional sample data." },
+];
+
+const linkClass = "text-blue-300 underline decoration-blue-300/40 underline-offset-4 hover:text-blue-200";
+const selectClass = "mt-2 w-full rounded-lg border border-neutral-600 bg-neutral-900 px-3 py-3 text-sm text-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-400";
+const panelClass = "rounded-xl border border-neutral-700 bg-neutral-800/60 p-5 sm:p-7";
+const vscodeGuideUrl = "/docs/getting-started/vscode-quickstart";
+
+// Same two Docker workflows, with the same names, as the homepage quick start.
+const dockerSetups = [
+ { value: "command", title: "Docker command", description: "Run it yourself" },
+ { value: "guided", title: "Guided setup", description: "VS Code extension" },
] as const;
+type DockerSetup = (typeof dockerSetups)[number]["value"];
-export default function PackagesPage() {
- const release = useReleaseInfo();
- const [method, setMethod] = useState("docker");
- const [packageFamily, setPackageFamily] = useState("apt");
- // Default to the paved road (Ubuntu 24.04 + PostgreSQL 18). The package
- // finder exposes only combinations built and tested in the mirrored release.
- const [aptTarget, setAptTarget] = useState("ubuntu24");
- const [rpmTarget, setRpmTarget] = useState("rocky9");
- const [aptArch, setAptArch] = useState("amd64");
- const [rpmArch, setRpmArch] = useState("x86_64");
- const [aptPgVersion, setAptPgVersion] = useState("18");
- const [rpmPgVersion, setRpmPgVersion] = useState("18");
- const availableAptPgVersions = aptTargetPgVersions[aptTarget];
+function InstallLocation({ onChange }: { onChange: (result: SelectionResult) => void }) {
+ const search = useSearchParams().toString();
+ useEffect(() => onChange(parseInstallSelection(search)), [onChange, search]);
+ return null;
+}
- useEffect(() => {
- if (!availableAptPgVersions.includes(aptPgVersion)) {
- setAptPgVersion(availableAptPgVersions[availableAptPgVersions.length - 1]);
- }
- }, [aptPgVersion, availableAptPgVersions]);
+export default function PackagesPage() {
+ const { release, status: releaseStatus, error: releaseError } = useReleaseInfo();
+ const [state, setState] = useState(null);
+ const [dockerSetup, setDockerSetup] = useState("command");
- const latestReleaseAptVersion = release.aptVersion;
- const latestReleaseRpmVersion = release.rpmVersion;
+ // A broken link still shows the method it asked for, with commands withheld.
+ const selection = state?.selection ?? (state?.error ? state.recovery : defaultInstallSelection);
+ const { method, packages } = selection;
+ const { family, target, pg, arch } = packages;
+ const selectionReady = state !== null && state.error === null;
+ // The commands install from the package repository, so only a confirmed gap in the release withholds them.
+ const packagesMissing = releaseStatus === "live" && !releaseHasPackages(release, packages);
+ const canInstall = selectionReady && !packagesMissing;
+ const targetLabel = packages.family === "apt" ? aptTargetLabels[packages.target] : rpmTargetLabels[packages.target];
+ const selectedPackageNames = `documentdb-${pg}`;
const packagingGuideUrl = `https://github.com/documentdb/documentdb/blob/${release.tagName}/packaging/README.md`;
- const currentReleaseExamples = [
- `ubuntu24.04-documentdb_${release.metaVersion}_all.deb`,
- `ubuntu24.04-postgresql-18-documentdb_${latestReleaseAptVersion}_amd64.deb`,
- `rhel9-postgresql18-documentdb-${latestReleaseRpmVersion}.x86_64.rpm`,
- ] as const;
+ const setupCommand = buildSetupCommand(pg);
+ const installCommand = packages.family === "apt"
+ ? buildAptInstallCommand(packages.target, packages.arch, packages.pg)
+ : buildRpmInstallCommand(packages.target, packages.arch, packages.pg);
+ // Same form as the getting-started guides.
+ const connectionCommand = `mongosh localhost:10260 -u ${method === "packages" ? "admin" : "''"} -p \\
+ --authenticationMechanism SCRAM-SHA-256 --tls --tlsAllowInvalidCertificates`;
+
+ function choose(result: SelectionResult) {
+ setState(result);
+ if (!result.selection) return;
+ const url = new URL(window.location.href);
+ for (const key of installQueryKeys) url.searchParams.delete(key);
+ for (const [key, value] of new URLSearchParams(installSelectionUrlQuery(result.selection))) {
+ url.searchParams.set(key, value);
+ }
+ window.history.replaceState(null, "", url);
+ }
- const aptCommand = buildAptInstallCommand(aptTarget, aptArch, aptPgVersion);
- const rpmCommand = buildRpmInstallCommand(rpmTarget, rpmArch, rpmPgVersion);
- // Tier-1 targets resolve the current full stack, so the selected package is
- // the per-major stand-alone rather than the bare extension.
- const isFullStack =
- packageFamily === "apt"
- ? aptServesFullStack(aptTarget, aptPgVersion)
- : rpmServesFullStack(rpmTarget, rpmPgVersion);
- const selectedPackageNames = isFullStack
- ? `documentdb-${packageFamily === "apt" ? aptPgVersion : rpmPgVersion}`
- : packageFamily === "apt"
- ? `postgresql-${aptPgVersion}-documentdb`
- : `postgresql${rpmPgVersion}-documentdb`;
- const selectedTargetText =
- packageFamily === "apt" ? aptTargetLabels[aptTarget] : rpmTargetLabels[rpmTarget];
- const selectedArchText = packageFamily === "apt" ? aptArch : rpmArch;
+ function changeChoice(key: "method" | "pg" | "arch", value: string) {
+ const params = new URLSearchParams(installSelectionQuery(selection));
+ params.set(key, value);
+ choose(parseInstallSelection(params.toString()));
+ }
return (
-
-
-
-
- Download DocumentDB
-
-
- Choose Docker for the fastest local setup, or Linux packages for a persistent
- install. On Ubuntu 24.04 and EL9 (Rocky Linux, AlmaLinux, CentOS Stream, or
- registered Red Hat Enterprise Linux), the packages install the full DocumentDB
- stack — the PostgreSQL extension, the wire-protocol gateway, the administrator
- tools and systemd units. Starting with v0.116, the hosted package matrix is
- intentionally smaller and mirrors only combinations attached to the current
- official release.
+
+
+
+
+
+
+ Install DocumentDB
+
+ Use Docker to evaluate and develop on Linux, macOS, or Windows. On a supported Linux
+ host, Linux packages give you control over PostgreSQL, services, and configuration.
-
-
- GPG-signed Repositories
-
-
- Docker + Linux Packages
-
-
- AMD64 + ARM64
-
-
-
+
+ Download release assets
+ {" · "}Package details
+
+
-
- 1. Choose your install method
-
+
+ {([
+ { value: "docker", title: "Docker container", description: "Recommended for evaluation and development on Linux, macOS, and Windows.", detail: null },
+ { value: "packages", title: "Linux packages", description: "For environments without Docker, or when you need control over PostgreSQL, topology, services, and configuration.", detail: "Ubuntu 24.04 and EL9 · PostgreSQL 17/18 · AMD64 and ARM64" },
+ ] as const).map((item) => (
setMethod("docker")}
- className={`rounded-lg border px-4 py-4 text-left transition-colors ${
- method === "docker"
- ? "border-blue-400 bg-blue-500/15"
- : "border-neutral-700 bg-neutral-800 hover:bg-neutral-700/70"
+ aria-pressed={state !== null && method === item.value}
+ onClick={() => changeChoice("method", item.value)}
+ className={`rounded-xl border p-5 text-left transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-400 ${
+ state !== null && method === item.value ? "border-blue-400 bg-blue-500/15" : "border-neutral-700 bg-neutral-800/60 hover:bg-neutral-800"
}`}
>
- Docker
- Best for: quick local setup and evaluation. No PostgreSQL installation required.
+ {item.title}
+ {item.description}
+ {item.detail && {item.detail} }
+ ))}
+
+
+
+
+ Enable JavaScript to select installation commands, or follow the{" "}
+ Linux quickstart{" "}
+ or Docker quickstart.
+
+
+
+ {state?.error && (
+
+
{state.error} No installation commands are shown for this link.
setMethod("packages")}
- className={`rounded-lg border px-4 py-4 text-left transition-colors ${
- method === "packages"
- ? "border-blue-400 bg-blue-500/15"
- : "border-neutral-700 bg-neutral-800 hover:bg-neutral-700/70"
- }`}
+ onClick={() => choose({ selection: state.recovery, error: null })}
+ className="mt-3 rounded-md border border-amber-300 px-3 py-2 font-semibold focus-visible:outline-2 focus-visible:outline-offset-2"
>
- Linux Packages
-
- Best for: persistent Ubuntu 24.04 or EL9 VM and server environments.
-
+ {state.recovery.method === "packages" ? "Use supported Linux package settings" : "Use default settings"}
-
-
-
-
- 2. Copy and run this command
-
+ )}
- {method === "docker" ? (
- <>
-
-
- Starts DocumentDB locally on port 10260 for quick evaluation and development.
+ {/* The static page can't see the query string, so show no flow until it is read. */}
+ {state === null ? (
+
Loading installation steps...
+ ) : method === "packages" ? (
+ <>
+
+ Choose your Linux host
+
+ The selected {selectedPackageNames} package brings PostgreSQL, the extension,
+ gateway, setup tools, and services together. The number {pg} is the PostgreSQL major,
+ not the DocumentDB release.
-
-
- Open Docker Quick Start →
-
-
- >
- ) : (
- <>
-
-
- The prebuilt package matrix was reduced in v0.116
-
-
- documentdb.io now publishes only the combinations built and tested for the
- current release: Ubuntu 24.04 and EL9, PostgreSQL 17 or 18, on both supported
- architectures. EL9 covers Rocky Linux, AlmaLinux, CentOS Stream, and registered
- Red Hat Enterprise Linux with different prerequisite commands. Packages from
- earlier releases are not carried forward to make unsupported targets appear
- current. This also withdraws the older PostgreSQL 16 extension packages
- previously served for Ubuntu 24.04 and EL9.
-
-
- Need another distribution or PostgreSQL major? We welcome community builds.
- Check out the matching source tag and use our version-parameterized{" "}
-
- packaging scripts
-
- . The extension, gateway, and remaining stand-alone packages use separate
- scripts. PostgreSQL 15 is extension-only. These builds are on demand and are
- not official release assets hosted by documentdb.io.
-
-
-
-
Package Finder
-
-
- Package format
- setPackageFamily(event.target.value as PackageFamily)}
- className="mt-1 w-full rounded-md border border-neutral-700 bg-neutral-800 px-3 py-2 text-sm text-gray-100"
- >
- APT (Ubuntu 24.04)
- RPM (EL9)
+
+ Linux distribution
+
+ choose(selectInstallTarget(selection, event.target.value))} className={selectClass}>
+ {Object.entries({ ...aptTargetLabels, ...rpmTargetLabels }).map(([value, label]) => (
+ {label}
+ ))}
+
+
+
+ Advanced options: PostgreSQL {pg}, {arch === "auto" ? "automatic architecture" : arch}
+
+
+
+ PostgreSQL major
+ changeChoice("pg", event.target.value)} className={selectClass}>
+ {aptTargetPgVersions.ubuntu24.map((value) => {value}{value === "18" ? " (recommended)" : ""} )}
+
+ Host architecture
+ changeChoice("arch", event.target.value)} className={selectClass}>
+ Detect on the Linux host (recommended)
+ {(family === "apt" ? ["amd64", "arm64"] : ["x86_64", "aarch64"]).map((value) => {value} )}
+
+
+
+
+
+ Architecture is resolved in your terminal, not from your browser. Use a supported AMD64 or ARM64 Linux host with sudo and systemd.
+ Registered RHEL needs an active subscription.
+
+
- {packageFamily === "apt" ? (
-
- Distribution
- setAptTarget(event.target.value as AptDistro)}
- className="mt-1 w-full rounded-md border border-neutral-700 bg-neutral-800 px-3 py-2 text-sm text-gray-100"
- >
- {Object.entries(aptTargetLabels).map(([value, label]) => (
-
- {label}
-
- ))}
-
-
- ) : (
-
- Distribution
- setRpmTarget(event.target.value as RpmDistro)}
- className="mt-1 w-full rounded-md border border-neutral-700 bg-neutral-800 px-3 py-2 text-sm text-gray-100"
- >
- {Object.entries(rpmTargetLabels).map(([value, label]) => (
-
- {label}
-
- ))}
-
-
- )}
-
- {packageFamily === "apt" ? (
-
- Architecture
- setAptArch(event.target.value as AptArch)}
- className="mt-1 w-full rounded-md border border-neutral-700 bg-neutral-800 px-3 py-2 text-sm text-gray-100"
- >
- amd64
- arm64
-
-
- ) : (
-
- Architecture
- setRpmArch(event.target.value as RpmArch)}
- className="mt-1 w-full rounded-md border border-neutral-700 bg-neutral-800 px-3 py-2 text-sm text-gray-100"
- >
- x86_64
- aarch64
-
-
- )}
+
+ Pre-GA: fresh installations only
+
+ Use a clean supported Linux host. In-place package upgrades from earlier releases are
+ not supported. Removing packages preserves database files; reinstalling is not a data reset.
+
+
- {packageFamily === "apt" ? (
-
- PostgreSQL version
- setAptPgVersion(event.target.value as AptPgVersion)}
- className="mt-1 w-full rounded-md border border-neutral-700 bg-neutral-800 px-3 py-2 text-sm text-gray-100"
- >
- {availableAptPgVersions.map((pgVersion) => (
-
- {pgVersion}
-
- ))}
-
-
- ) : (
-
- PostgreSQL version
- setRpmPgVersion(event.target.value as RpmPgVersion)}
- className="mt-1 w-full rounded-md border border-neutral-700 bg-neutral-800 px-3 py-2 text-sm text-gray-100"
- >
- 17
- 18
-
-
- )}
+
+ {releaseStatus === "loading" ? (
+
Checking the published package release...
+ ) : releaseStatus === "fallback" ? (
+
+
Cannot confirm the current repository release. {releaseError}
+
+ The commands below install the latest packages from the repository. Last known
+ release: {release.tagName}.{" "}
+ Browse release assets {" "}
+ or window.location.reload()} className={linkClass}>retry the lookup .
+
-
+ ) : (
+
+ Published repository release:{" "}
+ {release.tagName}
+ {" · "}{targetLabel}{" · "}{arch === "auto" ? "AMD64 / ARM64" : arch}
+
+ )}
+
+ {selectionReady && packagesMissing && (
+
+ The complete package set for this selection is not present in the published release.
+ Choose another target or a specific available architecture, or{" "}
+ inspect the release assets .
+
+ )}
-
-
- Target: {selectedTargetText} · Architecture: {selectedArchText} · package names{" "}
- {selectedPackageNames}
+
+ 1. Install the packages
+
+ Run this in your Linux terminal. It adds the PostgreSQL and DocumentDB repositories
+ and signing keys, enables the required distribution repositories, and installs the complete
+ stack. Review the command before running it. Installation does not start a usable DocumentDB endpoint.
-
- The generated command adds the PostgreSQL upstream repositories that provide
- PostgreSQL, pg_cron,{" "}
- pgvector, PostGIS, and{" "}
- rum for PostgreSQL 17.
+ {canInstall ? : (
+
No command is shown for this selection.
+ )}
+
+
+
+ 2. Configure and start DocumentDB
+
+ The wizard creates a new private PostgreSQL instance for major {pg}, configures the extensions,
+ creates your admin login, and starts the gateway and services at boot. It asks for the admin
+ password in your terminal. Keep that password for the connection step.
-
- It installs the full DocumentDB stack for this target: the extension, the gateway
- runtime, the administrator tools and the systemd units.
+ {canInstall && }
+
+ The gateway listens on port 10260 on all interfaces by default. Restrict that port with your
+ firewall before setup. Use trusted TLS certificates before exposing it beyond local development.
- {isFullStack ? (
- <>
-
- Then run the setup wizard. The generated command pins the PostgreSQL major
- you selected and creates a new private instance, so another installed major
- or an existing system cluster cannot be selected by accident. It installs
- the extensions, bootstraps the admin user and starts the gateway — the
- package install above on its own does not leave a reachable endpoint. It
- prompts for the admin password. For automation, use the complete{" "}
-
- unattended setup
- {" "}
- instructions.
-
-
-
- Sample data is opt-in. After installing{" "}
- mongosh, add{" "}
- --load-sample-data to seed the{" "}
- StoreData database with 41,505 stores
- and 2 ratings. The command above leaves the new instance empty.
-
-
- The gateway then listens on port{" "}
- 10260. It binds all interfaces by
- default, so firewall the port before exposing it to a network. For existing
- PostgreSQL clusters, real certificates, upgrades, reset, and other day-2
- tasks, use the{" "}
-
- operations guide
-
- .
-
- >
- ) : null}
- {packageFamily === "apt" ? (
-
- Running in a clean Ubuntu container as root?
- Run export DEBIAN_FRONTEND=noninteractive in the shell first
- (and omit sudo from the command above).
- Without it, tzdata prompts for input partway through
- and the install hangs with no visible error.
+
+ Need automation? Follow the complete{" "}
+ unattended setup{" "}
+ instructions. Already managing PostgreSQL? Use the{" "}
+ operations guide{" "}
+ instead of creating a new instance.
+
+
+ >
+ ) : (
+ <>
+
+ {dockerSetups.map((item) => (
+ setDockerSetup(item.value)}
+ className={`min-h-14 rounded-lg px-4 py-3 text-left text-sm font-semibold transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-400 ${
+ dockerSetup === item.value ? "bg-neutral-700 text-white" : "text-gray-300 hover:text-white"
+ }`}
+ >
+ {item.title}
+ {item.description}
+
+ ))}
+
+ {dockerSetup === "guided" ? (
+
+ 1. Set up in VS Code
+
+ Install and start Docker first. The VS Code extension creates your local database,
+ generates credentials, and saves a connection.
- ) : null}
-
-
- {isFullStack
- ? "What gets installed"
- : "Need the MongoDB-compatible gateway?"}
+
+ Set up in VS Code
+
+
+ Requires VS Code .
+ You may be prompted to install the{" "}
+ DocumentDB extension .
+
+
2. Run your first query
+
+ When setup finishes, select Open Connection. Then follow the{" "}
+ VS Code quickstart{" "}
+ to add a document and read it back.
- {isFullStack ? (
+
+ ) : (
+
+ 1. Start a Docker container
+
+ Install and start Docker first. Replace both credential placeholders before running the
+ command. This local example exposes port 10260 only on your machine's loopback interface.
+
+ {selectionReady && (
<>
-
- A per-major DocumentDB install resolves five package names. Installing{" "}
- {selectedPackageNames} pulls in
- everything below; the optional documentdb{" "}
- meta package selects PostgreSQL 18.
+
+
+ The container is up before DocumentDB accepts connections. Wait for the readiness banner:
-
- {packageRoles.map((entry) => (
-
-
- {entry.name}
-
- {entry.role}
-
- ))}
-
+
>
- ) : (
-
- Use the Docker image for the fastest gateway-backed local setup. If you want a
- package-backed host install that still works with mongosh,
- the Linux package guide includes the exact non-root gateway follow-up commands
- and host build prerequisites.
-
)}
-
-
-
- Full package install guide →
-
-
- >
- )}
-
+
+ The container initializes the database; do not run the Linux package setup wizard inside it.
+ For persistent volumes and a versioned image, follow the{" "}
+ Docker quickstart.
+
+
+ )}
+ >
+ )}
-
-
-
- Current release package catalog
-
-
-
-
-
- Format
- Distributions
- Architectures
- PostgreSQL versions
- Package naming
- Version served
-
-
-
-
- APT
- Ubuntu 24.04 · ubuntu24
- amd64, arm64
- 17, 18
-
- documentdb-<pg>
-
- {release.metaVersion}
-
-
- RPM
-
- Rocky/Alma/CentOS Stream 9 or registered RHEL 9 ·{" "}
- rpm/rhel9
-
- x86_64, aarch64
- 17, 18
-
- documentdb-<pg>
-
- {release.metaRpmVersion}
-
-
-
-
- Compared with earlier releases, v0.116 reduces the hosted package matrix. The
- repository contains only package combinations attached to{" "}
-
- {release.tagName}
-
- . Other combinations remain build-on-demand targets in the source repository;
- see the{" "}
-
- packaging guide
- {" "}
- to build the package you need from the matching tag.
-
-
- Use Package Finder above to generate the exact command for your selected
- target, or see the{" "}
-
- Linux Packages Quick Start
- {" "}
- for the supported repository components and install commands written out in full.
-
+ {state !== null && !(method === "docker" && dockerSetup === "guided") && (
+
+ {method === "packages" ? "3" : "2"}. Connect and run your first query
+
+ Install{" "}
+ mongosh {" "}
+ separately, then connect from the same host as DocumentDB.{" "}
+ {method === "packages" ? "Use the admin password you chose during setup." : "Use the username and password you chose for Docker."}{" "}
+ The shell prompts for the password, so it stays out of your shell history.
+
+ {selectionReady && (method === "docker" || canInstall) && (
+ <>
+
+ In mongosh, insert a document and read it back:
+
+ >
+ )}
+
+ Expect an acknowledged insert and the widget document back.
+ The example uses the quickstart database. The self-signed certificate bypass is
+ for local development only; use trusted certificates and remove the bypass for other deployments.
+
+
+ {nextGuides.map((guide) => (
+
+ {guide.title}
+ {guide.description}
+
+ ))}
-
+
+ )}
-
-
- Migrating from repository targets retired in v0.116
-
-
-
- documentdb.io no longer publishes packages for Ubuntu 22.04, Debian 11/12/13,
- RHEL-compatible 8, or PostgreSQL 16. Existing installations keep running, but
- they receive no package updates and cannot reinstall those packages from the
- documentdb.io repository.
-
-
- Empty signed metadata remains at the retired repository URLs so{" "}
- apt update and{" "}
- dnf makecache do not break unrelated
- package operations. Remove the DocumentDB source if that host will not move to
- the current matrix:
-
-
-
sudo rm -f /etc/apt/sources.list.d/documentdb.list && sudo apt update
-
- sudo rm -f /etc/yum.repos.d/documentdb.repo && sudo dnf clean all
-
-
-
- To remain on an older target, use the matching GitHub release assets or build
- from that release tag. Those paths are not part of the current hosted support
- matrix.
-
+ {state !== null && method === "packages" && (
+
+ Keep control after the first query
+
+ Your private database lives under /var/lib/documentdb-local/{pg}/data.
+ The per-major package uses documentdb-local@{pg}.target for service management.
+ A restart preserves your data.
+
+ {canInstall && }
+
+ Sample data is optional. After installing mongosh, add{" "}
+ --load-sample-data to seed the{" "}
+ StoreData database when running setup. The default setup leaves your new instance empty.
+
+
+
+ Use your existing local PostgreSQL
+ Keep its lifecycle under your control. Review configuration changes and restart requirements first. Remote/cloud-managed PostgreSQL is not supported by this packaged flow.
+
+
+ Install only the PostgreSQL extension
+ Use the SQL-facing capabilities without installing a gateway. Extension-only installation does not create a MongoDB-compatible endpoint.
+
-
+
+ See the operations guide{" "}
+ for logs, TLS, user management, and cleanup. Removing packages or using{" "}
+ --restore does not erase database data.
+
+
+ )}
-
-
- Version pinning and listing available versions
-
-
-
- Use the commands below to discover available versions before pinning, and pin{" "}
- {selectedPackageNames} — the package your
- selected target actually installs.
-
-
- APT and RPM use different version syntax, and individual subpackages can carry
- different release suffixes. Always copy the exact version returned below for{" "}
- {selectedPackageNames}; do not infer it
- from the extension or another package.
-
-
-
APT — list then pin
-
-
- apt-cache madison {selectedPackageNames}
-
-
-
-
- sudo apt install {selectedPackageNames}=<VERSION>
-
-
-
-
-
RPM — list then pin
-
-
- dnf --showduplicates list {selectedPackageNames}
-
-
-
-
- sudo dnf install {selectedPackageNames}-<VERSION>
-
+
+
+ All downloads and package details
+
+ Browse GitHub release assets {" "}
+ for individual DEB/RPM files, checksums, and the package inventory. Select the matching distribution,
+ PostgreSQL major, and architecture; install the matching package set together.
+
+
+ The optional documentdb meta package selects PostgreSQL 18 and adds the public{" "}
+ documentdb-local.target alias. The commands above install the explicit per-major
+ package instead.
+
+
+ {packageRoles.map((entry) => (
+
+
{entry.name}
+ {entry.role}
-
-
- See all releases and release notes on{" "}
-
- GitHub Releases
-
- .
-
-
-
-
-
-
- Direct package downloads
-
-
-
- Individual .deb and{" "}
- .rpm files are attached to each release on
- GitHub. Recent release examples:
-
-
-
{currentReleaseExamples[0]}
-
{currentReleaseExamples[1]}
-
{currentReleaseExamples[2]}
-
-
- Choose an asset whose PostgreSQL version and architecture match your host.
-
-
- Browse releases on GitHub →
-
-
+ ))}
+
+
+ Other OS/PostgreSQL combinations are build-on-demand targets, not current hosted packages.
+ See the {releaseStatus === "live" ? "matching release packaging guide" : "reference release packaging guide"} .
+ PostgreSQL 15 is extension-only for Linux packages.
+
-
-
-
- Troubleshooting quick checks
-
-
-
-
- sudo apt update && apt search documentdb && apt-cache policy
- postgresql-18-documentdb
-
-
-
-
- sudo dnf clean all && dnf search documentdb && rpm -qi
- postgresql18-documentdb
-
+
+ Available versions and retired targets
+
+ For fresh installs, list available versions before pinning. APT and RPM use different version
+ syntax, and individual subpackages can carry different release suffixes. Use the version
+ reported for {selectedPackageNames}, not the extension's version.
+
+ {selectionReady && (
+
+
-
+ )}
+
+ The hosted matrix was reduced in v0.116. Ubuntu 22.04, Debian 11/12/13, EL8, and
+ PostgreSQL 16 packages are no longer served here. Existing installations are not
+ automatically migrated, and do not receive package updates from these retired targets.
+ Empty signed repository metadata remains so unrelated package operations continue to work.
+
+
+ Use matching older release assets or build from that source tag if you must stay on a
+ retired target. For a current installation, use a clean supported host. In-place upgrades
+ from earlier releases are not supported.
+
-
-
-
-
-
- 3. Connect and try it
-
-
- Docker starts a gateway-backed local endpoint on port 10260. On Ubuntu 24.04 and
- EL9 the packages give you the same thing: install, then run{" "}
-
- {buildSetupCommand(packageFamily === "apt" ? aptPgVersion : rpmPgVersion)}
-
- {", "}which creates a private database instance for the selected PostgreSQL major and
- starts the gateway.
+
+ Troubleshooting and manual instructions
+
+ Dependency errors: run the complete repository setup command, including PGDG and the distribution prerequisites.
+ Port already in use: select an explicit alternate port using the operations guide. Do not stop an unrelated service.
+ Cannot connect: confirm setup finished, services are active, and you are using the right host, credentials, and TLS settings.
+ Missing shell: mongosh is not included in the Linux package set; install it separately.
+ Uninstalling is not a reset: data deletion is a separate, explicit operation.
+
+
+ Complete Linux quickstart
+ {" · "} Advanced operations
+ {" · "} Docker quickstart
-
-
-
- {nextGuides.map((guide) => (
-
-
- {guide.title}
-
-
{guide.description}
-
- ))}
-
-
-
-
- Linux package guide
-
-
- All docs
-
-
+
diff --git a/app/page.tsx b/app/page.tsx
index ccd5d03..87c6645 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -331,7 +331,7 @@ export default function Home() {
href="/packages"
className="inline-flex w-full items-center justify-center rounded-md border border-blue-400 bg-blue-500/10 px-6 py-3 text-sm font-semibold text-blue-200 transition-colors hover:bg-blue-500/20 sm:w-auto"
>
- Download
+ Install & Download
' \\
@@ -111,6 +113,14 @@ use StoreData
db.stores.find({}, { _id: 0, name: 1, city: 1, "sales.revenue": 1 }).limit(3)
\`\`\`
+Write and read back your own document; this does not require sample data:
+
+\`\`\`javascript
+use quickstart
+db.orders.insertOne({ item: "widget", qty: 5 })
+db.orders.find({ item: "widget" })
+\`\`\`
+
If you prefer certificate validation instead of \`--tlsAllowInvalidCertificates\`, follow the certificate steps in [DocumentDB Local](/docs/documentdb-local).
## Persistence and initialization
@@ -163,35 +173,22 @@ If something does not work as expected:
- [DocumentDB Local](/docs/documentdb-local)
- [Samples Gallery](/samples)
- [Linux Packages Quick Start](/docs/getting-started/packages)
-- [Package Finder](/packages)
+- [Install DocumentDB](/packages?method=packages)
`;
export const linuxPackagesGuideContent = `# Linux Packages Quick Start
Install DocumentDB from the published package repository and get a MongoDB-compatible endpoint on your own host.
-The current official release publishes the full stack — extension, gateway, setup wizard and systemd units — for **Ubuntu 24.04 and EL9, on PostgreSQL 17 or 18**. EL9 includes Rocky Linux, AlmaLinux, CentOS Stream, and registered Red Hat Enterprise Linux; the Package Finder supplies the prerequisite command for each family. Starting with v0.116, this is a deliberately smaller prebuilt matrix than earlier releases. The website repository mirrors only the current release assets and does not carry older packages forward to make other targets appear current.
-
-> [!NOTE]
-> Need another distribution or PostgreSQL major? We welcome community builds. Check out the matching release tag and use the version-parameterized [packaging scripts](https://github.com/documentdb/documentdb/blob/v0.117-0/packaging/README.md). \`build_packages.sh\` builds the extension, \`gateway/build_gateway_packages.sh\` builds the gateway, and \`build_extra_packages.sh\` builds the common, tools, stand-alone, and meta packages. PostgreSQL 15 is extension-only because the setup tools require PostgreSQL 16 or newer. These builds are on demand and are not official release assets hosted by documentdb.io.
-
-## If you used an earlier repository target
-
-documentdb.io no longer publishes packages for Ubuntu 22.04, Debian 11/12/13, RHEL-compatible 8, or PostgreSQL 16. Existing installations keep running, but receive no package updates and cannot reinstall those packages from documentdb.io.
-
-Empty signed metadata remains at the retired repository URLs so \`apt update\` and \`dnf makecache\` continue to work. Remove the source on a host that will not move to the current matrix:
+The current official release publishes the full stack — extension, gateway, setup wizard and systemd units — for **Ubuntu 24.04 and EL9, on PostgreSQL 17 or 18, amd64 or arm64**. EL9 includes Rocky Linux, AlmaLinux, CentOS Stream, and registered Red Hat Enterprise Linux; [Linux packages installation](/packages?method=packages) supplies the prerequisite command for each family. Starting with v0.116, this is a deliberately smaller prebuilt matrix than earlier releases. The website repository mirrors only the current release assets and does not carry older packages forward to make other targets appear current.
-\`\`\`bash
-# Debian / Ubuntu
-sudo rm -f /etc/apt/sources.list.d/documentdb.list
-sudo apt update
+**Recommended:** install the complete stack, then create a new private PostgreSQL 18 instance. The commands detect architecture on the Linux host where you run them. For containers or macOS/Windows evaluation, choose [Docker installation](/packages?method=docker).
-# RHEL-compatible
-sudo rm -f /etc/yum.repos.d/documentdb.repo
-sudo dnf clean all
-\`\`\`
+> [!IMPORTANT]
+> This pre-GA release supports **fresh installation only**, not in-place package upgrades from earlier releases. Use a clean host or a new, empty PostgreSQL instance. Removing packages preserves database files; reinstalling is not a data reset.
-To remain on an older target, use its GitHub release assets or build from the matching source tag. Neither path is part of the current hosted support matrix.
+> [!NOTE]
+> Need another distribution or PostgreSQL major? We welcome community builds. Check out the matching release tag and use the version-parameterized [packaging scripts](https://github.com/documentdb/documentdb/blob/v0.117-0/packaging/README.md). \`build_packages.sh\` builds the extension, \`gateway/build_gateway_packages.sh\` builds the gateway, and \`build_extra_packages.sh\` builds the common, tools, stand-alone, and meta packages. PostgreSQL 15 is extension-only because the setup tools require PostgreSQL 16 or newer. These builds are on demand and are not official release assets hosted by documentdb.io.
You do not need PostgreSQL already installed — the setup wizard creates and manages its own instance. The install does add the PGDG repository and pull PostgreSQL, PostGIS and around 160 packages (about 140 MB), so pick a host you are willing to have PGDG on.
@@ -218,7 +215,7 @@ This command requires an active Red Hat subscription. RHEL exposes CodeReady Bui
${buildRpmInstallCommand('rhel9', 'auto', '18')}
\`\`\`
-For PostgreSQL 17, install \`documentdb-17\`; there is no \`documentdb-16\`. Both EL9 flows enable CodeReady Builder, which supplies \`libqhull_r.so.7\` for PostGIS dependencies.
+For PostgreSQL 17, select it in [Linux packages installation](/packages?method=packages) to generate matching install and setup commands for \`documentdb-17\`; there is no \`documentdb-16\`. Both EL9 flows enable CodeReady Builder, which supplies \`libqhull_r.so.7\` for PostGIS dependencies.
Then install \`mongosh\`, which you need to talk to the endpoint:
@@ -248,18 +245,19 @@ It creates a new private PostgreSQL 18 instance, installs the extensions, starts
Sample data is opt-in. Add \`--load-sample-data\` to the setup command to seed the \`StoreData\` database with 41,505 documents in \`stores\` and 2 documents in \`ratings\`. This requires \`mongosh\`; the command above leaves the new instance empty.
-For automation, use the complete [unattended setup](/docs/linux-packages#unattended-setup) command. To adopt an existing PostgreSQL instance instead, follow [Adopt an existing PostgreSQL instance](/docs/linux-packages#adopt-an-existing-postgre-sql-instance); brownfield setup intentionally has different lifecycle and restart requirements.
+For automation, use the complete [unattended setup](/docs/linux-packages#unattended-setup) command. To use PostgreSQL you already manage on this host, follow [Adopt an existing PostgreSQL instance](/docs/linux-packages#adopt-an-existing-postgre-sql-instance); it changes configuration and may require an administrator-controlled restart. For SQL-only use without a gateway, see [Install the PostgreSQL extension only](/docs/linux-packages#install-the-postgre-sql-extension-only).
-Now open a shell against the endpoint:
+Now open a shell against the endpoint. The password prompt uses the admin password you chose during setup. The self-signed certificate bypass is for **local development only**; use a trusted certificate for network access.
\`\`\`bash
-mongosh localhost:10260 -u admin -p '' --authenticationMechanism SCRAM-SHA-256 \\
+mongosh localhost:10260 -u admin -p --authenticationMechanism SCRAM-SHA-256 \\
--tls --tlsAllowInvalidCertificates
\`\`\`
A database and collection are created on first write:
\`\`\`javascript
+> use quickstart
> db.orders.insertOne({ item: "widget", qty: 5 })
{ acknowledged: true, insertedId: ObjectId('...') }
@@ -274,17 +272,35 @@ A database and collection are created on first write:
- Build an application: [Node.js Quick Start](/docs/getting-started/nodejs-setup) or [Python Quick Start](/docs/getting-started/python-setup)
- Secure it, manage services, run SQL, upgrade, uninstall, and hosts without systemd: [Operating a package install](/docs/linux-packages)
- Install without internet access: [Offline / air-gapped install](/docs/linux-packages/offline)
-- Choose between the published distributions, architectures and PostgreSQL majors: [Package Finder](/packages)
+- Choose between the published distributions, architectures and PostgreSQL majors: [Linux packages installation](/packages?method=packages)
## Troubleshooting
-- \`Unable to locate package documentdb-18\` (apt) / \`No match for argument: documentdb-18\` (dnf) — the DocumentDB repository was not added, or the host is not in the current release matrix. Check the [Package Finder](/packages)
+- \`Unable to locate package documentdb-18\` (apt) / \`No match for argument: documentdb-18\` (dnf) — the DocumentDB repository was not added, or the host is not in the current release matrix. Check [Linux packages installation](/packages?method=packages)
- \`documentdb-18 : Depends: postgresql-18 but it is not installable\` — PGDG was not added first
- \`nothing provides libqhull_r.so.7\` — CRB or CodeReady Builder was not enabled for the selected EL9 family
- \`MongoServerError: Invalid key\` — empty or wrong password; a bare \`-p\` prompts, so a non-interactive shell sends nothing
- Anything else — \`sudo documentdb-setup --status\` reports the listener, service states and resolved paths
More failure modes, including hosts without systemd: [Operating a package install](/docs/linux-packages#troubleshooting).
+
+## If you used an earlier repository target
+
+documentdb.io no longer publishes packages for Ubuntu 22.04, Debian 11/12/13, RHEL-compatible 8, or PostgreSQL 16. Existing installations keep running, but receive no package updates and cannot reinstall those packages from documentdb.io.
+
+Empty signed metadata remains at the retired repository URLs so \`apt update\` and \`dnf makecache\` continue to work. Remove the source on a host that will not move to the current matrix:
+
+\`\`\`bash
+# Debian / Ubuntu
+sudo rm -f /etc/apt/sources.list.d/documentdb.list
+sudo apt update
+
+# RHEL-compatible
+sudo rm -f /etc/yum.repos.d/documentdb.repo
+sudo dnf clean all
+\`\`\`
+
+To remain on an older target, use its GitHub release assets or build from the matching source tag. Neither path is part of the current hosted support matrix.
`;
export const linuxPackagesOperationsContent = `# Operating a package install
@@ -345,8 +361,8 @@ sudo systemctl stop documentdb-local@18.target
## Adopt an existing PostgreSQL instance
-Use brownfield mode only when PostgreSQL already exists and its service and data remain
-operator-owned. Back up the instance first. The wizard does not create, delete, start, or stop
+Use this mode only when PostgreSQL already exists **locally on the gateway host** and its service and data remain
+operator-owned; remote PostgreSQL adoption is not supported. You need administrator access to change PostgreSQL configuration and restart its service. Back up the instance first. The wizard does not create, delete, start, or stop
that PostgreSQL instance, but it does add managed configuration blocks, create the gateway role,
install the DocumentDB extensions, and register the gateway.
@@ -368,6 +384,18 @@ The wizard's default \`default_toast_compression\` setting applies to newly writ
every database on an adopted instance. If other workloads must retain PostgreSQL's own default,
prefix both setup runs with \`sudo DOCUMENTDB_TOAST_COMPRESSION=default\`.
+## Install the PostgreSQL extension only
+
+Choose this advanced path for SQL-facing DocumentDB capabilities in PostgreSQL you manage.
+It does **not** create a MongoDB-compatible network endpoint, install the gateway, or run
+\`documentdb-setup\`. Shell, driver, and VS Code quick starts require the complete stack instead.
+
+Use the extension package for your PostgreSQL major: \`postgresql-N-documentdb\` on Ubuntu
+or \`postgresqlN-documentdb\` on EL9. You own PostgreSQL configuration, extension activation,
+and service restarts. Follow the matching release's [manual package instructions](https://github.com/documentdb/documentdb/blob/v0.117-0/packaging/README.md),
+or the [extension-only offline instructions](/docs/linux-packages/offline#smaller-offline-cases)
+when PostgreSQL and all extension dependencies are already installed.
+
## Running SQL against a package-managed private instance
A greenfield PostgreSQL instance runs as the \`documentdb-local\` user on a socket, so a bare
@@ -618,6 +646,32 @@ If the target already has PostgreSQL, the PGDG extension dependencies (\`postgre
- **Full stack from the release assets** — pass the five packages for the selected PostgreSQL major to a *single* \`apt install\` / \`dnf install\`: \`documentdb-N\`, the matching \`postgresql-N-documentdb\` / \`postgresqlN-documentdb\` extension, \`documentdb-common\`, \`documentdb-gateway\`, and \`documentdb-postgresql-tools\`. For PostgreSQL 18 only, the optional \`documentdb\` meta package may be included; it selects \`documentdb-18\`. Local files resolve dependencies only against enabled repositories, so a package whose dependencies are not included still fails.
`;
+const clientInstancePrerequisiteContent = `## Have a running DocumentDB instance?
+
+If yes, keep it and continue with the client prerequisites below. Otherwise, choose one server installation:
+
+- [Docker](/packages?method=docker): run a local container on Linux, macOS, or Windows. Recommended for evaluation and development.
+- [Linux packages](/packages?method=packages): install the complete stack, then create a private PostgreSQL instance with the setup wizard.
+
+The [Docker Quick Start](/docs/getting-started/docker) and [Linux Packages Quick Start](/docs/getting-started/packages) include the full server instructions. Do not start a second instance if one is already running.
+
+These examples connect to \`localhost:10260\`, so run the client on the same host as DocumentDB. Use the credentials chosen for Docker, or username \`admin\` and the password chosen during Linux package setup. If you changed the endpoint, use its configured host and port.
+
+Self-signed certificate bypasses below are for **local development only**. For network access, use a trusted certificate. Linux package setup binds the gateway on **all interfaces** by default: firewall port \`10260\` before setup and follow [network and certificate guidance](/docs/linux-packages#before-exposing-it-to-a-network). Docker examples publish only on loopback.
+`;
+
+const driverCredentialsContent = `## Set your client credentials
+
+Set these in the terminal that will run your application. Replace the placeholders with your existing instance's credentials (for Linux packages, \`admin\` and your setup password). The driver passes them as raw values, not embedded in a connection URI.
+
+\`\`\`bash
+export DOCUMENTDB_USERNAME=''
+export DOCUMENTDB_PASSWORD=''
+\`\`\`
+`;
+
+const optionalSampleDataContent = `Sample data is **opt-in**, not required for your first insert and read. Linux package installations can add \`--load-sample-data\` during setup, which separately requires [mongosh](https://www.mongodb.com/docs/mongodb-shell/install/). Docker installations can start with \`--init-data true\`. Without these options, \`StoreData\` does not exist. Existing Docker volumes are not migrated automatically; do not delete data you need just to load a sample.`;
+
const vscodeQuickStartGuideContent = `# Visual Studio Code Quick Start
Use DocumentDB for VS Code to set up a local DocumentDB instance, browse sample data, and create your first database without leaving the editor.
@@ -686,7 +740,7 @@ Use this for a DocumentDB instance that is already running. You only add a conne
2. In the local connection area, select **DocumentDB Local** and start the **New Local Connection** flow.
3. Enter your instance's port (\`10260\` for the command above), username, and password.
4. At the TLS/SSL prompt:
- - Choose **Disable TLS/SSL (Not recommended)** if you are using the default self-signed local setup and have not configured trust for the certificate yet.
+ - For **local development only**, choose **Disable TLS/SSL (Not recommended)** if you are using the default self-signed local setup and have not configured trust for the certificate yet.
- Keep **Enable TLS/SSL (Default)** if you already configured a trusted local certificate.
5. Finish the wizard and confirm the new connection appears in the connections tree.
@@ -729,7 +783,7 @@ If setup or the connection does not work on the first try:
- Verify the extension is installed and reload VS Code if the DocumentDB view does not appear
- Confirm your local DocumentDB instance is actually running before you connect
- If you used Docker, check \`docker ps\` and \`docker logs documentdb\`
-- If you used a host-built gateway, confirm the gateway process is running and listening on the port you entered
+- If you used Linux packages, check \`sudo documentdb-setup --status\`; for a manually built gateway, confirm its process is listening on the port you entered
- If the local connection wizard fails on security, retry and choose the TLS/SSL option that matches your certificate setup
- Use \`mongosh\` to confirm the endpoint works independently of VS Code
@@ -756,14 +810,19 @@ const nodejsGuideContent = `# Node.js Quick Start
Connect to DocumentDB from Node.js using the official MongoDB driver.
+${clientInstancePrerequisiteContent}
+
## Prerequisites
- Node.js 20.19 or later (required by the current \`mongodb\` driver)
- npm
-- [Docker](https://www.docker.com/)
- Basic familiarity with JavaScript
-## Start DocumentDB Local
+${driverCredentialsContent}
+
+## Optional: start a Docker instance
+
+Skip this if you installed Linux packages or already have a running instance. If you chose Docker and have [Docker](https://www.docker.com/) installed, replace the placeholders below with your chosen credentials. This self-contained command also sets the environment variables read by your application:
\`\`\`bash
export DOCUMENTDB_USERNAME=''
@@ -776,12 +835,7 @@ docker run -dt --name documentdb \\
--password "\${DOCUMENTDB_PASSWORD:?Set DOCUMENTDB_PASSWORD}"
\`\`\`
-> Replace the placeholder values before running the command. The Node.js process below
-> reads the same two environment variables, so the credentials are passed as raw values
-> rather than embedded in a URI.
->
-> DocumentDB Local uses a self-signed certificate by default, so the quickest local
-> Node.js connection uses \`tlsAllowInvalidCertificates=true\`.
+Wait for the readiness banner in \`docker logs documentdb\` before connecting; see [Docker Quick Start](/docs/getting-started/docker#verify-the-container).
## Create a project
@@ -794,7 +848,7 @@ npm install mongodb
## Connect and run your first queries
-Create an \`index.js\` file:
+Create an \`index.js\` file. The certificate bypass is for **local development only**, with the default self-signed certificate from Linux package setup or Docker.
\`\`\`javascript
const { MongoClient } = require("mongodb");
@@ -862,9 +916,7 @@ node index.js
## Connect with a trusted local certificate instead
-If you want certificate validation instead of \`tlsAllowInvalidCertificates=true\`,
-copy the generated certificate from the container, then replace the \`options\` object
-above with the trusted-certificate version below.
+If you want certificate validation instead of \`tlsAllowInvalidCertificates=true\`, obtain the trusted certificate or CA file for your endpoint and replace the original \`options\` object with the version below. For Linux packages, follow [certificate configuration](/docs/linux-packages#before-exposing-it-to-a-network). For Docker, copy the local certificate with:
\`\`\`bash
docker cp documentdb:/home/documentdb/.local/state/documentdb-gateway/tls/cert.pem ~/documentdb-cert.pem
@@ -892,16 +944,19 @@ const pythonQuickStartContent = `# Python Quick Start
Use PyMongo to connect to DocumentDB, verify authentication and TLS, and run your first document queries from Python.
+${clientInstancePrerequisiteContent}
+
## Prerequisites
- Python 3.9 or later
- pip
-- A local DocumentDB instance from [Docker Quick Start](/docs/getting-started/docker) or [Linux Packages Quick Start](/docs/getting-started/packages)
- Optional: [mongosh](https://www.mongodb.com/docs/mongodb-shell/install/) for independent connection checks
-## Start DocumentDB first
+${driverCredentialsContent}
+
+## Optional: start a Docker instance
-For the fastest local setup, start DocumentDB Local with Docker:
+Skip this if you installed Linux packages or already have a running instance. If you chose Docker and have [Docker](https://www.docker.com/) installed, replace the placeholders below with your chosen credentials. This self-contained command also sets the environment variables read by your application:
\`\`\`bash
export DOCUMENTDB_USERNAME=''
@@ -914,14 +969,7 @@ docker run -dt --name documentdb \\
--password "\${DOCUMENTDB_PASSWORD:?Set DOCUMENTDB_PASSWORD}"
\`\`\`
-If you prefer a host installation instead of Docker, use the [Linux Packages Quick Start](/docs/getting-started/packages) on a distribution in the current release matrix.
-
-> Replace the placeholder values before running the command. The Python process below
-> reads the same two environment variables, so the credentials are passed as raw values
-> rather than embedded in a URI.
->
-> DocumentDB Local uses a self-signed certificate by default, so the quickest local
-> PyMongo connection uses \`tlsAllowInvalidCertificates=true\`.
+Wait for the readiness banner in \`docker logs documentdb\` before connecting; see [Docker Quick Start](/docs/getting-started/docker#verify-the-container).
## Create a virtual environment (optional)
@@ -942,7 +990,7 @@ python -m pip install pymongo
## Connect and run your first queries
-Create a \`quickstart.py\` file:
+Create a \`quickstart.py\` file. The certificate bypass is for **local development only**, with the default self-signed certificate from Linux package setup or Docker.
\`\`\`python
import os
@@ -1002,7 +1050,9 @@ You should see the recent movie documents printed after a successful \`ping\`.
## Explore the built-in sample data
-Sample data is **opt-in** — this needs a container started with \`--init-data true\`. Without it \`StoreData\` does not exist and the query returns nothing. Add this snippet after \`client.admin.command("ping")\`:
+${optionalSampleDataContent}
+
+If you loaded the sample, add this snippet after \`client.admin.command("ping")\`:
\`\`\`python
for store in client["StoreData"]["stores"].find(
@@ -1014,7 +1064,7 @@ for store in client["StoreData"]["stores"].find(
## Use a trusted local certificate instead
-If you want certificate validation instead of \`tlsAllowInvalidCertificates=true\`, copy the generated certificate from the container, then replace the \`MongoClient\` call above with the trusted-certificate version below.
+If you want certificate validation instead of \`tlsAllowInvalidCertificates=true\`, obtain the trusted certificate or CA file for your endpoint and replace the original \`MongoClient\` call with the version below. For Linux packages, follow [certificate configuration](/docs/linux-packages#before-exposing-it-to-a-network). For Docker, copy the local certificate with:
\`\`\`bash
docker cp documentdb:/home/documentdb/.local/state/documentdb-gateway/tls/cert.pem ~/documentdb-cert.pem
@@ -1037,7 +1087,7 @@ If the Python quick start does not work on the first try:
- Verify your local DocumentDB instance is running before you start Python
- If you used Docker, check \`docker ps --filter "name=documentdb"\` and \`docker logs documentdb\`
-- If you used a host-built gateway, confirm the gateway process is running and listening on port \`10260\`
+- If you used Linux packages, check \`sudo documentdb-setup --status\`; for a manually built gateway, confirm its process is listening on port \`10260\`
- If Python cannot import \`pymongo\`, verify the active interpreter with \`python -c "import sys; print(sys.executable)"\` and reinstall with \`python -m pip install pymongo\`
- If you see TLS or certificate errors, either use the default local self-signed flow with \`tlsAllowInvalidCertificates=true\` or switch to a trusted local certificate with \`tlsCAFile\`
- Use [Mongo Shell Quick Start](/docs/getting-started/mongo-shell-quickstart) to validate the endpoint independently of your application code
@@ -1056,15 +1106,16 @@ const mongoShellQuickStartContent = `# Mongo Shell Quick Start
Use \`mongosh\` to verify a local DocumentDB instance, inspect sample data, and run your first document commands.
+${clientInstancePrerequisiteContent}
+
## Prerequisites
- [mongosh](https://www.mongodb.com/docs/mongodb-shell/install/)
-- A local DocumentDB instance from [Docker Quick Start](/docs/getting-started/docker) or [Linux Packages Quick Start](/docs/getting-started/packages)
-- A local port available for DocumentDB (the examples use \`10260\`)
+- Your instance's endpoint and credentials (the examples use \`localhost:10260\`)
-## Start DocumentDB first
+## Optional: start a Docker instance
-For the fastest local setup, start DocumentDB Local with Docker:
+Skip this if you installed Linux packages or already have a running instance. If you chose Docker and have [Docker](https://www.docker.com/) installed:
\`\`\`bash
docker run -dt --name documentdb \\
@@ -1074,14 +1125,12 @@ docker run -dt --name documentdb \\
--password ''
\`\`\`
-If you prefer a host installation instead of Docker, use the [Linux Packages Quick Start](/docs/getting-started/packages) on a distribution in the current release matrix.
-
-> Replace \`\` and \`\` with your own credentials.
->
-> DocumentDB Local starts **empty** — pass \`--init-data true\` on the \`docker run\` above to seed the \`StoreData\` sample data used below. It also uses a self-signed certificate by default, so the fastest local \`mongosh\` connection adds \`--tlsAllowInvalidCertificates\`.
+Replace the placeholders with your own credentials. Wait for the readiness banner in \`docker logs documentdb\` before connecting; see [Docker Quick Start](/docs/getting-started/docker#verify-the-container).
## Connect and verify the connection
+Use your existing instance's credentials. The certificate bypass is for **local development only** with a self-signed certificate, whether you used Docker or installed Linux packages.
+
\`\`\`bash
mongosh localhost:10260 \\
-u '' \\
@@ -1103,7 +1152,9 @@ Successful output confirms authentication, TLS, and the gateway endpoint are wor
## Explore the built-in sample data
-Sample data is **opt-in**: this section needs a container started with \`--init-data true\`. Without it \`StoreData\` does not exist and these queries return nothing.
+${optionalSampleDataContent}
+
+If you did not load the sample, skip directly to **Create your own collection** below.
\`\`\`javascript
use StoreData
@@ -1139,12 +1190,15 @@ db.movies.find(
## Use a trusted local certificate instead
-If you want certificate validation instead of \`--tlsAllowInvalidCertificates\`, copy
-the generated certificate from the container and pass it to \`mongosh\`.
+If you want certificate validation instead of \`--tlsAllowInvalidCertificates\`, obtain the trusted certificate or CA file for your endpoint. For Linux packages, follow [certificate configuration](/docs/linux-packages#before-exposing-it-to-a-network). For Docker, copy the local certificate with:
\`\`\`bash
docker cp documentdb:/home/documentdb/.local/state/documentdb-gateway/tls/cert.pem ~/documentdb-cert.pem
+\`\`\`
+Then pass your certificate file to \`mongosh\`:
+
+\`\`\`bash
mongosh localhost:10260 \\
-u '' \\
-p '' \\
@@ -1159,7 +1213,7 @@ If \`mongosh\` does not connect on the first try:
- Verify the local DocumentDB instance is running before you connect
- If you used Docker, check \`docker ps --filter "name=documentdb"\` and \`docker logs documentdb\`
-- If you used a host-built gateway, confirm the gateway process is running and listening on port \`10260\`
+- If you used Linux packages, check \`sudo documentdb-setup --status\`; for a manually built gateway, confirm its process is listening on port \`10260\`
- If authentication fails, confirm the username and password you used when you started DocumentDB
- If TLS validation fails, either keep \`--tlsAllowInvalidCertificates\` for the default local self-signed setup or switch to \`--tlsCAFile\` with a trusted certificate
- If \`mongosh\` is not installed, follow the [mongosh install guide](https://www.mongodb.com/docs/mongodb-shell/install/)
@@ -1249,26 +1303,29 @@ Together, these components let you use DocumentDB through MongoDB-compatible too
const gettingStartedIndexStartHereContent = `## Start here
-If you're new to DocumentDB, use this order:
+Choose your environment once, create a working instance, then connect with the client that fits your goal:
+
+1. **Choose Docker or Linux packages.** [Docker installation](/packages?method=docker) is recommended for evaluation and development on Linux, macOS, or Windows. [Linux packages installation](/packages?method=packages) is for environments without Docker, or when you need control over PostgreSQL, topology, services, and configuration.
+2. **Create a working instance.** Follow the [Docker Quick Start](/docs/getting-started/docker) or [Linux Packages Quick Start](/docs/getting-started/packages). Linux package installation has two stages: install packages, then run the setup wizard. Neither copying a command nor installing files alone proves the endpoint is ready.
+3. **Insert and read your first document.** Use the [Mongo Shell Quick Start](/docs/getting-started/mongo-shell-quickstart), [Node.js Quick Start](/docs/getting-started/nodejs-setup), [Python Quick Start](/docs/getting-started/python-setup), or [Visual Studio Code Quick Start](/docs/getting-started/vscode-quickstart). Keep the same running instance; no second server installation is needed.
-1. [Docker Quick Start](/docs/getting-started/docker) - Fastest local install for evaluation and development
-2. [Mongo Shell Quick Start](/docs/getting-started/mongo-shell-quickstart) - Verify connectivity, authentication, and your first queries
-3. [Node.js Quick Start](/docs/getting-started/nodejs-setup) or [Python Quick Start](/docs/getting-started/python-setup) - Connect from an application driver
-4. [Linux Packages Quick Start](/docs/getting-started/packages) or the [Package Finder](/packages) - Use this when you need a persistent Linux installation instead of Docker
+Linux packages are pre-GA and support **fresh installation only**, not in-place upgrades from earlier releases. Removing packages preserves database files; reinstalling does not reset data.
-If you prefer an editor-first workflow, start with the [Visual Studio Code Quick Start](/docs/getting-started/vscode-quickstart).
+For advanced control, [use an existing local PostgreSQL instance](/docs/linux-packages#adopt-an-existing-postgre-sql-instance) with administrator-managed configuration and restart, or [install the PostgreSQL extension only](/docs/linux-packages#install-the-postgre-sql-extension-only). Extension-only installation does not create a MongoDB-compatible endpoint.
`;
const gettingStartedIndexVerificationContent = `## Verify your setup
-Before moving on to application code, confirm that DocumentDB is reachable and you can run a simple query.
+Before moving on to application code, confirm that DocumentDB is reachable and can insert and read a document. For Docker, check \`docker ps --filter "name=documentdb"\` and wait for the readiness banner in \`docker logs documentdb\`; for Linux packages, inspect \`sudo documentdb-setup --status\`.
-\`\`\`bash
-docker ps --filter "name=documentdb"
+Install [mongosh](https://www.mongodb.com/docs/mongodb-shell/install/) separately for this shell example. Run it on the same host as DocumentDB. Use your Docker username, or \`admin\` for Linux packages, and enter your password at the prompt.
+
+The certificate bypass is for **local development only**. Linux package setup binds the gateway on **all interfaces** by default: firewall port \`10260\` before setup and follow [network and certificate guidance](/docs/linux-packages#before-exposing-it-to-a-network).
+\`\`\`bash
mongosh localhost:10260 \\
-u '' \\
- -p '' \\
+ -p \\
--authenticationMechanism SCRAM-SHA-256 \\
--tls \\
--tlsAllowInvalidCertificates
@@ -1278,8 +1335,13 @@ Then run:
\`\`\`javascript
db.runCommand({ ping: 1 })
+use quickstart
+db.orders.insertOne({ item: "widget", qty: 5 })
+db.orders.find({ item: "widget" })
\`\`\`
+The insert should report \`acknowledged: true\`, and the query should return your document. No sample-data loading is required.
+
For a fuller walkthrough, use the [Mongo Shell Quick Start](/docs/getting-started/mongo-shell-quickstart). Driver-based examples are available in the [Node.js Quick Start](/docs/getting-started/nodejs-setup) and [Python Quick Start](/docs/getting-started/python-setup).
`;
@@ -1287,11 +1349,11 @@ const gettingStartedIndexTroubleshootingContent = `## Troubleshooting and debugg
If setup does not work on the first try:
-- Confirm the container is running and port \`10260\` is published with \`docker ps\`.
-- Inspect startup, authentication, and TLS errors with \`docker logs documentdb\`.
-- If you want certificate validation instead of \`tlsAllowInvalidCertificates=true\`, follow the certificate steps in [DocumentDB Local](/docs/documentdb-local).
-- For more verbose local diagnostics, re-create DocumentDB Local with \`-e DOCUMENTDB_LOG_LEVEL=debug\` (the \`--log-level\` flag is currently a no-op); the available runtime options are documented in [DocumentDB Local](/docs/documentdb-local).
-- If you are installing on a host instead of Docker, use [Linux Packages Quick Start](/docs/getting-started/packages) or the [Package Finder](/packages) to get the correct apt or rpm flow.
+- For Linux packages, check \`sudo documentdb-setup --status\` and [package troubleshooting](/docs/getting-started/packages#troubleshooting). The default PostgreSQL 18 install uses \`documentdb-local@18.target\`, not the meta-package alias.
+- For Docker, confirm the container is running and port \`10260\` is published with \`docker ps\`. Inspect startup, authentication, and TLS errors with \`docker logs documentdb\`.
+- If you want certificate validation instead of \`tlsAllowInvalidCertificates=true\`, follow the Linux package [certificate steps](/docs/linux-packages#before-exposing-it-to-a-network) or [DocumentDB Local](/docs/documentdb-local) for Docker.
+- For more verbose Docker diagnostics, re-create DocumentDB Local with \`-e DOCUMENTDB_LOG_LEVEL=debug\` (the \`--log-level\` flag is currently a no-op); the available runtime options are documented in [DocumentDB Local](/docs/documentdb-local).
+- To change your installation choice, open [Docker installation](/packages?method=docker) or [Linux packages installation](/packages?method=packages).
`;
const gettingStartedIndexFeatureExplorationContent = `## Explore key features
@@ -1331,17 +1393,19 @@ const articleTitleOverrides: Record = {
const articleDescriptionOverrides: Record = {
'getting-started/index':
- 'Choose the fastest setup path for DocumentDB, verify your installation, and find troubleshooting and feature guides.',
+ 'Choose Docker or Linux packages, create a DocumentDB instance, and insert and read your first document with a shell, driver, or editor.',
+ 'getting-started/packages':
+ 'Install DocumentDB on Linux with Ubuntu APT or EL9 RPM/dnf packages, set up a private PostgreSQL instance, and run your first query.',
'getting-started/azure-setup':
'Deploy and manage DocumentDB on Microsoft Azure for a fully managed experience.',
'getting-started/vscode-quickstart':
- 'Install the VS Code extension, connect to DocumentDB Local, and verify your first editor-based workflow.',
+ 'Install the VS Code extension, connect to DocumentDB with Docker or Linux packages, and insert and read your first document.',
'getting-started/nodejs-setup':
- 'Start DocumentDB Local, connect with the MongoDB Node.js driver, and run your first queries.',
+ 'Connect to DocumentDB with Docker or Linux packages with the MongoDB Node.js driver and run your first queries.',
'getting-started/python-setup':
- 'Start DocumentDB Local, connect with PyMongo, and run your first queries from Python.',
+ 'Connect to DocumentDB with Docker or Linux packages with PyMongo and run your first queries from Python.',
'getting-started/mongo-shell-quickstart':
- 'Start DocumentDB Local, connect with mongosh, and run your first shell commands.',
+ 'Connect to DocumentDB with Docker or Linux packages with mongosh and insert and read your first document.',
};
function getArticleKey(section: string, file: string): string {
@@ -1681,7 +1745,7 @@ export function getArticleByPath(section: string, slug: string[] = []): {
content: linuxPackagesGuideContent,
frontmatter: {
title: articleTitleOverrides[getArticleKey(section, file)],
- description: 'Install the DocumentDB PostgreSQL extension with Linux packages and find package troubleshooting guidance.',
+ description: articleDescriptionOverrides[getArticleKey(section, file)],
},
navigation,
section,
diff --git a/blogs/_layouts/default.html b/blogs/_layouts/default.html
index f786f96..d95684b 100644
--- a/blogs/_layouts/default.html
+++ b/blogs/_layouts/default.html
@@ -6,6 +6,7 @@
{% if page.title %}{{ page.title }} · {% endif %}DocumentDB
+
{% assign social_title = page.title | default: site.title %}
{% assign social_description = page.description | default: site.description %}
@@ -60,7 +61,7 @@
GitHub
Discord
Docs
- Download
+ Install & Download
K8s Operator
Blogs
diff --git a/blogs/_posts/2026-09-10-linux-packages.md b/blogs/_posts/2026-09-10-linux-packages.md
new file mode 100644
index 0000000..455b19a
--- /dev/null
+++ b/blogs/_posts/2026-09-10-linux-packages.md
@@ -0,0 +1,71 @@
+---
+title: "Linux packages for DocumentDB: start simple, keep control"
+description: Install DocumentDB on Linux with apt or dnf and guided setup. Start with the complete stack, use your own local PostgreSQL, or install only the extension.
+date: 2026-09-10
+featured: true
+author: DocumentDB team
+category: documentdb-blog
+tags:
+ - DocumentDB
+ - Linux
+ - PostgreSQL
+ - APT
+ - RPM
+---
+{% assign site_root = site.baseurl | replace: '/blogs', '' %}
+
+Docker remains the fastest way to evaluate DocumentDB on Linux, macOS, or Windows. When you cannot use Docker, or need control over PostgreSQL, services, and configuration on a Linux host, Linux packages give you another option: familiar package managers, guided setup, and a choice about how much of the stack you manage.
+
+DocumentDB is an open-source, MongoDB API compatible document database built on PostgreSQL. The Linux packages bring the PostgreSQL extension, gateway, setup tools, and systemd services together, so you can start with a complete installation instead of assembling individual components.
+
+**Start simple. Keep control.** Use the complete stack for a new instance, or choose an advanced path for PostgreSQL you already manage.
+
+## Start with the complete stack
+
+The complete-stack path creates a new private PostgreSQL instance and a DocumentDB gateway on your Linux host. You do not need PostgreSQL installed beforehand. Package-managed services and persistent database storage give you a host installation you can inspect, stop, and restart with familiar Linux tools.
+
+Installation and setup are separate steps:
+
+1. **Install with apt or dnf.** Follow the [Linux installation guide]({{ site_root }}/docs/getting-started/packages/) to configure the signed DocumentDB and PostgreSQL repositories, meet the distribution prerequisites, and install the complete-stack package for your selected PostgreSQL major. This changes system-wide package sources and installs dependencies.
+2. **Run guided setup.** The guide's `documentdb-setup` command explicitly creates a new private instance, configures the database and gateway, and starts the services. Installing packages alone does not create a working endpoint. Enter the administrator password at the terminal prompt, not in a connection URI or shell history.
+3. **Connect and query.** Install `mongosh` separately if you want to use the shell examples or load the optional sample data. Follow the guide's connection instructions before running your first insert and read.
+
+This is a guided installation, not a one-command path from an unprepared machine to production.
+
+## Try a write, then keep it across a restart
+
+After setup and an authenticated connection in `mongosh`, insert a document and read it back:
+
+```javascript
+use quickstart
+db.notes.insertOne({ message: "Start simple. Keep control." })
+db.notes.findOne({ message: "Start simple. Keep control." })
+```
+
+The query should return the inserted document, including its `_id`. On a systemd host, follow [Services and paths]({{ site_root }}/docs/linux-packages/#services-and-paths) to restart the complete-stack target for your selected PostgreSQL major. Reconnect, select `quickstart`, and repeat the query to check that the same data remains. A service restart is not a data reset.
+
+The [operations guide]({{ site_root }}/docs/linux-packages/) keeps service commands, storage paths, troubleshooting, and removal guidance in one place.
+
+## Keep control of PostgreSQL
+
+The complete stack is the starting point, not the only option.
+
+**Use an existing local PostgreSQL instance.** Keep ownership of its service and data while configuring DocumentDB and the gateway alongside it. This requires explicit configuration changes and can require an operator-controlled PostgreSQL restart. Back up first and follow [the existing-instance guide]({{ site_root }}/docs/linux-packages/#adopt-an-existing-postgre-sql-instance). The gateway and PostgreSQL must be on the same host; a remote PostgreSQL backend is not supported.
+
+**Install only the PostgreSQL extension.** Choose this when you want the DocumentDB extension in PostgreSQL without the gateway or package-managed private instance. Extension-only installation does not create a MongoDB-compatible network endpoint. Review the component choices on the install page rather than treating this as a substitute for the complete-stack quickstart.
+
+## Supported platforms and release boundaries
+
+These details describe [v0.117-0](https://github.com/documentdb/documentdb/releases/tag/v0.117-0), the current release as of September 10, 2026.
+
+The shipped package matrix covers Ubuntu 24.04 with APT and RHEL/Rocky Linux 9 with RPM/dnf, on PostgreSQL 17 or 18 and amd64 or arm64. RPM names those architectures x86_64 and aarch64. RHEL requires registration and the documented repository prerequisites. PostgreSQL 18 is the default: `documentdb` selects it, while `documentdb-17` and `documentdb-18` select a specific major.
+
+**These pre-GA packages are for fresh installations. In-place upgrades from earlier releases are not supported.** Use a clean host or a new, empty PostgreSQL instance. Uninstalling packages preserves database files and in-database content; reinstalling does not make an existing database fresh.
+
+The default auto-generated self-signed TLS certificate is a development convenience only. The gateway listens on all interfaces by default, so restrict network access before setup on anything other than a private development machine. Follow [the network and TLS guidance]({{ site_root }}/docs/linux-packages/#before-exposing-it-to-a-network) before exposing the endpoint, and use a trusted certificate instead of treating a certificate-validation bypass as a production setting.
+
+## Choose your installation path
+
+**[Install DocumentDB on Linux]({{ site_root }}/packages/?method=packages)** for the complete, current prerequisites and install/setup commands.
+
+Prefer containers, or evaluating on macOS or Windows? [Use Docker]({{ site_root }}/packages/?method=docker). It remains an option on Linux, macOS, and Windows.
diff --git a/tests/fixtures/getting-started/index.md b/tests/fixtures/getting-started/index.md
new file mode 100644
index 0000000..8823aaa
--- /dev/null
+++ b/tests/fixtures/getting-started/index.md
@@ -0,0 +1,26 @@
+---
+title: Getting Started
+description: Source documentation fixture for onboarding normalization.
+---
+
+# Getting Started
+
+## Architecture Components
+
+Source architecture guidance.
+
+## Common Use Cases
+
+Source use cases remain available alongside the installation instructions.
+
+## Getting Started Options
+
+Read the [pre-built package guide](prebuilt-packages.md).
+
+## Community and Support
+
+Source community and support information remains available.
+
+## Next Steps
+
+Continue with the source documentation.
diff --git a/tests/fixtures/getting-started/navigation.yml b/tests/fixtures/getting-started/navigation.yml
new file mode 100644
index 0000000..8802dce
--- /dev/null
+++ b/tests/fixtures/getting-started/navigation.yml
@@ -0,0 +1,6 @@
+- title: Getting Started
+ link: index.md
+- title: Pre-built Packages
+ link: prebuilt-packages.md
+- title: Node.js Setup
+ link: nodejs-setup.md
diff --git a/tests/installSelection.test.ts b/tests/installSelection.test.ts
new file mode 100644
index 0000000..50326a1
--- /dev/null
+++ b/tests/installSelection.test.ts
@@ -0,0 +1,160 @@
+import { describe, expect, it } from "vitest";
+import {
+ defaultInstallSelection,
+ installSelectionQuery,
+ installSelectionUrlQuery,
+ parseInstallSelection,
+ releaseHasPackages,
+ selectInstallTarget,
+} from "../app/lib/installSelection";
+import { FALLBACK_RELEASE, parseReleaseInfo } from "../app/lib/releaseInfo";
+
+describe("install selection links", () => {
+ it("defaults to Docker, with packages preset to the PG18 stack and host-resolved architecture", () => {
+ expect(parseInstallSelection("")).toEqual({ selection: defaultInstallSelection, error: null });
+ });
+
+ it.each(["docker", "packages"])("opens the explicitly linked %s method", (method) => {
+ expect(parseInstallSelection(`?method=${method}`).selection?.method).toBe(method);
+ });
+
+ it.each([
+ "method=packages&family=apt&target=ubuntu24&pg=17&arch=arm64",
+ "method=packages&family=rpm&target=rhel9&pg=18&arch=aarch64",
+ "method=docker&family=rpm&target=rocky9&pg=17&arch=auto",
+ ])("round-trips all choices in %s", (query) => {
+ const result = parseInstallSelection(query);
+ expect(result.error).toBeNull();
+ if (!result.selection) throw new Error("Expected a valid selection");
+ expect(parseInstallSelection(installSelectionQuery(result.selection))).toEqual(result);
+ });
+
+ it.each([
+ "method=other",
+ "family=unknown",
+ "pg=15",
+ "pg=16",
+ "pg=19",
+ "arch=i386",
+ "target=ubuntu22",
+ "target=rocky9",
+ "family=rpm&arch=amd64",
+ "family=rpm&target=rhel8",
+ "method=docker&method=packages",
+ "pg=17&pg=18",
+ "target=__proto__",
+ "target=constructor",
+ "arch=%24%28touch%20anything%29",
+ ])("rejects unsupported or ambiguous choices without a usable command target: %s", (query) => {
+ expect(parseInstallSelection(query)).toEqual({
+ selection: null,
+ error: expect.any(String),
+ recovery: expect.any(Object),
+ });
+ });
+
+ it.each(["pg=16", "method=packages&pg=16", "target=ubuntu22"])(
+ "recovers a broken package link to package settings, not Docker: %s",
+ (query) => {
+ const result = parseInstallSelection(query);
+ expect(result.selection).toBeNull();
+ if (result.error === null) throw new Error("Expected an error");
+ expect(result.recovery).toEqual({ ...defaultInstallSelection, method: "packages" });
+ },
+ );
+
+ it("recovers an unknown method to the Docker default", () => {
+ const result = parseInstallSelection("method=other");
+ if (result.error === null) throw new Error("Expected an error");
+ expect(result.recovery).toEqual(defaultInstallSelection);
+ });
+
+ it("opens Docker even when a link carries stale package choices", () => {
+ expect(parseInstallSelection("method=docker&pg=16&target=ubuntu22")).toEqual({
+ selection: defaultInstallSelection,
+ error: null,
+ });
+ });
+
+ it("treats package choices without a method as a package link", () => {
+ expect(parseInstallSelection("family=rpm&target=rocky9").selection?.method).toBe("packages");
+ });
+
+ it("keeps Docker links short unless package choices were changed", () => {
+ expect(installSelectionUrlQuery(defaultInstallSelection)).toBe("method=docker");
+ const packages = { ...defaultInstallSelection, method: "packages" as const };
+ expect(installSelectionUrlQuery(packages)).toBe(installSelectionQuery(packages));
+ });
+
+ it("restores package choices after switching to Docker and back", () => {
+ const chosen = parseInstallSelection("method=packages&family=rpm&target=rhel9&pg=17&arch=aarch64").selection!;
+ const docker = parseInstallSelection(installSelectionUrlQuery({ ...chosen, method: "docker" })).selection!;
+ expect(docker.method).toBe("docker");
+ const back = parseInstallSelection(installSelectionUrlQuery({ ...docker, method: "packages" })).selection;
+ expect(back).toEqual(chosen);
+ });
+
+ it("allows campaign parameters without treating them as install choices", () => {
+ expect(parseInstallSelection("?utm_source=blog&method=docker").selection).toEqual(defaultInstallSelection);
+ });
+
+ it("preserves major and CPU family when switching distributions", () => {
+ const initial = parseInstallSelection("pg=17&arch=arm64").selection;
+ if (!initial) throw new Error("Expected a valid selection");
+ const rpm = selectInstallTarget(initial, "rhel9");
+ expect(rpm.selection?.packages).toEqual({ family: "rpm", target: "rhel9", arch: "aarch64", pg: "17" });
+ if (!rpm.selection) throw new Error("Expected an RPM selection");
+ expect(selectInstallTarget(rpm.selection, "ubuntu24").selection).toEqual(initial);
+ });
+
+ it("keeps automatic architecture and rejects unknown distributions", () => {
+ expect(selectInstallTarget(defaultInstallSelection, "rocky9").selection?.packages.arch).toBe("auto");
+ expect(selectInstallTarget(defaultInstallSelection, "other").selection).toBeNull();
+ });
+});
+
+describe("published package availability", () => {
+ const assetNames = [
+ ...["documentdb-18", "documentdb-common", "documentdb-postgresql-tools"].flatMap((name) => [
+ `ubuntu24.04-${name}_0.117.0_all.deb`,
+ `${name}-0.117.0-1.noarch.rpm`,
+ ]),
+ ...["amd64", "arm64"].flatMap((arch) => [
+ `ubuntu24.04-documentdb-gateway_0.117.0_${arch}.deb`,
+ `ubuntu24.04-postgresql-18-documentdb_0.117-0_${arch}.deb`,
+ ]),
+ ...["x86_64", "aarch64"].flatMap((arch) => [
+ `documentdb-gateway-0.117.0-1.el9.${arch}.rpm`,
+ `rhel9-postgresql18-documentdb-0.117.0-1.el9.${arch}.rpm`,
+ ]),
+ ];
+ const release = { ...FALLBACK_RELEASE, assetNames };
+
+ it("requires the full stack, including both architectures for automatic selection", () => {
+ expect(releaseHasPackages(release, defaultInstallSelection.packages)).toBe(true);
+ expect(releaseHasPackages(release, { family: "rpm", target: "rhel9", arch: "auto", pg: "18" })).toBe(true);
+ expect(releaseHasPackages(FALLBACK_RELEASE, defaultInstallSelection.packages)).toBe(false);
+ expect(releaseHasPackages(release, { family: "apt", target: "ubuntu24", arch: "amd64", pg: "17" })).toBe(false);
+ });
+
+ it.each(assetNames)("does not advertise a complete automatic install without %s", (missing) => {
+ const partial = { ...release, assetNames: assetNames.filter((name) => name !== missing) };
+ const selection = missing.endsWith(".deb")
+ ? defaultInstallSelection.packages
+ : { family: "rpm" as const, target: "rocky9" as const, arch: "auto" as const, pg: "18" as const };
+ expect(releaseHasPackages(partial, selection)).toBe(false);
+ });
+
+ it("allows a specific shipped architecture when the other one is missing", () => {
+ const partial = { ...release, assetNames: assetNames.filter((name) => !name.includes("_arm64.deb")) };
+ expect(releaseHasPackages(partial, { family: "apt", target: "ubuntu24", arch: "amd64", pg: "18" })).toBe(true);
+ expect(releaseHasPackages(partial, defaultInstallSelection.packages)).toBe(false);
+ });
+
+ it.each([null, {}, { tag_name: "v0.117-0", assets: [] }, { tag_name: "../other", assets: [] }])(
+ "surfaces malformed or incomplete metadata instead of inventing current versions",
+ (payload) => {
+ expect(() => parseReleaseInfo(payload)).toThrow();
+ },
+ );
+});
diff --git a/tests/packageArticles.test.ts b/tests/packageArticles.test.ts
index 63b5482..c19596a 100644
--- a/tests/packageArticles.test.ts
+++ b/tests/packageArticles.test.ts
@@ -1,9 +1,18 @@
-import { describe, expect, it } from 'vitest';
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
+import fs from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+import { kebabCase } from 'change-case';
import {
getArticleByPath,
linuxPackagesGuideContent,
linuxPackagesOperationsContent,
} from '../app/services/articleService';
+import {
+ buildAptInstallCommand,
+ buildRpmInstallCommand,
+ buildSetupCommand,
+} from '../app/lib/packageInstall';
function getCodeBlocks(content: string, language: string): string[] {
const pattern = new RegExp('```' + language + '\\n([\\s\\S]*?)\\n```', 'g');
@@ -11,6 +20,179 @@ function getCodeBlocks(content: string, language: string): string[] {
}
describe('Linux package articles', () => {
+ beforeEach(() => {
+ const fixturePaths = new Map(
+ ['index.md', 'navigation.yml'].map((file) => [
+ path.join(process.cwd(), 'articles', 'getting-started', file),
+ fileURLToPath(new URL(`./fixtures/getting-started/${file}`, import.meta.url)),
+ ]),
+ );
+ const existsSync = fs.existsSync;
+ const readFileSync = fs.readFileSync;
+
+ vi.spyOn(fs, 'existsSync').mockImplementation((file) =>
+ existsSync(fixturePaths.get(file.toString()) ?? file),
+ );
+ vi.spyOn(fs, 'readFileSync').mockImplementation((file, options) =>
+ readFileSync(fixturePaths.get(file.toString()) ?? file, options),
+ );
+ });
+
+ afterEach(() => {
+ vi.restoreAllMocks();
+ });
+
+ it('uses the shared Linux package install and fresh-instance setup commands', () => {
+ const blocks = getCodeBlocks(linuxPackagesGuideContent, 'bash');
+
+ expect(blocks).toContain(buildAptInstallCommand('ubuntu24', 'auto', '18'));
+ expect(blocks).toContain(buildRpmInstallCommand('rocky9', 'auto', '18'));
+ expect(blocks).toContain(buildRpmInstallCommand('rhel9', 'auto', '18'));
+ expect(blocks).toContain(buildSetupCommand('18'));
+ expect(linuxPackagesGuideContent).toContain('amd64 or arm64');
+ expect(linuxPackagesGuideContent.indexOf('fresh installation only')).toBeLessThan(
+ linuxPackagesGuideContent.indexOf('```bash'),
+ );
+ expect(linuxPackagesGuideContent).toContain('not in-place package upgrades');
+ expect(linuxPackagesGuideContent).toContain(
+ 'Removing packages preserves database files',
+ );
+ expect(linuxPackagesGuideContent).toContain('**all interfaces**');
+ expect(linuxPackagesGuideContent).toContain('Firewall port `10260`');
+ expect(linuxPackagesGuideContent).toContain('**local development only**');
+ expect(linuxPackagesGuideContent).toContain('> use quickstart');
+ expect(linuxPackagesGuideContent).toContain('db.orders.insertOne(');
+ expect(linuxPackagesGuideContent).toContain('db.orders.find(');
+ expect(linuxPackagesGuideContent).toContain(
+ 'mongosh localhost:10260 -u admin -p --authenticationMechanism',
+ );
+ expect(getArticleByPath('getting-started', ['packages'])?.frontmatter.description)
+ .toContain('Ubuntu APT or EL9 RPM/dnf packages');
+ });
+
+ it('aligns the Getting Started article and renderer with goal-based installation choices', async () => {
+ const article = getArticleByPath('getting-started', []);
+ if (!article) {
+ throw new Error('Missing Getting Started landing article');
+ }
+
+ const startHere = article.content.split('## Start here')[1]?.split('## Verify your setup')[0];
+ expect(startHere).toContain('/packages?method=packages');
+ expect(startHere).toContain('/packages?method=docker');
+ expect(startHere?.indexOf('/packages?method=docker')).toBeLessThan(
+ startHere?.indexOf('/packages?method=packages') ?? -1,
+ );
+ expect(startHere).toContain('recommended for evaluation and development');
+ expect(startHere).toContain('install packages, then run the setup wizard');
+ expect(startHere).toContain('no second server installation is needed');
+ expect(article.content).toContain('db.orders.insertOne(');
+ expect(article.content).toContain('db.orders.find(');
+ expect(article.content).toContain('acknowledged: true');
+ expect(article.content).toContain('Install [mongosh]');
+ expect(article.content).toContain('## Architecture Components');
+ expect(article.content).toContain('## Common Use Cases');
+ expect(article.content).toContain('## Community and Support');
+ const packageIndex = article.navigation.findIndex((item) =>
+ item.link === '/docs/getting-started/packages',
+ );
+ const dockerIndex = article.navigation.findIndex((item) =>
+ item.link === '/docs/getting-started/docker',
+ );
+ expect(dockerIndex).toBeGreaterThanOrEqual(0);
+ expect(packageIndex).toBeGreaterThan(dockerIndex);
+
+ const { readFile } = await import('node:fs/promises');
+ const { fileURLToPath } = await import('node:url');
+ const source = await readFile(
+ fileURLToPath(new URL('../app/docs/[section]/[[...slug]]/page.tsx', import.meta.url)),
+ 'utf8',
+ );
+
+ expect(source).toContain('href="/packages?method=packages"');
+ // The Docker card has one destination; the install page would only repeat its command.
+ expect(source).not.toContain('href="/packages?method=docker"');
+ expect(source.indexOf('href="/docs/getting-started/docker"')).toBeLessThan(
+ source.indexOf('href="/packages?method=packages"'),
+ );
+ expect(source).toContain('-p 127.0.0.1:10260:10260');
+ expect(source).not.toContain('-p 10260:10260');
+ expect(source).toContain("--username ''");
+ expect(source).toContain("--password ''");
+ expect(source).toContain('Pre-GA, fresh installation only');
+ });
+
+ it('offers both server methods before client-specific setup or optional Docker commands', () => {
+ for (const slug of ['nodejs-setup', 'python-setup', 'mongo-shell-quickstart']) {
+ const article = getArticleByPath('getting-started', [slug]);
+ if (!article) {
+ throw new Error(`Missing client quick start ${slug}`);
+ }
+ const content = article.content;
+ const prerequisite = content.split('## Have a running DocumentDB instance?')[1]
+ ?.split('## Prerequisites')[0];
+
+ expect(prerequisite, slug).toContain('/packages?method=packages');
+ expect(prerequisite, slug).toContain('/packages?method=docker');
+ expect(prerequisite, slug).toContain('localhost:10260');
+ expect(prerequisite, slug).toContain('username `admin`');
+ expect(prerequisite, slug).toContain('**local development only**');
+ expect(prerequisite, slug).toContain('firewall port `10260`');
+ expect(content, slug).toContain('## Optional: start a Docker instance');
+ expect(content, slug).toContain('Skip this if you installed Linux packages');
+ expect(content, slug).toContain('Wait for the readiness banner');
+ expect(content, slug).not.toContain('For the fastest local setup');
+ expect(content.indexOf('/packages?method=packages'), slug).toBeLessThan(
+ content.indexOf('docker run'),
+ );
+ }
+ });
+
+ it('keeps first writes independent of optional sample data for both installation methods', () => {
+ for (const slug of ['python-setup', 'mongo-shell-quickstart']) {
+ const content = getArticleByPath('getting-started', [slug])?.content;
+ expect(content, slug).toContain('not required for your first insert and read');
+ expect(content, slug).toContain('`--load-sample-data` during setup');
+ expect(content, slug).toContain('separately requires [mongosh]');
+ expect(content, slug).toContain('`--init-data true`');
+ }
+ const docker = getArticleByPath('getting-started', ['docker'])?.content;
+ expect(docker).toContain('db.orders.insertOne(');
+ expect(docker).toContain('db.orders.find(');
+ });
+
+ it('documents trusted certificates without requiring Docker for Linux package clients', () => {
+ for (const slug of ['nodejs-setup', 'python-setup', 'mongo-shell-quickstart']) {
+ const content = getArticleByPath('getting-started', [slug])?.content;
+ expect(content, slug).toContain('For Linux packages, follow [certificate configuration]');
+ expect(content, slug).toContain('/docs/linux-packages#before-exposing-it-to-a-network');
+ expect(content, slug).toContain('For Docker, copy the local certificate with:');
+ expect(content, slug).toContain('tlsCAFile');
+ }
+ });
+
+ it('links to rendered section anchors in the advanced Linux packages guide', () => {
+ const anchors = Array.from(
+ linuxPackagesOperationsContent.matchAll(/^## (.+)$/gm),
+ (match) => kebabCase(match[1]),
+ );
+ for (const slug of [
+ [], ['packages'], ['nodejs-setup'], ['python-setup'], ['mongo-shell-quickstart'],
+ ]) {
+ const article = getArticleByPath('getting-started', slug);
+ if (!article) {
+ throw new Error(`Missing Getting Started article ${slug.join('/')}`);
+ }
+ const links = Array.from(
+ article.content.matchAll(/\]\(\/docs\/linux-packages#([^)]+)\)/g),
+ (match) => match[1],
+ );
+ expect(links.length).toBeGreaterThan(0);
+ for (const anchor of links) {
+ expect(anchors).toContain(anchor);
+ }
+ }
+ });
+
it('keeps advanced setup details out of the quick start', () => {
expect(linuxPackagesGuideContent).toContain(
'/docs/linux-packages#unattended-setup',
@@ -35,6 +217,33 @@ describe('Linux package articles', () => {
expect(linuxPackagesOperationsContent).toContain(
'DOCUMENTDB_TOAST_COMPRESSION=default',
);
+ expect(linuxPackagesOperationsContent).toContain(
+ '**locally on the gateway host**',
+ );
+ expect(linuxPackagesOperationsContent).toContain(
+ 'remote PostgreSQL adoption is not supported',
+ );
+ expect(linuxPackagesOperationsContent).toContain(
+ 'administrator access to change PostgreSQL configuration and restart its service',
+ );
+ });
+
+ it('keeps extension-only guidance advanced and systemd names per major', () => {
+ expect(linuxPackagesGuideContent).toContain(
+ '/docs/linux-packages#install-the-postgre-sql-extension-only',
+ );
+ expect(linuxPackagesOperationsContent).toContain(
+ '## Install the PostgreSQL extension only',
+ );
+ expect(linuxPackagesOperationsContent).toContain(
+ 'does **not** create a MongoDB-compatible network endpoint',
+ );
+ expect(linuxPackagesOperationsContent).toContain(
+ 'sudo systemctl restart documentdb-local@18.target',
+ );
+ expect(linuxPackagesOperationsContent).not.toContain(
+ 'sudo systemctl restart documentdb-local.target',
+ );
});
it('distinguishes scoped systemd restore from no-systemd cleanup', () => {
@@ -291,6 +500,17 @@ describe('Linux package articles', () => {
(block) => block.includes('docker run'),
);
+ for (const content of [nodeGuide.content, pythonGuide.content]) {
+ const block = getCodeBlocks(content, 'bash').find(
+ (value) => value.includes('export DOCUMENTDB_USERNAME='),
+ );
+ expect(block).toContain("export DOCUMENTDB_USERNAME=''");
+ expect(block).toContain("export DOCUMENTDB_PASSWORD=''");
+ expect(content.indexOf('## Set your client credentials')).toBeLessThan(
+ content.indexOf('## Optional: start a Docker instance'),
+ );
+ }
+
for (const block of [nodeDockerBlock, pythonDockerBlock]) {
expect(block).toContain("export DOCUMENTDB_USERNAME=''");
expect(block).toContain("export DOCUMENTDB_PASSWORD=''");