User account menu

  • Log in
Dawei Bro

Main navigation

  • Home

Install Drupal CMS 2.0 on Ubuntu 24.04 with Apache2 PHP8.3 PostgreSQL 16

Breadcrumb

  • Home
  • Articles
  • Install Drupal CMS 2.0 on Ubuntu 24.04 with Apache2 PHP8.3 PostgreSQL 16
By daweibro | 10:04 PM CST, Wed April 22, 2026

As an open-source enthusiast, I have been using Drupal to build websites for over a decade, starting with Drupal 7. I have always viewed Drupal (now Drupal Core) as a bare-shell apartment: the structural foundation is rock-solid, but you have to install every wire, pipe, and tile yourself before it’s livable.

But as I started planning my new blog daweibro.com — a space where I'll be exploring the intersection of digital assets and financial independence — I realized that time is my most valuable asset. Instead of the old manual way, I decided to embrace a new path: Drupal CMS.

The Tech Stack

To bring this vision to life, I chose a stack that balances performance with long-term stability. While Drupal CMS is forward-looking, its foundation must be rock-solid. For this build, I am using:

  • OS: Ubuntu 24.04 LTS (Noble Numbat)
  • Web Server: Apache 2.4.58
  • Programing Language: PHP 8.3
  • Database: PostgreSQL 16
ubuntu@web:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04.4 LTS
Release:        24.04
Codename:       noble
ubuntu@web:~$ apache2 -v
Server version: Apache/2.4.58 (Ubuntu)
Server built:   2026-03-05T17:31:54
ubuntu@web:~$ php -v
PHP 8.3.6 (cli) (built: Jan  7 2026 08:40:32) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.6, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.6, Copyright (c), by Zend Technologies
ubuntu@web:~$ psql -v
/usr/lib/postgresql/16/bin/psql: option requires an argument -- 'v'
psql: hint: Try "psql --help" for more information.
ubuntu@web:~$ psql -V
psql (PostgreSQL) 16.13 (Ubuntu 16.13-0ubuntu0.24.04.1)

Step 1: Configure the Apache Virtual Host

With the underlying tech stack ready, it’s time to define where our new blog will live. In the world of Apache, this means setting up a Virtual Host.

Instead of writing a new configuration from scratch, I’ll leverage the existing blueprints on my server by copying a standard configuration file. This is the "move-in ready" approach—efficient and less prone to errors.

1. Copy the Configuration Template

I’ll start by copying an existing configuration to create a dedicated file for daweibro.com:

sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/daweibro.com.conf

2. Modifying the Configuration

Now, let’s edit the file:

sudo vim /etc/apache2/sites-available/daweibro.com.conf

I’ve streamlined this configuration. Since my server uses the Event MPM and has a global PHP-FPM configuration enabled (php8.3-fpm.conf), I don't even need to explicitly define the PHP proxy handler here. Apache is smart enough to handle it globally. Here is the clean, "rock-solid" version of my Virtual Host:

<VirtualHost *:80>
    ServerName dev.daweibro.com
    # The "web" directory is the public-facing entry point for Drupal CMS
    DocumentRoot /srv/www/html/daweibro.com/web

    <Directory /srv/www/html/daweibro.com/web>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/daweibro_error.log
    CustomLog ${APACHE_LOG_DIR}/daweibro_access.log combined
</VirtualHost>

By pointing the DocumentRoot to the /web sub-directory, I’m ensuring that sensitive system files and the vendor folder remain outside the public web root—a fundamental security practice for modern Drupal.

3. Create a Log Directory for daweibro.com

I prefer creating a dedicated log directory for each project. This isolation makes troubleshooting significantly easier and keeps the system logs clean.

# Create a dedicated directory for Apache logs
sudo mkdir -p /var/log/apache2/daweibro.com

# Ensure the log directory has the correct ownership
# On Ubuntu, Apache logs are typically owned by root:adm
sudo chown root:adm /var/log/apache2/daweibro.com

4. Apply for an SSL Certificate

Securing a website with HTTPS is essential, especially for a blog discussing digital assets. We will use Certbot and Let's Encrypt to obtain a free, automated SSL certificate for both the root domain and the www subdomain before final activation.

# Install Certbot and its Apache plugin in case you did not install it before
sudo apt install certbot python3-certbot-apache -y

# Run Certbot to obtain and install the certificate
# This automatically handles the challenge and configures the SSL Virtual Host
sudo certbot --apache -d daweibro.com -d www.daweibro.com

5. Enable the Site and Verify the Setup

With both the standard and secure configurations ready, we activate the site. It is best practice to test the configuration syntax before restarting the service to ensure that the automated changes are error-free.

