GardenCloud & systems

How an older WordPress VPS was put together

A retrospective on Nginx, PHP-FPM, MySQL, file ownership, backups, and certificate boundaries.

The earlier WordPress site used a conventional VPS stack: Nginx accepted web requests, PHP-FPM executed WordPress, and MySQL stored the application data. Understanding those boundaries is more useful than replaying an old installation transcript.

Historical architecture. The source targeted an older Ubuntu/PHP 7.2 environment. This article is a retrospective, not a current installation procedure. No server, database, user, certificate, or DNS record was changed.

Separate the services

Nginx selected the document root and routed ordinary requests through WordPress’s front controller. PHP requests were passed to a Unix socket exposed by PHP-FPM. The original representative virtual host was:

server {
    listen 80;
    listen [::]:80;

    root /home/nhancv/workspace/nhancv.com;
    index index.php index.html index.htm;
    server_name nhancv.com *.nhancv.com;
    # This order might seem weird - this is attempted to match last if rules below fail.
    # http://wiki.nginx.org/HttpCoreModule
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    # Add trailing slash to */wp-admin requests.
    rewrite /wp-admin$ $scheme://$host$uri/ permanent;
    # Directives to send expires headers and turn off 404 error logging.
    location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
           access_log off; log_not_found off; expires max;
    }
    # Uncomment one of the lines below for the appropriate caching plugin (if used).
    #include global/wordpress-wp-super-cache.conf;
    #include global/wordpress-w3-total-cache.conf;
    location ~ [^/]\.php(/|$) {
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        if (!-f $document_root$fastcgi_script_name) {
            return 404;
        }
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
    }
    location ~ /\.ht {
        deny all;
    }
}

# Make alias and apply
sudo ln -s /etc/nginx/sites-available/nhancv.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo service nginx reload

The hostname and paths record the old example. PHP version, socket path, file ownership, and the site’s actual root need to agree. A configuration existing on disk does not prove it is the one Nginx has loaded.

Keep administration distinct from application access

The original checklist created an administrative user, authorized SSH access, added database accounts, and configured FTP. It also included broad passwordless sudo, unrestricted database grants, example passwords, weakened FTP confinement, and a database listener on all interfaces. Those insecure shortcuts are deliberately omitted rather than restyled into deployment instructions.

An application’s database account, an administrator’s login, and the web process’s file permissions serve different purposes. Treating them as one unrestricted identity makes later access and recovery harder to reason about.

Understand the WordPress boundary

The setup downloaded the WordPress archive, selected a document root, and completed application configuration. The database credentials and actual WordPress configuration remain outside this site. The old fixed VPS price and provider-specific login advice are also omitted because they do not establish current requirements.

Preserve a database backup separately

The earlier backup command was:

mysqldump -u wordpress_user_sql -p wordpress_database_nc > wordpress_database_nc_bk.sql

The database and user names identify the source example. A successful dump still needs a restore check; it also does not include uploaded media, themes, or the server’s complete configuration.

Certificates and domain routing

The source later added Certbot, HTTP-to-HTTPS redirects, and a manual DNS challenge for a wildcard certificate. These are separate checks: DNS must answer the challenge, the server must load the right certificate, and each intended hostname must follow the intended route. Old challenge values and redundant configuration snapshots are not republished.

The site’s content and the host’s operational setup are separate recovery assets. That distinction remains useful even when the replacement site no longer needs PHP or a database.

← Back to the garden