How to Install and Configure Drupal on Ubuntu 22.04

Traducciones al Español
Estamos traduciendo nuestros guías y tutoriales al Español. Es posible que usted esté viendo una traducción generada automáticamente. Estamos trabajando con traductores profesionales para verificar las traducciones de nuestro sitio web. Este proyecto es un trabajo en curso.
Create a Linode account to try this guide with a $ credit.
This credit will be applied to any valid services used during your first  days.

Drupal is a flexible content management system (CMS) designed for structured content and scalable site architecture. While it runs well in many hosting environments, Akamai’s compute instance provides a resilient foundation for high-traffic, content-rich deployments. This guide walks through installing and configuring Drupal 11 on Ubuntu 22.04 with systems-aware practices and contributor-safe steps that hold up in real-world scenarios.

Before You Begin

This guide uses Drupal 11.1.8 to avoid known packaging issues in newer releases. Specifically a syntax error in drupal/core-recipe-unpack introduced in 11.2.x (see Drupal issue #3536487). You’ll install the stable version later using Composer after verifying system prerequisites.

Coming from Drupal 8 or new to Composer-based workflows? See Contributor-Safe Notes for context on modern Drupal workflows and what’s changed since earlier versions.

System Prerequisites

This guide is based on a tested configuration that ensures Drupal 11 installs cleanly and performs reliably within an Akamai-optimized infrastructure. The following prerequisites were used for validation.

  • OS: Ubuntu 22.04 LTS
  • Apache: Version 2.4.52+
  • PHP: Version 8.1+ (Drupal 11 optimized for PHP 8.3)
  • Composer: 2.7.0+ (Drupal 11) Installed globally
  • MariaDB 10.3.7+ or MySQL: 5.7.8 (Drupal 11) Installed and secured
  • Drupal: Latest stable version (11.1.8 as of Sept 2025) will be installed after the environment setup

This configuration was verified to support structured content management, contributor workflows, and integration with Akamai’s caching and security layers.

Configure the Web Server for Drupal

Apache is assumed to be installed and running. This section focuses on enabling the modules and configuration settings Drupal relies on for clean URLs, secure access, and flexible routing.

Summary Table

StepPurposeCommand / Config
Enable mod_rewriteSupport clean URLssudo a2enmod rewrite
sudo systemctl restart apache2
Set AllowOverride AllAllow .htaccess overridesEdit Apache config file (000-default.conf or drupal.conf) and set:
AllowOverride All inside the <Directory> block for your /web folder
Reload ApacheApply config changessudo systemctl reload apache2
Optional: Virtual HostUse custom domain for local devDefine <VirtualHost> block pointing to /web folder in drupal.conf
Update /etc/hostsMap custom domain to localhostAdd: 127.0.0.1 drupal.local
Enable site configActivate virtual hostsudo a2ensite drupal.conf
sudo systemctl reload apache2

Line-by-Line Walkthrough

Enable mod_rewrite

Drupal uses clean URLs, which depend on Apache’s rewrite module. Enable it with:

    sudo a2enmod rewrite
    sudo systemctl restart apache2

This activates mod_rewrite and restarts Apache to apply the change.

Success: No error output and Apache restarts cleanly.

If you see an error like Module rewrite already enabled, it’s safe to proceed–Apache is already configured for clean URLs.

Set AllowOverride All

Edit your Apache configuration file (typically /etc/apache2/sites-available/000-default.conf or a custom drupal.conf). Locate or add the <Directory> block for your Drupal web root and ensure it includes:

<Directory /var/www/html/my-drupal-site/web>
    AllowOverride All
</Directory>

This allows Drupal’s .htaccess file to apply security rules and URL rewrites. After editing, reload Apache:

sudo systemctl reload apache2

If the reload command fails or changes don’t apply, see the Troubleshooting section for Apache configuration issues.

Optional: Set Up a Virtual Host

For local development using a custom domain (e.g., drupal.local):

  1. Create or edit /etc/apache2/sites-available/drupal.conf:
<VirtualHost *:80>
    ServerName drupal.local
    DocumentRoot /var/www/html/my-drupal-site/web

    <Directory /var/www/html/my-drupal-site/web>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/drupal-error.log
    CustomLog ${APACHE_LOG_DIR}/drupal-access.log combined
</VirtualHost>
  1. Add an entry to /etc/hosts:
    127.0.0.1 drupal.local

This maps drupal.local to your local machine.

  1. Enable the site configuration:
sudo a2ensite drupal.conf
sudo systemctl reload apache2

This guide uses Drush 11.x to install Drupal 11.1.8 via the command line. The CLI method ensures consistent results and avoids exposing database credentials in the browser during installation.

Environment Validation (Phase 1)

CheckPurposeCommandExpected OutputIf Output Differs🔗 Further Info
PHP VersionEnsure PHP 8.1+ is installedphp -vPHP 8.1.2 or higherUpgrade PHP or switch environmentsPHP Docs
Required Extensions (see exts below)Confirm required PHP modulessee (exts) command belowAll listed extensions appearInstall missing modules via apt, dnf, or brewDrupal Requirements
Composer Health Check see (root) belowValidate Composer setupcomposer diagnoseAll checks return OK or WARNING (non-blocking)Type yes if prompted about root; note any warningsComposer Docs
Composer VersionEnsure Composer 2.x is installedcomposer --versionComposer version 2.x.xUpgrade Composer if version is < 2Composer Install Guide

(exts): Run php -m | grep -E 'pdo|mbstring|xml|json|ctype|tokenizer|curl|openssl|gd|dom|simplexml|zip' to confirm required extensions.

(root): Running Composer as root is discouraged. Safe for local testing, but avoid in production.

If you experience silent failures during verification and need to install missing components (e.g., PHP extensions):

Note

During installation, you may see a prompt like:

Do you want to continue?[Y/n]

This is a standard confirmation step. Type Y and press Enter to proceed. (If using a different package manager or install method, the prompt may vary slightly–but the intent is the same: confirm you want to install the listed components.)

Infrastructure Verification

This section outlines the steps used to verify system components, establish the file structure, and prepare the database–everything Drupal requires prior to installation.

Check PHP Version and Extensions

Use the following commands to check what PHP extensions are available:

    php -v
    php -m | grep -E 'gd|mbstring|xml|curl|zip|mysql|pdo_mysql|opcache'

If any required PHP extensions are missing, install them with:

    sudo apt install php-gd php-mbstring php-xml php-curl php-zip php-mysql php-opcache

Following installation, restart Apache or Nginx to activate the new extensions.

    sudo systemctl restart apache2

Verify they’re active:

    php -m | grep -E 'gd|mbstring|xml|curl|zip|mysql|pdo_mysql|opcache'

Each one should now be listed.

Check Composer

If checking for Composer installation yields a composer not found error, you can install it with:

    sudo apt update && sudo apt install composer

To verify installation:

    composer --version

You should see output like Composer version 2.7.0 or higher.

If the command fails, see Composer Installation - Manual Download for fallback steps.

Installation (Phase2)

Install the Drupal codebase using Composer. This sets up the recommended starter template and project structure.

Composer and PHP must be working to proceed. To confirm this, complete Environment Validation (Phase 1).

Create Project Structure

Creating the project structure sets up Drupal for modular development and secure deployment.

This step separates application logic from public content, making updates easier to manage and reducing security risks.

After running the composer create-project command below, your environment should include the core Drupal files and folder structure:

composer.json

web/index.php

vendor/

These files confirm that setup succeeded, prepare optional configuration scaffolding, and get the application ready for site installation. This guide was validated using Drupal 11.1.8 as noted earlier.

Create the Drupal Project Structure

Run the install command to generate the Drupal 11.1.8 structure. Replace my-drupal-site with your desired folder name. For directory layout details, see Drupal.org’s Directory Structure guide

    composer create-project drupal/recommended-project:11.1.8 my-drupal-site

Change to your project folder (remove the angle brackets (<>) and use your actual folder name):

    cd my-drupal-site

Install Drush

Add Drush to your project via Composer:

    composer require drush/drush:11.5.1

Drush will be installed in vendor/bin/.

Validate Drush Installation

Confirm Drush is working:

    vendor/bin/drush --version

Expected output: Drush version 11.5.1 or similar.

If you encounter errors, see the Troubleshooting section.

Troubleshooting Notes:

(drush-install):

  • Confirm composer.json is writable and not locked by another process.
  • Make sure your PHP version meets Drush’s minimum requirement (PHP 8.1+ for Drush 11.x).
  • If you see a memory error, try:
    COMPOSER_MEMORY_LIMIT=-1 composer require drush/drush:11.5.1

(drush-validate): If Drush throws a NotFoundHttpException, it was likely run outside a valid Drupal project root. Navigate to the directory containing composer.json before running Drush commands. See: Drush Usage Guide for valid command contexts.

Copy the Default Settings File

This creates the active configuration file that Drupal reads and writes to during installation and runtime.

    cp web/sites/default/default.settings.php web/sites/default/settings.php

Set File Permissions

Before running the Drupal installer, you need to make settings.php writable so Drupal can configure it during installation. Make sure you are in the Drupal project root folder and then run:

    chmod 644 web/sites/default/settings.php

This sets permissions to allow the owner to read/write and the web server to access the file during installation.

Optional: If you’re on a shared host or strict environment, you may need to tighten permissions after installation to 640 or even 600.

If you skip this step and Drupal can’t write to the file, the installer will fail with a permissions error.

Create the Files Directory

Drupal uses a writable files directory to store uploaded content, temporary files, and other runtime assets. From your project root (my-drupal-site) run:

    mkdir -p web/sites/default/files
    chmod 755 web/sites/default/files

To verify that it worked, run:

    ls -ld web/sites/default/files

The chmod allows owner and group read, write, and execute permissions and others read and execute rights. For stricter environments you can adjust ownership with:

    chown -R www-data web/sites/default/files

Use your actual web server for www-data. A writable files directory allows Drupal to store uploads (i.e., images or enabled modules) or generate cached assets so you don’t see any errors.

Verify the Web Server

Before proceeding, make sure your web server has permission to interact with the Drupal environment. Set the /web directory and its contents to be owned by www-data (or your system’s web server user), using:

    sudo chown -R www-data:www-data web

This step prevents permission errors during runtime and ensures that Drupal can safely generate files, manage uploads, and interact with modules.

Note
If you’re using Nginx or a different web server, replace www-data with your actual server user (e.g., nginx, apache, or a custom service account).

To confirm ownership was updated, run this from the parent directory of web:

    ls -ld web

This confirms the ownership and permissions of the web directory:

drwxr-xr-x 7 www-data www-data 4096 Sep 16 22:28 web

This means:

  • www-data owns the directory
  • www-data is also the group
  • The permissions are drwxr-xr-x (read/write/execute for owner, read/execute for group and others.)

To verify ownership of individual files, run:

    ls -l path/to/your/file (for example: `ls -l web/index.php`)

This shows the file’s owner and group.

Note

If ownership is incorrect, rerun:

    sudo chown -R www-data:www-data web

And replace www-data with your actual web server user if different.

Prepare the Database

Before installing Drupal, follow the official guide to create a database and user: Database Configuration.

  1. Once complete, confirm access with a contributor-safe check:
    mysql -u drupal_user -p -h localhost drupal_db

Replace drupaluser and drubaldb with your database username and name. You should be able to enter the MariaDB shell without errors.

  1. Confirm that your database uses utf8mb4 encoding:
    SHOW CREATE DATABASE drupal_db;
  1. Look for CHARACTER SET utf8mb4 in the output. If it’s missing, you may need to recreate the database with the correct encoding or convert it.

  2. Your database credentials should match what you’ll enter in settings.php:

    $databases['default']['default'] = [
        'driver' => 'mysql',
        'database' => 'drupal_db',
        'username' => 'drupal_user',
        'password' => 'your_secure_password',
        'host' => 'localhost',
        ];

This configuration is located in sites/default/settings.php.

  1. During setup you may need to temporarily relax file permissions:
    chmod 664 sites/default/settings.php

Common Errors and Fixes

Error MessageLikely CauseFixResource
Access denied for userWrong username or passwordDouble-check credentials in settings.phpDrupal.org: Database Configuration
Unknown databaseDatabase name typo or missingRecreate or correct name in configMoldStud: Avoid Common Pitfalls
Driver not foundIncorrect or missing driverUse 'driver' => 'mysql' for MariaDBDrupal.org: Database API Overview
Warning: count() during installMisconfigured array structureEnsure $databases array is properly nestedStack Overflow (yes, there is a typo in that title s/b correctly).

Optional: Environment Variables

You can abstract sensitive credentials using .env files or environment-specific config, see Drupal.org’s environment config practices.

Launch the Installer

Once your project structure is in place and Drush is installed, you can launch the Drupal installer using either a browser or CLI.

Method 1: Browser-Based Installation

Using the PHP built-in server, run:

    php -S localhost:8888 -t web

Then visit http://localhost:8888 in your browser. The Drupal installer page should load.

If the installer page is blank or throws errors:

  • Check PHP version and extensions (pdo, gd, mbstring)
  • Confirm file permissions in the web folder
  • Ensure index.php exists in web

Method 2: CLI-Based Installation (Recommended)

Install Drupal via Drush:

    vendor/bin/drush site:install

The site will be installed with default configuration.

If the installation fails:

  • Confirm database access and credentials
  • Verify Drush version compatibility
  • Check PHP version meets requirements

Post-Install Validation (Phase 3)

After installation, confirm that setup completed successfully and is complete and ready for configuration.

Verify Project Structure

Confirm the project was initialized correctly:

    ls composer.json
    ls -ld web/index.php
    ls -ld vendor/

Expected results:

  • composer.json confirms the metadata file exists
  • web/index.php confirms the application entry point exists
  • vendor/ confirms dependencies were installed

If any of these files are missing or return errors, installation may have failed or been interrupted. For troubleshooting see Installing Drupal - Getting Started Guide.

If any are missing:

If vendor/ is missing but composer.json exists, run: composer install. If all are missing, the project wasn’t created. Return to Phase 2.

CheckPurposeCommandExpected OutputIf Output Differs🔗 Further Info
Success ConfirmationValidate install completionReview terminal output“Project created successfully” or similar messageIf error shown, rerun with -vvv for verbose outputComposer Troubleshooting
Folder StructureConfirm expected files existls mysitecomposer.json, web/, vendor/, etc.If missing, check install logs or rerun installDrupal File Structure
Optional CleanupRemove message plugin (optional)composerPlugin removed, no errorsCheck Composer version or plugin dependenciesProject Message Plugin

Local Testing Setup

Before continuing, confirm that your local environment is serving the Drupal site correctly. This section helps validate Apache, PHP, and file permissions using a browser-based test.

Summary Table

StepPurposeCommand / Action
Map domain to localhostAccess site via drupal.localAdd 127.0.0.1 drupal.local to /etc/hosts
Test in browserConfirm site is served correctlyVisit http://drupal.local
Troubleshoot blank/errorIdentify common issuesCheck permissions, Apache config, PHP status
Validate PHP installConfirm PHP is installed and activeRun php -v

Line-by-Line Walkthrough

1. Add an entry to /etc/hosts

This maps drupal.local to your local machine:

    127.0.0.1 drupal.local

2. Test in browser

Visit http://drupal.local in your browser. The Drupal site should load.

3. Troubleshoot blank pae or errors

If the page is blank or shows errors:

  • Check file permissions in the web folder.
  • Verify Apache configuration (ensure AllowOverride All is set).
  • Confirm PHP is running: php -v.

Security and Optimization (Post-Install)

After your Drupal site is installed and validated, take these steps to harden security and optimize performance.

  1. Harden the MySQL Installation
    sudo mysql_secure_installation

This interactive tool lets you:

  • Set or update the root password
  • Remove anonymous users
  • Disallow remote root login
  • Remove the test database
  • Reload privilege tables
Note
These steps help protect your Drupal site from unauthorized access and are strongly recommended for production environments.
  1. Lock Down File Permissions

Ensure the web/sites/default directory is writable by the web server during installation:

    sudo chown -R www-data:www-data web/sites/default

After installation, lock down permissions:

    sudo chmod 444 web/sites/default/settings.php
  1. Verify .htaccess Rules

Drupal relies on .htaccess for security rules like:

  • Preventing access to sensitive files
  • Blocking directory listings
  • Enforcing clean URLs
Note
If .htaccess rules aren’t being applied, double-check AllowOverride All is set in your Apache config.
  1. Enable SSL (Optional)

If deploying Drupal in a production or public-facing environment, configure SSL to encrypt traffic:

  • Use Let’s Encrypt or a self-signed certificate.
  • Update your Apache virtual host to include:
1
2
3
4
5
<VirtualHost *:443>
    SSLEngine on
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/key.pem
</VirtualHost>

For local development, SSL is optional. For public sites it is essential.

  1. Security Checklist
  • Database hardened using mysql_secure_installation
  • File permissions set for install and post-install
  • .htaccess rules active and enforced
  • SSL configured (if public-facing)

Next Steps and Resources

Contributor-Safe Notes: Composer-First Workflow

Legacy Bridging for Users Coming From Drupal 8

Drupal 11.x expects Composer-managed workflow. Composer is now the official and recommended method for managing Drupal core, contributed modules, and dependencies. Contributors familiar with manual installs or .tar.gz packages from Drupal 8 may encounter unexpected behavior. This guide assumes a Composer-first setup to ensure compatibility with modern module management and dependency resolution.

Avoiding brittle Installs and Opaque Errors

Composer tracks dependencies explicitly, reducing the risk of missing extensions or mismatched versions. Manual installs often fail silently or introduce hard-to-trace errors. Using composer create-project ensures a reproducible, contributor-safe environment.

Encouraging use of Drush for Command-Line Efficiency

Drush streamlines tasks like site installation, cache clearing, and module management. Once installed via Composer, it becomes available in the project’s /vendor/bin directory. Check Drush status:

    ./vendor/bin/drush/status

If you get errors like missing “Symfony” classes or auto-load failures, check that you’re in the correct project folder containing:

`composer.json`, `vendor/`, and `web/`
  • Drush is installed locally–not globally in vendor/.
  • You’re running Drush from the project root–not from a parent or nested directory.

To confirm you’re in the right directory, run:

    ls

Expected output:

    composer.json, vendor/, web/

Contributor-Safe References

For official Drush installation guidance, see Drush on Drupal.org.

You can find additional information in Drupal’s Composer guide for deeper context.

Conclusion: What Comes Next

Your Drupal environment is now structured, validated, and ready for customization. From here, you can begin shaping your site:

  • Explore the Official Drupal Documentation for guidance on modules, configuration, and site building.

  • Get into theme development: create or install themes to control layout and styling. Browse the Drupal Themes Directory to see what’s possible.

To see inspiring real-world Drupal Websites explore how others have extended and styled their sites.

Troubleshooting

Apache reload/restart

IssuePossible CauseResolution
Apache reload fails with “control process exited with error code”Syntax error in config fileApache Configuration Test
Permission denied on reloadNot running with sudoApache Service Management
“Unit apache2.service not loaded”Apache not installed or startedApache Installation Guide
No error but .htaccess rules don’t applyWrong config file edited or incorrect Directory pathApache Virtual Host Documentation

This page was originally published on


Your Feedback Is Important

Let us know if this guide was helpful to you.


Join the conversation.
Read other comments or post your own below. Comments must be respectful, constructive, and relevant to the topic of the guide. Do not post external links or advertisements. Before posting, consider if your comment would be better addressed by contacting our Support team or asking on our Community Site.
The Disqus commenting system for Linode Docs requires the acceptance of Functional Cookies, which allow us to analyze site usage so we can measure and improve performance. To view and create comments for this article, please update your Cookie Preferences on this website and refresh this web page. Please note: You must have JavaScript enabled in your browser.