Correctly Configuring Linux Server Requirements for Magento
AI generated
$
/etc
Linux · Magento 2 · PHP · Server Administration
Correctly Configuring Linux Server Requirements for Magento
from the requirements list to a running production environment

The official Magento system requirements list only names version numbers, yet a great deal of configuration work on the Linux server sits between those numbers and a working shop. This article translates PHP extensions, memory_limit, OpenSearch, Redis and Varnish into concrete commands and configuration files, and closes with a pre-flight checklist that catches setup mistakes before the first deployment.

17 min read PHP 8.3 · OpenSearch · Redis · Varnish Magento 2.4.8 · Ubuntu/Debian · Nginx

1. Why the official requirements list is only the beginning

The Magento system requirements in the official documentation read like a short shopping list: PHP 8.1 to 8.3, MySQL 8.0 or MariaDB 10.6, OpenSearch 2.x, Redis recommended, Composer 2.x. What is missing from that list is the actual work: how many PHP workers an FPM pool needs under typical shop load, which kernel limits stop OpenSearch from crashing during indexing, and which Redis instance handles which task. Anyone who treats the requirements list as a literal installation guide often ends up with a server that passes every version check but buckles under real traffic.

The difference between a successful bin/magento setup:install run and a production-ready server lies in dozens of small configuration decisions: PHP extensions built with the right compile options, a memory_limit that matches the actual catalog size, an OpenSearch cluster with enough heap memory, and a reverse proxy that genuinely takes load off Magento's full page cache. The following sections translate every point on the official list into concrete Linux configuration, with real commands and testable values.

2. Installing the correct PHP version and extensions

Magento 2.4.8 requires PHP 8.3 (with support for 8.2 on older patch levels), and the list of mandatory extensions is longer than many default installations provide: bcmath, ctype, curl, dom, gd or imagick, intl, mbstring, openssl, pdo_mysql, simplexml, soap, sodium, xsl and zip. On Debian/Ubuntu systems with the Ondrej Sury PPA, all packages can be installed in one go, though sodium and intl are, in our experience, the two most commonly forgotten, since minimal PHP images tend to omit them by default.

After installation it always pays to double check with php -m against the requirements list rather than trusting the setup wizard's outcome, because the wizard sometimes aborts partway through the install process. The PHP CLI and the PHP-FPM pool also need to load the same extensions: a common mistake is a php.ini for CLI that drifts from the FPM configuration, so cron jobs end up running with different values than the web server. Composer itself additionally needs Git and Zip at the operating system level, not merely as PHP extensions.


#!/usr/bin/env bash
# Install PHP 8.3 and all required extensions for Magento 2.4.8 on Ubuntu
set -euo pipefail

sudo add-apt-repository -y ppa:ondrej/php
sudo apt-get update

sudo apt-get install -y \
  php8.3-fpm php8.3-cli \
  php8.3-bcmath php8.3-curl php8.3-gd php8.3-intl \
  php8.3-mbstring php8.3-mysql php8.3-soap php8.3-sodium \
  php8.3-xml php8.3-xsl php8.3-zip php8.3-opcache php8.3-igbinary \
  php8.3-redis php8.3-imagick

# Verify all Magento-required extensions are actually loaded
required=(bcmath ctype curl dom gd intl mbstring openssl pdo_mysql simplexml soap sodium xsl zip)
for ext in "${required[@]}"; do
  php -m | grep -qi "^${ext}$" || echo "[MISSING] ${ext}"
done

php -v

3. memory_limit, OPcache and PHP-FPM tuning

Magento officially recommends a memory_limit of at least 2 GB, but that value is not enough for bin/magento indexer:reindex or Composer operations on larger catalogs. In practice we set memory_limit = 4G for CLI contexts and deliberately keep the value lower for the FPM pool, since many parallel workers there hold memory at the same time, and a value set too high can push the server into swap during a traffic spike. Separate php.ini overrides per SAPI (/etc/php/8.3/cli/conf.d/ versus /etc/php/8.3/fpm/conf.d/) are the correct pattern here, not a single global file for both contexts.

OPcache is not optional for Magento, it is mandatory: without a compiled bytecode cache, every request noticeably slows down due to the framework's many thousands of classes. opcache.memory_consumption=512 and opcache.max_accelerated_files=60000 are realistic starting values for a mid-sized catalog, and max_accelerated_files must always exceed the actual number of PHP files, otherwise the cache keeps recycling. In the PHP-FPM pool, pm.max_children together with the available RAM determines the maximum concurrent request load: a rule of thumb is available RAM divided by the average memory footprint of a PHP process under load, typically 80 to 150 MB per worker for Magento.


