Skip to content
Wbcom Designs

How I Set Up WordPress on DigitalOcean: Complete Server to First Post Guide

· · 9 min read
Setup WordPress on DigitalOcean - Complete server to first post guide

Every WordPress site I build for clients starts the same way, a fresh DigitalOcean droplet, a terminal window, and about 45 minutes of setup time. I’ve done this enough times that the process is almost muscle memory. But “almost” isn’t good enough when you’re configuring a production server, so I documented every single command. This guide walks you through the entire process: creating a DigitalOcean droplet, installing the full LEMP stack (Linux, Nginx, MySQL, PHP), getting WordPress running, securing it with SSL, and then going further with Redis caching, MySQL tuning for large sites, and Nginx performance optimization. Every command is in a GitHub gist you can fork and customize. By the end, you’ll have a WordPress server that’s faster, more secure, and cheaper than most managed hosting, and you’ll actually understand what’s running on it.

What You Need Before Starting

Four things:

  • A DigitalOcean account, Sign up here. New accounts usually get free credit.
  • A domain name, registered anywhere (Namecheap, Cloudflare, GoDaddy).
  • An SSH key pair, if you don’t have one, run ssh-keygen -t ed25519 on your local machine. Add the public key to your DigitalOcean account under Settings → Security.
  • About 45 minutes, less if you’ve done this before.

That’s it. No special tools, no GUI panels. Just a terminal.

Create the Droplet

Log into DigitalOcean and create a new droplet with these settings:

  • Image: Ubuntu 24.04 LTS
  • Plan: Basic Shared CPU, $6/month (1 vCPU, 1GB RAM) for small sites, $12/month (2GB RAM) for anything with traffic
  • Region: Closest to your audience. I usually pick SFO3 or BLR1 depending on the project.
  • Authentication: SSH Key (never password)
  • Hostname: Something descriptive like wp-yourdomain

Hit Create and wait 30 seconds. Copy the IP address, you’ll need it for everything that follows. I recommend the $12/month droplet for anything beyond a personal blog. WordPress with a few plugins and any decent theme needs at least 2GB RAM to breathe. The $6 droplet works, but you’ll need swap space (we’ll set that up).

First Login and Server Security

SSH into your new droplet as root:

ssh root@YOUR_DROPLET_IP

First thing, never run WordPress as root. We create a dedicated user, give them sudo access, and disable root SSH login entirely. Important: Test SSH login with your new user in a separate terminal window before closing the root session. If you lock yourself out, you’ll need to use DigitalOcean’s console. Next, set up the firewall. We only want SSH, HTTP, and HTTPS traffic: From this point on, every command runs as your new sudo user, not root.

Add Swap Space

If you’re on the $6 droplet (1GB RAM), this step is essential. MySQL and PHP-FPM together can easily eat 1GB, and without swap, the OOM killer will start terminating processes, usually MySQL, at the worst possible time. Even on 2GB+ droplets, I add swap as a safety net. It’s free insurance. We set swappiness to 10, which means Linux will only use swap when RAM is nearly full. This is the right balance for a server, you want RAM to be the primary working space, with swap as overflow protection.

Install the LEMP Stack

LEMP stands for Linux + (E)Nginx + MySQL + PHP. Let’s install each component.

Nginx

After this, visiting your droplet’s IP in a browser should show the Nginx default page. If it doesn’t, check that the firewall is allowing HTTP traffic.

MySQL 8

When mysql_secure_installation runs, say yes to everything: set a root password, remove anonymous users, disable remote root login, remove the test database. Now create the WordPress database: Save those credentials. You’ll need them in a few minutes for wp-config.php.

PHP 8.3-FPM

Ubuntu 24.04 ships PHP 8.3 by default, which is what we’ll use. It includes all the performance improvements from 8.1 and 8.2, plus JIT compilation improvements. We install every PHP extension WordPress needs, plus php-redis for object caching and php-imagick for image processing.

Tune PHP-FPM

The default PHP-FPM config is conservative. For a WordPress server, we want more workers, higher memory limits, and OPcache enabled. Replace /etc/php/8.3/fpm/pool.d/www.conf with this config, then restart:

sudo systemctl restart php8.3-fpm

