Install WordPress on Ubuntu Server with Apache, MySQL & PHP
I’ll be honest with you, my first attempt at installing WordPress on an Ubuntu server was a complete disaster. I thought it would be simple, but I ended up staring at error messages for three straight hours. The PHP version didn’t match what WordPress wanted, MySQL kept refusing connections, and don’t even get me started on the file permission nightmare I created.
After breaking and rebuilding my test server more times than I care to admit, I finally figured out a process that actually works. Now I can set up WordPress on Ubuntu without wanting to throw my laptop out the window.
If you’re looking to get WordPress running on your Ubuntu server, this guide will walk you through everything I learned the hard way. I’ve tested this on Ubuntu 20.04, 22.04, and recently on 24.04 – all with the same reliable results.
Here’s what we’ll cover:
- Getting the LAMP stack running (that’s Linux, Apache, MySQL, and PHP if you’re new to this)
- Setting up MySQL without the usual database headaches
- Installing WordPress files and getting the permissions right
- Adding SSL so your site is secure from day one
- Some performance tweaks and security steps I wish I’d known earlier
Whether this is your first WordPress site or you’re just tired of hosting companies charging too much, this guide should get you up and running without the frustration I went through.
Prerequisites To Install WordPress With Your Ubuntu Root
Okay, before we start typing commands, let me save you from the mistakes I made. The first time I tried this, I jumped straight into installing stuff without checking if my server was actually ready. Big mistake.
Here’s what you need to have sorted before we begin:
- Ubuntu Server Running: I’ve done this on Ubuntu 20.04, 22.04, and the newer 24.04. They all work pretty much the same way. If you’re setting up a new server, go with 22.04 or 24.04 – they’ll get security updates for longer.
- Admin Access: You need either root access or a user account that can run sudo commands. If you can’t install software or edit system files, this whole process won’t work.
- Domain Name: This isn’t absolutely necessary – WordPress will work fine with just your server’s IP address. But having a domain makes everything easier later on, especially when you want to add SSL certificates.
- Some Command Line Experience: Look, you don’t need to be a Linux expert. But if you’ve never used commands like
cd
to change directories ornano
to edit files, maybe spend 30 minutes getting familiar with the basics first. It’ll save you headaches. - Network Stuff: Make sure your server can actually reach the internet, and that ports 80 and 443 are open. If you’re using Ubuntu’s firewall (UFW), you’ll need to allow these ports. I forgot about this once and spent an hour wondering why nothing was working.
- Quick Reality Check: Before moving on, just double-check: Can you SSH into your server? Can you run
sudo apt update
without errors? Do you have a domain pointing to your server’s IP? If something’s not right, fix it now rather than later.
I learned this the hard way – skipping these basics led to me rebuilding my entire server setup twice. Don’t be like past me.
Choosing the Stack: LAMP or LEMP
Alright, before we start installing stuff, there’s one thing you need to decide: do you want to use Apache or Nginx as your web server? I know, I know – more decisions when you just want WordPress running.
Here’s the deal. Most tutorials you’ll find online use what’s called a LAMP stack – that’s Linux, Apache, MySQL, and PHP. Apache has been the go-to web server for ages, and there’s a reason for that. It just works, and when something breaks, there are thousands of forum posts to help you fix it.
But there’s also something called LEMP, which swaps Apache for Nginx (they pronounce it “engine-x” for some reason). Nginx is faster, especially if you’re expecting lots of visitors. The thing is, it’s also a bit more finicky to configure.
When I started out, I went with Apache because honestly, I was scared of messing around with Nginx configuration files. Apache worked fine for my small blog. But later, when I was hosting a client’s site that got more traffic, I noticed the server was struggling a bit. Switched to Nginx and saw a pretty decent speed improvement.
The trade-off is that Apache is way more forgiving. With Nginx, if you mess up a config file, your site just stops working. With Apache, you can usually get away with small mistakes.
For this guide, I’m going to stick with Apache since it’s more beginner-friendly. If you’re feeling adventurous or you know you’ll need the extra performance, I can point you toward some Nginx resources later. But honestly? Start with Apache. You can always switch later if you need to. WordPress doesn’t care which one you use – it’ll run happily on either.
Step 1: System Update & Initial Setup
Okay, first things first – update your server. I know it seems boring, but trust me on this one. The very first time I tried installing WordPress, I skipped the updates because I was eager to get started. Big mistake. I spent the next two hours dealing with weird errors because some of my packages were out of date and didn’t play nice with the new stuff I was trying to install. Now I always update first, even if it takes a few extra minutes.
Update and Upgrade Your OS Packages
Run these commands:
sudo apt update && sudo apt upgrade -y
apt update
refreshes the list of available packages.apt upgrade
installs the latest versions of everything already on your server.
This ensures you’re not trying to install WordPress on a half-baked system with outdated libraries.
Install Some Basic Utilities
These little tools will save you time later:
sudo apt install curl wget unzip nano -y
- curl/wget: for downloading files
- unzip: to extract WordPress archives
- nano: simple text editor (trust me, editing configs in nano is easier than vim if you’re new)
Optional: Set Timezone and Locale
If you want your server logs and cron jobs to match your local time, set it now:
sudo timedatectl set-timezone YOUR_TIMEZONE
Example:
sudo timedatectl set-timezone Europe/Copenhagen
Basic Firewall Setup (UFW)
If you’re running Ubuntu’s firewall, make sure HTTP (port 80) and HTTPS (port 443) are open:
sudo ufw allow OpenSSH
sudo ufw allow 'Apache Full'
sudo ufw enable
I once forgot this step and spent an hour wondering why my fresh WordPress install wouldn’t load in the browser. Don’t be me open the ports.
Step 2: Install Apache (or Nginx) Web Server
Alright, now we need to get web server running. This is basically what’s going to actually show your website to people when they visit your domain. Without a web server, WordPress is just a bunch of files sitting there that nobody can see – like having a store with no front door.
Option 1: Apache (LAMP Stack)
If this is your first WordPress setup, Apache is the safer choice. It’s beginner-friendly, well-documented, and works perfectly with WordPress.
Run:
sudo apt install apache2 -y
Once installed, enable it to start automatically at boot:
sudo systemctl enable apache2
sudo systemctl start apache2
Check if it’s running:
sudo systemctl status apache2
If you see “active (running),” congrats Apache is alive. You can even visit your server’s IP address in a browser and you should see the default Apache welcome page.
Pro Tip: Don’t forget to enable mod_rewrite
. WordPress uses it for “pretty permalinks”:
sudo a2enmod rewrite
sudo systemctl restart apache2
Option 2: Nginx (LEMP Stack)
If you’re after better performance, Nginx is a solid pick. It handles more traffic with fewer resources, but requires a bit more configuration.
Install it with:
sudo apt install nginx -y
Enable and start Nginx:
sudo systemctl enable nginx
sudo systemctl start nginx
Check status:
sudo systemctl status nginx
Like Apache, you can test it by visiting your server’s IP in a browser you should see the Nginx default landing page.
Which One Should You Use?
Honestly? If you’re new to this stuff, just use Apache. Every WordPress tutorial on the planet assumes you’re using Apache, so when you run into problems, the solutions are easier to find.
Nginx is faster, but it’s also more likely to make you pull your hair out if you’re just starting. You can always switch later if you need the extra speed. Once we get this installed, your server will finally be able to serve up actual web pages instead of just sitting there.
Step 3: Install MySQL (Database Server)
Okay, so Apache is running – now we need somewhere for WordPress to actually store stuff. All your blog posts, user accounts, settings, comments – that all has to live in a database.
Most tutorials use either MySQL or MariaDB. They’re basically the same thing for what we’re doing, so don’t stress about the choice. I’m going to use MySQL because that’s what I’m used to, but MariaDB works just as well if you prefer it.
Install MySQL On Ubuntu Server
Run:
sudo apt install mysql-server -y
Once installed, check the status:
sudo systemctl status mysql
If it says “active (running),” you’re good.
Secure the Installation
This is one of those steps that I skipped early on… and regretted when I realized my test database was wide open. Don’t skip it.
Run the security script:
sudo mysql_secure_installation
You’ll be asked a series of questions. Here’s what I usually do:
- VALIDATE PASSWORD PLUGIN? → I usually say Y (helps enforce strong passwords).
- Remove anonymous users? → Y
- Disallow root login remotely? → Y
- Remove test database? → Y
- Reload privilege tables? → Y
Now you’ve got a clean and secure database environment.
Create a Database for WordPress
Now let’s actually give WordPress its own database and user.
Log in to MySQL:
sudo mysql
Inside the MySQL shell, run these commands (swap your_db_name
, your_user
, and your_password
with your own values):
CREATE DATABASE wordpress_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'StrongPasswordHere';
GRANT ALL PRIVILEGES ON wordpress_db.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Now you’ve got:
- A database called
wordpress_db
- A user
wp_user
with full access to it - A strong password that WordPress will use later
Quick Sanity Check
I once forgot to create a proper user and tried to connect WordPress with the MySQL root account. Bad idea. Always create a dedicated user just for WordPress it’s safer and easier to manage.
Step 4: Install PHP and Required Extensions
Okay, we’ve got Apache and MySQL running, but we’re still missing the most important piece: PHP. WordPress is written in PHP, so without it, you’re basically just hosting a bunch of files that don’t do anything.
When I first did this setup, I installed PHP but completely forgot about all the extensions WordPress needs. Spent the next hour staring at blank white screens wondering what I broke. Learn from my mistake – just install everything you need right from the start.
Install PHP On Ubuntu Root
Run this command to install PHP and all the extensions WordPress loves:
sudo apt install php php-mysql php-xml php-gd php-curl php-mbstring php-zip php-intl -y
Here’s what some of those do:
- php-mysql → lets PHP talk to your MySQL database
- php-xml → handles WordPress’s XML needs (themes/plugins rely on this)
- php-gd → for image manipulation (think thumbnails, image resizing)
- php-curl → used by plugins and updates
- php-mbstring → handles multibyte strings (important for non-English sites)
- php-zip → required for installing plugins/themes via dashboard
- php-intl → helps with translations and localization
Check PHP Version
Run:
php -v
You should see something like:
PHP 8.1.x (cli) (built: ...)
WordPress recommends PHP 7.4 or higher, but honestly, I’d go with PHP 8.1 or 8.2 if your Ubuntu version supports it it’s faster and more secure.
Configure PHP (Optional but Helpful)
Sometimes WordPress needs a little more breathing room. You can tweak the PHP settings by editing php.ini
:
sudo nano /etc/php/8.1/apache2/php.ini
Look for these lines and bump them up if you’re planning to upload big themes/plugins:
memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
Save, then restart Apache or PHP-FPM (if using Nginx):
sudo systemctl restart apache2
# or
sudo systemctl restart php8.1-fpm
Okay, so we’ve got the whole stack running now. Apache is serving web pages, MySQL is ready to store data, and PHP can actually run WordPress code. We’re finally ready to get WordPress itself installed.
Step 5: Download & Configure WordPress
Okay, this is the part I was excited about when I first started – actually putting WordPress on the server. But man, did I mess this up the first time. So I downloaded WordPress, right? And I was so eager to get it working that I just threw the files wherever seemed convenient. Big mistake.
Spent like an hour refreshing my browser wondering why I kept getting “page not found” errors. Turns out I put everything in the wrong directory. Let me walk you through doing it the right way so you don’t have to deal with that frustration.
Download the Latest WordPress Package
Go to your web root directory:
cd /var/www/html
Download WordPress:
wget https://wordpress.org/latest.tar.gz
Extract it:
tar -xvzf latest.tar.gz
This will create a folder called wordpress
inside /var/www/html
.
Move Files to the Right Place
If you want WordPress to load directly when someone visits your domain (not at /wordpress
), move the files into /var/www/html
:
sudo mv wordpress/* /var/www/html/
Then clean up:
rm -rf wordpress latest.tar.gz
Set Correct Permissions
This is the step I used to mess up the most. Wrong permissions mean WordPress can’t upload themes or update plugins.
Run:
sudo chown -R www-data:www-data /var/www/html/
sudo find /var/www/html/ -type d -exec chmod 755 {} \;
sudo find /var/www/html/ -type f -exec chmod 644 {} \;
www-data
is the user Apache/Nginx runs as.- Directories get 755 (read/execute for everyone, write for owner).
- Files get 644 (read for everyone, write for owner).
Create wp-config.php
WordPress comes with a sample config file. Copy it and edit:
cp /var/www/html/wp-config-sample.php /var/www/html/wp-config.php
nano /var/www/html/wp-config.php
Find these lines and replace with the database details you created earlier:
define( 'DB_NAME', 'wordpress_db' );
define( 'DB_USER', 'wp_user' );
define( 'DB_PASSWORD', 'StrongPasswordHere' );
define( 'DB_HOST', 'localhost' );
Bonus: Add security salts (unique keys) by generating them at WordPress.org secret key service pasting them into wp-config.php
.
Step 6: Configure Apache Virtual Host
Alright, so we’ve got Apache running, PHP installed, and WordPress files sitting on the server. But here’s the thing – Apache has no clue what to do with any of it yet. Right now if you visit your domain, you’re probably just seeing that boring “It works!” page.
I remember being so confused about this part. I had everything installed and I kept typing in my domain name expecting to see WordPress. Instead, just that stupid default Apache page over and over. I must have cleared my browser cache like ten times thinking that would magically fix it.
Turns out you have to actually tell Apache where your website files are and which domain they belong to. That’s what this virtual host thing is all about – it’s basically Apache’s instruction manual for your specific site.
Create a New Virtual Host File
Run:
sudo nano /etc/apache2/sites-available/wordpress.conf
Paste in something like this (replace yourdomain.com
with your actual domain or server IP):
<VirtualHost *:80>
ServerAdmin admin@yourdomain.com
ServerName yourdomain.com
ServerAlias www.yourdomain.com
DocumentRoot /var/www/html
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/wordpress_error.log
CustomLog ${APACHE_LOG_DIR}/wordpress_access.log combined
</VirtualHost>
Enable the New Site & Rewrite Module
Run these commands:
sudo a2ensite wordpress.conf
sudo a2enmod rewrite
sudo systemctl restart apache2
This does two things:
- a2ensite tells Apache to actually use your new config.
- a2enmod rewrite enables WordPress-friendly permalinks.
Disable the Default Site (Optional)
If you don’t want the default Apache page interfering, disable it:
sudo a2dissite 000-default.conf
sudo systemctl reload apache2
Test It Out
Open your browser and visit http://yourdomain.com
(or your server IP if you don’t have a domain yet). If everything’s set up right, you should see the WordPress installation screen.
If you don’t see it, double-check that:
- Your DNS is pointing to the server
- Firewall ports 80/443 are open
- The virtual host file syntax is correct (
apachectl configtest
can help)
Step 7: Configure wp-config.php & Connect WordPress to the Database
Okay, so WordPress is on the server and Apache knows where to find it. But we’re not done yet. Right now, WordPress has no idea how to connect to that MySQL database we set up earlier.
If you try visiting your site now, you’ll probably get this lovely error message: “Error establishing a database connection.” God, I hate that error. I swear I must have seen it like fifty times when I was figuring this out. Every time I thought I had it working, boom – database connection error again.
The problem is WordPress doesn’t magically know your database password or even which database to use. We have to tell it all that stuff manually by editing this config file.
Open the wp-config File
If you followed Step 5, you should already have a wp-config.php
file inside /var/www/html/
. If not, create one by copying the sample:
cd /var/www/html
cp wp-config-sample.php wp-config.php
nano wp-config.php
Add Your Database Details
Scroll down until you see these lines:
define( 'DB_NAME', 'database_name_here' );
define( 'DB_USER', 'username_here' );
define( 'DB_PASSWORD', 'password_here' );
define( 'DB_HOST', 'localhost' );
Replace them with the credentials you created earlier in Step 3:
define( 'DB_NAME', 'wordpress_db' );
define( 'DB_USER', 'wp_user' );
define( 'DB_PASSWORD', 'StrongPasswordHere' );
define( 'DB_HOST', 'localhost' );
DB_NAME
= your WordPress database (e.g.,wordpress_db
)DB_USER
= the MySQL user you created (e.g.,wp_user
)DB_PASSWORD
= the strong password you assignedDB_HOST
= usuallylocalhost
Add Security Keys (Salts)
WordPress uses security keys and salts to make your site more secure. Instead of using the defaults, grab fresh keys from the official WordPress API:
curl -s https://api.wordpress.org/secret-key/1.1/salt/
Copy the output and paste it into the corresponding section of wp-config.php
. It’ll look like this:
define('AUTH_KEY', 'random-key-here');
define('SECURE_AUTH_KEY', 'random-key-here');
define('LOGGED_IN_KEY', 'random-key-here');
define('NONCE_KEY', 'random-key-here');
define('AUTH_SALT', 'random-key-here');
define('SECURE_AUTH_SALT', 'random-key-here');
define('LOGGED_IN_SALT', 'random-key-here');
define('NONCE_SALT', 'random-key-here');
This makes it much harder for attackers to hijack sessions.
Optional: Set Table Prefix
If you want extra security, change the default table prefix:
$table_prefix = 'wp_';
to something like:
$table_prefix = 'wpx9_';
It doesn’t stop hackers completely, but it makes automated attacks harder.
Save & Exit
Once you’ve updated everything, save and close the file (CTRL+O
, Enter
, CTRL+X
in nano).
Step 8: Enable SSL Certificate (HTTPS)
Alright, your WordPress site is working, but we’re not quite done. If you visit your site right now, your browser is probably showing that “Not Secure” warning in the address bar. Yeah, that’s not a good look.
I made this mistake on my first site. I got WordPress running and was so excited that I figured I’d deal with the SSL stuff later. Bad idea. Within like a week, I noticed that scary “Not Secure” message every time I visited my own site. Plus Google apparently cares about this stuff for rankings now.
Luckily, getting HTTPS working isn’t as complicated as it used to be. There’s this thing called Let’s Encrypt that basically gives you free SSL certificates, and it’s actually pretty straightforward to set up.
Install Certbot (Let’s Encrypt Client)
On Ubuntu, install Certbot and the Apache plugin:
sudo apt install certbot python3-certbot-apache -y
If you’re using Nginx:
sudo apt install certbot python3-certbot-nginx -y
Request a Free SSL Certificate
For Apache:
sudo certbot --apache -d yourdomain.com -d www.yourdomain.com
For Nginx:
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
- Replace
yourdomain.com
with your actual domain. - Certbot will automatically configure Apache/Nginx for HTTPS.
- When asked, choose the option to redirect all traffic to HTTPS.
Test Auto-Renewal
Let’s Encrypt certificates expire every 90 days, but Certbot sets up auto-renew. Test it with:
sudo certbot renew --dry-run
If you see “Congratulations, all renewals succeeded,” you’re set.
My Pro Tip For You
Oh, one thing I should mention – if you’re just testing this on a server without a real domain name, Let’s Encrypt won’t work. It needs an actual domain to verify you own the site.
When I was testing stuff out, I ran into this problem. You’ve got a couple options if you’re in the same boat:
- You can create what’s called a self-signed certificate, but honestly, that’s more trouble than it’s worth unless you really know what you’re doing. Your browser will still complain that the site isn’t secure.
- What I ended up doing was setting up a subdomain just for testing – something like test.mydomain.com – and pointing that at my test server. Then Let’s Encrypt worked fine.
Once you get SSL working though, you’re golden. Your site will show that little lock icon, Google will stop penalizing you for not having HTTPS, and you won’t have to worry about this stuff anymore.
Step 9: Complete the WordPress Installation Wizard
Okay, this is it. We’ve got Apache running, MySQL ready to go, PHP installed, and all the WordPress files where they need to be. Plus we even got that SSL certificate working. Time for the moment of truth – actually setting up WordPress.
I’m not gonna lie, the first time I got to this point, I was kind of nervous. After spending hours messing around with server config files and database passwords, I half expected something else to break. But when I typed in my domain and saw that WordPress welcome screen load up… man, that was a good feeling. Like finally getting to the end of a really long, frustrating puzzle.
Step 9.1: Open the Installer in Your Browser
Go to your domain (or server IP if you skipped the domain setup):
https://yourdomain.com
If everything is set correctly, you’ll be greeted by the WordPress installation wizard.
Step 9.2: Select Your Language
The first screen asks you to choose a language. Pick your preferred language (English, Bengali, Danish whatever you want your WordPress dashboard in) and click Continue.
Step 9.3: Site Information & Admin Account
Next, you’ll see a form asking for:
- Site Title → This will be the name of your site (don’t worry, you can change it later).
- Username → Choose something other than “admin” (hackers love that).
- Password → Use a strong one (WordPress will even warn you if it’s weak).
- Your Email → Used for password resets and notifications.
- Search Engine Visibility → Leave unchecked if this is a live site. (Check it if you’re just testing and don’t want Google indexing it yet.)
Click Install WordPress.
Step 9.4: Login to the Dashboard
After a few seconds, WordPress will confirm the installation and give you a Log In button. Click it, enter your username and password, and… boom! You’re in the famous WordPress dashboard.
Step 9.5: First Things to Do After Install
Here’s what I usually do right away (so I don’t forget later):
- Change Permalink Settings → Go to Settings > Permalinks and switch from the ugly
?p=123
URLs to something clean like “Post Name.” - Delete sample content → Remove the “Hello World” post and sample page.
- Update everything → Make sure WordPress core, plugins, and themes are up to date.
Congratulations! You now have a fully functional WordPress site running on your Ubuntu server.