Launch a site on a new VPS by provisioning Ubuntu, securing a sudo account and firewall, installing Apache, MySQL and PHP, creating an Apache virtual host, uploading files over SFTP, pointing your domain’s A records to the VPS address, and issuing an HTTPS certificate with Certbot. The sequence below uses current Ubuntu 24.04 practices and keeps the database private while giving your application only the access it needs.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
What you are building
LAMP means Linux, Apache, MySQL and PHP. Linux is the VPS operating system, Apache accepts HTTP requests, MySQL stores application data, and PHP generates dynamic responses. Together they provide the basic runtime for many PHP websites and web applications.
As an Amazon Associate I earn from qualifying purchases.
Free tools Windows power users keep installed
One-click scans. No signup required.
The finished deployment has five important boundaries:
- SSH is used for administration and SFTP, preferably with a key and a non-root sudo account.
- Apache listens publicly on ports 80 and 443.
- MySQL listens only for local application connections unless your architecture explicitly requires otherwise.
- A dedicated Apache virtual host serves your domain from its own document root.
- DNS sends both the apex domain and its
wwwhostname to the VPS IPv4 address.
Prepare the VPS, domain and access
Choose the operating system and server address
Create a VPS running Ubuntu 24.04 LTS and record its public IPv4 address. You will need that address for DNS and for the first Apache test. A VPS provider’s one-click LAMP image can shorten setup; a plain Ubuntu server gives you more control over every package and setting.
#1 Best Overall
DigitalOcean’s 2026 Ubuntu 24.04 LAMP Marketplace image lists Apache 2.4.58, MySQL 8.0.43, PHP 8.4.11, Fail2ban 1.0.2 and Certbot 2.9.0. Those are image versions at the time documented, not permanent version guarantees; packages installed manually will follow the repositories available to your VPS.
Create a non-root administrator
If the provider creates only a root login, add a sudo user immediately and test it in a second SSH session before closing the first one:
adduser adminuser
usermod -aG sudo adminuser
Copy your SSH public key to that account through the provider console or with ssh-copy-id. Routine work should use adminuser with sudo, not a root shell.
Enable the firewall without locking yourself out
On a plain Ubuntu installation, configure UFW after confirming that SSH works:
sudo apt update
sudo apt full-upgrade -y
sudo apt install ufw -y
sudo ufw allow OpenSSH
sudo ufw allow 'Apache Full'
sudo ufw enable
sudo ufw status verbose
Apache Full permits HTTP (80) and HTTPS (443). Do not open MySQL’s 3306 port for a normal single-server application. The current DigitalOcean LAMP image exposes SSH 22, HTTP 80 and HTTPS 443 by default, with SSH rate-limited; check the image’s firewall rules rather than assuming a different image has the same policy.
Install and test Apache
On a plain Ubuntu VPS, install Apache and start it at boot:
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →sudo apt install apache2 -y
sudo systemctl enable --now apache2
The configuration test should report Syntax OK. Before creating a virtual host, open http://SERVER_IP in a browser. The default Apache page proves that the service is reachable through the firewall; it does not yet prove that your domain configuration works.
Install MySQL and create an application account
Run the hardening routine
Install the database server and run the supplied security routine:
Rank #2
sudo apt install mysql-server -y
sudo systemctl enable --now mysql
sudo mysql_secure_installation
Answer the routine’s prompts deliberately. Remove anonymous accounts, disallow remote root access, remove the test database when prompted, and reload the privilege tables. Keep the database local unless a documented design calls for a separate database host.
Create a least-privilege database and user
Do not put a MySQL root password in application configuration. Create a database and account that is limited to that database:
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallsudo mysql
CREATE DATABASE site_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'site_app'@'localhost' IDENTIFIED BY 'use-a-long-unique-secret';
GRANT ALL PRIVILEGES ON site_db.* TO 'site_app'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Use a randomly generated secret in the real command and store it in the application’s protected configuration. The localhost host restriction prevents this account from authenticating from an arbitrary network address.
Install PHP and verify Apache’s PHP handler
Install PHP, Apache’s module and the MySQL extension:
sudo apt install php libapache2-mod-php php-mysql -y
php -v
sudo systemctl restart apache2
For a temporary test, create a file in the current Apache document root:
echo '<?php phpinfo(); ?>' | sudo tee /var/www/html/info.php
Open http://SERVER_IP/info.php. A PHP information page confirms that Apache is executing PHP instead of serving the source code. Delete it immediately after testing because it exposes server paths, modules and configuration details:
sudo rm /var/www/html/info.php
Create a domain-specific document root
Make a deployment account and directory
A custom virtual host should not share the one-click image’s default /var/www/html root. Create a separate tree for the domain and an SFTP account that owns the files:
sudo adduser deploy
sudo usermod -aG www-data deploy
sudo mkdir -p /var/www/example.com/public
sudo chown -R deploy:www-data /var/www/example.com
sudo find /var/www/example.com -type d -exec chmod 750 {} ;
sudo find /var/www/example.com -type f -exec chmod 640 {} ;
Replace example.com with the real hostname. The owner can upload and update files, while Apache’s www-data group can read them. If the application must write to a particular cache or upload directory, grant write permission only to that directory rather than making the whole site world-writable.
Define the Apache virtual host
Create /etc/apache2/sites-available/example.com.conf:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public
<Directory /var/www/example.com/public>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>
ServerName must be the real apex domain, and ServerAlias covers the www hostname. AllowOverride All is useful for applications that ship an .htaccess file; if your application does not need it, use a narrower policy.
Enable the site, enable URL rewriting when the application requires it, and optionally disable Apache’s default site so it cannot win the host match:
sudo a2enmod rewrite
sudo a2ensite example.com.conf
sudo a2dissite 000-default.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
Place the site’s index file, such as index.php, under /var/www/example.com/public. Keep application secrets and private source files outside the public directory whenever the framework supports that layout.
Upload the site with SFTP
SFTP is file transfer over SSH; it is not the unencrypted FTP protocol. Use the deploy account, the VPS IP address or a hostname that already resolves, port 22, and your SSH key (or the temporary password created for that account).
Command-line transfer
From your workstation:
sftp deploy@SERVER_IP
In the SFTP prompt, select the virtual host’s document root and upload the files:
Recommended Free Tools
cd /var/www/example.com/public
lcd ./site
put -r *
Graphical SFTP clients expose the same fields: protocol SFTP, host, port 22, username deploy, and the private key. Upload into /var/www/example.com/public, not into /var/www/html, because the virtual host points to the custom directory.
Fix ownership without broad write access
If an upload creates files owned by the wrong account, reset the tree:
Rank #4
sudo chown -R deploy:www-data /var/www/example.com
sudo find /var/www/example.com -type d -exec chmod 750 {} ;
sudo find /var/www/example.com -type f -exec chmod 640 {} ;
Do not solve an SFTP error with chmod -R 777. It gives every local process and, depending on the directory, every web-exploited process unnecessary write access.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsPoint DNS at the VPS
At the DNS provider, create these records for the same public IPv4 address:
| Host/name | Type | Value | Use |
|---|---|---|---|
@ or the provider’s apex notation |
A | VPS public IPv4 address | example.com |
www |
A | VPS public IPv4 address | www.example.com |
Some DNS dashboards display the apex name as a blank field rather than @. Do not create an A record pointing to a private address. Keep the existing nameservers unless you intentionally move DNS hosting, and wait for the provider’s records to become visible before troubleshooting Apache.
Check resolution from a terminal:
dig +short example.com
dig +short www.example.com
Both commands should eventually return the VPS IPv4 address. DNS caching means different networks can update at different times; test the domain after resolution rather than relying only on the IP address.
Enable HTTPS with Certbot
Certbot needs a registered domain and two DNS records: the apex and www names must resolve to this server, and Apache must have matching ServerName and ServerAlias values. Leave ports 80 and 443 reachable while validation runs.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →The one-click LAMP image includes Certbot. On a plain Ubuntu installation, install the Apache integration if it is not already present:
sudo apt install certbot python3-certbot-apache -y
Request certificates for both names:
sudo certbot --apache -d example.com -d www.example.com
Choose the redirect option when Certbot offers it, or configure the HTTP-to-HTTPS redirect after successful validation. Test both URLs in a browser and renew with:
sudo certbot renew --dry-run
Do not run the certificate command before DNS and the virtual host are correct; validation will reach the wrong server or fail to connect.
Best Value
Validate the complete deployment
Run these checks in order so that a failure identifies the layer that needs attention:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
- Load
http://SERVER_IPand confirm Apache responds. - Load the temporary PHP test, confirm it executes, and remove the file.
- Use a small application-side database test with
site_app, not MySQL root, and confirm it can connect tosite_db. - Run
dig +shortfor both domain names and confirm they return the VPS address. - Open the domain, verify that the custom site—not Apache’s default page—is served, and check the virtual-host logs under
/var/log/apache2if it is not. - Open the HTTPS URL, confirm the certificate covers the hostname, and verify that HTTP redirects to HTTPS.
- Connect through SFTP as
deploy, create or update a harmless file, and confirm Apache can read it without granting general write access.
Security and maintenance after launch
- Use SSH keys and avoid routine root login. If keys work in a second session, set
PermitRootLogin noin/etc/ssh/sshd_config, runsudo sshd -t, then reload SSH. SetPasswordAuthentication noonly after every required account has working keys. - Keep UFW limited to SSH, HTTP and HTTPS unless another service is intentionally part of the design. Review rules after installing control panels or container software.
- Keep MySQL bound to local access and use the dedicated application account. Never publish 3306 merely to make a remote administration tool convenient.
- Apply Ubuntu and application updates. A one-click image reduces initial work but does not remove the operator’s responsibility to patch it.
- Remove test pages such as
phpinfo(), sample applications and unused virtual hosts. - Back up both the database and uploaded files. A VPS snapshot is useful for a rollback, but it is not a substitute for a recoverable, separately stored database backup.
- Review Apache access and error logs, SSH authentication logs and Fail2ban activity when investigating unexpected traffic.
Manual installation or a one-click LAMP image?
| Decision factor | Manual Ubuntu installation | One-click LAMP image |
|---|---|---|
| Setup time | More commands and decisions before the first page loads. | Faster initial deployment because the stack is preinstalled. |
| Package-version control | You choose when to install and upgrade repository packages. | You start from the image’s tested snapshot, then follow its update path. |
| Firewall and hardening | You must configure UFW, SSH policy, MySQL hardening and intrusion controls. | The documented DigitalOcean image includes firewall defaults, Fail2ban and Certbot; verify each setting on the actual image. |
| Database placement | MySQL is normally local unless you design a separate service. | The image uses local MySQL and can optionally attach Managed MySQL, separating database operations from the web VPS. |
| Rollback and rebuild | A clean runbook makes a rebuild predictable, but you assemble every component again. | A provider snapshot or image can make an equivalent rebuild quicker; application data still needs its own backups. |
| Ongoing responsibility | You own every package, configuration and security update from the start. | You still own updates and application security after the image is deployed. |
Choose manual installation when you need deliberate package choices, a custom layout or a repeatable configuration-management process. Choose the image when a conventional PHP stack and quicker first deployment matter more than building each layer yourself.
Troubleshoot by symptom
The IP shows Apache’s default page
The web server is reachable, but the request is not matching your site. Confirm that the file in /etc/apache2/sites-available is enabled, that ServerName matches the requested host, and that the custom document root contains an index file. Disable 000-default.conf if it is still taking the request, then run sudo apache2ctl configtest and reload Apache.
The domain does not resolve
Use dig against the exact apex and www names. Check for a typographical error, an old A record at the DNS provider, or a record still pointing to a previous server. DNS changes can remain cached after the provider shows the new value.
Certbot cannot validate the hostname
Verify both A records, the Apache host names and the public firewall rules. Port 80 must be reachable for the normal HTTP challenge. If the domain resolves to another address, Certbot is contacting that server instead of this VPS.
PHP source code downloads or appears as text
Confirm that libapache2-mod-php is installed, Apache was restarted after installation, and the file has a .php extension. Check the Apache error log and run php -v to confirm the CLI package exists.
The application reports database access denied
Check the database name, username, password and host in the application configuration. The account created above is site_app at localhost; it is not the MySQL root account. Re-run SHOW GRANTS FOR 'site_app'@'localhost'; in MySQL to confirm its privileges.
SFTP reports permission denied
Confirm that you connected as deploy, that the remote path is /var/www/example.com/public, and that the tree is owned by deploy:www-data. Reapply the targeted ownership and permissions rather than making the directory world-writable.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




