Installation

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

This sub-section’s WordPress bibliography lists the reference material consulted while preparing these pages.

This page was written against WordPress 7.1.3 (released 2026-10-06; 7.1.4, a security release of 2026-10-28, is the version to run in production) and WP-CLI 2.12.0, and checked on 2026-10-28. WordPress 7.1 requires PHP 7.4 at minimum, and PHP 8.3 or newer is recommended. WordPress 7.2 is in beta and planned for 2026-12-08; nothing on this page is expected to change with it. Every command was run against a MariaDB 11.8 container with the official wordpress:cli image (PHP 8.3, WP-CLI 2.12.0), and every output block below is real output with secrets replaced by placeholders.

The page installs the site of Lumen Press, the fictitious publisher used throughout this sub-section: a database called lumen_press, a database user lumen, the table prefix lp_ and an administrator account lp_admin. The server must already meet the requirements described in Requirements and Hosting; a disposable local copy is easier to get from Local Development Environments.

The three ways to install

A WordPress install is always the same four results: the core files on disk, an empty database with a user that may write to it, a wp-config.php file that connects the two, and the initial rows (site title, URLs, the first administrator) that the installer writes into the database. Three routes lead there:

Route What does the work Typical use

Browser installer ("famous 5-minute install")

wp-admin/setup-config.php writes wp-config.php, wp-admin/install.php creates the tables and the administrator

Shared hosting with FTP or a file manager, first-time users

WP-CLI (wp core download, wp config create, wp core install)

The command line performs the same steps, without a browser

Servers with shell access, scripts, CI, containers, repeatable staging copies

Host one-click installer

A control-panel tool (Softaculous, Installatron, the Plesk WordPress Toolkit and similar) runs one of the above for you

Managed and shared hosting

The browser and WP-CLI routes produce the same database tables and options. The following diagram shows the browser route; WP-CLI replaces each screen with one command.

flowchart LR A[Upload core files] --> B{wp-config.php exists?} B -- no --> C[setup-config.php: language, database details] C --> D[Connection test and salts from the secret-key API] D --> E[wp-config.php written] B -- yes --> F[install.php: site title, admin user, email, visibility] E --> F F --> G[Tables created, options and admin user saved] G --> H[Log in at wp-login.php]

Before installing

The official checklist asks for access to the server (FTP, SFTP or a shell), a text editor, an FTP client when there is no shell, and a browser. The server side needs PHP, a MySQL or MariaDB database server, and HTTPS support.

The official pages do not agree on the database versions. The WordPress.org requirements page recommends PHP 8.3+, MySQL 8.0+ or MariaDB 10.11+, and says PHP 7.4 and MySQL 5.5.5 still work but are no longer supported. The Advanced Administration "Before You Install" page still names MySQL 5.7 or MariaDB 10.3, and the Hosting Handbook recommends the current LTS lines (MySQL 8.4, MariaDB 11.8, 11.4 or 10.11). The safest choice for a new site is the newest LTS database the host offers. Older books give MySQL 5.7 as the baseline, which reflects the "Before You Install" page rather than the current recommendation.

The PHP mysqli extension is mandatory. Without it, every request stops with the message "Your PHP installation appears to be missing the MySQL extension which is required by WordPress", unless a wp-content/db.php drop-in replaces the database layer (the SQLite integration works that way).

The browser install, step by step

Step 1: download and extract

The current release is published at https://wordpress.org/latest.zip and https://wordpress.org/latest.tar.gz; every release, with checksums, is listed on the releases page. On a server with a shell:

cd /var/www
wget https://wordpress.org/wordpress-7.1.3.tar.gz
tar -xzf wordpress-7.1.3.tar.gz          # creates ./wordpress
mv wordpress lumenpress.example          # the document root of the virtual host

When uploading by FTP instead, upload the contents of the wordpress folder to the document root (or the folder itself, renamed, for an install in a sub-folder such as /blog/). FTP clients that convert file names to lower case must have that option turned off. File and directory permissions are covered in File Permissions and Filesystem: 644 for files and 755 for directories is the baseline, never 666 or 777.

Step 2: create the database and its user

WordPress needs one database (or one table prefix inside a shared database) and a database user that has all privileges on it, and on nothing else. Hosting control panels (cPanel’s MySQL Database Wizard, Plesk, DirectAdmin) and phpMyAdmin do this through forms; on shared hosts the database name usually has to start with the account name and an underscore. With the command-line client, as an administrative database account:

