Published on
Decide first: nginx or Apache?
Both do the job reliably; the differences in everyday use are smaller than often claimed. In short:
- nginx is more economical with memory and serves static files faster. That makes it the obvious choice on small VPS plans. It is configured centrally - nginx does not know
.htaccessfiles. - Apache is more flexible if you rely on
.htaccess- for example because an application ships its rewrite rules that way. In return, it uses more memory per connection.
This guide uses nginx. If you prefer Apache, replace the installation commands accordingly with apt install apache2 libapache2-mod-php; database, certificate and hardening stay identical.
Prerequisite: the VPS is set up and secured. If not, work through the first steps and SSH hardening first.
Step 1: Install nginx
sudo apt update
sudo apt install nginx -y
sudo systemctl enable --now nginx
Then open the two web ports in the firewall:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw status
If you now open your VPS's IP address in a browser, the nginx default page appears. The foundation is in place.
Step 2: Set up PHP-FPM
nginx does not run PHP itself but passes requests on to PHP-FPM. Install PHP together with the extensions that practically every application needs:
sudo apt install php-fpm php-mysql php-mbstring php-xml php-curl php-zip php-gd php-intl -y
Check which version was installed - you will need the value in the nginx configuration shortly:
php -v
systemctl status php*-fpm --no-pager | head -n 3
For applications that process larger files, it is worth looking at the PHP configuration in /etc/php/VERSION/fpm/php.ini. Typical adjustments:
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 120
After changes, reload the service: sudo systemctl reload php*-fpm.
Step 3: Install and secure MariaDB
sudo apt install mariadb-server -y
sudo mysql_secure_installation
The hardening script asks several questions. Sensible answers: remove anonymous users (yes), disallow remote root login (yes), remove the test database (yes), reload privilege tables (yes).
Then create a database and user for your project:
sudo mariadb
CREATE DATABASE myapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'myapp'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON myapp.* TO 'myapp'@'localhost';
FLUSH PRIVILEGES;
EXIT;
The @'localhost' is important: the database should only be reachable from the server itself, never directly from the internet. A database server reachable from the network is one of the most common causes of compromised systems.
Step 4: Point your domain to the VPS
Before you can request a certificate, your domain must point to the VPS's IP address. To do this, create an A record in your domain's DNS:
yourdomain.com. A YOUR-SERVER-IP
www.yourdomain.com. A YOUR-SERVER-IP
Depending on the TTL, it takes between a few minutes and a few hours until the change is known everywhere. You can check whether it already applies with:
dig +short yourdomain.com
No domain yet? At MainHoster.de, you can register the domain you want including management of the DNS records. The details of the DNS setup are in the guide Point a domain to your VPS.
Step 5: Create a virtual host
A virtual host - called a server block in nginx - tells the web server which files to serve for which domain. First create the directory:
sudo mkdir -p /var/www/yourdomain.com/html
sudo chown -R www-data:www-data /var/www/yourdomain.com
echo "<h1>It works</h1>" | sudo tee /var/www/yourdomain.com/html/index.html
Then the configuration:
sudo nano /etc/nginx/sites-available/yourdomain.com
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
root /var/www/yourdomain.com/html;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
Enable, check the configuration, reload:
sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
The command nginx -t is the most important line: it reports syntax errors before a restart takes the site offline. If it reports an error for the fastcgi_pass path, check with ls /run/php/ what the socket is actually called on your system.
Step 6: Set up a free SSL certificate
HTTPS is mandatory today - for search engines, for browser warnings and simply for your visitors' security. Certificates from Let's Encrypt are free and set up with two commands:
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Certbot asks for an email address for expiry warnings, fetches the certificate and adjusts your nginx configuration automatically - including a redirect from HTTP to HTTPS if you confirm it.
Renewal then runs automatically via a systemd timer. You can check that it is set up like this:
systemctl list-timers | grep certbot
sudo certbot renew --dry-run
The dry run simulates the renewal without touching the real certificate. If it succeeds, you never have to worry about it again.
Secure it and keep it running
A few points that make the difference between "works" and "works reliably":
- Hide the server version: add the line
server_tokens off;in/etc/nginx/nginx.conf. This reveals less about your version to attackers. - Set security headers:
X-Content-Type-Options,Referrer-PolicyandX-Frame-Optionsbelong in every server block. With HTTPS, addStrict-Transport-Securityas well. - Automatic security updates: install
unattended-upgradesso that nginx, PHP and MariaDB receive patches without you doing anything. - Keep an eye on the logs:
sudo tail -f /var/log/nginx/error.logis the first thing to check when something does not work. - Set up backups: files and database dumps, to a target outside the server. Details in the guide Set up backups.
Would web hosting not be easier?
Honest answer: in many cases, yes. If you want to run a WordPress site with a few mailboxes, web hosting with Plesk takes exactly the work described in this guide off your hands - including updates, SSL management and a backup manager, without you having to worry about server security.
Your own web server on a VPS pays off as soon as you want to install software that does not run on web hosting, bundle several services, need your own caching or proxy setups, or simply want to learn how it all fits together. A detailed comparison is in the guide VPS or web hosting. If you would rather run your applications in containers, the Docker guide shows the alternative route.
Frequently asked questions
A VPS for your web project
For a typical website with a database, plan S is enough; for several projects in parallel or an online shop, M or L is recommended. All plans with NVMe SSD in RAID 1, unmetered traffic and located in Frankfurt am Main.
View VPS plans & pricesRent a VPS
from €2.95 / month
Prepaid without a contract, full root access, DDoS protection up to 250 Gbit/s.
View plans & pricesRead more
- VPS - plans & prices
- First steps on your VPS
- Secure SSH access
- Install Docker
- Set up backups
- Web hosting or VPS?
- Point a domain to your VPS
Discover more