New Customers: 50% OFF Your First Month on All VPS Servers & Web Hosting Plans!

Installing a web server and PHP

Install and configure a web server on your VPS using either Apache or Nginx, paired with PHP-FPM. This guide covers Ubuntu 24.04 and AlmaLinux 9 in parallel, including firewall configuration and PHP version selection for long-term support.

Rhys CallowayLinux VPS, servers, security and the command line 10 min read Updated 23 Sep 2026 AlmaLinux 9, Ubuntu 24.04

Getting a web server running on a VPS is three pieces of work over SSH: install Apache or Nginx from the distribution's own repositories, install PHP (almost always PHP-FPM), then connect the two and open ports 80 and 443 on the firewall. On Ubuntu 24.04 that is apt and possibly ufw. On AlmaLinux 9 it is dnf, firewalld, and SELinux, which is enforcing by default and will quietly block things the Ubuntu box would allow.

This guide covers both operating systems side by side, tells you which PHP version is worth running in 2026, and flags the two or three places where people lose an afternoon.

Before you start

This picks up from a VPS you can already reach over SSH as a user with sudo. If you are not there yet, work through our VPS guides first, because everything below happens inside the server, not in a control panel.

That distinction matters on a Hostworld VPS. Virtualizor, reached from your client area, is where you start, stop, reboot or rebuild the VPS, mount a custom ISO and open the VNC console. It does not install software. Every command in this guide is typed inside the operating system over SSH. The one Virtualizor feature you should know about before you touch a firewall is the VNC console: if you lock SSH out with a bad rule, VNC is how you get back in without a rebuild.

Things worth knowing up front:

  • You need a document root and a domain eventually. Testing by IP address is fine for now. When you are ready to point a domain at the server, your nameservers at the registrar are ns1.serverworld.uk, ns2.serverworld.uk, ns3.serverworld.uk and ns4.serverworld.uk.
  • Do not install both Apache and Nginx. They will both try to bind port 80 and the second one will fail to start.
  • AlmaLinux users: leave SELinux enforcing. Plenty of guides tell you to disable it the moment something returns a 502. Disabling SELinux removes a real security layer and breaks compliance requirements including PCI-DSS and HIPAA. There is a correct fix for every common symptom and they are in Step 6.

Step 1: Decide between Apache and Nginx

Both are in the stock repositories of both operating systems, both are maintained, and either will serve PHP correctly.

Apache is the shorter path if you want per-directory configuration via .htaccess files, which a lot of PHP applications assume. Nginx is usually lighter on memory at the same load and is the more common choice for a PHP application behind PHP-FPM. Nginx has no built-in PHP support at all, so it always hands PHP files to PHP-FPM over a socket. Apache can do it either way.

Our default recommendation on a VPS is PHP-FPM regardless of which web server you pick. It keeps PHP in its own service with its own pool settings, its own logs and its own restart path, which makes both tuning and debugging far less painful than the older Apache module.

Step 2: Install the web server

These commands refresh the package list and install the server, then enable it so it survives a reboot.

Ubuntu 24.04, Nginx:

sudo apt update
sudo apt install nginx
sudo systemctl enable --now nginx

Ubuntu 24.04, Apache:

sudo apt update
sudo apt install apache2
sudo systemctl enable --now apache2

AlmaLinux 9, Nginx. Nginx is an AppStream module with more than one stream available. List them first so you know what you are choosing, rather than accepting whatever DNF picks:

dnf module list nginx
sudo dnf install nginx
sudo systemctl enable --now nginx

AlmaLinux 9, Apache:

sudo dnf install httpd
sudo systemctl enable --now httpd

On AlmaLinux the Apache service is called httpd, not apache2. That naming difference follows you through every log path and config directory, so it is worth registering now.

Step 3: Open the firewall

Until this is done the server is running and the page will not load, which is the single most common "my web server is broken" report we see.

AlmaLinux 9. firewalld is installed and running by default. This allows HTTP and HTTPS permanently, then reloads the running configuration:

sudo firewall-cmd --permanent --add-service=http --add-service=https
sudo firewall-cmd --reload

Ubuntu 24.04. Check whether ufw is active before you change anything, because enabling it carelessly over SSH is how people lock themselves out:

sudo ufw status
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Allow 443 now even though you have no certificate yet. Adding it later is one more thing to forget. Load http://your-server-ip/ in a browser: you should get the distribution's default page.

Step 4: Choose a PHP version before you install one

