How to Install WordPress on an Ubuntu Server
Install WordPress on your own VPS: database, files, permissions, virtual host, SSL and security keys — plus an honest look at whether it beats shared hosting.
Installing WordPress on your own Ubuntu server takes about thirty minutes and gives you full control: your own PHP settings, no neighbours slowing you down, and no host deciding what you may install.
It also makes you the system administrator. Before you start, it is worth being honest about whether that trade is right for you.
Is this better than shared hosting?
| Your own VPS | Shared hosting | |
|---|---|---|
| Speed | Much faster | Depends on neighbours |
| Control | Complete | Whatever cPanel allows |
| Security updates | Your job | Host handles the server |
| When it breaks at 2am | Your problem | Their support |
| Cost | $5–10 / month | $3–5 / month |
Choose a VPS if you want to learn server administration, run several sites, or need settings shared hosting will not give you.
Choose shared hosting if the site matters commercially and you do not want to be responsible for patching the operating system. That is a perfectly reasonable answer — see the cPanel route instead.
Before you start
You need a working LAMP stack. If you do not have one, follow how to install a LAMP server on Ubuntu first — it covers creating a non-root user and setting the firewall, both of which matter here.
You also need a domain already pointing at the server IP. Check:
dig +short yourdomain.com
Step 1: Install the PHP extensions WordPress needs
A base LAMP install is not enough. Missing extensions cause blank pages and broken media uploads.
sudo apt update
sudo apt install php-curl php-gd php-mbstring php-xml php-zip php-intl php-imagick -y
sudo systemctl restart apache2
Step 2: Create the database
sudo mysql
CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL ON wordpress.* TO 'wpuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Use utf8mb4. Without it, emoji and non-Latin characters in posts break.
Step 3: Download WordPress
cd /tmp
curl -O https://wordpress.org/latest.tar.gz
tar xzvf latest.tar.gz
sudo mkdir -p /var/www/yourdomain.com
sudo cp -a /tmp/wordpress/. /var/www/yourdomain.com/
The -a flag copies hidden files too. Plain cp -r misses .htaccess, which then breaks permalinks in a way that is hard to trace.
Step 4: Set the permissions correctly
This step causes more trouble than any other, and the usual bad advice is to run chmod 777. Never do that — it lets any user on the server write to your site.
sudo chown -R www-data:www-data /var/www/yourdomain.com
sudo find /var/www/yourdomain.com -type d -exec chmod 755 {} \;
sudo find /var/www/yourdomain.com -type f -exec chmod 644 {} \;
That gives directories 755 and files 644, which is what WordPress actually wants. Apache runs as www-data, so it can write uploads and update plugins, and nobody else can.
Step 5: Apache virtual host
sudo nano /etc/apache2/sites-available/yourdomain.com.conf
<VirtualHost *:80>
ServerName yourdomain.com
ServerAlias www.yourdomain.com
DocumentRoot /var/www/yourdomain.com
<Directory /var/www/yourdomain.com>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/yourdomain_error.log
CustomLog ${APACHE_LOG_DIR}/yourdomain_access.log combined
</VirtualHost>
AllowOverride All is essential. Without it WordPress ignores .htaccess and every page except the homepage returns 404.
sudo a2ensite yourdomain.com.conf
sudo a2dissite 000-default.conf
sudo a2enmod rewrite
sudo apache2ctl configtest
sudo systemctl restart apache2
Step 6: SSL before the installer
Do this now, not later. Installing WordPress over HTTP stores http:// URLs in the database and you then have to clean them out.
sudo apt install certbot python3-certbot-apache -y
sudo certbot --apache -d yourdomain.com -d www.yourdomain.com
Say yes to the HTTPS redirect. Details in the SSL guide.
Step 7: Configure wp-config.php
cd /var/www/yourdomain.com
sudo cp wp-config-sample.php wp-config.php
sudo nano wp-config.php
Set the database details:
define( 'DB_NAME', 'wordpress' );
define( 'DB_USER', 'wpuser' );
define( 'DB_PASSWORD', 'your-password' );
define( 'DB_HOST', 'localhost' );
The security keys — do not skip this
Further down is a block of "Authentication Unique Keys and Salts" full of placeholder text. These encrypt login cookies. Left as the default, session hijacking becomes far easier.
Generate real ones:
curl -s https://api.wordpress.org/secret-key/1.1/salt/
Replace the whole placeholder block with what that returns.
Two more worth adding
define( 'DISALLOW_FILE_EDIT', true );
define( 'WP_DEBUG', false );
The first removes the plugin and theme file editor from wp-admin. If an attacker gets into your dashboard, that editor is how a site turns into a permanent back door.
Step 8: Run the installer
Open https://yourdomain.com:
- Site title
- Username — not "admin". Every bot tries that first.
- Password — long and random
- Email — one you actually read
Then log in at /wp-admin and immediately set Settings → Permalinks → Post name.
Step 9: Server-side hardening
Four things shared hosting would normally do for you:
Protect wp-config.php
<Files wp-config.php>
Require all denied
</Files>
Add that to .htaccess in the site root.
Stop PHP running inside uploads
Create /var/www/yourdomain.com/wp-content/uploads/.htaccess:
<FilesMatch "\.php$">
Require all denied
</FilesMatch>
If someone ever uploads a PHP file through a plugin vulnerability, this stops it executing.
Automatic security updates
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades
Set up backups
Database and the wp-content folder, both. Nobody else is doing this for you now.
mysqldump -u wpuser -p wordpress > ~/wp-backup-$(date +%F).sql
Common problems
"Error establishing a database connection"
Wrong credentials in wp-config.php, or MySQL is not running. Test the login directly:
mysql -u wpuser -p wordpress
Every page except the homepage returns 404
AllowOverride All is missing from the virtual host, or mod_rewrite is not enabled. Both are needed. Then re-save permalinks.
WordPress asks for FTP details when installing a plugin
It cannot write to its own folders. Fix ownership:
sudo chown -R www-data:www-data /var/www/yourdomain.com
Media uploads fail
Either permissions on wp-content/uploads, or PHP limits. Raise upload_max_filesize and post_max_size in php.ini and restart Apache.
The white screen of death
A PHP fatal error. Read the real cause:
sudo tail -f /var/log/apache2/yourdomain_error.log
See the whitelabel error guide.
The site is slow
A default Apache and PHP setup is not tuned. Add a caching plugin and consider switching PHP to FPM. See how to increase WordPress speed.
Where to go next
- Building the site itself — themes, pages, plugins
- Speed and Core Web Vitals
- Moving an existing site onto this server
- SEO setup