Deploying LeadCMS with Docker Compose

This guide provides a sample deployment approach for LeadCMS using Docker Compose. It's designed to help you quickly get LeadCMS running on your premises for evaluation, development, or as a starting point for your own deployment strategy.

Sample Configuration Notice

The provided docker-compose.yml is a sample that demonstrates how to run LeadCMS with its dependencies (PostgreSQL) for convenience. In production environments, you may want to use managed services for PostgreSQL, implement proper backup strategies, and add monitoring solutions.

Prerequisites

1. Clone the Deployment Repository

git clone https://github.com/LeadCMS/leadcms.deploy.git
cd leadcms.deploy

2. Generate Environment Variables

LeadCMS uses a .env file for configuration. You must generate this file before starting the containers.

On Linux/macOS

Run the provided shell script:

chmod +x generate-env.sh
./generate-env.sh

On Windows

Run the PowerShell script:

.\generate-env.ps1

The script will:

  • Read .env.sample
  • Generate secure random secrets and passwords
  • Write a new .env file
Environment File Security

If a .env file already exists, you will be prompted before overwriting. Never commit the .env file to version control as it contains secrets and credentials.

3. Review and Customize Environment

Open the generated .env file in your editor and configure the following essential settings:

Email Configuration (Required)

EMAIL__USERNAME=your-smtp-username
EMAIL__PASSWORD=your-smtp-password
EMAIL__SERVER=smtp.your-provider.com
EMAIL__PORT=587
EMAIL__USESSL=true

CORS Origins

CORS__ALLOWEDORIGINS__0=https://yourdomain.com
CORS__ALLOWEDORIGINS__1=https://admin.yourdomain.com

Supported Languages

SUPPORTEDLANGUAGES__0=en
SUPPORTEDLANGUAGES__1=de
# Add more languages by incrementing the index

Plugin Configuration

PLUGINS__0=LeadCMS.Plugin.Site
# Add more plugins as needed

4. Start the Sample Stack

From the repository root, run:

docker compose up -d

This will start:

  • PostgreSQL (sample, local container)
  • LeadCMS core application

5. Access the Services

Once all containers are running, you can access:

6. Default Admin User

Use these credentials to access the system:

  • Username: As set in .env (DEFAULTUSERS__0__USERNAME)
  • Password: As generated in .env (DEFAULTUSERS__0__PASSWORD)
  • Email: As set in .env (DEFAULTUSERS__0__EMAIL)

7. Stopping and Cleaning Up

To stop the stack:

docker compose down

To remove all data (PostgreSQL volumes):

docker compose down -v
Data Loss Warning

Using docker compose down -v will permanently delete all data in PostgreSQL. Only use this if you want to start completely fresh.

Troubleshooting

PostgreSQL Authentication Issues

If you encounter authentication errors when connecting to PostgreSQL, it may be due to an existing Docker volume containing an old database with different credentials:

  1. Stop all running containers:

    docker compose down
    
  2. Remove all persistent data volumes (this will delete all data):

    docker compose down -v
    
  3. Start the stack again:

    docker compose up -d
    

This will recreate the databases with the current credentials from your .env file.

Container Health Issues

Check container status and logs:

# View running containers
docker compose ps

# Check specific service logs
docker compose logs leadcms
docker compose logs postgres

Plugin Configuration

LeadCMS supports two types of plugins: default plugins that come with LeadCMS Core and custom plugins that you develop or obtain from third parties.

Default Plugins

All default plugins that come with LeadCMS Core can be enabled simply by adding them to your .env file:

PLUGINS__0=LeadCMS.Plugin.Site
PLUGINS__1=LeadCMS.Plugin.AI
PLUGINS__2=LeadCMS.Plugin.EmailSync
PLUGINS__3=LeadCMS.Plugin.SendGrid
PLUGINS__4=LeadCMS.Plugin.Sms
PLUGINS__5=LeadCMS.Plugin.ReverseProxy
PLUGINS__6=LeadCMS.Plugin.Vsto

These plugins are already included in the LeadCMS Core container image and only need to be listed in the configuration to be loaded.

Custom Plugins

