Skip to main contentSkip to navigation
[email protected]
Client AreaSupport
Hosting Mammoth
HostingMammothYour Data, Our Responsibility
Home
Solutions
Hosting Services
Store
Pricing
About
Blog
API
Contact

Stay Ahead of the Curve

Get the latest insights on cybersecurity, AI innovations, and enterprise data solutions delivered to your inbox.

Hosting Mammoth
HostingMammothEnterprise Solutions

Enterprise-grade data solutions. Hosting, recovery, cybersecurity, and AI-powered services for businesses worldwide.

[email protected]
Sun - Fri, 9:00am - 5:00pm

Services

  • Cloud Hosting
  • Data Recovery
  • Cybersecurity
  • Legal Support
  • MSP Services
  • Web Development
  • AI Services
  • Free Server Migration

Hosting

  • VPS Hosting (NVMe SSD)
  • VDS Hosting (NVMe)
  • Storage VPS (High SSD)
  • GPU Servers
  • Managed Services
  • Cloud Firewall
  • Load Balancer
  • One-Click Apps
  • n8n Hosting
  • Object Storage
  • FAQ

Company

  • Store
  • Pricing
  • About Us
  • Locations
  • Blog
  • Testimonials
  • Contact
  • Affiliate Program
  • White-Label
  • Terms of Service
  • Privacy Policy
  • Browser Cookies
  • SLA

Support

  • Client Area
  • Submit Ticket
  • Knowledge Base
  • Server Status
  • API Documentation

© 2026 Hosting Mammoth. All rights reserved.

Knowledge Base
Getting StartedAccount ManagementVPS HostingGPU ServersStorage VPSCloud FirewallLoad BalancerServer ManagementBilling & PaymentsSupport & TicketsAffiliate ProgramReseller ProgramMarketplace & Appsn8n HostingManaged ServicesServer MigrationAPI & DevelopersSecurityTroubleshootingGlossaryInstall Guides
  1. Home
  2. /
  3. Support
  4. /
  5. Install Guides
  6. /
  7. How To Install Woocommerce Ubuntu
GUIDEInstall Guides

How to Install WooCommerce on Ubuntu 24.04 VPS: Self-Hosted WordPress Store

31 min read

How to Install WooCommerce on Ubuntu 24.04 VPS — Self-Hosted WordPress Store

WooCommerce powers nearly a third of all online stores because it turns a standard WordPress install into a full-featured ecommerce platform without locking you into a hosted marketplace. Running it on your own Ubuntu 24.04 VPS gives you full database ownership, unlimited products, zero transaction fees, and the freedom to integrate any payment gateway, tax engine, or shipping provider you need. This guide walks you through installing and hardening WooCommerce on top of a LEMP stack, from PHP extensions to Redis object caching and system-level cron.

Skip the setup? Deploy a pre-configured WooCommerce store in one click with our Ecommerce VPS image. Launch a WooCommerce-ready VPS now and start selling in under 60 seconds.