Bash
# Enable the site configurations
sudo a2ensite daweibro.com.conf
sudo a2ensite daweibro.com-le-ssl.conf

# Verify the Apache configuration syntax
sudo apache2ctl configtest

# If the output shows "Syntax OK", restart the service
sudo systemctl restart apache2

Step 2: Prepare the PostgreSQL 16 Database

Since my server is already a dedicated Drupal environment, the core software (Apache, PHP 8.3, and PostgreSQL 16) is already installed and optimized.

For now, we just need to prepare a new "vault" for daweibro.com.

1. Create the Database User and Database

Instead of entering the SQL interactive shell, I prefer using PostgreSQL’s command-line binary utilities. This method is faster and prevents passwords from being saved in your shell history.

# Switch to the postgres system user to access administrative tools
sudo su - postgres

# 1. Create a new database user (role)
# --pwprompt: Interactively set a secure password
# --no-createrole --no-createdb: Follow the principle of least privilege
createuser --pwprompt --encrypted --no-createrole --no-createdb daweibroadmin

# 2. Create the database with the correct encoding and set the new user as owner
createdb --encoding=UNICODE --owner=daweibroadmin daweibro

# Exit the postgres user session
exit

2. Verify Public Schema Permissions

A quick technical note: Since PostgreSQL 15, the default "public" schema permissions have been tightened for security. However, because we assigned daweibroadmin as the Database Owner in the previous step, it automatically inherits the necessary CREATE permissions.

If for some reason you are not using the database owner for the installation, you would need to run the following command to grant access:

# Optional: Only needed if the user is NOT the database owner
# sudo -u postgres psql -d daweibro -c "GRANT ALL ON SCHEMA public TO daweibroadmin;"

3. Install Required pg_trgm Extension

Drupal 11 requires the pg_trgm extension to handle advanced search queries and case-insensitive matching in PostgreSQL. This is no longer optional; without it, the installer or certain search features may fail.

# Install the pg_trgm extension required by Drupal
sudo -u postgres psql -d daweibro -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
CREATE EXTENSION

Step 3: Deploy the Codebase via Composer

If you are familiar with modern Drupal development, this step will feel like home. Whether you are installing Drupal Core or the new Drupal CMS, the industry-standard tool for managing the codebase is Composer.

The deployment process remains identical to the traditional workflow, but instead of the bare-bones "recommended-project," we are fetching the drupal/cms package—the official distribution for the Starshot initiative.

The only difference here is the package name. We’ll use the create-project command to fetch the Drupal CMS ecosystem, which includes the core files along with the pre-bundled "Recipes" that define the Starshot experience.

Navigate to your web server's parent directory and run:

# Move to the Apache html directory
cd /var/www/html

# Create the project using the Drupal CMS package
# This command automatically creates the 'daweibro.com' folder
composer create-project drupal/cms daweibro.com

This command builds the familiar Drupal directory structure. Once completed, your project will contain a vendor folder for dependencies and a web folder, which serves as the public entry point we previously configured in Apache.

Before we head to the browser, let’s confirm the directory layout is correct. It should follow the standard Composer-based Drupal architecture:

  • /vendor: Where the PHP libraries and Drupal core reside (safely above the web root).
  • /web: The folder containing index.php, the sites directory, and the public assets.
  • composer.json: The manifest that manages all your site's "digital assets"—the modules, themes, and recipes.

The codebase is now in place, following the same reliable patterns we've used for years, but now loaded with the potential of Project Starshot.

Step 4: Run the Web Installer

With the codebase deployed and the server ready, we can now leave the command line behind and complete the setup through the web browser. This is where the "Starshot" experience truly distinguishes itself from a standard Drupal Core installation.

