Magento Open Source (now maintained by Adobe) is a PHP e-commerce platform built for large catalogs, multiple store views and complex pricing. It has more moving parts than most web applications: a web server, PHP-FPM, a MySQL-compatible database, a search engine and, for good performance, Redis. In this tutorial you will install Magento 2.4 on Ubuntu 24.04 with Nginx, PHP 8.3, MariaDB 11.4, OpenSearch 2 and Redis, secure it with HTTPS, and switch it to production mode.
Prerequisites
To follow this guide you need:
- A server running Ubuntu 24.04 LTS, for example a CubePath VPS, with at least 4 CPU cores, 8 GB of RAM and 40 GB of SSD storage. OpenSearch alone needs 1 to 2 GB of RAM.
- A non-root user with
sudoprivileges. This guide calls ityour_user; it will own the Magento files. - A domain such as
shop.your_domainwith a DNS A record pointing toyour_server_ip. - Magento Marketplace access keys. Sign in at
commercemarketplace.adobe.com, open My Profile > Access Keys and create a key pair. Composer uses the public key as username and the private key as password to download Magento.
NoteSupported versions change with every Magento release. This guide targets Magento 2.4.8, which supports PHP 8.3, MariaDB 11.4 and OpenSearch 2.19. Check the official system requirements page for the release you install and adjust the versions if needed.
Step 1 - Installing Nginx and PHP 8.3
Ubuntu 24.04 ships PHP 8.3, which Magento 2.4.8 supports. Install Nginx, PHP-FPM, the PHP extensions Magento requires, Composer and unzip:
sudo apt update
sudo apt install nginx php8.3-fpm php8.3-cli php8.3-mysql php8.3-bcmath php8.3-curl php8.3-gd php8.3-intl php8.3-mbstring php8.3-soap php8.3-xml php8.3-zip composer unzip
Check that the extensions Magento checks for are loaded:
php -m | grep -E "bcmath|intl|soap|sodium|xsl|zip|gd|pdo_mysql|sockets"
bcmath
gd
intl
pdo_mysql
soap
sockets
sodium
xsl
zip
Magento needs more memory and a larger OPcache than the PHP defaults. Create a drop-in file that applies to both PHP-FPM and the CLI:
sudo nano /etc/php/8.3/mods-available/magento.ini
memory_limit=2G
max_execution_time=1800
realpath_cache_size=10M
realpath_cache_ttl=7200
opcache.memory_consumption=512
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=60000
opcache.save_comments=1
zlib.output_compression=On
opcache.save_comments=1 is mandatory: Magento reads annotations from PHP comments. Enable the file for all SAPIs and restart PHP-FPM:
sudo phpenmod magento
sudo systemctl restart php8.3-fpm
php -i | grep -E "^memory_limit|opcache.save_comments"
memory_limit => 2G => 2G
opcache.save_comments => On => On
Step 2 - Installing MariaDB 11.4
Ubuntu 24.04 includes MariaDB 10.11 and MySQL 8.0, but Magento 2.4.8 is tested against MariaDB 11.4 and MySQL 8.4. Install MariaDB 11.4 LTS from the official MariaDB repository.
Download the repository signing key:
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL -o /etc/apt/keyrings/mariadb-keyring.pgp https://mariadb.org/mariadb_release_signing_key.pgp
Create the repository file:
sudo nano /etc/apt/sources.list.d/mariadb.sources
Types: deb
URIs: https://deb.mariadb.org/11.4/ubuntu
Suites: noble
Components: main
Signed-By: /etc/apt/keyrings/mariadb-keyring.pgp
Install the server and check its version:
sudo apt update
sudo apt install mariadb-server
sudo mariadb -e "SELECT VERSION();"
+-----------------------------+
| VERSION() |
+-----------------------------+
| 11.4.8-MariaDB-ubu2404 |
+-----------------------------+
Create the database and a dedicated user. Replace your_db_password with a strong password:
sudo mariadb
CREATE DATABASE magento;
CREATE USER 'magento'@'localhost' IDENTIFIED BY 'your_db_password';
GRANT ALL PRIVILEGES ON magento.* TO 'magento'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Give InnoDB enough memory to keep the catalog cached. Create a drop-in file:
sudo nano /etc/mysql/mariadb.conf.d/99-magento.cnf
[mysqld]
innodb_buffer_pool_size = 2G
max_allowed_packet = 64M
On an 8 GB server, 2 GB is a sensible start. Restart MariaDB:
sudo systemctl restart mariadb
Step 3 - Running OpenSearch
Magento 2.4 requires a search engine; current releases use OpenSearch. The simplest reliable way to run a single node on the same server is the official container, with the security plugin disabled and the port bound to localhost only, so it is never exposed to the Internet.
If Docker is not installed yet, install it from Docker's official repository:
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
OpenSearch needs a higher memory map limit than the kernel default:
echo "vm.max_map_count=262144" | sudo tee /etc/sysctl.d/99-opensearch.conf
sudo sysctl --system
Start OpenSearch with a 1 GB heap and a named volume for its data:
sudo docker run -d --name opensearch --restart unless-stopped \
-p 127.0.0.1:9200:9200 \
-e "discovery.type=single-node" \
-e "DISABLE_SECURITY_PLUGIN=true" \
-e "DISABLE_INSTALL_DEMO_CONFIG=true" \
-e "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g" \
-v opensearch-data:/usr/share/opensearch/data \
opensearchproject/opensearch:2.19.1
After about 30 seconds, check that the cluster is healthy:
curl -s http://127.0.0.1:9200/_cluster/health?pretty | grep status
"status" : "green",
Step 4 - Installing Redis
Magento can store its application cache, full-page cache and sessions in Redis instead of the file system, which is much faster and works when you later add more web servers. Install Redis and check it:
sudo apt install redis-server
redis-cli ping
PONG
Step 5 - Downloading Magento with Composer
Create the web root and give it to your_user, who will run Composer and bin/magento:
sudo mkdir -p /var/www/magento
sudo chown your_user:www-data /var/www/magento
cd /var/www/magento
Download Magento Open Source. When Composer asks for credentials, enter your Marketplace public key as the username and the private key as the password, and let it save them:
composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition .
The download takes several minutes. When it finishes, set the permissions Magento documents for a shared group setup: the files belong to your_user, the group is www-data (the PHP-FPM user), and the directories Magento writes to are group writable:
find var generated vendor pub/static pub/media app/etc -type f -exec chmod g+w {} +
find var generated vendor pub/static pub/media app/etc -type d -exec chmod g+ws {} +
sudo chown -R your_user:www-data .
chmod u+x bin/magento
Step 6 - Running the Magento installer
Run the installer from the Magento root. Replace the placeholders with your own values; the admin password must be at least 7 characters and contain letters and numbers:
bin/magento setup:install \
--base-url=http://shop.your_domain/ \
--db-host=localhost \
--db-name=magento \
--db-user=magento \
--db-password=your_db_password \
--admin-firstname=Admin \
--admin-lastname=User \
--admin-email=admin@your_domain \
--admin-user=your_admin_user \
--admin-password=your_admin_password \
--language=en_US \
--currency=USD \
--timezone=UTC \
--use-rewrites=1 \
--search-engine=opensearch \
--opensearch-host=127.0.0.1 \
--opensearch-port=9200 \
--session-save=redis \
--session-save-redis-host=127.0.0.1 \
--session-save-redis-db=2 \
--cache-backend=redis \
--cache-backend-redis-server=127.0.0.1 \
--cache-backend-redis-db=0 \
--page-cache=redis \
--page-cache-redis-server=127.0.0.1 \
--page-cache-redis-db=1
The Redis options put the default cache in database 0, the full-page cache in database 1 and sessions in database 2, so they can be flushed independently. At the end the installer prints the admin path:
[SUCCESS]: Magento installation complete.
[SUCCESS]: Magento Admin URI: /admin_1x2y3z
Write it down. You can print it again later with bin/magento info:adminuri.
Step 7 - Configuring Nginx
Magento ships a tested Nginx configuration in nginx.conf.sample, which you include instead of writing your own. It expects an upstream called fastcgi_backend and a variable called $MAGE_ROOT.
Create the server block:
sudo nano /etc/nginx/sites-available/magento
upstream fastcgi_backend {
server unix:/run/php/php8.3-fpm.sock;
}
server {
listen 80;
listen [::]:80;
server_name shop.your_domain;
set $MAGE_ROOT /var/www/magento;
include /var/www/magento/nginx.conf.sample;
}
The sample configuration serves files from $MAGE_ROOT/pub, so the application code, app/etc/env.php and vendor/ are never reachable from the web. Enable the site, remove the default one and reload:
sudo ln -s /etc/nginx/sites-available/magento /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
If UFW is active, allow web traffic:
sudo ufw allow 'Nginx Full'
Open http://shop.your_domain in your browser. You should see the default Luma storefront.
Step 8 - Enabling HTTPS
Install Certbot and request a certificate. Certbot edits the Magento server block to add TLS and a redirect from HTTP:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d shop.your_domain
Tell Magento to use HTTPS for the storefront and the admin:
cd /var/www/magento
bin/magento setup:store-config:set --base-url="https://shop.your_domain/" --base-url-secure="https://shop.your_domain/" --use-secure=1 --use-secure-admin=1
bin/magento cache:flush
Load https://shop.your_domain and confirm that the browser shows a valid certificate and no mixed content warnings.
Step 9 - Setting up cron
Magento depends on cron for indexing, emails, currency rates, sitemap generation and cleaning up caches. Without it, product changes do not appear on the storefront. Install Magento's crontab for your_user:
bin/magento cron:install
crontab -l
#~ MAGENTO START ...
* * * * * /usr/bin/php8.3 /var/www/magento/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule" >> /var/www/magento/var/log/magento.cron.log
#~ MAGENTO END ...
Set the indexers to update on schedule, so they run in the background from cron instead of during admin saves:
bin/magento indexer:set-mode schedule
bin/magento indexer:status
After a few minutes every indexer should show Ready.
Step 10 - Switching to production mode
A fresh install runs in default mode, which generates static files and code on demand. Production mode compiles dependency injection, deploys static content once and disables developer features. It is the single biggest speed gain for a Magento store:
bin/magento deploy:mode:set production
This runs setup:di:compile and setup:static-content:deploy, which takes several minutes. Confirm the mode:
bin/magento deploy:mode:show
Current application mode: production. (Note: Environment variables may override this value.)
In production mode, after installing an extension or changing a theme you must rerun bin/magento setup:upgrade, bin/magento setup:di:compile and bin/magento setup:static-content:deploy.
Check that every cache type is enabled and that the full-page cache is working. Request a category page twice and compare the time to first byte:
bin/magento cache:status
curl -s -o /dev/null -w "%{time_starttransfer}\n" https://shop.your_domain/
curl -s -o /dev/null -w "%{time_starttransfer}\n" https://shop.your_domain/
1.428
0.087
The second request is served from the Redis full-page cache.
Step 11 - Signing in to the admin
Open https://shop.your_domain/admin_1x2y3z (your own admin path) and sign in. Magento enables two-factor authentication for the admin by default and sends the setup link by email, so outgoing mail must work on the server first. Configure an SMTP relay or a transactional email service, then choose Google Authenticator or another supported provider when prompted.
WarningGuides often suggest disabling the
Magento_TwoFactorAuthmodule to skip this step. Only do that on a local test machine, never on a store that is reachable from the Internet.
Troubleshooting
setup:install fails with Could not validate a connection to the OpenSearch. OpenSearch is not ready or not running. Check sudo docker logs opensearch and the health endpoint from Step 3. Heap errors mean the server does not have enough free memory.
The storefront loads without CSS and images. Static files were not deployed or Nginx points to the wrong root. Check that set $MAGE_ROOT is /var/www/magento (not /var/www/magento/pub) and rerun bin/magento setup:static-content:deploy -f in production mode.
Permission denied errors in var/log or generated. Commands were run as root and created files PHP-FPM cannot write. Never run bin/magento with sudo; repeat the permission commands from Step 5.
Product changes do not show on the storefront. Cron is not running. Check crontab -l for your_user and read var/log/magento.cron.log.
Conclusion
You now have Magento Open Source 2.4 running on Ubuntu 24.04 with Nginx, PHP 8.3, MariaDB 11.4, OpenSearch and Redis, served over HTTPS in production mode with cron and scheduled indexers. As next steps, put Varnish in front of Nginx for full-page caching at scale, configure a transactional email provider for order emails, and set up daily database and pub/media backups stored off the server.