This is the step that gets skipped, and it decides how long the server stays supported.

As of September 2026 the PHP branches still receiving security updates are 8.5, 8.4, 8.3 and 8.2. PHP 8.5 was released on 20 November 2025 and has active support to 31 December 2027. PHP 8.4 leaves active support on 31 December 2026. PHP 8.3 left active support on 31 December 2025 and is security-only until end of life on 31 December 2027. PHP 8.2 reaches end of life on 31 December 2026, and 8.1 already did so at the end of 2025. The release cycle was extended in March 2024 to four years: two of bug fixes, then two of security fixes.

Against that:

  • Ubuntu 24.04 ships PHP 8.3 in its default repositories. It is supported, but it is a security-only branch, not a current one.
  • AlmaLinux 9 offers PHP as AppStream modules with more than one stream. Which streams are present depends on when your AppStream metadata was built, and older 8.1 content is end of life. Run dnf module list php on your own VPS and read what it actually says rather than trusting a version number from an article, including this one.

If the stock version suits the application you are deploying, use it. If you need a newer branch, both distributions have a well-known third-party route, covered in Step 5.

Step 5: Install PHP

Ubuntu 24.04

The php package includes the command line interpreter and the Apache module. The php-fpm package provides the FastCGI Process Manager that Nginx needs. Install FPM plus the extensions your application asks for:

sudo apt install php-fpm php-cli
sudo systemctl enable --now php8.3-fpm

Extensions are separate packages (php-mysql, php-mbstring, php-xml, php-curl and so on). Confirm exact names with apt search php8.3- before installing rather than guessing.

For a newer or older branch than 8.3, versioned packages such as php8.5 or php8.2 come from Ondrej Sury's third-party APT repository, added with sudo add-apt-repository ppa:ondrej/php. That is not an Ubuntu repository and you are taking on an extra update source by adding it. Understand that trade before you do it.

AlmaLinux 9

AppStream in RHEL 9 and its rebuilds does not define default module streams, so specify the stream explicitly. That also leaves you a record of which version you chose. Substitute the stream you saw in dnf module list php:

dnf module list php
sudo dnf module enable php:8.2 -y
sudo dnf module install php:8.2/common -y
sudo dnf install php-mysqlnd php-mbstring php-xml php-json
php --version
sudo systemctl enable --now php-fpm

For a newer branch, the Remi repository is the standard route. Remi is third-party, maintained by PHP package maintainer Remi Collet, and EPEL is a prerequisite:

sudo dnf config-manager --set-enabled crb
sudo dnf install epel-release -y
sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-9.rpm
sudo dnf module reset php
sudo dnf module enable php:remi-8.3 -y
sudo dnf module install php:remi-8.3/common -y

Check rpms.remirepo.net for the current release RPM rather than copying a point-release URL from anywhere.

One trap: if PHP is already installed, you cannot switch streams with enable. DNF refuses with a message about module_stream_switch and tells you to reset the module first. The cleaner command on AlmaLinux 9 is sudo dnf module switch-to php:8.2, which moves the installed packages across.

Step 6: Connect PHP to the web server

Nginx on either OS

In your server block, pass .php requests to the FPM socket. On Ubuntu the socket is version-numbered, typically /run/php/php8.3-fpm.sock. Confirm the real path with ls /run/php/ before you paste it, because a PHP minor-version change renames that socket and breaks the site.

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

AlmaLinux plus Nginx has a specific trap. The FPM pool config at /etc/php-fpm.d/www.conf ships configured to run as the apache user. If you switch it to nginx, do it consistently, and be aware AlmaLinux also drops a PHP snippet at /etc/nginx/default.d/php.conf that may conflict with a handler you have written yourself. The usual failure is nginx: [emerg] no port in upstream. Session errors in the Nginx log afterwards normally mean old session files are still owned by root or apache, and are fixed by resetting ownership to nginx.

Apache with PHP-FPM

Apache delegates PHP to FPM through proxy_fcgi. On Ubuntu, enable the modules and the packaged config:

sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.3-fpm
sudo systemctl reload apache2

If you are writing the handler yourself, this block in the site config sends PHP files to the socket. Alter the version and path to match your server:

<FilesMatch \.php$>
    SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost/"
</FilesMatch>

Note that /var/run is a symlink to /run on modern Ubuntu, so both paths work. Pick one and stay consistent.

SELinux on AlmaLinux

SELinux covers Nginx as well as Apache, because Nginx runs in the same httpd_t domain. Every httpd_* boolean and file context applies to both.