; /etc/php/8.3/fpm/pool.d/magento.conf - PHP-FPM pool tuned for Magento 2
[magento]
user = magento
group = magento
listen = /run/php/php8.3-fpm-magento.sock
listen.owner = www-data
listen.group = www-data

pm = dynamic
pm.max_children = 40
pm.start_servers = 8
pm.min_spare_servers = 6
pm.max_spare_servers = 12
pm.max_requests = 500

; FPM workers stay below CLI limit to avoid pushing the host into swap
php_admin_value[memory_limit] = 1G
php_admin_value[max_execution_time] = 120
php_admin_value[upload_max_filesize] = 64M
php_admin_value[post_max_size] = 64M

; opcache tuning - shared across CLI and FPM via /etc/php/8.3/conf.d/10-opcache.ini
; opcache.memory_consumption=512
; opcache.max_accelerated_files=60000
; opcache.validate_timestamps=0  ; production only, requires manual reload on deploy

4. Database: configuring MySQL/MariaDB for Magento

Magento 2.4.8 supports MySQL 8.0.x and MariaDB 10.6 LTS, and both the InnoDB engine and the utf8mb4 character set are strictly required. A commonly overlooked configuration value is innodb_buffer_pool_size, which on a dedicated database server should be roughly 60 to 70 percent of available RAM, since Magento's EAV data model produces many small joins that benefit heavily from the InnoDB buffer pool. Without a sufficient buffer pool, the problem usually shows up first on category page performance, long before it becomes visible in checkout.

max_connections needs to match the number of PHP-FPM workers plus cron processes plus admin sessions, since Magento typically holds its own database connection per active request. A value of 40 pm.max_children plus cron parallelism plus a safety margin quickly adds up to max_connections = 200 or more. In addition, sql_mode should not enable any of the strict modes that Magento explicitly flags as incompatible with certain legacy modules, such as STRICT_TRANS_TABLES, without first checking compatibility with every installed extension.

5. Setting up OpenSearch/Elasticsearch as the search index

Since Magento 2.4.4, an external search index via OpenSearch or Elasticsearch is mandatory, MySQL-based search is no longer supported. Magento 2.4.8 specifically requires OpenSearch 2.5 to 2.19 or Elasticsearch 8.11, with OpenSearch now the recommended option since Elastic has changed its license multiple times. The most common error on first start: vm.max_map_count defaults to 65530 on standard Linux systems, which is too low for the mmap-based indices OpenSearch uses, and must be permanently set to at least 262144, otherwise the service crashes on startup with a cryptic error about virtual memory.

OpenSearch's JVM heap should never exceed 50 percent of available RAM, and never more than 31 GB, since above that threshold the JVM loses the compressed-oops optimization and effective heap usage becomes less efficient. bin/magento indexer:reindex catalogsearch_fulltext is the command to run after configuration to confirm the connection actually works, before the first real product import runs.


# /etc/opensearch/opensearch.yml - single-node setup for a Magento store
cluster.name: magento-search
node.name: magento-search-01
network.host: 127.0.0.1
http.port: 9200
discovery.type: single-node

# Security plugin disabled for internal-only access behind firewall
plugins.security.disabled: true

# Heap size set separately in jvm.options: -Xms4g -Xmx4g (never above 50% of RAM)
bootstrap.memory_lock: true

#!/usr/bin/env bash
# Persist vm.max_map_count so OpenSearch survives a reboot
set -euo pipefail

echo "vm.max_map_count=262144" | sudo tee /etc/sysctl.d/99-opensearch.conf
sudo sysctl -p /etc/sysctl.d/99-opensearch.conf

# Connect Magento to the local OpenSearch instance
bin/magento config:set catalog/search/engine opensearch
bin/magento config:set catalog/search/opensearch_server_hostname 127.0.0.1
bin/magento config:set catalog/search/opensearch_server_port 9200
bin/magento indexer:reindex catalogsearch_fulltext

6. Redis for cache, session and full page cache

Magento can run backend cache, sessions and full page cache all three through Redis, yet the official recommendation to use separate Redis databases or, better, separate instances for each is often ignored in practice. The reason for the separation: a FLUSHALL or a memory eviction event in the session database must never simultaneously clear the full page cache, otherwise every active user loses their cart at once and the server faces a sudden cache-miss storm. Redis 7.x is officially supported by Magento 2.4.8, and maxmemory-policy allkeys-lru makes sense for cache instances, while the session instance should use noeviction instead, so active sessions are never silently dropped.