CREATE DATABASE lumen_press
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_520_ci;

CREATE USER 'lumen'@'localhost' IDENTIFIED BY '<lumen-db-password>';
GRANT ALL PRIVILEGES ON lumen_press.* TO 'lumen'@'localhost';
FLUSH PRIVILEGES;

The host part of the user ('localhost' above) must match where PHP connects from. When the web server and the database run on different machines or containers, it is the web server’s address or '%' (any host, acceptable only on a private network). GRANT ALL PRIVILEGES ON lumen_press.* gives the user full rights on that database only; global privileges stay at their defaults. FLUSH PRIVILEGES is not strictly needed after CREATE USER and GRANT, but the official page keeps it and it does no harm.

The official page still suggests a utf8_ collation in phpMyAdmin. On any current server, use utf8mb4: WordPress has converted its tables to utf8mb4 since 4.2 so that emoji and all of Unicode can be stored, and utf8 (an alias of utf8mb3 in MySQL and MariaDB) cannot hold four-byte characters. The collation only matters if the database is created before WordPress; WordPress creates its tables with the charset and collation that $wpdb negotiates, as the WP-CLI section below shows.

Step 3: wp-config.php and the salts

wp-config.php is the only configuration file of a WordPress install. The download ships wp-config-sample.php; copy it to wp-config.php and fill in the database settings, or skip this step and let the installer write the file.

<?php
// wp-config.php for Lumen Press (database section).
define( 'DB_NAME', 'lumen_press' );
define( 'DB_USER', 'lumen' );
define( 'DB_PASSWORD', getenv( 'LUMEN_DB_PASSWORD' ) ?: '<lumen-db-password>' );
define( 'DB_HOST', 'localhost' );   // also 'db.internal:3307' or 'localhost:/run/mysqld/mysqld.sock'
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );         // empty: let WordPress pick the best collation

// Replace with the eight lines returned by https://api.wordpress.org/secret-key/1.1/salt/.
define( 'AUTH_KEY',         '<your-salt>' );
define( 'SECURE_AUTH_KEY',  '<your-salt>' );
define( 'LOGGED_IN_KEY',    '<your-salt>' );
define( 'NONCE_KEY',        '<your-salt>' );
define( 'AUTH_SALT',        '<your-salt>' );
define( 'SECURE_AUTH_SALT', '<your-salt>' );
define( 'LOGGED_IN_SALT',   '<your-salt>' );
define( 'NONCE_SALT',       '<your-salt>' );

$table_prefix = 'lp_';              // letters, digits and underscores only

/* Add any custom values between this line and the "stop editing" line. */
define( 'WP_ENVIRONMENT_TYPE', 'production' );

/* That's all, stop editing! Happy publishing. */

if ( ! defined( 'ABSPATH' ) ) {
	define( 'ABSPATH', __DIR__ . '/' );
}

require_once ABSPATH . 'wp-settings.php';

The eight keys and salts sign the authentication cookies and nonces. The sample file ships them as put your unique phrase here and points to the WordPress.org secret-key service, which returns eight freshly generated define() lines on every request:

curl -s https://api.wordpress.org/secret-key/1.1/salt/
define('AUTH_KEY',         '<random-64-chars>');
define('SECURE_AUTH_KEY',  '<random-64-chars>');
define('LOGGED_IN_KEY',    '<random-64-chars>');
define('NONCE_KEY',        '<random-64-chars>');
define('AUTH_SALT',        '<random-64-chars>');
define('SECURE_AUTH_SALT', '<random-64-chars>');
define('LOGGED_IN_SALT',   '<random-64-chars>');
define('NONCE_SALT',       '<random-64-chars>');

Changing the keys at any time invalidates every existing login cookie, so all users must log in again; that is the standard reaction to a suspected compromise (wp config shuffle-salts does it from WP-CLI). Keys belong in wp-config.php or in environment variables, never in version control. If a key is missing, left as the placeholder phrase or duplicated, wp_salt() ignores it and falls back to a random value that it generates once and stores in the options table, so the site still works; defining unique keys in the file keeps them out of the database, where a SQL injection or a leaked backup would expose them.