Key settings explained:

  • pm.max_children = 10, Maximum PHP worker processes. Each worker can handle one request. On 2GB RAM, 10 is the sweet spot.
  • memory_limit = 256M, Per-request memory cap. WordPress with WooCommerce or page builders can use 128MB+.
  • OPcache, Stores compiled PHP bytecode in shared memory so PHP doesn’t recompile files on every request. This alone can double your response time.

Configure Nginx for WordPress

Now we connect Nginx to PHP-FPM and set up the WordPress-specific rules: permalinks, security blocks, static file caching. Replace yourdomain.com with your actual domain, then:

sudo ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

The nginx -t command tests the config syntax. Never reload without testing first, a syntax error will take Nginx down. Notice we block xmlrpc.php, deny PHP execution in the uploads directory, and hide .git folders. These are the most common WordPress attack vectors.

Download and Configure WordPress

File permissions matter. Directories get 755 (owner can write, everyone can read and execute), files get 644 (owner can write, everyone can read). Everything owned by www-data so Nginx/PHP can access them. Now configure wp-config.php with your database credentials and fresh security salts: Replace your-password-from-step-05 with the actual database password from earlier. The script fetches unique salts from the WordPress API, never use the placeholder values. We also disable the in-dashboard file editor (security) and built-in WP-Cron (we’ll use system cron instead, it’s more reliable).

Install WP-CLI

WP-CLI is the command-line interface for WordPress. Once you start using it, you’ll wonder how you ever managed WordPress without it. With WP-CLI installed, you can manage plugins, users, options, database operations, and more, all from the terminal. No clicking through the dashboard.

Run the WordPress Installation

Instead of running through the browser-based installer (which exposes your site to the internet in an unfinished state), we install via WP-CLI: This script installs WordPress, sets pretty permalinks, creates a first post, and cleans up the default Hello World content and unused themes/plugins. Save the generated admin password somewhere secure, and change it after your first login.

Point Your Domain

WordPress is running, but it’s only accessible by IP address. Let’s point your domain to the droplet. DNS propagation usually takes 5-30 minutes, though it can take longer. You can check propagation globally at dnschecker.org. Once dig yourdomain.com returns your droplet’s IP, you’re ready for SSL.

SSL with Let’s Encrypt

No excuse not to have SSL in 2026. Let’s Encrypt provides free certificates, and Certbot automates the entire process including renewal. Certbot will automatically modify your Nginx config to enable SSL and redirect HTTP to HTTPS. But I prefer having full control, so here’s the complete production SSL config: This config includes:

  • HTTP → HTTPS redirect
  • www → non-www redirect (pick one canonical URL)
  • HTTP/2 enabled
  • HSTS header (tells browsers to always use HTTPS)
  • Security headers for XSS, clickjacking, and MIME sniffing protection

After updating, test and reload:

sudo nginx -t && sudo systemctl reload nginx

You can verify your SSL grade at SSL Labs, you should get an A or A+.

Install Redis Object Cache

WordPress stores a lot of data in the database that doesn’t change between requests, options, transients, user sessions. An object cache keeps this data in memory (RAM) so WordPress doesn’t hit the database for every page load. Redis is the industry standard. Here’s the server setup: Then add the Redis configuration to wp-config.php and install the drop-in: The easiest approach is the Redis Object Cache plugin:

sudo -u www-data wp plugin install redis-cache --activate --path=/var/www/wordpress
sudo -u www-data wp redis enable --path=/var/www/wordpress

Verify it’s working:

sudo -u www-data wp redis status --path=/var/www/wordpress

You should see “Status: Connected.” On a typical WordPress site, Redis reduces database queries by 50-80%. On WooCommerce stores with lots of transients, the improvement is even bigger.

MySQL Tuning for Large Sites

The default MySQL configuration is designed to run on minimal hardware. For a WordPress site with thousands of posts, WooCommerce products, or BuddyPress members, you need to tune it. Save this to /etc/mysql/mysql.conf.d/wordpress-tuning.cnf and restart MySQL:

sudo systemctl restart mysql

The most impactful settings:

  • innodb_buffer_pool_size = 768M, This is MySQL’s main cache. It stores frequently accessed data and indexes in RAM. Set it to 50-70% of available RAM (after accounting for Nginx, PHP, Redis).
  • innodb_flush_log_at_trx_commit = 2, Flushes transaction logs once per second instead of on every commit. Slight risk of losing 1 second of data on a crash, but significantly faster writes.
  • slow_query_log, Logs queries that take longer than 2 seconds. Review /var/log/mysql/slow.log periodically to find and optimize slow queries.

Note: MySQL 8 removed the query cache entirely. Use Redis for query-level caching instead, it’s faster and more reliable.

Nginx Performance for High Traffic

For sites expecting serious traffic, these Nginx optimizations make a measurable difference: Save to /etc/nginx/conf.d/performance.conf and reload Nginx. The FastCGI cache section is the biggest win here. It caches the full HTML output of PHP at the Nginx level, so repeat visitors get served from memory without PHP or MySQL being involved at all. For a blog or content site, this can handle thousands of concurrent users on a $12 droplet. The rate limiting on wp-login.php blocks brute force attacks. One request per second with a burst of 3, enough for legitimate logins but stops automated attacks.

Install Essential Tools

A few tools I install on every server:

  • htop, interactive process viewer. Way better than top for understanding what’s eating your resources.
  • ncdu, interactive disk usage analyzer. ncdu /var/www/wordpress to find what’s eating disk space.
  • Composer, PHP dependency manager. You’ll need it if you use any PHP packages outside WordPress.
  • Node/npm, for building theme or plugin assets. Install via nvm so you can switch versions easily.

Security Hardening

We’ve already done the basics (non-root user, firewall, SSH keys). Now let’s add active protection: Three layers:

  1. Fail2ban, monitors logs and bans IPs that fail authentication too many times. We set SSH to 3 attempts then a 24-hour ban.
  2. Unattended upgrades, automatically installs security patches. You want this on every production server.
  3. SSH key-only auth, disables password authentication entirely. If you lose your SSH key, the only way in is DigitalOcean’s console.

Automated Backups

A server without backups is a server waiting to ruin your week. This backup script exports the database and archives wp-content (themes, plugins, uploads) daily: We don’t back up WordPress core files, they can be reinstalled in seconds with wp core download. The database and wp-content are what matter. Set up the cron jobs to automate everything: This gives you:

  • 3:00 AM daily, full WordPress backup (DB + files)
  • Every 5 minutes, WP-Cron tasks (scheduled posts, plugin tasks)
  • Every 12 hours, SSL certificate renewal check

Backups are kept for 14 days. For additional safety, consider syncing the /opt/backups/ directory to DigitalOcean Spaces or S3, keeping backups on the same server as the site defeats the purpose if the server dies.

Final Verification Checklist

Run this script to verify every component is working: You should see all green [PASS] results. If anything fails, the script tells you what to fix.

What This Costs

Here’s the full picture:

  • DigitalOcean droplet: $6-12/month
  • Domain: ~$10-15/year
  • SSL: Free (Let’s Encrypt)
  • Redis, Nginx, MySQL, PHP: Free (open source)
  • Total: $6-12/month for a fully tuned WordPress server

Compare that to managed WordPress hosting at $25-50/month, and you get full root access, no traffic limits, and the ability to run multiple sites on the same droplet. The tradeoff is maintenance. You’re responsible for updates, security patches, and monitoring. The unattended upgrades and Fail2ban we set up handle most of this automatically, but you should check in on your server at least monthly.

What to Do Next

Your server is production-ready. Here’s what I typically do next:

  1. Install a theme, Upload via WP-CLI: wp theme install theme-name --activate
  2. Set up a CDN, Cloudflare’s free tier is enough for most sites. Point your DNS through Cloudflare for automatic caching and DDoS protection.
  3. Install monitoring, DigitalOcean’s built-in monitoring is decent. For more detail, the free tier of UptimeRobot pings your site every 5 minutes.
  4. Enable DigitalOcean backups, $1-2/month for weekly server snapshots. Belt and suspenders with our daily file backups.
  5. Off-server backup sync, Use rclone or s3cmd to sync your daily backups to DigitalOcean Spaces or AWS S3.

Every file referenced in this guide is available in the GitHub gist. Fork it, customize the variables for your domain and credentials, and you have a repeatable setup process you can use for every new project. If you run into issues or have questions about any step, reach out. I’ve deployed this stack dozens of times and I’m happy to help troubleshoot.

You Might Also Like

Varun Dubey
Varun Dubey

We specialize in web design & development, search engine optimization and web marketing, eCommerce, multimedia solutions, content writing, graphic and logo design. We build web solutions, which evolve with the changing needs of your business.