Database User Privileges (WordPress VPS)
WordPress needs a database user with enough privileges to create and modify tables during installs and updates, but it should not run as a full admin user. Use least privilege: a dedicated WordPress DB user scoped to the WordPress database. This reduces the impact of compromised credentials and prevents accidental admin operations.
Create a dedicated user like 'wpuser'@'localhost', grant it privileges only on wordpress.*, then verify with SHOW GRANTS.
Do not use the database root user in wp-config.php. If WordPress is compromised, a root DB user makes the incident far worse.
Mental Model
Prerequisites
- Admin access to MySQL/MariaDB (typically
root). - Ability to run
mysqlcommands.
Common WordPress Privileges
WordPress typically needs privileges to read/write data and manage schema changes. Common privileges include:
SELECT,INSERT,UPDATE,DELETECREATE,DROP,ALTER,INDEXCREATE TEMPORARY TABLES,LOCK TABLES
Exact needs vary by plugins and tooling.
Examples (Commands + Expected Output)
Privileges and authentication plugins vary by MySQL/MariaDB version.
List database users (admin)
mysql -u root -p -e "SELECT user, host FROM mysql.user ORDER BY user, host;"
Expected output (excerpt):
user host
root localhost
wpuser localhost
Use case: Audit which accounts exist.
Show grants for the WordPress user
mysql -u root -p -e "SHOW GRANTS FOR 'wpuser'@'localhost';"
Expected output:
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX ON `wordpress`.* TO `wpuser`@`localhost`
Use case: Confirm least-privilege scope.
Create a dedicated WordPress user
mysql -u root -p -e "CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'REPLACE_ME_WITH_A_STRONG_PASSWORD';"
Expected output:
(no output on success)
Use case: Create a dedicated user for the application.
Grant WordPress privileges (scoped to one database)
mysql -u root -p -e "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX, CREATE TEMPORARY TABLES, LOCK TABLES ON wordpress.* TO 'wpuser'@'localhost';"
Expected output:
(no output on success)
Use case: Allow WordPress to install/update and operate normally.
Create a read-only user for reporting
mysql -u root -p -e "CREATE USER 'wpreadonly'@'localhost' IDENTIFIED BY 'REPLACE_ME'; GRANT SELECT ON wordpress.* TO 'wpreadonly'@'localhost';"
Expected output:
(no output on success)
Use case: Give a developer/reporting job safe read-only access.
Revoke privileges (cleanup)
mysql -u root -p -e "REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'wpuser'@'localhost';"
Expected output:
(no output on success)
Use case: Remove access when rotating credentials or decommissioning.
Avoid using 'wpuser'@'%' (any host) unless you really need remote connections. Prefer localhost or a specific host/IP.
WordPress VPS Use Cases
| Scenario | Recommended user | Why |
|---|---|---|
| Normal WP operation | wpuser@localhost | Limits blast radius |
| Scheduled reporting | wpreadonly@localhost | Prevents accidental writes |
| Migration tooling | Temporary user with required privileges | Rotate/remove after migration |
Troubleshooting
| Error | Likely cause | Fix |
|---|---|---|
Access denied | Wrong password or host mismatch | Confirm 'user'@'host' matches connection source |
| WP asks for FTP credentials | DB user OK, filesystem perms not | Check Linux ownership/permissions (separate topic) |
| Plugins fail to create tables | Missing schema privileges | Add CREATE/ALTER/INDEX on wordpress.* |
Best Practices
- Keep WordPress DB user scoped to a single database.
- Rotate DB passwords during incident response.
- Audit grants periodically with
SHOW GRANTS.
Cheat Sheet
-- list users
SELECT user, host FROM mysql.user;
-- show grants
SHOW GRANTS FOR 'wpuser'@'localhost';
-- create user
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'REPLACE_ME';
-- grant scoped privileges
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX, CREATE TEMPORARY TABLES, LOCK TABLES
ON wordpress.* TO 'wpuser'@'localhost';
-- revoke
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'wpuser'@'localhost';