Table of Contents

  • What is WooCommerce?
  • Why Self-Host WooCommerce Instead of Using Shopify?
  • Prerequisites
  • Step 1: Prepare the LEMP Stack and PHP Extensions
  • Step 2: Tune PHP and MariaDB for WooCommerce
  • Step 3: Install WooCommerce via WP-CLI
  • Step 4: Run the WooCommerce Setup Wizard
  • Step 5: Add Products, Variations, and Categories
  • Step 6: Configure Shipping Zones and Methods
  • Step 7: Connect Payment Gateways (Stripe, PayPal, Bank Transfer)
  • Step 8: Set Up Tax Rules
  • Step 9: Enable Redis Object Cache
  • Step 10: Configure Nginx FastCGI Caching
  • Step 11: Replace WP-Cron with a System Cron
  • Step 12: Harden WooCommerce and WordPress
  • Backup Strategy
  • Scaling WooCommerce
  • Troubleshooting
  • FAQ
  • Next Steps
  • What is WooCommerce?

    WooCommerce is an open-source ecommerce plugin for WordPress, originally developed by WooThemes and now maintained by Automattic, the company behind WordPress.com. It turns any WordPress site into a fully functional online store capable of selling physical products, digital downloads, subscriptions, bookings, and services. Because it is just a plugin, you keep everything WordPress already gives you — themes, SEO plugins, the Gutenberg editor, multilingual support — and add a complete commerce layer on top.

    Out of the box, WooCommerce handles product catalogs with variations (size, color, material), inventory tracking, tax calculation, multi-currency storefronts, coupon codes, customer accounts, order management, refunds, and transactional emails. The plugin ecosystem extends it in every direction: subscriptions via WooCommerce Subscriptions, memberships via WooCommerce Memberships, bookings via WooCommerce Bookings, point-of-sale integration, marketplace functionality, dropshipping connectors, and hundreds of shipping and payment gateway integrations. For developers, a well-documented REST API and hook system make it straightforward to build custom checkout flows, connect to ERPs, or integrate with headless frontends built in Next.js or Nuxt.

    Typical WooCommerce deployments range from single-product creator stores selling PDFs or courses, to mid-market retailers moving thousands of SKUs per month, to multi-vendor marketplaces using Dokan or WC Vendors. Self-hosting it on a VPS like Ubuntu 24.04 gives you full control over the database, server resources, caching strategy, and third-party services — something hosted SaaS platforms simply cannot match.

    Why Self-Host WooCommerce Instead of Using Shopify?

    Choosing between WooCommerce on your own VPS and a hosted platform like Shopify or BigCommerce comes down to cost, control, and ownership. The tradeoffs favor self-hosting for most serious stores:

    • Zero transaction fees -- Shopify charges 0.5% to 2% per transaction on top of payment processor fees unless you use Shopify Payments. WooCommerce charges nothing. On $100,000 in annual sales, that saves $500 to $2,000 per year in platform fees alone.
    • Full database ownership -- Your products, orders, customers, and analytics live in your own MariaDB database on your own VPS. You can export, back up, migrate, or query it directly. No vendor can lock you out, raise prices, or change terms.
    • Unlimited products and variations -- Shopify's entry tier limits product variants. WooCommerce has no artificial limits; only your database schema and server resources matter. Stores with 50,000+ SKUs run comfortably on a well-tuned VPS.
    • Flat, predictable cost -- A CloudCore Professional VPS handles small-to-mid traffic stores for EUR 19.99/month. Shopify's equivalent tier starts at $79/month and climbs sharply with traffic and features.
    • Any payment gateway you want -- Shopify penalizes you for using non-Shopify Payments gateways. WooCommerce integrates with hundreds of gateways — Stripe, PayPal, Mollie, Klarna, Square, Razorpay, regional providers — with no platform surcharge.
    • Full code access -- Every theme file, every plugin hook, every database column is yours to modify. You can build custom checkout experiences, integrate with internal ERPs, or fork any plugin to fit your workflow.
    • SEO and content flexibility -- WordPress is still the best blogging and content platform on the web. WooCommerce inherits that, letting you build a content-driven commerce site — buyer guides, comparison posts, tutorials — that ranks on Google and drives organic traffic.
    • GDPR and data residency -- Your customer data sits on your chosen server in your chosen jurisdiction. Easy to comply with EU, UK, or regional data residency rules.

    Cost Comparison: Self-Hosted WooCommerce vs. Shopify

    ScenarioShopify BasicShopify AdvancedSelf-Hosted WooCommerce (VPS)
    Monthly platform cost$39/mo$399/moEUR 19.99/mo
    Transaction fee (non-native gateway)2.0%0.5%0%
    Product limitUnlimitedUnlimitedUnlimited
    Staff accounts215Unlimited
    Custom checkoutNoLimitedFull code access
    Database accessNoNoYes
    Typical cost at $100K/year revenue~$2,460/yr~$5,290/yr~EUR 240/yr
    For any store processing more than a few hundred orders per month, self-hosting WooCommerce on a VPS pays for itself within weeks.

    Prerequisites

    Before starting, make sure you have:

    • A VPS running Ubuntu 24.04 LTS with root or sudo access
    • A LEMP stack already installed (Nginx, MariaDB, PHP-FPM) — follow our LEMP stack install guide if you have not set this up yet
    • WordPress installed and reachable via HTTPS — follow How to Install WordPress on Ubuntu 24.04 first
    • A registered domain pointed at your server with a valid SSL certificate (Let's Encrypt)
    • MariaDB 10.6 or newer — see our MariaDB install guide if needed
    • PHP 8.3 (recommended by WooCommerce for performance and long-term support)
    • At least 4 GB of RAM and 40 GB of disk space for small stores; 8 GB+ for mid-sized catalogs
    Recommended Plan: CloudCore Professional
    >
    For a production WooCommerce store with Redis, FastCGI cache, and room for a product catalog of several thousand SKUs, we recommend the CloudCore Professional plan:
    >
    - 6 vCPU cores
    - 12 GB RAM
    - 100 GB NVMe SSD
    - Unmetered bandwidth
    - EUR 19.99/month
    >
    This handles 20,000-50,000 monthly visitors comfortably when combined with the caching and tuning steps in this guide.

    Connect to your server via SSH:

    bash
    ssh root@your-server-ip

    Step 1: Prepare the LEMP Stack and PHP Extensions

    WooCommerce has specific PHP extension requirements beyond what base WordPress needs. Install all of them before activating the plugin to avoid runtime errors during checkout.

    Start by updating the package index:

    bash
    sudo apt update && sudo apt upgrade -y

    Install the PHP 8.3 extensions required or recommended by WooCommerce:

    bash
    sudo apt install -y \
      php8.3-cli php8.3-fpm php8.3-common \
      php8.3-mysql php8.3-curl php8.3-gd \
      php8.3-mbstring php8.3-xml php8.3-zip \
      php8.3-bcmath php8.3-intl php8.3-soap \
      php8.3-imagick php8.3-redis php8.3-opcache

    Expected output (abbreviated):

    text
    The following additional packages will be installed:
      php8.3-cli php8.3-common php8.3-opcache ...
    Setting up php8.3-gd (8.3.x-1+ubuntu24.04.1+deb.sury.org+1) ...
    Setting up php8.3-imagick (3.7.0-4ubuntu2) ...
    Setting up php8.3-redis (6.0.2-1+ubuntu24.04.1+deb.sury.org+1) ...

    Why each extension matters for WooCommerce:

    • php8.3-curl -- required for payment gateway API calls (Stripe, PayPal, etc.)
    • php8.3-gd + php8.3-imagick -- product image resizing and thumbnails
    • php8.3-mbstring -- handling multi-byte strings in product descriptions and international content
    • php8.3-bcmath -- precise decimal arithmetic for order totals and tax calculation (never use floats for money)
    • php8.3-intl -- currency formatting and localization across international storefronts
    • php8.3-soap -- required by some carrier shipping integrations (UPS, FedEx)
    • php8.3-zip -- plugin/theme upload and digital product downloads
    • php8.3-redis -- connects WordPress to the Redis object cache (Step 9)
    • php8.3-opcache -- bytecode caching; mandatory for any production WordPress site
    Restart PHP-FPM to load the new extensions:

    bash
    sudo systemctl restart php8.3-fpm

    Verify all extensions are loaded:

    bash
    php -m | grep -E 'curl|gd|mbstring|bcmath|intl|soap|zip|redis|imagick|opcache'

    Expected output:

    text
    bcmath
    curl
    gd
    imagick
    intl
    mbstring
    opcache
    redis
    soap
    zip

    Step 2: Tune PHP and MariaDB for WooCommerce

    WooCommerce checkout and admin pages are heavier than typical WordPress pages. The defaults ship with Ubuntu are too low for a real store.

    Edit the PHP-FPM config:

    bash
    sudo nano /etc/php/8.3/fpm/php.ini

    Update the following values:

    ini
    memory_limit = 512M
    upload_max_filesize = 64M
    post_max_size = 64M
    max_execution_time = 300
    max_input_time = 300
    max_input_vars = 5000
    • memory_limit = 512M -- WooCommerce admin, especially reports and bulk product edits, commonly pushes past the 256M default.
    • max_input_vars = 5000 -- products with many variations (sizes x colors x materials) submit thousands of form fields. 1000 default is a frequent cause of "some variations failed to save" errors.
    • max_execution_time = 300 -- CSV product imports and bulk order operations need headroom.
    Also enable OPcache properly. Edit:

    bash
    sudo nano /etc/php/8.3/fpm/conf.d/10-opcache.ini
    ini
    opcache.enable=1
    opcache.memory_consumption=256
    opcache.interned_strings_buffer=16
    opcache.max_accelerated_files=20000
    opcache.revalidate_freq=60
    opcache.validate_timestamps=1

    Restart PHP-FPM:

    bash
    sudo systemctl restart php8.3-fpm

    Next, tune MariaDB. Edit /etc/mysql/mariadb.conf.d/50-server.cnf and add (or adjust) under [mysqld]:

    ini
    innodb_buffer_pool_size = 2G
    innodb_log_file_size = 256M
    innodb_flush_log_at_trx_commit = 2
    max_connections = 150
    query_cache_type = 0
    query_cache_size = 0

    For a 12 GB RAM VPS, innodb_buffer_pool_size = 2G is a safe starting point. WooCommerce stores order and product metadata in wp_postmeta, which can grow large quickly — a well-sized InnoDB buffer pool is the single biggest lever for store performance.

    Restart MariaDB:

    bash
    sudo systemctl restart mariadb

    Step 3: Install WooCommerce via WP-CLI

    WP-CLI is the fastest way to install and configure WordPress plugins on the command line. If you followed our WordPress install guide, WP-CLI should already be available. If not:

    bash
    curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
    chmod +x wp-cli.phar
    sudo mv wp-cli.phar /usr/local/bin/wp
    wp --info

    Navigate to your WordPress install directory:

    bash
    cd /var/www/yourstore.com

    Install and activate WooCommerce:

    bash
    sudo -u www-data wp plugin install woocommerce --activate

    Expected output:

    text
    Installing WooCommerce (9.4.2)
    Downloading installation package from https://downloads.wordpress.org/plugin/woocommerce.9.4.2.zip...
    Unpacking the package...
    Installing the plugin...
    Plugin installed successfully.
    Activating 'woocommerce'...
    Plugin 'woocommerce' activated.
    Success: Installed 1 of 1 plugins.

    Verify WooCommerce is active and check the version:

    bash
    sudo -u www-data wp plugin list --status=active

    Expected output:

    text
    +---------------+----------+--------+---------+
    | name          | status   | update | version |
    +---------------+----------+--------+---------+
    | woocommerce   | active   | none   | 9.4.2   |
    +---------------+----------+--------+---------+

    Install a WooCommerce-compatible theme. Storefront is the official Automattic theme, but most users today choose Astra, Kadence, or a block theme like Twenty Twenty-Four with WooCommerce blocks:

    bash
    sudo -u www-data wp theme install storefront --activate

    Step 4: Run the WooCommerce Setup Wizard

    WooCommerce ships an onboarding wizard that configures your store's basic settings. You can complete it through the admin UI at https://yourstore.com/wp-admin/admin.php?page=wc-admin&path=/setup-wizard, or script it entirely via WP-CLI for automated deployments.

    The wizard asks for:

    • Store location -- country, state, and postcode. This sets default currency, default tax regions, and default shipping zones.
    • Industry -- used for analytics and to surface relevant plugin recommendations.
    • Product types -- physical, digital, subscriptions, bookings. Affects which plugins are suggested.
    • Business details -- number of products, existing platform (for migration hints).
    • Theme choice -- optional; skip if you already installed one.
    To set the core options via WP-CLI instead:

    bash
    sudo -u www-data wp option update woocommerce_store_address "123 Main St"
    sudo -u www-data wp option update woocommerce_store_city "Berlin"
    sudo -u www-data wp option update woocommerce_default_country "DE:BE"
    sudo -u www-data wp option update woocommerce_store_postcode "10115"
    sudo -u www-data wp option update woocommerce_currency "EUR"
    sudo -u www-data wp option update woocommerce_product_type "physical"
    sudo -u www-data wp option update woocommerce_allow_tracking "no"

    Create the essential WooCommerce pages (Shop, Cart, Checkout, My Account):

    bash
    sudo -u www-data wp wc tool run install_pages --user=admin

    Expected output:

    text
    Success: Executed tool: Create default WooCommerce pages

    Verify the pages exist:

    bash
    sudo -u www-data wp post list --post_type=page --fields=ID,post_title,post_status

    You should see Shop, Cart, Checkout, My account, and Refund and Returns Policy in the list.

    Step 5: Add Products, Variations, and Categories

    You can add products via the admin UI (WooCommerce > Products > Add New) or through WP-CLI, which is dramatically faster for bulk loads. Start by creating product categories:

    bash
    sudo -u www-data wp wc product_cat create --name="T-Shirts" --user=admin
    sudo -u www-data wp wc product_cat create --name="Hoodies" --user=admin
    sudo -u www-data wp wc product_cat create --name="Accessories" --user=admin

    Create a simple product:

    bash
    sudo -u www-data wp wc product create \
      --name="Classic Logo T-Shirt" \
      --type=simple \
      --regular_price=24.99 \
      --description="100% organic cotton t-shirt with our classic logo." \
      --short_description="Organic cotton, unisex fit." \
      --sku="TSHIRT-001" \
      --manage_stock=true \
      --stock_quantity=100 \
      --user=admin

    Variable Products (Size, Color, Material)

    Variable products need an attribute, then individual variations per combination. The UI is simpler for this; the flow is:

  • WooCommerce > Attributes -- create Size (Small, Medium, Large) and Color (Black, White, Navy).
  • Products > Add New -- set product type to Variable product.
  • In the Attributes tab, add both attributes, check Used for variations, and save.
  • In the Variations tab, click Generate variations from all attributes. WooCommerce creates one variation per combination (Small/Black, Small/White, Medium/Black, etc.).
  • Set the price, SKU, stock, and image for each variation individually (or use Bulk actions > Set regular price to apply one price to all).
  • Bulk CSV Import

    For catalogs of hundreds or thousands of products, use the built-in CSV importer at WooCommerce > Products > Import. WooCommerce accepts its standard product CSV schema, including columns for variations, images (URLs or paths), categories, tags, stock, and custom attributes.

    Increase the import batch size if you hit timeouts. Add to wp-config.php:

    php
    define( 'WC_PRODUCT_IMPORTER_BATCH_SIZE', 30 );

    Step 6: Configure Shipping Zones and Methods

    Shipping in WooCommerce is organized into zones. Each zone is a set of regions (countries, states, postcodes), and each zone has one or more methods (flat rate, free shipping, local pickup, or carrier-calculated rates via plugins).

    Navigate to WooCommerce > Settings > Shipping. Create zones that match how you actually ship:

    • Domestic (Germany) -- flat rate EUR 4.99, free shipping over EUR 50
    • European Union -- flat rate EUR 9.99
    • Rest of World -- flat rate EUR 19.99 or disabled
    Example flat rate via WP-CLI (using the REST API):

    bash
    sudo -u www-data wp wc shipping_zone create --name="Germany" --user=admin
    sudo -u www-data wp wc shipping_zone_method create 1 \
      --method_id=flat_rate \
      --settings='{"title":"Standard Shipping","cost":"4.99"}' \
      --user=admin

    For real-time carrier rates (UPS, DHL, USPS, FedEx), install a carrier plugin — for example, the free WooCommerce Shipping plugin from Automattic or a paid integration like Table Rate Shipping for complex per-weight/per-zone pricing.

    Shipping Classes

    Use shipping classes to charge different rates per product type: heavy items, fragile items, oversized items. Create them under WooCommerce > Settings > Shipping > Shipping classes, assign products to classes on the product edit page, and then set per-class costs inside each flat rate method.

    Step 7: Connect Payment Gateways (Stripe, PayPal, Bank Transfer)

    WooCommerce ships with three payment methods enabled by default: Direct bank transfer, Check payments, and Cash on delivery. To accept card payments, install a gateway plugin.

    Stripe (Cards, Apple Pay, Google Pay, SEPA)

    bash
    sudo -u www-data wp plugin install woocommerce-gateway-stripe --activate

    Navigate to WooCommerce > Settings > Payments > Stripe and enter your Stripe publishable key and secret key from the Stripe dashboard. Enable Payment Request buttons for one-click Apple Pay / Google Pay checkout.

    Configure the Stripe webhook endpoint so WooCommerce receives payment confirmations:

  • In Stripe: Developers > Webhooks > Add endpoint.
  • Endpoint URL: https://yourstore.com/?wc-api=wc_stripe.
  • Select events: charge.succeeded, charge.failed, charge.refunded, review.opened, review.closed, payment_intent.succeeded, payment_intent.payment_failed.
  • Copy the signing secret back into WooCommerce > Settings > Payments > Stripe > Webhook secret.
  • PayPal

    bash
    sudo -u www-data wp plugin install woocommerce-paypal-payments --activate

    Connect via WooCommerce > Settings > Payments > PayPal Payments > Connect to PayPal. The plugin handles the OAuth flow and pulls your merchant credentials automatically.

    Direct Bank Transfer (BACS)

    Direct bank transfer is useful for B2B orders, wholesale customers, or markets where bank-to-bank transfers are common (Germany, Netherlands). Enable it under WooCommerce > Settings > Payments > Direct bank transfer and add your IBAN, BIC/SWIFT, and bank name. Customers see the bank details on the order confirmation page and the confirmation email.

    Test Mode

    Every gateway has a test/sandbox mode. Always place at least one successful test order and one refund before taking a store live. Stripe provides test card numbers like 4242 4242 4242 4242 for success and 4000 0000 0000 0002 for a decline.

    Step 8: Set Up Tax Rules

    Taxes in WooCommerce are configured under WooCommerce > Settings > Tax. Enable the tax system by going to WooCommerce > Settings > General and checking Enable taxes.

    Key decisions:

    • Prices entered with tax -- typical for EU/UK (customers see tax-inclusive prices). "No" for US (sales tax added at checkout).
    • Calculate tax based on -- customer billing address, shipping address, or shop base address.
    • Display prices in the shop -- including tax or excluding tax.
    • Display prices during cart and checkout -- including or excluding tax.

    Manual Tax Rates

    For a simple EU store selling to one country, add rates manually at WooCommerce > Settings > Tax > Standard rates:

    CountryStatePostcodeCityRate %Tax NameShipping
    DE19.0000VAT✓
    FR20.0000VAT✓
    ES*21.0000VAT✓

    Automated Tax Calculation

    For cross-border commerce (EU OSS, US sales tax across 50 states, Canadian GST/HST), manual rates quickly become unmanageable. Use one of:

    • WooCommerce Tax (free from Automattic) -- automatic rates for US, CA, UK, EU via Jetpack connection.
    • Avalara AvaTax -- enterprise-grade; real-time rate lookup and tax return filing.
    • TaxJar -- US-focused with strong nexus tracking and auto-filing.

    Digital Goods (EU VAT MOSS)

    If you sell digital downloads to EU consumers, you are required to charge VAT based on the customer's country, not yours. Enable Shop base address for physical goods but Customer billing address for digital, or use the EU VAT Assistant plugin which collects VAT numbers for B2B zero-rating and validates them against the VIES database automatically.

    Step 9: Enable Redis Object Cache

    WooCommerce hits the database hundreds of times per page load — product queries, cart state, session data, user meta. A Redis object cache reduces that to a handful of database queries and is the single largest performance win for a self-hosted store.

    Install and start Redis (if not already running) by following our Redis install guide, then:

    bash
    cd /var/www/yourstore.com
    sudo -u www-data wp plugin install redis-cache --activate

    Add the Redis connection details to wp-config.php:

    bash
    sudo nano /var/www/yourstore.com/wp-config.php

    Add before the / That's all, stop editing! / line:

    php
    define( 'WP_REDIS_HOST', '127.0.0.1' );
    define( 'WP_REDIS_PORT', 6379 );
    define( 'WP_REDIS_DATABASE', 0 );
    define( 'WP_REDIS_PREFIX', 'yourstore:' );
    define( 'WP_REDIS_MAXTTL', 86400 );
    define( 'WP_CACHE_KEY_SALT', 'yourstore.com' );

    Enable the drop-in:

    bash
    sudo -u www-data wp redis enable

    Expected output:

    text
    Success: Object cache enabled.

    Verify it is working:

    bash
    sudo -u www-data wp redis status

    Expected output:

    text
    Status:  Connected
    Client:  PhpRedis (v6.0.2)
    Drop-in: Valid

    After 5-10 minutes of traffic, check the hit ratio:

    bash
    redis-cli info stats | grep keyspace

    A healthy WooCommerce site shows a 90%+ cache hit rate within an hour.

    Step 10: Configure Nginx FastCGI Caching

    While Redis caches database queries, FastCGI cache stores fully rendered HTML at the Nginx layer — skipping PHP entirely for anonymous visitors. This easily doubles your effective capacity.

    Critical WooCommerce rule: never cache /cart, /checkout, /my-account, or any page with a logged-in user. Serving a cached cart to the wrong visitor is the classic WooCommerce caching disaster.

    Edit your Nginx server block:

    bash
    sudo nano /etc/nginx/sites-available/yourstore.com

    Add at the top of the file (outside the server block):

    nginx
    fastcgi_cache_path /var/cache/nginx/fastcgi
                       levels=1:2
                       keys_zone=WOOCACHE:100m
                       max_size=1g
                       inactive=60m
                       use_temp_path=off;

    fastcgi_cache_key "$scheme$request_method$host$request_uri";

    Inside the server { ... } block for your domain, add:

    nginx
    # Bypass cache for logged-in users and cart/checkout pages
    set $skip_cache 0;

    if ($request_method = POST) { set $skip_cache 1; } if ($query_string != "") { set $skip_cache 1; } if ($request_uri ~ "/wp-admin/|/wp-json/|/xmlrpc.php|wp-.\.php|^/feed/|sitemap(_index)?\.xml") { set $skip_cache 1; } if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in|woocommerce_items_in_cart|woocommerce_cart_hash") { set $skip_cache 1; } if ($request_uri ~* "/(cart|checkout|my-account)") { set $skip_cache 1; }

    location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock;

    fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache; fastcgi_cache WOOCACHE; fastcgi_cache_valid 200 301 302 60m; fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_503; add_header X-FastCGI-Cache $upstream_cache_status; }

    Create the cache directory and test the config:

    bash
    sudo mkdir -p /var/cache/nginx/fastcgi
    sudo chown www-data:www-data /var/cache/nginx/fastcgi
    sudo nginx -t
    sudo systemctl reload nginx

    Verify the cache is active:

    bash
    curl -I https://yourstore.com/ | grep -i x-fastcgi-cache

    First request shows MISS, subsequent requests show HIT:

    text
    X-FastCGI-Cache: HIT

    Install the Nginx Cache plugin so editing a product or page automatically purges the cache:

    bash
    sudo -u www-data wp plugin install nginx-cache --activate

    In Settings > Nginx Cache, set the cache path to /var/cache/nginx/fastcgi and enable auto-purge.

    Step 11: Replace WP-Cron with a System Cron

    WordPress triggers scheduled tasks (emails, Action Scheduler jobs, plugin cleanups) via wp-cron.php, which fires on every pageview. On a busy WooCommerce site, this adds latency to customer requests and causes missed jobs when traffic is low.

    Replace it with a system cron. First, disable the built-in one by adding to wp-config.php:

    php
    define( 'DISABLE_WP_CRON', true );

    Then create a system cron job:

    bash
    sudo crontab -u www-data -e

    Add:

    cron
    /5    * cd /var/www/yourstore.com && /usr/bin/php wp-cron.php > /dev/null 2>&1

    This runs every 5 minutes, independently of traffic. Verify it is scheduled:

    bash
    sudo crontab -u www-data -l

    For Action Scheduler (WooCommerce's queue for subscription renewals, email retries, order syncs), also add a dedicated runner so it processes batches more aggressively:

    cron
    /1    * cd /var/www/yourstore.com && /usr/local/bin/wp action-scheduler run --batches=3 --batch-size=25 > /dev/null 2>&1

    Check queued actions:

    bash
    sudo -u www-data wp action-scheduler status

    Expected output:

    text
    Action Status        Count
    pending              12
    in-progress          0
    complete             1,482
    failed               0

    Step 12: Harden WooCommerce and WordPress

    Stores are high-value targets. The basic WordPress hardening steps apply, plus WooCommerce-specific ones.

    Limit login attempts and protect wp-login.php

    Install Limit Login Attempts Reloaded:

    bash
    sudo -u www-data wp plugin install limit-login-attempts-reloaded --activate

    Or use Fail2ban with a WordPress jail for server-level protection.

    Disable XML-RPC

    XML-RPC is rarely used by WooCommerce but is a common brute-force target. Block it in Nginx:

    nginx
    location = /xmlrpc.php {
        deny all;
        access_log off;
        log_not_found off;
        return 444;
    }

    Force HTTPS on checkout and admin

    Add to wp-config.php:

    php
    define( 'FORCE_SSL_ADMIN', true );

    Nginx should already redirect all HTTP traffic to HTTPS at the server level.

    Restrict file permissions

    bash
    sudo find /var/www/yourstore.com -type d -exec chmod 755 {} \;
    sudo find /var/www/yourstore.com -type f -exec chmod 644 {} \;
    sudo chmod 600 /var/www/yourstore.com/wp-config.php
    sudo chown -R www-data:www-data /var/www/yourstore.com

    WooCommerce-specific hardening

    • Disable the REST API for unauthenticated users if you do not use a headless frontend. The Disable WP REST API plugin handles this cleanly.
    • Restrict /wp-json/wc/ endpoints to authenticated API keys only. WooCommerce REST API keys are generated at WooCommerce > Settings > Advanced > REST API.
    • Enable two-factor authentication for all admin accounts using Two Factor or WP 2FA.
    • Turn off file editing in the admin:
    php
    define( 'DISALLOW_FILE_EDIT', true );
      define( 'DISALLOW_FILE_MODS', true );
    • Enable WooCommerce fraud tools — Stripe Radar, PayPal Seller Protection, or a plugin like FraudLabs Pro for velocity checks and blocklists.
    • Install a WAF like CrowdSec or Cloudflare's free WAF rules for OWASP protection at the edge.

    Daily security checks

    bash
    sudo -u www-data wp core verify-checksums
    sudo -u www-data wp plugin verify-checksums --all

    These compare installed files against the official WordPress.org checksums. Any mismatch is a red flag.

    Backup Strategy

    A WooCommerce store loses money every hour it is offline, so backups need to be frequent, automated, and tested.

    What to back up

    • MariaDB database -- all product, order, and customer data
    • /var/www/yourstore.com/wp-content/uploads/ -- product images, invoices, digital downloads
    • /var/www/yourstore.com/wp-content/plugins/ and themes/ -- if you use custom or modified code
    • wp-config.php -- site-specific secrets and DB credentials

    Daily database dump

    Create /usr/local/bin/backup-woocommerce.sh:

    bash
    #!/bin/bash
    DATE=$(date +%Y%m%d-%H%M)
    BACKUP_DIR=/var/backups/woocommerce
    mkdir -p $BACKUP_DIR

    Database

    mysqldump --single-transaction --quick --routines --triggers \ wordpress_db | gzip > $BACKUP_DIR/db-$DATE.sql.gz

    Uploads

    tar czf $BACKUP_DIR/uploads-$DATE.tar.gz \ -C /var/www/yourstore.com/wp-content uploads

    Keep 14 daily + 8 weekly backups, then prune

    find $BACKUP_DIR -name "db-*.sql.gz" -mtime +14 -delete find $BACKUP_DIR -name "uploads-*.tar.gz" -mtime +56 -delete

    Schedule it:

    bash
    sudo chmod +x /usr/local/bin/backup-woocommerce.sh
    sudo crontab -e

    Add:

    cron
    0 2   * /usr/local/bin/backup-woocommerce.sh >> /var/log/woocommerce-backup.log 2>&1

    Offsite replication

    Local backups do not protect against drive loss or server compromise. Push daily to object storage (Backblaze B2, AWS S3, Wasabi) with rclone:

    bash
    sudo apt install -y rclone
    rclone config  # set up remote "b2" or "s3"
    rclone sync /var/backups/woocommerce b2:yourstore-backups/ --log-file=/var/log/rclone.log

    Add this to the same cron, 15 minutes after the local backup.

    Test restores quarterly

    A backup you have never restored is a theory, not a backup. Every quarter, spin up a scratch VPS, restore the latest dump, and verify an order can be placed. See reference_dev_server.md style workflows for staging restores.

    Scaling WooCommerce

    Once traffic grows past what a single VPS can serve cached, you have several lever to pull before moving to multi-server.

    Action Scheduler optimization

    Action Scheduler is the job queue behind subscription renewals, webhook retries, email sending, and order syncs. On busy stores it becomes the bottleneck. Tune it:

    • Run the dedicated cron every 1 minute (see Step 11).
    • Purge completed jobs older than 30 days: wp action-scheduler clean --batch-size=200.
    • For very high-volume stores, move Action Scheduler to a dedicated queue runner — a second VPS running nothing but the scheduler, connected to the same database.

    Object cache scaling

    When the Redis cache grows past available RAM, Redis evicts keys. Increase maxmemory in /etc/redis/redis.conf or move Redis to its own VPS. Set the eviction policy:

    text
    maxmemory 4gb
    maxmemory-policy allkeys-lfu

    allkeys-lfu (least frequently used) is the best match for WooCommerce's access patterns.

    CDN for static assets

    Put Cloudflare, Bunny.net, or BunnyCDN in front of the store. Offload /wp-content/uploads/ and all static assets. Combined with FastCGI cache, this can cut origin traffic by 95%+. Configure Cloudflare page rules to bypass cache for /cart, /checkout, /my-account, and /wp-admin.

    Database read replicas

    For stores above 10,000 products or 1,000 orders/day, use HyperDB or LudicrousDB to split reads across replica MariaDB servers. The admin and checkout hit the primary; product catalog pages read from replicas.

    Image optimization

    Product images are often 70% of page weight. Install ShortPixel, Imagify, or use self-hosted Imgproxy to serve WebP/AVIF on demand. Enable lazy loading (built into WordPress core since 5.5).

    Move assets to object storage

    Store uploads in S3-compatible storage (Wasabi, Backblaze B2) via the WP Offload Media plugin. Frees up server disk and enables CDN without origin bandwidth cost.

    When to upgrade the VPS

    Watch three signals in your monitoring stack:

    • CPU > 70% sustained during peak traffic -- upgrade vCPU.
    • Memory > 85% used -- upgrade RAM or move Redis/MariaDB off-box.
    • MariaDB slow query log growing -- tune indexes, increase innodb_buffer_pool_size, add read replicas.
    Build a proper monitoring stack first — see How to Build a Monitoring Stack on Ubuntu for a Prometheus + Grafana setup.

    Troubleshooting

    ProblemCauseSolution
    Fatal error: Allowed memory size exhausted during checkout or adminPHP memory_limit too low for cart/admin pagesRaise memory_limit to 512M in /etc/php/8.3/fpm/php.ini and restart PHP-FPM. In wp-config.php add define('WP_MEMORY_LIMIT', '512M'); define('WP_MAX_MEMORY_LIMIT', '768M');
    Stripe / PayPal payments succeed but order stays on "Pending payment"Webhook not reaching site, or signing secret wrongVerify endpoint URL in gateway dashboard. Re-copy the signing secret. Check WooCommerce > Status > Logs for gateway entries. Test with curl -v to the webhook URL.
    Transactional emails not sending (order confirmation, receipts)PHP mail() blocked by VPS provider or marked spamInstall a transactional mail plugin (WP Mail SMTP) and connect to SendGrid, Mailgun, Amazon SES, or Postmark. Never rely on default PHP mail for order receipts.
    "Some variations failed to save" in product editormax_input_vars too lowSet max_input_vars = 5000 in php.ini and restart PHP-FPM.
    Cart empties when user logs in, or sessions leak between usersFastCGI cache serving cached cart/checkoutReview Nginx $skip_cache rules. /cart, /checkout, /my-account must never be cached. Verify with curl -I -- those paths should show BYPASS.
    Product images uploaded but not showingimagick or gd missing; Nginx blocks /wp-content/uploads/php -m \</td><td>grep -E 'gd\</td><td>imagick'<code>. Check uploads directory owner: </code>sudo chown -R www-data:www-data /var/www/yourstore.com/wp-content/uploads.
    Admin dashboard extremely slowWooCommerce Analytics regenerating data, or no object cacheEnable Redis (Step 9). Under WooCommerce > Status > Tools > Regenerate analytics, let it finish. Set define('WP_DEBUG', false); in production.
    wp-cron.php runs but scheduled jobs never fireDISABLE_WP_CRON set but no system cron installedInstall the system cron from Step 11. Verify with sudo crontab -u www-data -l.
    Checkout throws Sorry, your session has expiredSession cookie blocked by cache or wrong site URLMake sure siteurl and home options match exactly the HTTPS canonical URL. Disable page cache on /checkout and /cart.
    Action Scheduler queue stuck with thousands of pending jobsCron not running, or PHP memory limit for CLI too lowConfirm the per-minute cron from Step 11. Set memory_limit = 512M in /etc/php/8.3/cli/php.ini. Run wp action-scheduler run --force manually to clear the backlog.

    Viewing WooCommerce logs

    WooCommerce writes its own logs under /var/www/yourstore.com/wp-content/uploads/wc-logs/. View recent entries:

    bash
    sudo -u www-data wp wc tool run clear_sessions --user=admin
    ls -lth /var/www/yourstore.com/wp-content/uploads/wc-logs/ | head

    Enable verbose debugging temporarily by adding to wp-config.php:

    php
    define( 'WP_DEBUG', true );
    define( 'WP_DEBUG_LOG', true );
    define( 'WP_DEBUG_DISPLAY', false );

    Logs write to /wp-content/debug.log. Disable these in production when you are done.

    FAQ

    Can I run WooCommerce on a 4 GB RAM VPS?

    Yes, for small stores with a few hundred products and modest traffic, 4 GB of RAM is enough. You can comfortably serve 10,000-20,000 monthly visitors if you enable Redis object cache and Nginx FastCGI cache, and keep innodb_buffer_pool_size around 1 GB. The limits appear at the admin layer — bulk product edits, CSV imports over 1,000 SKUs, and the WooCommerce Analytics dashboard will feel sluggish. For serious stores, CloudCore Professional's 12 GB of RAM gives you the headroom to run Redis, MariaDB, PHP-FPM, and a full cache all at once without trading performance between them.

    Do I need SSL for WooCommerce?

    Yes, absolutely. WooCommerce will not let you process real card payments without HTTPS, and every modern payment gateway rejects checkout requests from non-HTTPS origins. Beyond the compliance requirement, browsers flag non-HTTPS checkout pages as insecure, which destroys conversion. Use Let's Encrypt (free, automated) or a paid certificate from your registrar. Certbot with the Nginx plugin issues and renews certificates automatically — the LEMP stack guide linked above covers this step in detail.

    How do I migrate from Shopify or BigCommerce to WooCommerce?

    Export products, customers, and orders as CSV from the source platform. WooCommerce's built-in CSV importer at Products > Import handles product data directly — map the columns to WooCommerce's schema (name, SKU, regular_price, sale_price, stock_quantity, categories, images). For orders and customers, use the Cart2Cart or LitExtension migration services, which handle the heavy lifting including redirects, or the WP All Import Pro plugin for custom mappings. Always migrate to a staging site first, verify data integrity, and set up 301 redirects from the old URL structure to the new one to preserve SEO.

    Can WooCommerce handle subscriptions and recurring payments?

    Yes, with the official WooCommerce Subscriptions extension ($239/year) or free alternatives like SUMO Subscriptions. WooCommerce Subscriptions integrates with Stripe and PayPal for automatic recurring billing, supports trial periods, sign-up fees, prorated upgrades/downgrades, and failed-payment retries via Action Scheduler. For membership sites specifically, pair it with WooCommerce Memberships to gate content and restrict product access to active subscribers.

    How many products can WooCommerce handle on a single server?

    With Redis object cache, FastCGI cache, and proper MariaDB tuning, a well-configured VPS easily handles 50,000+ products. The bottleneck is almost never the product count itself but rather the wp_postmeta table — WooCommerce stores product attributes, variations, and metadata as rows in this table, which can balloon to millions of rows. Add indexes on wp_postmeta.meta_key and wp_postmeta.meta_value(191), consider the WooCommerce Custom Order Tables feature (enabled by default in recent versions) which moves order data out of wp_posts into dedicated tables, and upgrade to CloudCore Professional or higher for stores past 10,000 SKUs.

    Is WooCommerce PCI DSS compliant?

    WooCommerce itself does not store card data — that is handled entirely by the payment gateway (Stripe, PayPal, etc.), which takes on the PCI compliance burden. As long as you use a hosted/tokenized gateway integration (the default for Stripe and PayPal on WooCommerce), your store falls under the simpler PCI DSS SAQ-A category. Keep TLS enabled everywhere, patch WordPress and plugins promptly, enforce strong admin passwords with 2FA, and you meet the baseline. If you ever process raw card numbers on your server (strongly discouraged), you enter full PCI DSS SAQ-D territory, which is a major compliance project.

    Next Steps

    Now that WooCommerce is running on your VPS, here are recommended next steps to grow your store:

    • Install an SEO plugin -- Rank Math or Yoast SEO handle product schema, breadcrumbs, sitemaps, and meta tags. Product schema markup is critical for Google Shopping and rich snippets.
    • Set up email marketing -- Install MailPoet, Klaviyo, or connect Brevo (Sendinblue) for abandoned cart emails, post-purchase flows, and broadcast campaigns. Abandoned cart recovery alone typically recovers 10-15% of lost checkouts.
    • Enable analytics and tracking -- Connect Google Analytics 4 with enhanced ecommerce events, install Microsoft Clarity for session replay, and add the Meta Pixel and Google Ads conversion tags via Google Tag Manager. See How to Install Umami on Ubuntu for a privacy-friendly self-hosted alternative.
    • Deploy a staging environment -- Spin up a second VPS, clone your production database and uploads, and test plugin updates and theme changes there first. Never update plugins directly on production.
    • Add a monitoring and uptime stack -- Follow How to Install Uptime Kuma on Ubuntu for uptime monitoring and How to Build a Monitoring Stack on Ubuntu for Prometheus + Grafana dashboards of your server, MariaDB, and Nginx.
    • Harden with a WAF -- Install CrowdSec or put your store behind Cloudflare's WAF with OWASP Core Rule Set enabled.
    • Explore headless WooCommerce -- Pair the WooCommerce REST API with a Next.js or Nuxt frontend on a separate server for lightning-fast storefronts while keeping the WooCommerce admin for catalog and order management.

    Skip the Manual Install — Get WooCommerce Pre-Installed
    >
    Our Ecommerce VPS plans come with WordPress, WooCommerce, Redis, Nginx FastCGI cache, and Let's Encrypt SSL pre-configured on Ubuntu 24.04. Deploy in 60 seconds and start selling immediately.
    >
    - WordPress 6.7 + WooCommerce latest pre-installed
    - Redis object cache enabled and verified
    - Nginx FastCGI cache with WooCommerce-safe rules
    - PHP 8.3 tuned for WooCommerce (512M memory, 5000 input vars)
    - Let's Encrypt SSL on your domain
    - System cron replacing wp-cron out of the box
    >
    Deploy Your WooCommerce VPS Now — Plans start at EUR 19.99/month on CloudCore Professional.

    Was this article helpful?

    ← Back to Install GuidesBrowse all categories →

    Still have questions?

    Contact Support →Submit a Ticket