Chapter 03Lesson 02~140 minutes

Installation Prerequisites, Database Planning, and First Server: Guided Hands-On Workflow

Install and operate one pinned disposable Community Build server while capturing host, Java, path, database, port, process, and log evidence before and after startup.

ZIP installCommunity BuildH2 labLogsHealth check

Learning objectives

  • Install a pinned SonarQube Community Build 26.9.0.129388 ZIP in an isolated local path.
  • Prove the JDK, user identity, disk, port, and Linux search prerequisites before startup.
  • Start the server locally, distinguish Web/Compute Engine/search log evidence, and verify the default endpoint.
  • Explain where H2 fits in the lab and how a supported external database changes the architecture.
  • Stop and restart cleanly while preserving an installation evidence manifest.

1. Lab contract and stop conditions

This workflow uses Community Build 26.9.0.129388 from the official ZIP distribution and the embedded H2 database only because the instance is disposable and local. Do not reuse the H2 result as a production deployment pattern.

Safety boundary: keep the web listener local to the lab host, use no proprietary source code, use no real secrets, do not run SonarQube as root on Unix-like systems, and do not change host kernel limits unless the machine is an authorized disposable lab or the administrator has approved the change. If port 9000 is already owned by another service, stop and choose a lab port instead of killing an unknown process.

Abort before installation if the current Community Build host requirements are not met, the JDK is unsupported, disk is critically low, the intended directories are outside the lab scope, or the machine cannot provide the required embedded-search behavior.

2. Create the installation manifest before touching the server

Use a working directory such as C:\sq-lab on Windows or $HOME/sq-lab on Linux/macOS. Record the planned values first:

sonarqube_product=Community Build
sonarqube_version=26.9.0.129388
install_mode=ZIP
java_requirement=JDK 21 or 25 (re-check current docs)
database=embedded H2 (lab only)
web_url=http://127.0.0.1:9000
source=synthetic/local only
cleanup=stop server, preserve evidence, remove lab directory when finished

The manifest turns assumptions into reviewable inputs. If a later startup differs—wrong Java, wrong path, wrong port—you can see the drift instead of guessing.

3. Download the pinned distribution and prove its identity

The pinned binary URL used by the official Community Build image for this release is:

https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-26.9.0.129388.zip

Windows PowerShell example:

$Root = 'C:\sq-lab'
$Version = '26.9.0.129388'
$Zip = Join-Path $Root "sonarqube-$Version.zip"
New-Item -ItemType Directory -Force -Path $Root | Out-Null
curl.exe -L 'https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-26.9.0.129388.zip' -o $Zip
Get-Item $Zip | Select-Object FullName,Length,LastWriteTime
Get-FileHash $Zip -Algorithm SHA256

Linux/macOS example:

set -eu
ROOT="$HOME/sq-lab"
VERSION="26.9.0.129388"
mkdir -p "$ROOT"
curl -fL 'https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-26.9.0.129388.zip' -o "$ROOT/sonarqube-$VERSION.zip"
sha256sum "$ROOT/sonarqube-$VERSION.zip" 2>/dev/null || shasum -a 256 "$ROOT/sonarqube-$VERSION.zip"

Record the calculated hash in your lab evidence. For production acquisition, use the current SonarSource verification/signature guidance rather than treating a copied URL as sufficient provenance.

4. Prove runtime and host prerequisites

On Windows, confirm the exact Java executable and version:

Get-Command java | Select-Object Source
java -version
Get-NetTCPConnection -State Listen -LocalPort 9000 -ErrorAction SilentlyContinue
Get-PSDrive -PSProvider FileSystem | Select-Object Name,Used,Free

On Linux, add the embedded-search prerequisites:

java -version
id
sysctl vm.max_map_count
sysctl fs.file-max
ulimit -n
ulimit -u
ss -ltn | grep ':9000' || true
df -h "$HOME"

Expected: a supported JDK (current baseline Java 21 or 25), enough disk, no unintended listener conflict, a non-root Unix user, and current documented search limits. If any prerequisite fails, preserve the output and stop. Do not hide a host incompatibility by disabling bootstrap checks.

5. Unpack into a clean path and inspect before execution

Extract the ZIP. The release directory should be sonarqube-26.9.0.129388. Inspect rather than immediately launching it.

$Home = 'C:\sq-lab\sonarqube-26.9.0.129388'
Expand-Archive -Path $Zip -DestinationPath 'C:\sq-lab' -Force
Get-ChildItem $Home
Get-ChildItem (Join-Path $Home 'bin')
Get-ChildItem (Join-Path $Home 'conf')
Get-ChildItem (Join-Path $Home 'logs') -ErrorAction SilentlyContinue
cd "$HOME/sq-lab"
unzip -q "sonarqube-26.9.0.129388.zip"
SQ_HOME="$HOME/sq-lab/sonarqube-26.9.0.129388"
printf 'SQ_HOME=%s
' "$SQ_HOME"
find "$SQ_HOME" -maxdepth 1 -mindepth 1 -printf '%f
' | sort

