342 lines
7.8 KiB
Markdown
342 lines
7.8 KiB
Markdown
---
|
|
title: "Install WordPress on a VPS"
|
|
description: "Set up WordPress on your Arcline VPS from scratch — LAMP or LEMP stack with PHP, MySQL, and Nginx or Apache."
|
|
section: wordpress
|
|
order: 2
|
|
---
|
|
|
|
# Install WordPress on a VPS
|
|
|
|
Installing WordPress on a VPS gives you full control over the server configuration, performance tuning, and security. This guide covers both a LEMP stack (Linux, Nginx, MySQL, PHP-FPM) and a LAMP stack (Linux, Apache, MySQL, PHP).
|
|
|
|
If you haven't set up your VPS yet, start with [Initial VPS Setup](/vps/initial-setup/).
|
|
|
|
---
|
|
|
|
## Choose your stack
|
|
|
|
| Stack | Web Server | Best for |
|
|
|---|---|---|
|
|
| **LEMP** | Nginx + PHP-FPM | High traffic, static caching, modern setups |
|
|
| **LAMP** | Apache + PHP | Simpler `.htaccess` support, beginner-friendly |
|
|
|
|
This guide covers the LEMP stack (Nginx) as the primary setup with LAMP (Apache) notes where they differ.
|
|
|
|
---
|
|
|
|
## Step 1 — Install the stack
|
|
|
|
### LEMP (Nginx)
|
|
|
|
```bash
|
|
sudo apt update
|
|
sudo apt install -y nginx mysql-server php-fpm php-mysql php-curl php-gd \
|
|
php-mbstring php-xml php-zip php-intl php-imagick unzip curl
|
|
```
|
|
|
|
### LAMP (Apache)
|
|
|
|
```bash
|
|
sudo apt update
|
|
sudo apt install -y apache2 mysql-server php libapache2-mod-php php-mysql \
|
|
php-curl php-gd php-mbstring php-xml php-zip php-intl php-imagick unzip curl
|
|
```
|
|
|
|
### Secure MySQL and create the database
|
|
|
|
```bash
|
|
sudo mysql_secure_installation
|
|
```
|
|
|
|
Follow the prompts — set a root password, remove anonymous users, disallow remote root login, remove test databases, and reload privileges.
|
|
|
|
Now create the WordPress database and user:
|
|
|
|
```bash
|
|
sudo mysql -u root -p
|
|
```
|
|
|
|
```sql
|
|
CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'a-strong-password-here';
|
|
GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'localhost';
|
|
FLUSH PRIVILEGES;
|
|
EXIT;
|
|
```
|
|
|
|
Replace `a-strong-password-here` with an actual strong password.
|
|
|
|
---
|
|
|
|
## Step 2 — Download and set up WordPress
|
|
|
|
```bash
|
|
cd /tmp
|
|
curl -O https://wordpress.org/latest.tar.gz
|
|
tar xzf latest.tar.gz
|
|
sudo mv wordpress /var/www/yourdomain.com
|
|
sudo chown -R www-data:www-data /var/www/yourdomain.com
|
|
```
|
|
|
|
---
|
|
|
|
## Step 3 — Configure Nginx (LEMP)
|
|
|
|
Create the Nginx site configuration:
|
|
|
|
```bash
|
|
sudo nano /etc/nginx/sites-available/yourdomain.com
|
|
```
|
|
|
|
```nginx
|
|
server {
|
|
listen 80;
|
|
server_name yourdomain.com www.yourdomain.com;
|
|
root /var/www/yourdomain.com;
|
|
index index.php index.html;
|
|
|
|
location / {
|
|
try_files $uri $uri/ /index.php?$args;
|
|
}
|
|
|
|
location ~ \.php$ {
|
|
include snippets/fastcgi-php.conf;
|
|
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
|
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
include fastcgi_params;
|
|
}
|
|
|
|
location = /favicon.ico { access_log off; log_not_found off; }
|
|
location = /robots.txt { access_log off; log_not_found off; }
|
|
|
|
# Block access to sensitive files
|
|
location ~* /\.(?!well-known\/) { deny all; }
|
|
location ~* /wp-config\.php { deny all; }
|
|
location ~* /xmlrpc\.php { deny all; }
|
|
|
|
# Cache static assets in the browser
|
|
location ~* \.(css|js|ico|gif|jpg|jpeg|png|webp|svg|woff2?|ttf|otf|eot)$ {
|
|
expires 1y;
|
|
add_header Cache-Control "public, immutable";
|
|
}
|
|
}
|
|
```
|
|
|
|
Enable the site and test the config:
|
|
|
|
```bash
|
|
sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/
|
|
sudo nginx -t
|
|
sudo systemctl reload nginx
|
|
```
|
|
|
|
Replace `php8.1-fpm.sock` with the PHP version you installed. Check your PHP version:
|
|
|
|
```bash
|
|
php -v
|
|
```
|
|
|
|
---
|
|
|
|
## Step 3 (alt) — Configure Apache (LAMP)
|
|
|
|
```bash
|
|
sudo nano /etc/apache2/sites-available/yourdomain.com.conf
|
|
```
|
|
|
|
```apache
|
|
<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>
|
|
</VirtualHost>
|
|
```
|
|
|
|
Enable and restart:
|
|
|
|
```bash
|
|
sudo a2ensite yourdomain.com.conf
|
|
sudo a2enmod rewrite
|
|
sudo systemctl reload apache2
|
|
```
|
|
|
|
---
|
|
|
|
## Step 4 — Set up SSL with Let's Encrypt
|
|
|
|
```bash
|
|
sudo apt install -y certbot python3-certbot-nginx
|
|
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
|
|
```
|
|
|
|
For Apache, use `python3-certbot-apache` instead.
|
|
|
|
Certbot modifies your Nginx/Apache config to add SSL automatically. Certificates renew automatically via a systemd timer — verify with:
|
|
|
|
```bash
|
|
sudo certbot renew --dry-run
|
|
```
|
|
|
|
---
|
|
|
|
## Step 5 — Complete the WordPress install
|
|
|
|
Visit `https://yourdomain.com` in your browser and complete the WordPress setup wizard. When prompted for database credentials, enter:
|
|
|
|
| Field | Value |
|
|
|---|---|
|
|
| Database Name | `wordpress` |
|
|
| Username | `wpuser` |
|
|
| Password | the password you set in Step 1 |
|
|
| Database Host | `localhost` |
|
|
| Table Prefix | `wp_` |
|
|
|
|
---
|
|
|
|
## Step 6 — Configure file permissions
|
|
|
|
WordPress needs write access to `wp-content/uploads` (for media) but the rest of your install should be read-only for the web server to prevent tampering.
|
|
|
|
```bash
|
|
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 {} \;
|
|
sudo chmod 640 /var/www/yourdomain.com/wp-config.php
|
|
```
|
|
|
|
---
|
|
|
|
## Step 7 — Configure PHP-FPM for WordPress
|
|
|
|
Edit the PHP-FPM pool config:
|
|
|
|
```bash
|
|
sudo nano /etc/php/8.1/fpm/pool.d/www.conf
|
|
```
|
|
|
|
Increase resource limits for a production WordPress site:
|
|
|
|
```ini
|
|
pm = dynamic
|
|
pm.max_children = 20
|
|
pm.start_servers = 5
|
|
pm.min_spare_servers = 5
|
|
pm.max_spare_servers = 10
|
|
pm.max_requests = 500
|
|
```
|
|
|
|
Adjust `pm.max_children` based on your VPS RAM: roughly `(available_RAM - 512MB) / 50MB` per child.
|
|
|
|
Apply changes:
|
|
|
|
```bash
|
|
sudo systemctl restart php8.1-fpm
|
|
```
|
|
|
|
---
|
|
|
|
## Step 8 — Set up a firewall
|
|
|
|
```bash
|
|
sudo ufw allow 22/tcp
|
|
sudo ufw allow 80/tcp
|
|
sudo ufw allow 443/tcp
|
|
sudo ufw enable
|
|
```
|
|
|
|
For stricter security, see [Set up fail2ban](/vps/fail2ban/).
|
|
|
|
---
|
|
|
|
## Step 9 — Configure WordPress cron properly
|
|
|
|
WordPress's default pseudo-cron runs on every page load, which is wasteful on a VPS. Replace it with a real system cron job:
|
|
|
|
```bash
|
|
sudo crontab -u www-data -e
|
|
```
|
|
|
|
Add:
|
|
|
|
```
|
|
*/5 * * * * /usr/bin/php /var/www/yourdomain.com/wp-cron.php > /dev/null 2>&1
|
|
```
|
|
|
|
Then disable WordPress pseudo-cron in `wp-config.php`:
|
|
|
|
```php
|
|
define( 'DISABLE_WP_CRON', true );
|
|
```
|
|
|
|
---
|
|
|
|
## Performance tuning
|
|
|
|
### PHP opcache
|
|
|
|
Uncomment and tweak in `/etc/php/8.1/fpm/php.ini`:
|
|
|
|
```ini
|
|
opcache.enable=1
|
|
opcache.memory_consumption=256
|
|
opcache.interned_strings_buffer=16
|
|
opcache.max_accelerated_files=10000
|
|
opcache.revalidate_freq=2
|
|
opcache.fast_shutdown=1
|
|
```
|
|
|
|
### MySQL tuning
|
|
|
|
For a 2 GB VPS, add to `/etc/mysql/mysql.conf.d/mysqld.cnf`:
|
|
|
|
```ini
|
|
innodb_buffer_pool_size = 512M
|
|
innodb_log_file_size = 128M
|
|
query_cache_type = 0
|
|
```
|
|
|
|
Run MySQLTuner after a few days of uptime for more specific recommendations:
|
|
|
|
```bash
|
|
sudo apt install mysqltuner
|
|
sudo mysqltuner
|
|
```
|
|
|
|
### WordPress object caching with Redis
|
|
|
|
If your VPS has enough RAM (2 GB+ free), Redis dramatically speeds up WordPress:
|
|
|
|
```bash
|
|
sudo apt install redis-server
|
|
sudo systemctl enable redis-server
|
|
```
|
|
|
|
Install the **Redis Object Cache** plugin in WordPress admin and click **Enable Object Cache**.
|
|
|
|
---
|
|
|
|
## Automating updates
|
|
|
|
Set up unattended security updates for the OS:
|
|
|
|
```bash
|
|
sudo apt install unattended-upgrades
|
|
sudo dpkg-reconfigure unattended-upgrades
|
|
```
|
|
|
|
WordPress core auto-updates are enabled by default for minor versions. For plugins and themes, enable auto-updates in WordPress admin → Plugins → toggle **Enable auto-updates** on each plugin you trust.
|
|
|
|
---
|
|
|
|
## Next steps
|
|
|
|
- [Configure W3 Total Cache](/wordpress/w3-total-cache/) for page caching and performance
|
|
- [WordPress security hardening](/wordpress/security/) — tighten file permissions, disable XML-RPC, and set up login protection
|
|
- [Automated backups with restic](/vps/restic-backups/) for off-site backups of your files and database
|
|
|