diff --git a/app/components/CommandSnippet.tsx b/app/components/CommandSnippet.tsx index 6d2633f..5e836e4 100644 --- a/app/components/CommandSnippet.tsx +++ b/app/components/CommandSnippet.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useEffect, useRef, useState } from "react"; type CommandSnippetProps = { command: string; @@ -8,13 +8,24 @@ type CommandSnippetProps = { }; export default function CommandSnippet({ command, label = "Command" }: CommandSnippetProps) { - const [copied, setCopied] = useState(false); + const [feedback, setFeedback] = useState<{ command: string; error: boolean } | null>(null); + const timeout = useRef | null>(null); + + useEffect(() => () => { + if (timeout.current !== null) clearTimeout(timeout.current); + }, []); const copyCommand = async () => { - await navigator.clipboard.writeText(command); - setCopied(true); - window.setTimeout(() => setCopied(false), 1500); + if (timeout.current !== null) clearTimeout(timeout.current); + try { + await navigator.clipboard.writeText(command); + setFeedback({ command, error: false }); + timeout.current = setTimeout(() => setFeedback(null), 2000); + } catch { + setFeedback({ command, error: true }); + } }; + const currentFeedback = feedback?.command === command ? feedback : null; return (
@@ -25,11 +36,17 @@ export default function CommandSnippet({ command, label = "Command" }: CommandSn
+

+ {currentFeedback?.error + ? "Could not copy. Select the command text and copy it manually." + : currentFeedback ? `${label} copied. Run it in your terminal.` : ""} +

           {command}
diff --git a/app/components/HomeQuickstart.tsx b/app/components/HomeQuickstart.tsx
new file mode 100644
index 0000000..028d5ac
--- /dev/null
+++ b/app/components/HomeQuickstart.tsx
@@ -0,0 +1,126 @@
+"use client";
+
+import { useState } from "react";
+import Link from "next/link";
+import CommandSnippet from "./CommandSnippet";
+import {
+  aptTargetLabels,
+  buildSetupCommand,
+  rpmFullStackDistros,
+  rpmTargetLabels,
+} from "../lib/packageInstall";
+
+const nativeInstallHref = "/packages?method=packages&family=apt&target=ubuntu24&pg=18&arch=auto";
+const setupCommand = buildSetupCommand("18");
+const dockerCommand = `docker run -dt --name documentdb \\
+  -p 127.0.0.1:10260:10260 \\
+  ghcr.io/documentdb/documentdb/documentdb-local:latest \\
+  --username '' \\
+  --password ''`;
+
+const linkClass = "font-semibold text-blue-300 underline underline-offset-4 hover:text-blue-200 focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-blue-400";
+
+export default function HomeQuickstart() {
+  const [method, setMethod] = useState<"packages" | "docker">("packages");
+
+  return (
+    
+ + Quick start + +
+ {([ + { value: "packages", label: "Native Linux", id: "native-linux-quickstart" }, + { value: "docker", label: "Docker", id: "run-with-docker" }, + ] as const).map((item) => ( + + ))} +
+

+ For macOS and Windows, choose Docker. +

+ +
+ {method === "packages" ? ( + <> +

+ Run directly on Linux +

+

+ Recommended: {aptTargetLabels.ubuntu24} with PostgreSQL 18. +

+

+ Also available for {rpmFullStackDistros.map((target) => rpmTargetLabels[target]).join("; ")}. +

+

+ Pre-GA: fresh installs only. In-place upgrades from earlier releases are not supported. +

+
    +
  1. +

    1. Install the complete stack

    +

    + First configure the PostgreSQL (PGDG) and DocumentDB repositories + and signing keys, then install the packages. +

    + + Open complete installation instructions + +
  2. +
  3. +

    2. Set up after installation

    +

    + Create a private PostgreSQL instance and start the gateway. + The wizard prompts for your admin password in the terminal. +

    + +
  4. +
+

+ The complete instructions continue through connecting and your first query. +

+ + ) : ( + <> +

+ Run locally with Docker +

+

+ Install and start Docker, then run DocumentDB Local in a container. +

+

+ Replace the placeholders with your own local-development credentials. + Command-line passwords can remain in shell history; do not reuse production credentials. + Port 10260 is exposed only on loopback. +

+ +

+ Wait for DocumentDB to be ready, then connect with your app or shell. + Follow the full instructions for TLS, connection examples, and data persistence. +

+ + Open Docker installation instructions + + + )} +
+
+ ); +} diff --git a/app/components/Navbar.tsx b/app/components/Navbar.tsx index 9a8087a..05e7281 100644 --- a/app/components/Navbar.tsx +++ b/app/components/Navbar.tsx @@ -32,7 +32,7 @@ const navItems: NavItem[] = [ }, { label: "Docs", href: "/docs", kind: "link" }, { label: "AI", href: "/ai", kind: "link" }, - { label: "Download", href: "/packages", kind: "link" }, + { label: "Install", href: "/packages?method=packages", kind: "link" }, { label: "K8s Operator", href: "/kubernetes-operator", kind: "link" }, { label: "Blogs", href: withBasePath("/blogs/"), kind: "anchor" }, { label: "Samples", href: "/samples", kind: "link" }, @@ -117,7 +117,7 @@ export default function Navbar() { {navItems.map((item) => renderNavItem( item, - "flex items-center gap-2 text-gray-300 transition-colors duration-200 font-medium hover:text-blue-400", + "flex items-center gap-2 text-gray-300 transition-colors duration-200 font-medium hover:text-blue-400 focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-blue-400", ), )}
@@ -148,7 +148,7 @@ export default function Navbar() { {navItems.map((item) => renderNavItem( item, - "flex items-center gap-3 rounded-md px-3 py-2.5 text-sm font-medium text-gray-300 transition-colors duration-200 hover:bg-neutral-800 hover:text-white", + "flex items-center gap-3 rounded-md px-3 py-2.5 text-sm font-medium text-gray-300 transition-colors duration-200 hover:bg-neutral-800 hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-400", closeMenu, ), )} diff --git a/app/docs/[section]/[[...slug]]/page.tsx b/app/docs/[section]/[[...slug]]/page.tsx index 1e91f6d..fa1964a 100644 --- a/app/docs/[section]/[[...slug]]/page.tsx +++ b/app/docs/[section]/[[...slug]]/page.tsx @@ -7,12 +7,13 @@ import ComingSoon from "../../../components/ComingSoon"; import CommandSnippet from "../../../components/CommandSnippet"; import Markdown from "../../../components/Markdown"; import MovedNotice from "../../../components/MovedNotice"; +import { aptTargetLabels, buildAptInstallCommand, buildSetupCommand } from "../../../lib/packageInstall"; const dockerQuickRunCommand = `docker run -dt --name documentdb \\ - -p 10260:10260 \\ + -p 127.0.0.1:10260:10260 \\ ghcr.io/documentdb/documentdb/documentdb-local:latest \\ - --username \\ - --password `; + --username '' \\ + --password ''`; const primerPrimaryLinkClass = "inline-flex w-full items-center justify-center rounded-md bg-blue-500 px-4 py-2 text-sm font-semibold text-white transition-colors hover:bg-blue-400 sm:w-auto"; @@ -241,11 +242,11 @@ export default async function ArticlePage({ params }: PageProps) { Recommended flow

- Install and verify DocumentDB + Choose an environment, then run your first query

- Choose one install path first. After DocumentDB is running, verify the - connection with mongosh before moving to a driver quick start. + Install with Native Linux packages or Docker once. Create a working + instance, then insert and read a document using a shell, driver, or editor.

@@ -257,51 +258,87 @@ export default async function ArticlePage({ params }: PageProps) { Choose an install path

- Use Docker for the fastest local setup, or Linux packages for a - persistent host installation. + Use native packages on a supported Linux host, or Docker for + containers and macOS/Windows evaluation.

- Run locally with Docker + Native Linux: complete stack

- Best for evaluation, local development, and quick testing. + Recommended: {aptTargetLabels.ubuntu24} with PostgreSQL 18. + The command detects amd64 or arm64 on your host and configures + trusted package repositories before installing system-wide packages. +

+

+ Pre-GA, fresh installation only; in-place upgrades from earlier + releases are not supported. Removing packages preserves data. +

+
+ +
+

+ Setup creates a new private PostgreSQL instance and prompts for + your admin password. The gateway binds all interfaces by default: + firewall port 10260 before setup. Self-signed TLS is for local + development; use trusted certificates for network access.

- +
- Docker Quick Start + Native Linux installation
+

+ For EL9 RPM/dnf commands, other supported choices, and the full walkthrough, see the{" "} + + Linux Packages Quick Start + + . +

- Install from Linux packages + Docker: local container

- Use the repository-backed package flow when you want a persistent - server install. Generate the exact apt or rpm command with the{" "} - - Package Finder - - . + With Docker installed, run a local instance on Linux, macOS, or + Windows. Replace the credential placeholders before running. + The port stays on loopback. +

+
+ +
+

+ Wait for the readiness banner in{" "} + docker logs documentdb before connecting.

- Linux Packages Quick Start + Docker installation
+

+ For persistence, certificates, and the full walkthrough, see the{" "} + + Docker Quick Start + + . +

@@ -312,14 +349,13 @@ export default async function ArticlePage({ params }: PageProps) {

- 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.getAll(key).length > 1)) { + return { selection: null, error: "This link contains conflicting install choices. Choose your settings below." }; + } + const method = params.get("method") ?? "packages"; + 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 (method !== "packages" && method !== "docker") { + return { selection: null, error: "This install method is not supported. Choose Native Linux or Docker." }; + } + if (pg !== "17" && pg !== "18") { + return { selection: null, error: "Native packages are available for PostgreSQL 17 and 18. Choose a supported version." }; + } + if (family === "apt") { + if (!isAptTarget(target) || !aptTargetPgVersions[target].includes(pg)) { + return { selection: null, error: "This APT target is not supported. Choose Ubuntu 24.04." }; + } + if (arch !== "auto" && arch !== "amd64" && arch !== "arm64") { + return { selection: null, error: "Choose automatic architecture, amd64, or arm64 for APT." }; + } + return { selection: { method, packages: { family, target, arch, pg } }, error: null }; + } + if (family === "rpm") { + if (!isRpmTarget(target) || !rpmServesFullStack(target, pg)) { + return { selection: null, error: "This RPM target is not supported. Choose an EL9 distribution below." }; + } + if (arch !== "auto" && arch !== "x86_64" && arch !== "aarch64") { + return { selection: null, error: "Choose automatic architecture, x86_64, or aarch64 for RPM." }; + } + return { selection: { method, packages: { family, target, arch, pg } }, error: null }; + } + return { selection: null, error: "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(); +} + +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." }; + } + 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..d65309d 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 - Native Linux Packages and Docker", 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.", + "Install DocumentDB on Ubuntu 24.04 or RHEL/Rocky 9 with apt or dnf, then run guided PostgreSQL setup. Native packages are pre-GA and for fresh installs. Docker is also available.", 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..a1e43e2 100644 --- a/app/packages/page.tsx +++ b/app/packages/page.tsx @@ -1,723 +1,419 @@ "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, + parseInstallSelection, + releaseHasPackages, + selectInstallTarget, + type SelectionResult, +} from "../lib/installSelection"; import { useReleaseInfo } from "../lib/releaseInfo"; -type InstallMethod = "docker" | "packages"; -type PackageFamily = "apt" | "rpm"; - const dockerCommand = `docker run -dt --name documentdb \\ -p 127.0.0.1:10260:10260 \\ ghcr.io/documentdb/documentdb/documentdb-local:latest \\ --username '' \\ --password ''`; +const firstQuery = `db.starter.insertOne({ message: "Hello, DocumentDB!" }) +db.starter.findOne({ message: "Hello, DocumentDB!" })`; + 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.", - }, -] as const; + { 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." }, +]; -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]; +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"; - useEffect(() => { - if (!availableAptPgVersions.includes(aptPgVersion)) { - setAptPgVersion(availableAptPgVersions[availableAptPgVersions.length - 1]); - } - }, [aptPgVersion, availableAptPgVersions]); +function InstallLocation({ onChange }: { onChange: (result: SelectionResult) => void }) { + const search = useSearchParams().toString(); + useEffect(() => onChange(parseInstallSelection(search)), [onChange, search]); + return null; +} + +export default function PackagesPage() { + const { release, status: releaseStatus, error: releaseError } = useReleaseInfo(); + const [state, setState] = useState(null); - const latestReleaseAptVersion = release.aptVersion; - const latestReleaseRpmVersion = release.rpmVersion; + const selection = state?.selection ?? defaultInstallSelection; + const { method, packages } = selection; + const { family, target, pg, arch } = packages; + const selectionReady = state !== null && state.error === null; + const packagesAvailable = releaseStatus === "live" && releaseHasPackages(release, packages); + const canInstall = selectionReady && packagesAvailable; + 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); + const connectionCommand = `mongosh 'mongodb://127.0.0.1:10260/mydb?authSource=admin&tls=true&tlsAllowInvalidCertificates=true' \\ + --username ${method === "packages" ? "admin" : "''"} --password`; - 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 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(installSelectionQuery(result.selection))) { + url.searchParams.set(key, value); + } + window.history.pushState(null, "", url); + } + + 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. +

+ + + +
+
+

Start simple. Keep control.

+

Install DocumentDB

+

+ Run directly on Linux with guided setup, or use Docker. Start with the complete + database stack; choose individual components when you need more control.

-
- - GPG-signed Repositories - - - Docker + Linux Packages - - - AMD64 + ARM64 - -
-
+

+ Native packages: Ubuntu 24.04 and EL9 · PostgreSQL 17/18 · AMD64 and ARM64 +

+ Looking for individual package downloads? + -
-

1. Choose your install method

-
+
+ {([ + { value: "packages", title: "Native Linux", description: "Recommended on supported Linux hosts. No container or source build required." }, + { value: "docker", title: "Docker", description: "A container-based path for Linux, macOS, and Windows." }, + ] as const).map((item) => ( + ))} +
+ + + + {state?.error && ( +
+

{state.error} No installation commands are shown for this link.

-
+ )} -
-

- 2. Copy and run this command -

- - {method === "docker" ? ( - <> - -

- Starts DocumentDB locally on port 10260 for quick evaluation and development. + {method === "packages" ? ( + <> +

+

One complete stack. No package decisions.

+

+ 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

-
-
- - -

- Target: {selectedTargetText} · Architecture: {selectedArchText} · package names{" "} - {selectedPackageNames} + +

+ 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.

-

- The generated command adds the PostgreSQL upstream repositories that provide - PostgreSQL, pg_cron,{" "} - pgvector, PostGIS, and{" "} - rum for PostgreSQL 17. -

-

- It installs the full DocumentDB stack for this target: the extension, the gateway - runtime, the administrator tools and the systemd units. -

- {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. -

- ) : null} -
-

- {isFullStack - ? "What gets installed" - : "Need the MongoDB-compatible gateway?"} -

- {isFullStack ? ( - <> -

- A per-major DocumentDB install resolves five package names. Installing{" "} - {selectedPackageNames} pulls in - everything below; the optional documentdb{" "} - meta package selects PostgreSQL 18. -

-
- {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 → - -
- - )} -
+
-
-
- - Current release package catalog - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FormatDistributionsArchitecturesPostgreSQL versionsPackage namingVersion served
APTUbuntu 24.04 · ubuntu24amd64, arm6417, 18 - documentdb-<pg> - {release.metaVersion}
RPM - Rocky/Alma/CentOS Stream 9 or registered RHEL 9 ·{" "} - rpm/rhel9 - x86_64, aarch6417, 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. +

-
+ -
- - 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 +
+ {releaseStatus === "loading" ? ( +

Checking the published package release...

+ ) : releaseStatus === "fallback" ? ( +
+

Cannot confirm the current repository release. {releaseError}

+

+ Reference release: {release.tagName}, not confirmed current. Installation commands are + withheld until availability can be confirmed.{" "} + Browse release assets{" "} + or . +

-
-

- 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. -

+ ) : ( +

+ Published repository release:{" "} + {release.tagName} + {" · "}{targetLabel}{" · "}{arch === "auto" ? "AMD64 / ARM64" : arch} +

+ )}
-
- -
- - 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. + {selectionReady && releaseStatus === "live" && !packagesAvailable && ( +

+ 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.

-
-

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> - -
-
-

- See all releases and release notes on{" "} - - GitHub Releases - - . + )} + +

+

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.

-
-
+ {canInstall ? : ( +

Commands will appear after your selection and the published package set are confirmed.

+ )} +
-
- - Direct package downloads - -
-

- Individual .deb and{" "} - .rpm files are attached to each release on - GitHub. Recent release examples: +

+

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.

-
-
{currentReleaseExamples[0]}
-
{currentReleaseExamples[1]}
-
{currentReleaseExamples[2]}
-
-

- Choose an asset whose PostgreSQL version and architecture match your host. + {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.

- - Browse releases on GitHub → - -
-
- -
- - 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 - -
-
-
- - -
-
-

- 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. +

+ Need automation? Follow the complete{" "} + unattended setup{" "} + instructions. Already managing PostgreSQL? Use the{" "} + operations guide{" "} + instead of creating a new instance. +

+
+ + ) : ( +
+

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 && } +

+ The container initializes the database; do not run the native setup wizard inside it. + For persistent volumes and a versioned image, follow the{" "} + Docker quickstart. +

+ + )} -
+
+

{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; it is not included in the connection URI. +

+ {selectionReady && (method === "docker" || canInstall) && ( + <> + +

In mongosh, insert a document and read it back:

+ + + )} +

+ Expect an acknowledged insert and a document containing "Hello, DocumentDB!". + The example uses the mydb 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}

+ + {guide.title} + {guide.description} ))}
+
-
- - Linux package guide - - - All docs - -
+ {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. +

+
+ )} + +
+
+ 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}
+
+ ))} +
+

+ 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 native packaging. +

+
+
+ 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. +

+
+
+ 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 native package set; install it separately.
  • +
  • Uninstalling is not a reset: data deletion is a separate, explicit operation.
  • +
+

+ Complete Linux quickstart + {" · "}Advanced operations + {" · "}Docker quickstart +

+
diff --git a/app/page.tsx b/app/page.tsx index a8a7098..56b8c3f 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,6 +1,6 @@ import Image from "next/image"; import Link from "next/link"; -import CommandSnippet from "./components/CommandSnippet"; +import HomeQuickstart from "./components/HomeQuickstart"; import { documentdbKubernetesOperatorQuickStartUrl } from "./services/externalLinks"; import { getMetadata } from "./services/metadataService"; import { @@ -33,27 +33,6 @@ type Capability = { linkLabel?: string; }; -const quickRunCommand = `docker run -dt --name documentdb \\ - -p 10260:10260 \\ - ghcr.io/documentdb/documentdb/documentdb-local:latest \\ - --username \\ - --password `; - -const quickStartSteps = [ - { - step: "01", - description: "Run DocumentDB Local with Docker.", - }, - { - step: "02", - description: "Connect on port 10260 with your app, shell, or client.", - }, - { - step: "03", - description: "Continue with the docs or Linux packages for the setup you need.", - }, -]; - const kubernetesOperatorEntryPoints = [ { title: "Local clusters", @@ -87,7 +66,7 @@ const whyDocumentDB = [ { title: "Open and portable", description: - "MIT licensed, runs locally with Docker, and fits your own infrastructure or cloud.", + "MIT licensed, runs directly on Linux or with Docker, and fits your own infrastructure or cloud.", }, ]; @@ -132,7 +111,7 @@ const trustBadges = [ "Built on PostgreSQL", "Native BSON", "MIT licensed", - "Runs locally with Docker", + "Native Linux or Docker", ]; const credibilityPoints = [ @@ -327,28 +306,26 @@ export default function Home() {

A powerful, scalable, fully MongoDB compatible open-source database built for modern applications

-

+

Open source and MIT licensed, with native BSON, advanced indexing, and vector search on PostgreSQL.

+

+ Run directly on Linux without a source build or container. + Start with the complete stack and guided setup, or use Docker. +

- Get Started - - - Download + Install DocumentDB - View Docs + Read the docs
@@ -363,53 +340,7 @@ export default function Home() {
-
-
- - Quick start - -

- Run locally with Docker -

-

- Start DocumentDB Local with Docker, then connect on port - 10260. -

-
- -
    - {quickStartSteps.map((item) => ( -
  1. - - {item.step} - -

    - {item.description} -

    -
  2. - ))} -
-
- - Docker quick start - - - Download packages - -
-
+
@@ -472,6 +403,74 @@ export default function Home() {
+
+
+
+

+ Installation choices +

+

+ Start simple. Keep control. +

+

+ No source build required. Guided setup. Choose what you manage. +

+ + Read about native Linux packages + +
+
+
+

Recommended

+

Complete stack

+

+ Install PostgreSQL, the DocumentDB extension, and the gateway + together. Guided setup creates a private instance with persistent + storage and systemd services. +

+ + Install the complete stack + +
+
+

Advanced

+

Your local PostgreSQL

+

+ Use PostgreSQL you manage on the same host as the gateway, + not a remotely hosted database. Review configuration changes + and restart requirements before setup. +

+ + Read the local PostgreSQL guide + +
+
+

Advanced

+

Extension only

+

+ Add DocumentDB to your local PostgreSQL installation for SQL use. + The extension alone does not create a MongoDB-compatible network endpoint. +

+ + Read the extension-only guide + +
+
+
+
+
@@ -701,20 +700,26 @@ export default function Home() { Ready to try DocumentDB?

- Start locally with Docker, then explore the project on GitHub. + Install directly on Linux, or use Docker on Linux, macOS, and Windows.

+ Install DocumentDB + + - Get Started + Use Docker GitHub diff --git a/app/services/articleService.ts b/app/services/articleService.ts index 2be8647..0112e04 100644 --- a/app/services/articleService.ts +++ b/app/services/articleService.ts @@ -28,7 +28,7 @@ const virtualSections: Record' \\ @@ -107,6 +109,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 @@ -159,35 +169,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 +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; [Native Linux 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. -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: +**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). -\`\`\`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 -\`\`\` +> [!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. @@ -214,7 +211,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 [Native Linux 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: @@ -244,18 +241,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('...') } @@ -270,17 +268,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: [Native Linux 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 [Native Linux 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 @@ -341,8 +357,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. @@ -364,6 +380,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 @@ -614,15 +642,42 @@ 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: + +- [Native Linux](/packages?method=packages): install the complete stack, then create a private PostgreSQL instance with the setup wizard. +- [Docker](/packages?method=docker): run a local container, including for macOS or Windows evaluation. + +The [Linux Packages Quick Start](/docs/getting-started/packages) and [Docker Quick Start](/docs/getting-started/docker) 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 username \`admin\` and the password chosen during native setup, or the credentials chosen for Docker. 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. Native 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 (\`admin\` and your setup password for the recommended native installation). 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. Native 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 connect to a local DocumentDB instance, browse sample data, and create your first database without leaving the editor. +Use DocumentDB for VS Code to connect to DocumentDB and insert and read your first document without leaving the editor. + +${clientInstancePrerequisiteContent} ## Prerequisites - [Visual Studio Code](https://code.visualstudio.com/) - The [DocumentDB for VS Code extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-documentdb) -- A local DocumentDB instance from [Docker Quick Start](/docs/getting-started/docker) or a host setup with a running DocumentDB gateway - Optional: [mongosh](https://www.mongodb.com/docs/mongodb-shell/install/) for independent connection checks ## Install the extension @@ -635,9 +690,9 @@ code --install-extension ms-azuretools.vscode-documentdb If VS Code prompts you to reload after installation, do that before creating a connection. -## Start DocumentDB first +## Optional: start a Docker instance -For the fastest local setup, start DocumentDB Local with Docker: +Skip this if you installed native 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 \\ @@ -647,7 +702,7 @@ 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 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). ## Add a local connection in VS Code @@ -655,7 +710,7 @@ If you prefer a host installation instead of Docker, use the [Linux Packages Qui 2. In the local connection area, select **DocumentDB Local** and start the **New Local Connection** flow. 3. Enter port \`10260\`, your username, and your 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. @@ -663,10 +718,8 @@ If you prefer a host installation instead of Docker, use the [Linux Packages Qui Once connected: -1. Expand the connection and open \`StoreData\`. This exists only if you started the container with \`--init-data true\`; without it DocumentDB Local starts empty. -2. Open the \`stores\` or \`ratings\` collection. -3. Switch between the **Table**, **Tree**, and **JSON** views to confirm the extension is reading data correctly. -4. Create your own database and collection from the context menu, then add a test document like: +1. Expand the connection and create a \`quickstart\` database and an \`orders\` collection from the context menu. +2. Add a test document: \`\`\`json { @@ -676,8 +729,16 @@ Once connected: } \`\`\` +3. Refresh the \`orders\` collection and find the document with \`"source": "vscode"\`. Read it back in the **Table**, **Tree**, or **JSON** view to confirm that both writing and reading work. + If you prefer to validate outside the extension first, use [Mongo Shell Quick Start](/docs/getting-started/mongo-shell-quickstart). +### Optional: browse sample data + +${optionalSampleDataContent} + +If you loaded it, open \`StoreData\`, then the \`stores\` or \`ratings\` collection. + ## Import, export, and querying After the connection works, the extension can help you continue without leaving VS Code: @@ -694,7 +755,7 @@ If the extension does not connect 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 native 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 @@ -721,14 +782,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 native 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='' @@ -741,12 +807,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 @@ -759,7 +820,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 native setup or Docker. \`\`\`javascript const { MongoClient } = require("mongodb"); @@ -827,9 +888,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 native 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 @@ -857,16 +916,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 native 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='' @@ -879,14 +941,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) @@ -907,7 +962,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 native setup or Docker. \`\`\`python import os @@ -967,7 +1022,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( @@ -979,7 +1036,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 native 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 @@ -1002,7 +1059,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 native 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 @@ -1021,15 +1078,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 native 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 \\ @@ -1039,14 +1097,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 installed native packages or used Docker. + \`\`\`bash mongosh localhost:10260 \\ -u '' \\ @@ -1068,7 +1124,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 @@ -1104,12 +1162,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 native 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 '' \\ @@ -1124,7 +1185,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 native 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/) @@ -1214,26 +1275,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 Native Linux or Docker.** [Native Linux installation](/packages?method=packages) is recommended for a complete stack on supported Linux hosts, with a new private PostgreSQL 18 instance. [Docker installation](/packages?method=docker) is for containers, including macOS/Windows evaluation. +2. **Create a working instance.** Follow the [Linux Packages Quick Start](/docs/getting-started/packages) or [Docker Quick Start](/docs/getting-started/docker). Native 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 +Native 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 native packages, inspect \`sudo documentdb-setup --status\`; for Docker, check \`docker ps --filter "name=documentdb"\` and wait for the readiness banner in \`docker logs documentdb\`. -\`\`\`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 \`admin\` for the recommended native setup, or your Docker username, and enter your password at the prompt. + +The certificate bypass is for **local development only**. Native 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 @@ -1243,8 +1307,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). `; @@ -1252,11 +1321,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 native packages, check \`sudo documentdb-setup --status\` and [package troubleshooting](/docs/getting-started/packages#troubleshooting). The recommended 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 native [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 [Native Linux installation](/packages?method=packages) or [Docker installation](/packages?method=docker). `; const gettingStartedIndexFeatureExplorationContent = `## Explore key features @@ -1296,17 +1365,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 native Linux packages or Docker, 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 on native Linux or Docker, 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 on native Linux or Docker 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 on native Linux or Docker 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 on native Linux or Docker with mongosh and insert and read your first document.', }; function getArticleKey(section: string, file: string): string { @@ -1373,14 +1444,14 @@ function splitPrebuiltNavigation(section: string, links: Link[]): Link[] { const isMergedVscodeGuide = (link: Link) => link.link.includes('vscode-extension-guide') || /visual studio code extension guide/i.test(link.title); const gettingStartedQuickLinks: Link[] = [ - { - title: articleTitleOverrides['getting-started/docker'], - link: '/docs/getting-started/docker', - }, { title: articleTitleOverrides['getting-started/packages'], link: '/docs/getting-started/packages', }, + { + title: articleTitleOverrides['getting-started/docker'], + link: '/docs/getting-started/docker', + }, ]; const filteredLinks = links.filter((link) => !isPrebuiltPackages(link) && !isMergedVscodeGuide(link)); const gettingStartedIndex = filteredLinks.find((link) => link.link === 'index.md'); @@ -1646,7 +1717,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..ce3e711 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 %} @@ -43,7 +44,7 @@ {% assign home_href = site_root | append: '/' | replace: '//', '/' %} {% assign docs_href = site_root | append: '/docs' | replace: '//', '/' %} - {% assign packages_href = site_root | append: '/packages' | replace: '//', '/' %} + {% assign packages_href = site_root | append: '/packages/?method=packages' | replace: '//', '/' %} {% assign operator_href = site_root | append: '/kubernetes-operator' | replace: '//', '/' %} {% assign logo_href = site_root | append: '/images/DocumentDB Logo - background removed.png' | replace: '//', '/' %} {% assign blogs_href = site.baseurl | append: '/' | replace: '//', '/' %} @@ -60,7 +61,7 @@ GitHub Discord Docs - Download + Install K8s Operator Blogs diff --git a/blogs/_posts/2026-09-10-native-linux-packages.md b/blogs/_posts/2026-09-10-native-linux-packages.md new file mode 100644 index 0000000..a1d2f13 --- /dev/null +++ b/blogs/_posts/2026-09-10-native-linux-packages.md @@ -0,0 +1,71 @@ +--- +title: "Native Linux packages for DocumentDB: start simple, keep control" +description: Run DocumentDB directly 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', '' %} + +You want to try DocumentDB on a Linux host without building from source or making containers part of your environment. Native Linux packages give you that 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 native package experience brings 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 recommended 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 native_packages_demo +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 `native_packages_demo`, 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. Native packages are not new to this release. + +The shipped native 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..7925d34 --- /dev/null +++ b/tests/installSelection.test.ts @@ -0,0 +1,117 @@ +import { describe, expect, it } from "vitest"; +import { + defaultInstallSelection, + installSelectionQuery, + parseInstallSelection, + releaseHasPackages, + selectInstallTarget, +} from "../app/lib/installSelection"; +import { FALLBACK_RELEASE, parseReleaseInfo } from "../app/lib/releaseInfo"; + +describe("install selection links", () => { + it("defaults to the complete native PG18 stack with 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), + }); + }); + + it("allows campaign parameters without treating them as install choices", () => { + expect(parseInstallSelection("?utm_source=blog&method=packages").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..bb42eb8 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,193 @@ 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 native 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=packages')).toBeLessThan( + startHere?.indexOf('/packages?method=docker') ?? -1, + ); + expect(startHere).toContain('new private PostgreSQL 18 instance'); + 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(packageIndex).toBeGreaterThanOrEqual(0); + expect(dockerIndex).toBeGreaterThan(packageIndex); + + 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('buildAptInstallCommand("ubuntu24", "auto", "18")'); + expect(source).toContain('buildSetupCommand("18")'); + expect(source).toContain('href="/packages?method=packages"'); + expect(source).toContain('href="/packages?method=docker"'); + expect(source.indexOf('href="/packages?method=packages"')).toBeLessThan( + source.indexOf('href="/packages?method=docker"'), + ); + 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('firewall port 10260 before setup'); + 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 [ + 'vscode-quickstart', '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 native 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 [ + 'vscode-quickstart', '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 vscode = getArticleByPath('getting-started', ['vscode-quickstart'])?.content; + expect(vscode).toContain('create a `quickstart` database'); + expect(vscode).toContain('Add a test document'); + expect(vscode).toContain('Refresh the `orders` collection'); + expect(vscode?.indexOf('Add a test document')).toBeLessThan( + vscode?.indexOf('### Optional: browse sample data') ?? -1, + ); + 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 native clients', () => { + for (const slug of ['nodejs-setup', 'python-setup', 'mongo-shell-quickstart']) { + const content = getArticleByPath('getting-started', [slug])?.content; + expect(content, slug).toContain('For native 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 native guide', () => { + const anchors = Array.from( + linuxPackagesOperationsContent.matchAll(/^## (.+)$/gm), + (match) => kebabCase(match[1]), + ); + for (const slug of [ + [], ['packages'], ['nodejs-setup'], ['python-setup'], ['mongo-shell-quickstart'], + ['vscode-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 +231,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 +514,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=''");