The symptom you will actually see is a 502 Bad Gateway with something like connect() to 127.0.0.1:9000 failed (13: Permission denied) while connecting to upstream in the error log. That is not a file permission problem. The default policy forbids outgoing network connections from the web server. Allow it persistently:

sudo setsebool -P httpd_can_network_connect on

The -P makes it survive a reboot. Without it the boolean resets and the site breaks on next restart. If you only need database connectivity, httpd_can_network_connect_db is narrower and therefore better.

Serving from a directory outside the default document root needs a file context, not a chmod:

sudo semanage fcontext -a -t httpd_sys_content_t "/custom/web(/.*)?"
sudo restorecon -Rv /custom/web

Step 7: Test, then delete the test file

Create a file in your document root that prints the PHP configuration:

echo "<?php phpinfo();" | sudo tee /var/www/html/info.php

On AlmaLinux with Nginx the default root is usually /usr/share/nginx/html. Check your config rather than assuming. Load http://your-server-ip/info.php. You should see the PHP information table. If you see the raw source code instead, or the browser downloads the file, PHP is not wired to the web server and Step 6 is where to look.

Delete the file immediately afterwards. It publishes your paths, modules and versions to anyone who finds it:

sudo rm /var/www/html/info.php

Finally, note where the config files live, because there is one per SAPI and per version on Ubuntu: CLI at /etc/php/8.3/cli/php.ini, Apache at /etc/php/8.3/apache2/php.ini, FPM at /etc/php/8.3/fpm/php.ini. Editing the CLI file and wondering why the website has not changed is a classic. Pool settings are separate again, at /etc/php/8.3/fpm/pool.d/www.conf on Ubuntu and /etc/php-fpm.d/www.conf on AlmaLinux. Under FPM, changes need a service restart, not an Apache reload.

What next

The logical next step is adding HTTPS with Let's Encrypt and Certbot. Three things to carry into it. First, install the web server plugin as well as Certbot itself: apt install certbot alone, followed by certbot --nginx, produces unrecognized arguments: --nginx because python3-certbot-nginx is missing. On AlmaLinux 9 the Certbot packages come from EPEL, so confirm the names with dnf search certbot. Second, do not install Certbot twice, for example the Ubuntu archive package and the snap. Two installs mean two renewal timers pointed at the same /etc/letsencrypt tree, and the one you forgot is the one that bites. Third, keep port 80 open after HTTPS works. Let's Encrypt starts HTTP-01 validation on port 80 and a redirect to HTTPS is fine, but a firewall that only allows 443 blocks every unattended renewal.

After that, look at PHP-FPM pool tuning and backups in our VPS guides. If a command in this guide behaves differently on your server, tell us what you ran and what came back and open a support ticket. Tickets are logged against your account, so whoever picks it up can see the machine.

Common questions

Do I need PHP-FPM if I am using Apache?

Not strictly. Apache can run PHP as a module, which is the shortest Apache-only path. We still recommend PHP-FPM on a VPS because PHP then has its own service, its own pool limits and its own logs, which makes both tuning and restarting far less disruptive.

My site started serving PHP as plain text after an upgrade. Why?

The web server is no longer handing .php files to PHP. After a distribution upgrade the Apache module symlinks are not always moved: administrators upgrading Ubuntu 22.04 to 24.04 have found php8.1.conf and php8.1.load still enabled in mods-enabled instead of the 8.3 equivalents. With Nginx, the usual cause is a fastcgi_pass socket path that no longer exists after a PHP version change.

Can I run more than one PHP version on the same VPS?

Yes, and the switching mechanism differs by setup. With Apache and mod_php you use a2dismod and a2enmod. With Apache and PHP-FPM you use a2disconf php8.3-fpm and a2enconf php8.2-fpm. With Nginx you change the fastcgi_pass socket. Mixing those up gives you either source code in the browser or a 502.

Should I disable SELinux to get past a 502?

No. It is the most commonly suggested fix online and it is the wrong one. The 502 almost always comes from one boolean or one missing file context, and the targeted fix takes one command. Disabling SELinux removes a security layer across the whole server.

Does Hostworld set any of this up for me?

A Linux VPS is delivered as a clean operating system, so the web server and PHP are yours to install. You control the rebuild, the ISO and the console yourself through Virtualizor in your client area. If you would rather have cPanel handle PHP versions and virtual hosts for you, our shared, reseller and WordPress hosting are all cPanel instead.