Do not copy an old conf, extensions, or data directory into this fresh release. That would convert a controlled first install into an undocumented migration.

6. Start locally and follow process-specific evidence

For Windows, open a dedicated terminal as the normal lab user and run:

Set-Location 'C:\sq-lab\sonarqube-26.9.0.129388\bin\windows-x86-64'
.\StartSonar.bat

For Linux, run as the non-root lab user:

"$SQ_HOME/bin/linux-x86-64/sonar.sh" console

In a second shell, inspect the log files rather than repeatedly refreshing the browser:

$Logs='C:\sq-lab\sonarqube-26.9.0.129388\logs'
Get-Content (Join-Path $Logs 'sonar.log') -Tail 80
Get-Content (Join-Path $Logs 'web.log') -Tail 80
Get-Content (Join-Path $Logs 'ce.log') -Tail 80
Get-Content (Join-Path $Logs 'es.log') -Tail 80

A successful startup reaches the documented SonarQube is operational state. The files separate orchestration, Web, Compute Engine, and embedded-search evidence. Preserve the first failure if startup stops before that point.

7. Verify the local endpoint and bootstrap state

Only after the logs show a healthy startup should you inspect the web endpoint:

curl.exe -I http://127.0.0.1:9000/
Get-NetTCPConnection -State Listen -LocalPort 9000
curl -I http://127.0.0.1:9000/
ss -ltnp | grep ':9000'

Open http://127.0.0.1:9000. The current ZIP installation documentation identifies admin/admin as the bootstrap administrator credentials. For this disposable lab, note that state in the evidence packet. For any persistent instance, change bootstrap credentials immediately and review permissions before widening network exposure.

Evidence chain: browser response + listening socket + process-specific logs + exact release/JDK identity is stronger than any one of those signals alone.

8. Compare the H2 lab to a production-shaped database plan

Do not convert this lesson into a database installation course. Instead, write the production delta. A supported external database requires a pre-created SonarQube database/schema, a least-privilege database user with the permissions required by current documentation, an explicit JDBC URL, and secure credential delivery.

# Production-shaped example only; use fake values here.
sonar.jdbc.username=sonarqube
sonar.jdbc.password=FAKE_DO_NOT_USE
sonar.jdbc.url=jdbc:postgresql://db.example.invalid:5432/sonarqube

Do not put a real database password in a course repository. In a real deployment, use the supported environment/secret mechanism for your operating model. The lesson’s key distinction is architectural: switching from H2 to PostgreSQL changes the durable-state boundary and backup/recovery plan; it does not change scanner project keys or quality-gate semantics.

9. Stop gracefully, restart, and compare evidence

On Linux/macOS ZIP installations, use the documented graceful stop command. On Windows, use the appropriate console/service stop path for how you started the instance. Do not kill Java processes until you have preserved logs and attempted a graceful stop.

"$SQ_HOME/bin/linux-x86-64/sonar.sh" stop
"$SQ_HOME/bin/linux-x86-64/sonar.sh" start

After restart, verify the same URL, version, port, and log sequence. The expected result is a repeatable startup, not merely a lucky first run.

10. Challenge: identify the layer before choosing the fix

For each symptom, name the owning layer before proposing a change:

Symptom Likely first layer First evidence
java -version reports 17 Runtime compatibility PATH/JDK identity, host requirements
9000 already listening before SonarQube starts Network/process ownership listener PID/process
es.log reports bootstrap limit failure Host/search prerequisites sysctl/ulimit values
Database login refused Database/network/credential JDBC config + DB logs, without printing secrets

11. Cleanup and retained evidence

Preserve the manifest, version/hash record, preflight output, first startup logs, endpoint verification, and shutdown result. Then stop the server. Delete only the explicitly named lab directory after confirming no persistent work is needed. Do not delete database/search/log directories on a real instance as “cleanup.”

Knowledge check

Why does the lab record a file hash even though it uses an official download URL?

Why do we inspect logs before opening the browser?

What changes when a real PostgreSQL database replaces H2?

Why must you not disable Elasticsearch bootstrap checks just to make the server start?

What proves the restart is reproducible?

Next lesson

From one working server to installation design choices

Lesson 3 compares ZIP/service, container, database, service-account, storage, and network patterns so you can choose an operating model deliberately instead of copying the lab unchanged into production.

Official references and version notes

Version and compatibility note

Version-sensitive statements were rechecked against current SonarSource primary documentation on 2026-09-07. Executable ZIP examples pin SonarQube Community Build 26.9.0.129388. Current Community Build host requirements specify a JDK with Java 21 or 25 for ZIP installation. Current database guidance treats embedded H2 as test/trial-only and lists PostgreSQL 14–18 plus supported Microsoft SQL Server and Oracle versions. Linux embedded-search prerequisites include vm.max_map_count ≥ 524288, fs.file-max ≥ 131072, at least 131072 open file descriptors for the SonarQube user, and at least 8192 threads. Re-check all of these before future reproduction.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.