The PHP redis extension (not the pure predis library) should be installed, since it serializes significantly faster, especially combined with igbinary as the serialization format. In env.php, each Redis role is configured with its own database number and its own port or instance, which considerably simplifies monitoring and capacity planning, since cache hit rate and session load can then be observed separately.


#!/usr/bin/env bash
# Configure three separate Redis roles for Magento via bin/magento CLI
set -euo pipefail

# Backend cache (database 0)
bin/magento setup:config:set \
  --cache-backend=redis \
  --cache-backend-redis-server=127.0.0.1 \
  --cache-backend-redis-db=0 \
  --cache-backend-redis-port=6379

# Full Page Cache (database 1) - separate from backend cache on purpose
bin/magento setup:config:set \
  --page-cache=redis \
  --page-cache-redis-server=127.0.0.1 \
  --page-cache-redis-db=1 \
  --page-cache-redis-port=6379

# Sessions (database 2) - noeviction policy required, never share with cache
bin/magento setup:config:set \
  --session-save=redis \
  --session-save-redis-host=127.0.0.1 \
  --session-save-redis-db=2 \
  --session-save-redis-port=6379

7. Varnish as an HTTP accelerator in front of Magento

Magento ships a built-in full page cache, but it still runs through the PHP process and is therefore considerably slower than a Varnish reverse proxy placed in front, which serves cached pages directly from RAM without ever starting PHP. Magento 2.4.8 officially supports Varnish 7.5 and 7.6, and the VCL configuration Magento generates (bin/magento varnish:vcl:generate) already covers the most important header rules for cache invalidation, but it must always be adapted to the actual domain and backend configuration.

A key pitfall: the X-Magento-Cache-Debug header must be disabled, or at least not publicly visible, in production, while it is indispensable during setup to verify HIT/MISS behavior per request. Equally important is making sure the X-Forwarded-For header is passed through correctly, otherwise Magento logs the same Varnish IP for every visitor, which breaks both analytics and IP-based security rules.


#!/usr/bin/env bash
# Generate and deploy Varnish VCL for Magento 2.4.8
set -euo pipefail

bin/magento config:set system/full_page_cache/caching_application 2
bin/magento config:set system/full_page_cache/varnish/access_list "localhost,127.0.0.1"
bin/magento config:set system/full_page_cache/varnish/backend_host 127.0.0.1
bin/magento config:set system/full_page_cache/varnish/backend_port 8080

bin/magento varnish:vcl:generate --export-version=7.5 > /etc/varnish/default.vcl

# Verify HIT/MISS behaviour before removing the debug header in production
curl -sI https://shop.example.com/ | grep -i x-magento-cache

sudo systemctl restart varnish

8. Pre-flight checklist before deployment

Before bin/magento setup:install or a production deployment even starts, a fixed checklist that systematically ticks off every requirement, rather than relying on gut feeling, pays off. This list has proven itself in practice because it covers exactly the spots where setups fail most often: PHP extensions, memory limits, database connectivity, search index reachability, and file system permissions for var/, pub/media/ and generated/.

An often underestimated point is file system performance: during a deployment, Magento writes tens of thousands of small files into generated/code/ and pub/static/, and a slow network file system such as NFS without matching mount options can stretch a deployment from a few minutes to over an hour. The checklist should therefore also include a brief dd write test on the target directory, to catch gross I/O problems early, before they become visible in a live deployment.

Check point Wrong assumption Correct approach Effect
PHP extensions Setup wizard starts, so everything is fine Check php -m against the official list Prevents a mid-setup abort
memory_limit 2 GB is always enough, per the docs 4 GB for CLI on larger catalogs No abort during reindex/Composer
OpenSearch The default vm.max_map_count is enough Set vm.max_map_count to 262144 No crash on startup
Redis roles One database for cache, FPC and session Separate databases/instances per role No shared cache flush
File system NFS behaves like local disk Run an I/O test before deployment Deployment time stays predictable

Mironsoft

Magento server setup, Linux administration and deployment infrastructure

A Magento server that runs clean from day one?

We configure PHP, OpenSearch, Redis and Varnish for your Magento shop according to the official requirements, and check every point of the pre-flight checklist before your first deployment goes live.

Server audit

Comparing the running configuration against the official Magento requirements

Setup & tuning

Configuring PHP-FPM, OpenSearch heap and Redis roles for production

Deployment safeguards

Integrating pre-flight checks and Varnish VCL into the deploy pipeline

9. Common requirement mismatch errors during setup

