Skip to content

25 October 2026 · 6 min read

How to Deploy a PHP Website to a VPS, Step by Step

To deploy a PHP website to a VPS is to put your code on a server you control and make it reachable over HTTPS. It is a rite of passage for many developers, and it is easier than it looks once you know the order of operations. This guide walks the classic manual route, in order, then shows where it usually goes wrong, and finally how to reach the same result without a terminal.

What you need

  • A VPS running a recent Debian or Ubuntu release, with root or sudo access over SSH
  • A domain name pointing at the server's IP address
  • Your PHP application files, ready to upload

The steps below assume a plain LEMP-style stack: nginx, PHP-FPM and MySQL. Other distributions package the same software under different names, but the shape of the process is identical everywhere.

The manual route

1. Update the system

Always start from a current base, otherwise package versions will disagree with the documentation you are reading.

sudo apt update && sudo apt upgrade -y

2. Install nginx, PHP-FPM and MySQL

Install the web server, the PHP handler and the database in one pass. PHP-FPM is what actually executes your PHP files; nginx only talks to it.

sudo apt install -y nginx php-fpm php-mysql mysql-server

3. Create the site directory and a server block

Give the site its own directory and its own nginx configuration file.

sudo mkdir -p /var/www/mysite
sudo nano /etc/nginx/sites-available/mysite

A minimal server block looks like this:

server {
    listen 80;
    server_name mysite.co.uk www.mysite.co.uk;
    root /var/www/mysite;
    index index.php index.html;

    location / {
        try_files $uri $uri/ =404;
    }

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

Enable it, test the syntax, then reload:

sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

4. Upload your files

rsync is the friendliest way to copy a project from your machine to the server. It only transfers what changed, so repeat deploys are quick. scp works for one-off files.

rsync -avz --exclude .git ./dist/ user@your-server-ip:/var/www/mysite/

Run a final ls -la on the directory afterwards to confirm nothing was copied with the wrong owner.

5. Create the database and a dedicated user

Do not let the application connect as root. Create a database and a least-privilege user for it:

sudo mysql
CREATE DATABASE mysite CHARACTER SET utf8mb4;
CREATE USER 'mysite'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON mysite.* TO 'mysite'@'localhost';
FLUSH PRIVILEGES;

6. Get a TLS certificate

With DNS already pointing at the server, a free certificate takes one command. It also rewrites your nginx block to listen on 443.

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d mysite.co.uk -d www.mysite.co.uk

7. Set permissions

The web server needs to read the files, and your deploy user needs to own them. Keep write access out of anything nginx serves directly.

sudo chown -R user:www-data /var/www/mysite
sudo find /var/www/mysite -type d -exec chmod 755 {} \;
sudo find /var/www/mysite -type f -exec chmod 644 {} \;

Where it usually goes wrong

Almost every failed first deployment traces back to one of four causes.

  • Permissions. A 403 error, or a blank page, after an upload is almost always an ownership or chmod problem on the new directory.
  • The wrong PHP-FPM socket. The path in fastcgi_pass must match the socket your PHP version actually created. Check /run/php/ if the site downloads PHP files as plain text or returns a 502.
  • DNS. Certificate issuance fails if the domain has not propagated to the server's IP yet. Verify with dig +short mysite.co.uk before running Certbot.
  • Port 80 blocked. Some providers ship a firewall that blocks port 80, which both Let's Encrypt and the initial HTTP redirect need. Check sudo ufw status and the provider's own firewall panel.

Deploying PHP without the terminal

The manual route teaches you a great deal, but you do not have to type it every time. Local Panel's PHP deployment flow handles the uploads, the database and the web-server configuration from a desktop app, and its nginx configuration screen lets you create and edit server blocks with the syntax checked for you. One-click installations cover the stack itself, and SSL certificate management is built in, so the whole sequence above becomes a short guided task rather than an afternoon.

Your SSH passwords and private keys stay on your device, encrypted by the operating system's keychain. Connections run straight from the app to your server, and nothing is installed on the server itself. Once the site is live, live monitoring of CPU, memory, disk and services helps you confirm the deployment is behaving as expected — our VPS monitoring guide covers what to watch first.

When managed hosting is the better choice

To be fair: if you do not want to think about operating systems at all, a good managed PHP host is a legitimate choice. You give up some control and pay an ongoing fee rather than the cost of a VPS, but updates, security and backups are someone else's problem. The same trade-off applies to shared hosting versus a VPS more broadly: less responsibility, less flexibility. Managed PHP hosting and self-hosting on a VPS both have their place; the right answer depends on how much of the stack you actually want to own. If you choose the VPS route, the steps above will get you there, with or without a terminal.

Prefer the guided route? Local Panel is a one-off payment of £59.99 with no subscription, and Local Panel Lite is free forever if you want to start small.