A containerized local development environment for Provus Drupal 11 distributions, built on the DevPanel platform. This repository provides all configuration, startup scripts, and tooling needed to spin up a fully working Drupal site locally or in CI/CD.
Supports three install profiles, selected via .env:
| Profile | Recipe |
|---|---|
edu (default) |
recipes/provus_edu |
gov_fire |
recipes/provus_gov_recipe |
duswds |
recipes/provus_duswds_recipe |
- Overview
- Tech Stack
- Prerequisites
- Quick Start
- Project Structure
- Configuration
- Development Workflow
- CI/CD
- Contributing
This repo configures a Drupal 11 CMS site using one of the supported Provus install recipes. The active recipe is controlled by PROVUS_RECIPE in a local .env file (see Choosing a Recipe). It is designed to run inside DevPanel-managed containers but also supports:
- VS Code Dev Containers (primary local workflow)
- DDEV (alternative local workflow)
Key capabilities out of the box:
- Recipe-based Drupal installation (EDU, Gov Fire, or USWDS)
- Hourly automatic updates via Supercronic
- OPcache with JIT + APCu for performance
- Database import/export and volume sync for registry mode
- Automated Docker image publishing via GitHub Actions
| Layer | Technology |
|---|---|
| CMS | Drupal 11 |
| PHP | 8.4 / 8.5 |
| Database | MySQL 8.0 |
| Package Manager | Composer 2.0 |
| Drupal CLI | Drush |
| Containers | Docker + Docker Compose |
| Dev Environment | VS Code Dev Containers |
| Alternative Dev | DDEV |
| Cron | Supercronic |
| Caching | OPcache (JIT), APCu |
| CI/CD | GitHub Actions |
- Docker Desktop (for Dev Container or DDEV)
- VS Code with the Dev Containers extension, or DDEV
- Git
-
Clone the repository:
git clone git@github.com:promet/devpanel.git cd devpanel -
Choose a recipe (optional):
cp .env.example .env # Edit .env and set PROVUS_RECIPE=edu | gov_fire | duswds -
Open in VS Code and reopen in container:
- Press
F1→ Dev Containers: Reopen in Container - VS Code will build the PHP 8.4 container and run
.devpanel/init.shautomatically.
- Press
-
Access the site:
- The site is forwarded on port 80 — open http://localhost.
- Default admin credentials:
admin/admin
-
Clone the repository and start DDEV:
git clone git@github.com:promet/devpanel.git cd devpanel -
Choose a recipe (optional):
cp .env.example .env # Edit .env and set PROVUS_RECIPE=edu | gov_fire | duswds -
Start DDEV and initialize:
ddev start ddev exec .devpanel/init.sh -
Launch the site:
ddev launch
devpanel/
├── .devpanel/ # DevPanel configuration & scripts
│ ├── init.sh # Main container initialization (loads .env, selects recipe, composer, cron)
│ ├── init-container.sh # Registry-mode initialization (DB import, volume sync)
│ ├── re-config.sh # Container reconfiguration on redeploy
│ ├── config.yml # Git hook configuration (branch → composer install)
│ ├── custom_package_installer.sh # System packages & PHP extensions setup
│ ├── composer_setup.sh # Generates composer.json/lock with all dependencies
│ ├── settings.devpanel.php # Drupal DB credentials & trusted hosts overrides
│ ├── crontab # Supercronic schedule (hourly automatic updates)
│ ├── warm # Cache warming path list
│ ├── drupal-settings.patch # Patch to include DevPanel settings in settings.php
│ ├── create_quickstart.sh # Packages DB + files for Docker image publishing
│ └── README.md # DevPanel file reference
│
├── .devcontainer/ # VS Code Dev Container
│ ├── devcontainer.json # Container spec (PHP 8.4, port 80, init hook)
│ ├── docker-compose.yml # App service definition
│ └── base/
│ └── docker-compose.base.yml # MySQL 8.0 service + volumes
│
├── .ddev/ # DDEV (alternative local dev)
│ ├── config.yaml # Drupal 11, Apache-FPM, PHP 8.5, MySQL 8.0
│ └── launch.json # Xdebug/VSCode debugger configuration
│
├── .github/
│ ├── workflows/
│ │ └── docker-publish-template.yml # Docker image publish on main push / weekly
│ └── FUNDING.yml
│
├── drush/
│ ├── Commands/
│ │ └── DrupalForgeInstallerCommands.php # Custom drush command: drupalforge:contrib-recipes-path
│ └── drush.yml # Drush defaults (site name, admin password)
│
├── .env.example # Recipe selector template (copy to .env, not committed)
├── patches.json # Composer patches (Drupal core #3531174)
└── logs/ # Runtime logs
The install recipe is controlled by the PROVUS_RECIPE variable in a .env file at the project root. Copy the example file and set your preferred value before starting the container:
cp .env.example .env# .env
PROVUS_RECIPE=edu # Provus EDU → recipes/provus_edu
# PROVUS_RECIPE=gov_fire # Provus Gov Fire → recipes/provus_gov_recipe
# PROVUS_RECIPE=duswds # Provus USWDS → recipes/provus_duswds_recipeIf .env is absent or PROVUS_RECIPE is unset, the default edu recipe is used. The .env file is excluded from version control via .gitignore; commit .env.example instead.
These variables are consumed by settings.devpanel.php and Docker Compose:
| Variable | Description | Default |
|---|---|---|
PROVUS_RECIPE |
Install recipe (edu, gov_fire, duswds) — set in .env |
edu |
APP_ROOT |
Application root path | /var/www/html |
WEB_ROOT |
Drupal web directory | $APP_ROOT/web |
DB_HOST |
Database hostname | db |
DB_PORT |
Database port | 3306 |
DB_NAME |
Database name | drupaldb |
DB_USER |
Database user | user |
DB_PASSWORD |
Database password | password |
DB_DRIVER |
Database driver | mysql |
DP_APP_ID |
DevPanel application ID | provus_edu |
DP_HOSTNAME |
Trusted host pattern | (runtime value) |
COMPOSER_HOME |
Composer config directory | /var/www/.composer |
DRUPALFORGE_DEVCONTAINER |
Marks dev container mode | 1 |
The database service (MySQL 8.0) is defined in .devcontainer/base/docker-compose.base.yml. Credentials can be overridden via environment variables. The settings.devpanel.php file reads them automatically.
In registry mode (pre-built Docker images), .devpanel/init-container.sh imports a SQL dump and syncs static files via rsync.
Automatic updates run hourly via Supercronic. The schedule is defined in .devpanel/crontab:
@hourly php auto-update
Supercronic is installed and configured by custom_package_installer.sh during container build.
Common Drush commands used in this project:
# Install Drupal — recipe is chosen automatically from PROVUS_RECIPE in .env
drush si recipes/provus_edu --account-pass=admin --site-name="Provus EDU" -y # edu (default)
drush si recipes/provus_gov_recipe --account-pass=admin -y # gov_fire
drush si recipes/provus_duswds_recipe --account-pass=admin -y # duswds
# Run database updates
drush updb -y
# Clear all caches
drush cr
# Run cron
drush cron
# Warm caches
drush cache:warm
# Enable a module
drush en <module_name> -y
# Get the contrib recipes path (custom command)
drush drupalforge:contrib-recipes-path.devpanel/config.yml configures post-push hooks that automatically run composer install when pushing to main or develop:
hooks:
post_push:
main: composer install
develop: composer installHook output is logged to /tmp/composer_<branch>.txt.
The GitHub Actions workflow in .github/workflows/docker-publish-template.yml automatically builds and publishes a Docker image:
- Trigger: Push to
mainbranch, or weekly on schedule - Base image:
devpanel/php:8.5-base - Action: DevPanel Docker Publish
- Fork the repository and create a feature branch.
- Make your changes and test locally using the Dev Container or DDEV.
- Submit a pull request against
main.
For bug reports or feature requests, open an issue on GitHub.
Maintainer: Promet Source · Sponsor: @darrenoh