Custom plugins require the plugin code to be published into the /app/plugins/LeadCMS.Plugin.CustomPlugin folder within the container. This can be achieved in two different ways:

Method 1: Dynamic Plugin Loading (Runtime)

Mount external plugin directories into the container using Docker volumes. This approach is ideal for development and allows you to update plugins without rebuilding the container image.

Plugin Configuration in .env:

PLUGINS__0=LeadCMS.Plugin.Site
PLUGINS__1=LeadCMS.Plugin.CustomPlugin

Volume Mapping in Docker Compose:

services:
  leadcms:
    volumes:
      - ./plugins/LeadCMS.Plugin.CustomPlugin:/app/plugins/LeadCMS.Plugin.CustomPlugin

Method 2: Static Plugin Inclusion (Build Time)

Create a custom Docker image based on the standard leadcms/core:latest image. This approach is better for production deployments as it creates a self-contained image.

Sample Dockerfile for Custom Plugin:

# Dockerfile for LeadCMS Core with Custom Plugin
# This extends the base LeadCMS Core image with a custom plugin

# Use the official LeadCMS Core image as base
FROM leadcms/core:latest AS base

# Build stage for the plugin
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src

# Copy the plugin project files
COPY ["LeadCMS.Plugin.CustomPlugin.csproj", "./"]
COPY ["LeadCMS.Plugin.CustomPlugin.sln", "./"]

# Restore dependencies for the plugin
RUN dotnet restore "LeadCMS.Plugin.CustomPlugin.csproj"

# Copy the entire plugin source code
COPY . .

# Build the plugin
RUN dotnet build "LeadCMS.Plugin.CustomPlugin.csproj" -c Release -o /app/build

# Publish the plugin
FROM build AS publish
RUN dotnet publish "LeadCMS.Plugin.CustomPlugin.csproj" -c Release -o /app/publish/plugins/LeadCMS.Plugin.CustomPlugin /p:UseAppHost=false

# Final stage - extend the base LeadCMS image
FROM base AS final

# Copy the published plugin to the plugins directory
COPY --from=publish /app/publish/plugins/LeadCMS.Plugin.CustomPlugin /app/plugins/LeadCMS.Plugin.CustomPlugin

Build and use the custom image:

# Build the custom image
docker build -t leadcms-with-custom-plugin:latest .

# Update docker-compose.yml to use your custom image
# Replace: image: leadcms/core:latest
# With: image: leadcms-with-custom-plugin:latest
Plugin Development

The dynamic approach (Method 1) is ideal for development and testing, while the static approach (Method 2) is recommended for production deployments as it creates immutable, self-contained images.

HTTPS and SSL/TLS Configuration

Depending on your environment, SSL/HTTPS handling may be managed by your hosting provider or load balancer. However, if you need to implement SSL termination yourself, we have a tested solution that works well with Let's Encrypt and sites built with different technologies like Next.js or Gatsby.

For comprehensive SSL/TLS setup using Let's Encrypt, static site hosting, and preview server configurations, see our companion repository:

LeadCMS Nginx Configuration

This repository provides:

  • Sample Nginx configurations for SSL termination
  • Let's Encrypt automation scripts
  • Static site hosting setup
  • Preview server configurations

Deployment Considerations

Sample Setup Limitations

This Docker Compose setup is ideal for:

  • Local development and testing
  • Evaluation and proof-of-concept deployments
  • Small-scale on-premises installations

Production Considerations

For production deployments, consider these enhancements:

  • Managed Services: Use managed PostgreSQL services (AWS RDS, Azure Database, etc.) instead of containerized versions
  • High Availability: Implement load balancing and failover mechanisms
  • Security: Add proper firewall rules, VPN access, and security hardening
  • Monitoring: Implement logging, metrics, and alerting systems
  • Backups: Set up automated backup and disaster recovery procedures
  • Scaling: Plan for horizontal scaling and resource optimization
DevOps Responsibility

The sample Docker Compose configuration does not include production-grade features such as automated backups, high availability, monitoring, or scaling. These must be implemented by your DevOps team according to your organization's requirements.

Next Steps

After successfully deploying LeadCMS, you may want to explore: