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") |
|
Shared hosting with FTP or a file manager, first-time users |
WP-CLI ( |
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.
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.
Source: WordPress.org: Requirements
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>');
Source: WordPress.org secret-key service
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 showwp-config.phpending 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
<?phpon the first line. -
ABSPATHis computed from__DIR__and must not be edited. WordPress findswp-config.phpin the WordPress directory or one level above it on its own; moving it there does not require changingABSPATH, 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:
-
asks for the language of the install (when the package is the default English one and WordPress.org is reachable);
-
asks for the database name, user name, password, database host and table prefix;
-
tests the connection, fetches the keys from the secret-key service, and writes
wp-config.phpif 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 |
Username |
The first administrator’s login. It cannot be changed later from the dashboard, so avoid |
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 ( |
Search engine visibility |
"Discourage search engines from indexing this site" sets |
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
Source: WP-CLI Handbook: Installing
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
Source: WP-CLI Commands: wp core
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
Source: WP-CLI Commands: wp core install
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 |
|---|---|
|
|
|
|
|
Creates the database named in |
|
|
|
Exit status 0 if the tables exist, 1 otherwise; the building block of idempotent provisioning scripts. |
|
Compares every core file with the checksums published by WordPress.org. |
|
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, andwp core downloadran out of memory while extracting WordPress 7.1.3 ("Allowed memory size of 134217728 bytes exhausted"). Calling the PHAR throughphp -d memory_limit=512Mfixes 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.gzpackage truncated a few long file names underwp-includes/php-ai-client/, andwp core verify-checksumsfailed. Passing the.zipURL as<download-url>produced a clean tree ("Success: WordPress installation verifies against checksums."). Whatever the download method, runwp core verify-checksumsafter 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.phpwere 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 withwp 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:
-
WordPress Address (URL), the
siteurloption: where the core files live,https://lumenpress.example/wp. -
Site Address (URL), the
homeoption: what visitors type,https://lumenpress.example.
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 |
Test the same credentials with the |
A directory listing instead of the site |
The web server does not use |
Apache: |
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 |
"Warning: Cannot modify header information - headers already sent" |
Output before |
Remove the stray bytes, drop the closing tag, save without BOM. |
"Your PHP installation appears to be missing the MySQL extension" |
The |
Install and enable |
|
The WordPress directory is not writable by the PHP user. |
Paste the displayed content into |
"Already Installed" after re-running the installer |
The tables with the configured prefix already exist. |
Use another |
WP-CLI: "Allowed memory size … exhausted" |
PHP CLI |
|
WP-CLI: "Undefined array key HTTP_HOST" |
Code that reads |
Pass |
|
Incomplete upload or extraction. |
Download again (the |
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.