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_passmust 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.ukbefore 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 statusand 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.