Private customers Business customers

Set up a web server on your VPSnginx, PHP, MariaDB and a free SSL certificate

Your own web server on a VPS gives you control over every setting - from PHP limits and caching strategy to the TLS configuration. This guide takes you from an empty system to a site that is reachable via HTTPS.

nginxPHP-FPMMariaDBLet's Encrypt45 minutes

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 .htaccess files.
  • 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.

Rent a VPS from €2.95 / month

Prepaid without a contract, full root access.

View plans & prices

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-Policy and X-Frame-Options belong in every server block. With HTTPS, add Strict-Transport-Security as well.
  • Automatic security updates: install unattended-upgrades so that nginx, PHP and MariaDB receive patches without you doing anything.
  • Keep an eye on the logs: sudo tail -f /var/log/nginx/error.log is 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

Not for testing - the server can also be reached via its IP address. For real operation, you need a domain, at the latest for the SSL certificate: Let's Encrypt does not issue certificates for bare IP addresses. You can register a domain at MainHoster.de; the current prices per extension are on the domains page.

For a typical website with a database and moderate traffic, plan S is enough. An online shop, several projects in parallel or an application with many simultaneous users are better served from M upwards. Since you can upgrade at any time without data loss, starting small is no problem.

No. Certificates from Let's Encrypt are free and accepted by all common browsers. Certbot requests and renews them automatically. You only pay for the VPS itself.

Yes, and that is one of the main advantages over small web hosting packages. Create a separate server block for each domain under /etc/nginx/sites-available/, set up a separate directory under /var/www/ and request the certificate with one certbot call per domain. The number is only limited by the resources of your plan.

Almost always, the path to the PHP-FPM socket in the nginx configuration does not match the installed PHP version. Check with "ls /run/php/" what the socket is actually called and enter the exact name for fastcgi_pass. Then run "sudo nginx -t" and "sudo systemctl reload nginx".

Technically, that is possible on a VPS, but rarely sensible in practice: control panels are resource-hungry and oversized for small plans, and they often come with their own licence costs. If you want graphical management, our web hosting is usually the better fit - Plesk is already included there and maintained by us.

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 & prices