Probably the most common error in Magento setups is an incorrect database character set: if the database is created with utf8 instead of utf8mb4, installation only fails later at certain tables with long indexes, often well after the first steps have already succeeded. A second classic is a PHP version that formally sits within the supported range but, as an outdated patch release, carries known incompatibilities with Magento's Composer dependencies, which only surface during composer install with cryptic version constraint errors.

A third recurring error concerns file system permissions: if var/, pub/media/ or generated/ is not owned by the PHP-FPM user, write operations only fail at the first cache flush or media upload, not during setup itself. And a fourth, particularly tricky error: OpenSearch is running, but is unreachable due to a wrong port or firewall rule, so setup:install completes without issue while the live shop's search returns empty results, until someone checks the firewall log.


{
  "_comment": "app/etc/env.php excerpt - common mismatch: db table_prefix and utf8mb4 charset",
  "db": {
    "connection": {
      "default": {
        "host": "127.0.0.1",
        "dbname": "magento",
        "username": "magento",
        "password": "REPLACE_ME",
        "model": "mysql4",
        "engine": "innodb",
        "initStatements": "SET NAMES utf8mb4;",
        "active": "1",
        "driver_options": {
          "1013": "utf8mb4"
        }
      }
    }
  },
  "cache_types": {
    "config": 1,
    "layout": 1,
    "block_html": 1,
    "full_page": 1
  }
}

10. Summary

The Linux server requirements for Magento are not a one-off version check, but an interplay of PHP extensions, memory limits, database configuration, search index and caching services that only works as a whole. PHP 8.3 with all mandatory extensions and separate CLI/FPM configurations forms the foundation, memory_limit and OPcache determine performance under load, and OpenSearch with the correct vm.max_map_count prevents crashes during indexing. Redis split into three separate roles and Varnish as a front-end accelerator take a noticeable amount of load off the PHP process.

The biggest lever is a systematic pre-flight checklist ahead of every deployment: anyone who checks PHP extensions, character set, file system permissions and search index reachability before the first setup:install avoids the typical requirement mismatch errors that would otherwise only surface mid-operation. A checklist set up once can be reused and automated for every subsequent deployment.

Linux Server Requirements for Magento: The Essentials at a Glance

Set up PHP correctly

PHP 8.3 with all mandatory extensions, separate php.ini for CLI and FPM, OPcache always active.

Memory & database

memory_limit 4G for CLI, utf8mb4 as the character set, innodb_buffer_pool_size sized to available RAM.

OpenSearch & Redis

vm.max_map_count set to 262144, Redis split into three separate roles for cache, FPC and session.

Pre-flight checklist

Systematically check PHP extensions, permissions and search index before every deployment.

11. FAQ: Linux Server Requirements for Magento

1Which PHP version does Magento 2.4.8 need on Linux?
PHP 8.3 with limited support for 8.2. Mandatory extensions include bcmath, curl, gd/imagick, intl, mbstring, pdo_mysql, soap, sodium, xsl, zip. Check with php -m.
2Is a memory_limit of 2 GB enough for Magento?
2 GB is the minimum value but is often not enough for reindex or Composer on larger catalogs. 4 GB recommended for CLI, keep the FPM pool deliberately lower.
3Why does OpenSearch crash on first start?
vm.max_map_count is too low. The default of 65530 is not enough, set it permanently to at least 262144 via sysctl.
4Shared Redis instance for cache, session and FPC?
No. Use separate databases or instances per role, otherwise a FLUSHALL or eviction event drags all three areas down at once.
5Is Varnish necessary or does the built-in FPC suffice?
The built-in FPC runs through PHP and is slower. Varnish serves directly from RAM and is the recommended standard for live shops with real traffic.
6Which MySQL/MariaDB version does Magento 2.4.8 support?
MySQL 8.0.x and MariaDB 10.6 LTS, each with InnoDB and utf8mb4. A wrong character set causes later installation errors on long indexes.
7How many PHP-FPM workers does a Magento shop need?
Rule of thumb: available RAM divided by 80 to 150 MB per worker. pm.max_children must also fit within the database's max_connections.
8Most common requirement mismatch error during setup?
Wrong database character set, utf8 instead of utf8mb4, followed by wrong file system permissions for var/, pub/media/ and generated/.
9How do I systematically check all requirements before deployment?
Fixed pre-flight checklist: PHP extensions via php -m, memory limits, database connectivity, OpenSearch reachability via curl, file system permissions checked before setup:install.
10Why does search return no results despite a successful setup?
Usually a misconfigured port or a firewall rule that makes OpenSearch unreachable for PHP. indexer:reindex catalogsearch_fulltext reveals it right away.