Modern Drupal is managed with Composer: core, modules and their libraries are all dependencies in composer.json. This guide shows how to install Drupal with Composer and Drush on a Linux VPS with Nginx and PHP-FPM.
Before you start
- A VPS with Nginx, PHP-FPM and MySQL/MariaDB or PostgreSQL (a LEMP stack), plus Composer.
- The PHP version required by the Drupal major version you install (check Drupal's requirements page).
- PHP extensions:
gd,mbstring,xml,pdo_mysql(orpdo_pgsql),curl,zip,opcache,intl. - For cPanel hosting, Softaculous offers a one-click Drupal install instead.
Create the database
mysql -e "CREATE DATABASE drupal CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER 'drupal'@'localhost' IDENTIFIED BY 'strong-password'; GRANT ALL ON drupal.* TO 'drupal'@'localhost';"Create the project with Composer
As your deploy user:
composer create-project drupal/recommended-project /var/www/drupalcd /var/www/drupal && composer require drush/drushThe project has a web folder (the document root) and keeps vendor and config outside it, which is more secure.
Configure Nginx
server {
server_name example.com;
root /var/www/drupal/web;
index index.php;
location ~ (^|/)\. { return 403; }
location ~ \..*/.*\.php$ { return 403; }
location ~ ^/sites/.*/private/ { return 403; }
location ~ ^/sites/[^/]+/files/.*\.php$ { deny all; }
location / {
try_files $uri /index.php?$query_string;
}
location ~ '\.php$|^/update.php' {
fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ ^/sites/.*/files/styles/ {
try_files $uri @rewrite;
}
location @rewrite {
rewrite ^ /index.php;
}
}Reload Nginx and add SSL with Certbot.
Install the site with Drush
vendor/bin/drush site:install standard --db-url=mysql://drupal:strong-password@localhost/drupal --site-name="My Site" --account-name=admin --account-mail=admin@example.comDrush prints a generated admin password (or set one with --account-pass). You can also run the web installer at https://example.com instead.
Permissions and settings
- The web server must write only to
web/sites/default/files:chown -R deploy:www-data web/sites/default/files && chmod -R g+w web/sites/default/files - Protect
settings.phpafter install:chmod 444 web/sites/default/settings.php. - Set trusted hosts in
settings.phpto block host header attacks:$settings['trusted_host_patterns'] = ['^example\.com$', '^www\.example\.com$']; - Move configuration sync outside the web root:
$settings['config_sync_directory'] = '../config/sync';
Cron
Drupal runs maintenance tasks via cron. Disable the built-in "automated cron" module for performance and use system cron:
*/15 * * * * cd /var/www/drupal && vendor/bin/drush cron >/dev/null 2>&1Install modules and update
composer require drupal/pathauto && vendor/bin/drush en pathauto -yUpdate core and modules:
composer update "drupal/core-*" --with-all-dependencies && vendor/bin/drush updatedb -y && vendor/bin/drush cache:rebuildBack up the database first (drush sql:dump --gzip --result-file=../backup.sql).
Troubleshooting
- The provided host name is not valid: add the domain to
trusted_host_patterns. - Image styles not generated (404): the
styleslocation rules are missing in Nginx. - White screen: check
drush watchdog:showand the PHP error log; usually memory limit or a missing extension. - Composer runs out of memory: run
COMPOSER_MEMORY_LIMIT=-1 composer ...or add swap.
Drupal FAQ
Should I still use tarball installs?
No. Composer is the supported way; it manages module dependencies that tarballs cannot.
What is Drush?
Drupal's command-line tool for installs, updates, cache clears, cron and configuration import/export.
Can I run Composer-based Drupal on cPanel?
Yes, with SSH access: run Composer in your home directory and point the domain's document root at the web folder.