A few details that older material gets wrong:

  • The shipped sample ends with require_once ABSPATH . 'wp-settings.php'; and has no closing ?> tag. Omitting it is the PHP convention for files that contain only code, because any byte after a closing tag (a newline, a space, a byte order mark) is sent to the browser and causes "headers already sent" errors. Older books show wp-config.php ending in ?>; it works if nothing follows it, but there is no reason to add it.

  • Save the file as UTF-8 without a BOM, with nothing before <?php on the first line.

  • ABSPATH is computed from __DIR__ and must not be edited. WordPress finds wp-config.php in the WordPress directory or one level above it on its own; moving it there does not require changing ABSPATH, contrary to what one of the older books says.

The full list of constants is in wp-config.php Reference.

Step 4: run the installer

Open the site in a browser. If wp-config.php does not exist, WordPress redirects to wp-admin/setup-config.php, which:

  1. asks for the language of the install (when the package is the default English one and WordPress.org is reachable);

  2. asks for the database name, user name, password, database host and table prefix;

  3. tests the connection, fetches the keys from the secret-key service, and writes wp-config.php if the directory is writable. Otherwise it displays the file’s content for you to paste.

A successful connection ends with the "All right, sparky!" screen and a Run the installation button. The installer proper is wp-admin/install.php (for a sub-folder install, https://lumenpress.example/blog/wp-admin/install.php):

Field Meaning

Site Title

Stored in the blogname option; editable later in Settings > General.

Username

The first administrator’s login. It cannot be changed later from the dashboard, so avoid admin.

Password

Pre-filled with a strong random password and a strength meter. A weak password needs the "Confirm use of weak password" box; core does not enforce a policy.

Your Email

The administrator’s address, also used as the site’s admin email (admin_email) for notifications.

Search engine visibility

"Discourage search engines from indexing this site" sets blog_public to 0, which makes every page send a noindex, nofollow robots meta tag (the virtual robots.txt is not changed). It is a request to crawlers, not access control; uncheck it at launch.

Install WordPress creates the twelve tables (see Database Schema), writes the default options, the first post, page and comment, activates the latest default theme and creates the administrator, then shows Success! and a Log In link. The siteurl and home options are set to the URL the browser used, so the installer must be reached through the final domain and scheme (https://), not an IP address or a temporary host name. Changing them later is covered in Importing, Exporting and Migrating.

Calling install.php again on an installed site only shows "Already Installed". To reinstall, the tables must be dropped first.

An uploaded but not yet installed copy is open to anyone: whoever reaches setup-config.php or install.php first can point the site at their own database or create the administrator account. Run the installer immediately after uploading, or restrict access to the directory (HTTP authentication, an IP allow-list) until it is done.

Installing with WP-CLI

WP-CLI performs the same steps from a shell. It is a single PHAR file that needs PHP 7.2.24 or newer and nothing else beyond WordPress’s own requirements:

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
php wp-cli.phar --info
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
wp --version

The whole Lumen Press install is then four commands, run from the directory that will hold WordPress. The database password and the administrator password are read from files (or a secrets manager) rather than typed on the command line, so they do not end up in the shell history (LUMEN_DB_PASSWORD is exported by the deployment environment):

# 1. Download WordPress 7.1.3 (en_US) into the current directory. The .zip package
#    is used because of the .tar.gz extraction problem described further down.
wp core download https://wordpress.org/wordpress-7.1.3.zip

# 2. Write wp-config.php with new salts, after testing the database connection.
wp config create \
  --dbname=lumen_press \
  --dbuser=lumen \
  --dbhost=localhost \
  --dbprefix=lp_ \
  --dbcharset=utf8mb4 \
  --dbpass="$LUMEN_DB_PASSWORD" \
  --extra-php <<'PHP'
define( 'WP_ENVIRONMENT_TYPE', 'production' );
define( 'DISALLOW_FILE_EDIT', true );
PHP

# 3. Create the tables, options and the first administrator.
wp core install \
  --url=https://lumenpress.example \
  --title="Lumen Press" \
  --admin_user=lp_admin \
  --admin_email=webmaster@lumenpress.example \
  --skip-email \
  --prompt=admin_password < ~/.secrets/lp_admin-password

# 4. Check the result.
wp core is-installed && wp core version --extra
wp core verify-checksums

The run below used 7.1.3, the release current when it was made. For a new production site download 7.1.4 instead (https://wordpress.org/wordpress-7.1.4.zip), the security release of 2026-10-28, or whatever release is current when you install: an older package is updated by the next automatic minor update anyway, but runs with known vulnerabilities until then.

--prompt=<arg> and --extra-php both read standard input, so one call cannot use both: wp config create takes the password from the environment and the extra constants from standard input, while wp core install reads the administrator password from a file. Constants can also be added later with wp config set. The output of the run, with the password replaced:

$ wp core download https://wordpress.org/wordpress-7.1.3.zip
Downloading from https://wordpress.org/wordpress-7.1.3.zip ...
md5 hash verified: 391b0aceed0eb3dc8ae929ed1a1381f7
Success: WordPress downloaded.

$ wp config create --dbname=lumen_press --dbuser=lumen --dbpass="$LUMEN_DB_PASSWORD" --dbhost=db --dbprefix=lp_ --dbcharset=utf8mb4 --extra-php <<'PHP' ...
Success: Generated 'wp-config.php' file.

$ wp core install --url=http://localhost:8080 --title="Lumen Press" --admin_user=lp_admin --admin_email=webmaster@lumenpress.example --skip-email --prompt=admin_password < admin-password.txt
2/3 [--admin_password=<password>]: <the password read from the file>
wp core install --title='Lumen Press' --admin_user='lp_admin' --admin_email='webmaster@lumenpress.example' --skip-email --admin_password='<the password read from the file>'
Success: WordPress installed successfully.

$ wp core version --extra
WordPress version: 7.1.3
Database revision: 61833
TinyMCE version:   4.9110 (49110-20250317)
Package language:  en_US

wp db tables then lists the twelve tables with the lp_ prefix, from lp_commentmeta to lp_users. The output also shows that --prompt keeps the password out of the shell history but echoes the completed command, password included. In CI logs, redirect that output or set the password afterwards with wp user update lp_admin --user_pass="$ADMIN_PASSWORD" from a masked secret.

The commands and their options

Command Options that matter for an install

wp core download

--version=<x.y.z|latest|nightly>, --locale=<locale> (a localized package such as es_ES), --skip-content (no default themes and plugins), --force (overwrite), --path=<dir>, --extract=false (keep the archive), and an optional <download-url> instead of the WordPress.org servers.

wp config create

--dbname, --dbuser, --dbpass, --dbhost (default localhost), --dbprefix (default wp_), --dbcharset (default utf8), --dbcollate (default empty), --locale, --extra-php (PHP from standard input inserted before the "stop editing" line), --skip-salts, --skip-check (no connection test), --force, --config-file.

wp db create

Creates the database named in wp-config.php with the credentials in it; only useful when that user may create databases (local and container setups).

wp core install

--url, --title, --admin_user, --admin_password (a random one is generated and printed if omitted), --admin_email, --locale (since WP-CLI 2.7.0), --skip-email (no notification to the new administrator).

wp core is-installed

Exit status 0 if the tables exist, 1 otherwise; the building block of idempotent provisioning scripts.

wp core verify-checksums

Compares every core file with the checksums published by WordPress.org.

wp config shuffle-salts

Replaces the eight keys and salts with new ones, logging everyone out.

wp config create defaults to --dbcharset=utf8, while the sample file uses utf8mb4. On a current server this makes no practical difference: $wpdb upgrades utf8 to utf8mb4 whenever the database supports it. A test install created without --dbcharset, so with DB_CHARSET set to utf8, still reported utf8mb4 utf8mb4_unicode_520_ci from wp eval 'global $wpdb; echo $wpdb->charset, " ", $wpdb->collate;'. Passing --dbcharset=utf8mb4 simply makes the file say what really happens.

Running the same install in containers

The official wordpress:cli image contains PHP, the mariadb client and WP-CLI, which makes it a convenient way to script or test an install without installing anything on the host. This is the setup used to produce the output above (the full local environment, with a web server, is in Local Development Environments):

export LUMEN_DB_ROOT_PASSWORD='<db-root-password>'
export LUMEN_DB_PASSWORD='<lumen-db-password>'

docker network create lumen
docker run -d --name db --network lumen \
  -e MARIADB_ROOT_PASSWORD="$LUMEN_DB_ROOT_PASSWORD" \
  -e MARIADB_DATABASE=lumen_press \
  -e MARIADB_USER=lumen \
  -e MARIADB_PASSWORD="$LUMEN_DB_PASSWORD" \
  mariadb:11.8
until docker exec db healthcheck.sh --connect --innodb_initialized >/dev/null 2>&1; do sleep 2; done

mkdir -p site
# Linux hosts: UID 33 is www-data in the Debian-based wordpress image; the Alpine wordpress:cli
# image uses UID 82, so the wpcli function below forces -u 33:33.
sudo chown 33:33 site

# A shell function that runs one command in a throwaway wordpress:cli container.
wpcli() {
  docker run --rm -i --network lumen -u 33:33 -e HOME=/tmp \
    -v "$PWD/site:/var/www/html" wordpress:cli "$@"
}

wpcli php -d memory_limit=512M /usr/local/bin/wp core download https://wordpress.org/wordpress-7.1.3.zip
wpcli wp config create --dbname=lumen_press --dbuser=lumen --dbpass="$LUMEN_DB_PASSWORD" \
  --dbhost=db --dbprefix=lp_ --dbcharset=utf8mb4
wpcli wp core install --url=http://localhost:8080 --title="Lumen Press" \
  --admin_user=lp_admin --admin_email=webmaster@lumenpress.example --skip-email
wpcli wp core verify-checksums

# Tear down.
docker rm -f db && docker network rm lumen

Two things showed up when running this:

  • The image runs PHP with a 128 MB memory_limit, and wp core download ran out of memory while extracting WordPress 7.1.3 ("Allowed memory size of 134217728 bytes exhausted"). Calling the PHAR through php -d memory_limit=512M fixes it, as the WP-CLI common-issues page recommends for memory errors.

  • With WP-CLI 2.12.0 in that image, extracting the default .tar.gz package truncated a few long file names under wp-includes/php-ai-client/, and wp core verify-checksums failed. Passing the .zip URL as <download-url> produced a clean tree ("Success: WordPress installation verifies against checksums."). Whatever the download method, run wp core verify-checksums after it.

One-click installers at hosts

Most hosting control panels offer an auto-installer: Softaculous and Installatron in cPanel and other panels, the WordPress Toolkit in Plesk, and host-specific tools on managed WordPress plans. They download WordPress, create the database and user, write wp-config.php and run the installer in one form, and usually add update, staging, cloning and backup features. They are a legitimate shortcut; the older books recommend them, and this page does not endorse any particular host or tool. Before relying on one, check:

  • which WordPress version it installs (some lag behind the latest release), and that it uses the latest default theme rather than a bundle of extra plugins and themes you will have to remove;

  • the administrator user name and table prefix it chooses, and whether you can set them;

  • that the keys and salts in wp-config.php were generated, not left as the placeholder phrase;

  • whether it later updates WordPress itself, possibly competing with core’s own automatic updates (see Updates and Auto-Updates).

WordPress.com is a different product from these installers: it is a hosted service run by one company, while every route on this page installs self-hosted WordPress from WordPress.org.

Installing in another language

There are three ways to get WordPress in a language other than English:

  • A localized package, downloaded from the language’s WordPress.org site (for example es.wordpress.org) or with wp core download --locale=es_ES. It sets the language from the start and its installer is already translated.

  • The installer’s language picker. Since WordPress 4.0 the first screen of the English package lists every available translation; the chosen language pack is downloaded and installed automatically.

  • After installation, under Settings > General > Site Language (since 4.1 language packs are downloaded from the dashboard). Each user can override it under Users > Profile > Language. On Multisite the network default is set in Network Admin > Settings.

The setting is stored in the WPLANG option. Defining a WPLANG constant in wp-config.php is the pre-4.0 method and is no longer used. With WP-CLI:

wp language core install es_ES --activate
wp option get WPLANG
wp site switch-language en_US      # back to English

On the test install, the first command downloaded es_ES.zip for 7.1.3 from downloads.wordpress.org, printed "Success: Installed 1 of 1 languages.", and wp option get WPLANG returned es_ES.

Translations of plugins and themes are separate language packs (wp language plugin install, wp language theme install); how a plugin such as lumen-catalog becomes translatable is covered in Internationalization.

Giving WordPress its own directory

Some sites keep the core files in a sub-directory (/wp/) while the site itself is served from the root, which keeps the root of the web space tidy and lets a deployment replace wp/ as a unit. Two settings make this work:

For an existing install (Method II of the official guide): set both addresses in Settings > General (the site shows errors until the next steps are done), move the core files into wp/, copy index.php and .htaccess from wp/ back to the root, change the require line of the root index.php, log in at /wp/wp-admin/ and re-save Settings > Permalinks. The root index.php of Lumen Press then reads:

<?php
/**
 * Front controller in the web root; WordPress core lives in ./wp.
 */
define( 'WP_USE_THEMES', true );

require __DIR__ . '/wp/wp-blog-header.php';

For a new install, the same layout is easier from WP-CLI:

wp core download https://wordpress.org/wordpress-7.1.3.zip --path=wp
cp wp/index.php index.php
sed -i "s#/wp-blog-header.php#/wp/wp-blog-header.php#" index.php
wp config create --path=wp --dbname=lumen_press --dbuser=lumen --dbpass="$LUMEN_DB_PASSWORD" --dbprefix=lp_ --dbcharset=utf8mb4
mv wp/wp-config.php wp-config.php     # one level above core, found automatically
wp core install --path=wp --url=https://lumenpress.example --title="Lumen Press" \
  --admin_user=lp_admin --admin_email=webmaster@lumenpress.example --skip-email
wp option update siteurl https://lumenpress.example/wp --path=wp
wp option get home --path=wp          # https://lumenpress.example

In the test of this layout the front page answered at / with its assets under /wp/wp-includes/, and the login screen at /wp/wp-login.php. wp-content stays inside wp/ unless it is moved with WP_CONTENT_DIR and WP_CONTENT_URL (see wp-config.php Reference); a setup that also keeps themes and plugins out of the core directory is the usual basis for Composer-managed sites. Method I of the official guide keeps the URL at the root and maps it to the sub-directory with web-server rewrites instead; the Apache and nginx rules are in Web Servers: Apache and nginx. Multisite in a sub-directory needs WordPress 3.5 or later.

Common installation errors

Symptom Usual cause Fix

"Error establishing a database connection"

Wrong DB_NAME, DB_USER, DB_PASSWORD or DB_HOST; the user has no privileges on the database, or exists only for another host ('lumen'@'localhost' versus a container address); the database server is down.

Test the same credentials with the mysql/mariadb client from the web server; check the GRANT; check DB_HOST, including port or socket. wp db check reproduces the error from the shell.

A directory listing instead of the site

The web server does not use index.php as the index file.

Apache: DirectoryIndex index.php in the virtual host or .htaccess; nginx: index index.php;.

The PHP source code is displayed or downloaded

PHP is not installed or not connected to the web server.

Install PHP-FPM or the PHP module and route .php files to it.

"Warning: Cannot modify header information - headers already sent"

Output before <?php or after a closing ?> in wp-config.php, or a UTF-8 BOM.

Remove the stray bytes, drop the closing tag, save without BOM.

"Your PHP installation appears to be missing the MySQL extension"

The mysqli extension is not enabled.

Install and enable mysqli (for example the php8.3-mysql package).

setup-config.php cannot write wp-config.php

The WordPress directory is not writable by the PHP user.

Paste the displayed content into wp-config.php by hand; do not loosen permissions to 777.

"Already Installed" after re-running the installer

The tables with the configured prefix already exist.

Use another $table_prefix, or drop the tables to reinstall (wp db reset on a disposable copy).

WP-CLI: "Allowed memory size …​ exhausted"

PHP CLI memory_limit too low for the operation.

php -d memory_limit=512M "$(command -v wp)" core download, or raise it in the CLI php.ini.

WP-CLI: "Undefined array key HTTP_HOST"

Code that reads $_SERVER values a CLI run does not set; core itself emits it when wp core is-installed runs before the install.

Pass --url=; in custom wp-config.php code, guard $_SERVER reads with isset().

wp core verify-checksums reports missing files

Incomplete upload or extraction.

Download again (the .zip package, or another extraction tool) and verify again.

Further problems after a successful install, such as the white screen of death, redirect loops or lost administrator access, are covered in Debugging, Site Health and Troubleshooting.

After installing

A fresh install still needs its settings reviewed (Settings Screens), a permalink structure (Lumen Press uses /%postname%/, see Rewrite API and Permalinks), the sample post, page and comment removed, hardening (Security Hardening) and backups (Backups and Disaster Recovery). The PHP background, including Composer, is in Composer and Packages, and container tooling in Compose for Local Development. Installing WooCommerce is covered in Installation and Local Environments, not here.