Navigate to your domain in your browser (e.g., https://daweibro.com). If your Apache configuration is correct, you should be automatically redirected to the installation script. If not, you can access it directly at https://daweibro.com/core/install.php.

1. Configure the Database

In a departure from the traditional Drupal Core installer, which usually starts with profile selection, the Drupal CMS installer gets straight to business. The first screen asks for your database credentials.

Select PostgreSQL and enter the "vault" details we prepared in Step 2:

  • Database type: PostgreSQL (default if only PostgreSQL installed on your Server)
  • Database name: daweibro
  • Database username: daweibroadmin
  • Database password: [YourSecurePassword]
  • Host: localhost
  • Port number: 5432
  • Table name prefix:leave it blank by default

Once you click "Save and continue," Drupal will verify the connection and begin the initial site setup.

2. Set the Site Name

Next, the installer prompts for the identity of your website.

Site name: Enter your chosen Site Name (e.g., Dawei Bro).

3. Choose a Site Template: The Death of the "Ugly" Drupal

This is the moment where Drupal CMS 2.0 truly sheds its old reputation. For years, a fresh Drupal install was notoriously "blank and ugly," requiring a developer's touch just to make it look professional. Starshot changes the game by offering a library of Site Templates.

These templates aren't just themes; they are functional blueprints tailored for specific needs—from SaaS products (Byte) to non-profits (Haven) and even specialized sectors like Healthcare or Education.

To be honest, some of these templates look incredibly modern and professional right out of the box. However, since daweibro.com is a focused personal blog, I wanted to avoid the "bloat" of complex landing pages or pre-configured corporate features. I opted for the Starter template.

Why Starter?

It provides just the essentials. It is clean, fast, and gives me a modern typographic foundation without a hundred pre-built pages I don't need. It’s the digital equivalent of a "minimalist studio"—everything you need, and nothing you don't. This "lean" approach ensures that my digital home remains high-performance and easy to manage as I grow.

4. Create Your Account

Finally, you set up your administrative credentials. This is the Superuser account that gives you full access to the site:

  • Email: Your professional email address.
  • Password: A strong, secure password.

5. Automatic Installation

Unlike the earlier development versions of the Drupal CMS project (often referred to as "CMS 1.0"), there is no longer a manual "Select Recipes" screen in this version.

For those coming from a traditional Drupal Core background, the very concept of a "Recipe" step is entirely new—standard Core has never had such a feature.

In Drupal CMS 2.0, the process is now seamless: once you create your account, the installer immediately begins a background process. It "cooks" the site by automatically applying the specific Recipes associated with your chosen Starter template—configuring the blog structure, media library, and SEO tools without requiring any further manual input.

Step 5 Post-Installation Reality — We Got an Error!

After watching the progress bar reach 100%, I expected to be redirected to a beautiful, polished homepage. Instead, I was met with every developer's nightmare: the "White Screen of Death" (WSOD) and a daunting PHP error message:

ArgumentCountError: Too few arguments to function Drupal\mercury\Hook\ThemeHooks::__construct(), 0 passed in /var/www/html/daweibro.com/web/core/lib/Drupal/Component/DependencyInjection/Container.php on line 259 and exactly 9 expected in Drupal\mercury\Hook\ThemeHooks->__construct() (line 36 of /var/www/html/daweibro.com/web/themes/contrib/mercury/src/Hook/ThemeHooks.php).

Why did this happen?

This is the reality of working with Drupal CMS 2.0 while it is still in active development.

The error originates from the Mercury theme, the default frontend for the Starshot project.

Mercury uses a modern Drupal 11 pattern where hooks are handled by classes that require Dependency Injection (DI). The system expected 9 specific services (like the path matcher and theme manager) to be "injected" into the theme, but it received none.

Essentially, while the installer successfully built the site, the final "handshake"—rebuilding the service container for the theme—didn't trigger correctly in my PHP 8.3 / ARM environment.

The finely decorated apartment was finished, but the master fuse had tripped.

The Fix: Rebuilding the "Brain"

In the Drupal world, the first rule of troubleshooting is: When in doubt, rebuild the cache. Since the web interface was inaccessible, I had to return to the command line to use Drush (The Drupal Shell), which is conveniently pre-installed with the Drupal CMS package.

# Navigate to the project root
cd /var/www/html/daweibro.com

# Rebuild the service container and clear all caches
./vendor/bin/drush cr

The drush cr (cache-rebuild) command forced Drupal to re-scan its services and properly "inject" the missing arguments into the Mercury theme.

I refreshed the browser, and the error vanished. In its place was a crisp, modern, and fully-functional site.

Conclusion: A Lean Foundation for Digital Growth

Setting up a blog used to be a choice between the simplicity of a locked-in platform or the complexity of a self-hosted CMS.

With Drupal CMS 2.0, that gap is finally closing.

Setting up a blog used to be a choice between the simplicity of a locked-in platform or the complexity of a self-hosted CMS. With Drupal CMS 2.0, that gap is closing.

Despite the minor post-install hiccup, the speed at which I went from a "bare-shell" server to a secure, SEO-ready site on a stack of PHP 8.3 and PostgreSQL 16 is unprecedented. I’ve successfully moved into my "move-in ready" digital home. It’s currently empty, but like any good investment, it has the perfect structure for long-term growth.

The Starshot journey has just begun. My foundation is built, the "vault" is secure, and now the real fun—and the real work—begins: writing about digital assets and financial independence.

Welcome to the new daweibro.com.

  • Log in to post comments

Footer

  • Privacy Policy
  • Terms of Use
  • Disclaimer

Copyright © 2026 Dawei Bro - All rights reserved