Skip to content

Deploying Concrete5 CMS

Introduction

Concrete5 is an open-source, PHP-based content management system that stands out for its intuitive interface and powerful in-context editing capabilities. Unlike many CMSs that separate content editing from page preview, Concrete5 allows you to edit content directly on the page you’re viewing—a feature that significantly reduces the learning curve for content editors.

Built with flexibility in mind, Concrete5 is designed to serve businesses of all sizes. Whether you’re running a small corporate website, a large-scale e-commerce platform, or a complex multi-site installation, Concrete5 provides the tools you need without unnecessary complexity.

Key Strengths of Concrete5:

In-Context Editing: The standout feature that makes Concrete5 unique. Edit your website content directly in the page editor, seeing exactly how it will appear to visitors.

User-Friendly Interface: A clean, intuitive dashboard that doesn’t require extensive training. Content editors can focus on creating rather than learning complicated workflows.

Enterprise-Grade CMS: Despite its ease of use, Concrete5 is built on solid architecture with version control, workflow management, and granular permission controls.

Extensible Architecture: A robust system for extending functionality through add-ons, themes, and custom code. The community has built thousands of add-ons.

Powerful Content Management: Support for multiple sites, complex page hierarchies, version control, scheduling, and workflow approval systems.

Flexible Theming: Create responsive, modern themes using HTML, CSS, and JavaScript without deep Concrete5 knowledge.

Multi-Language Support: Built-in internationalization for managing content in multiple languages.

SEO-Friendly: Clean URL structures, XML sitemaps, meta tag management, and structured data support out of the box.

This guide walks you through deploying Concrete5 on Klutch.sh using Docker. You’ll learn how to configure the application with persistent storage for uploads and content, set up the database, optimize performance, implement security measures, and troubleshoot common deployment issues.

Prerequisites

Before deploying Concrete5 to Klutch.sh, ensure you have:

  • A Klutch.sh account with dashboard access
  • A GitHub account for repository hosting
  • Docker installed locally for testing (optional but recommended)
  • Basic PHP and web server knowledge
  • Understanding of MySQL/PostgreSQL databases
  • A domain name for your site (recommended for production)
  • SMTP server credentials for email (optional but recommended)
  • Basic understanding of content management systems

Understanding Concrete5 Architecture

Technology Stack

Concrete5 is built on proven web technologies:

Backend:

  • PHP 7.4+ with object-oriented architecture
  • MySQL 5.7+ or PostgreSQL 10+ for data storage
  • Doctrine ORM for database abstraction
  • Zend Framework components
  • RESTful API with JSON responses

Frontend:

  • HTML5 and CSS3 for responsive design
  • jQuery and modern JavaScript
  • Bootstrap integration for default theme
  • Built-in WYSIWYG editor (CKEditor)

File Storage:

  • Local filesystem for content uploads
  • File versioning and management
  • Image optimization and thumbnails
  • Media library organization

Core Components

Dashboard: Administrative interface for managing site configuration, users, and content

Page Builder: Visual editor for creating page layouts without code

Content Library: Manage all images, videos, and downloadable files

Users and Permissions: Granular access control with role-based permissions

Add-ons Marketplace: Thousands of community and commercial extensions

Theming System: Template-based design with full Concrete5 API access

Installation and Setup

Step 1: Create Your Project Directory

Start with a dedicated directory for your Concrete5 deployment:

Terminal window
mkdir concrete5-deployment
cd concrete5-deployment
git init

Step 2: Create Directory Structure

Set up the necessary directories:

Terminal window
mkdir -p public html config cache var/files

Your project structure will look like:

concrete5-deployment/
├── Dockerfile
├── docker-entrypoint.sh
├── .dockerignore
├── .gitignore
├── public/
│ └── (web root)
├── config/
│ └── (configuration files)
└── var/
└── files/
└── (user uploads - persistent)

Step 3: Create the Dockerfile

Create a Dockerfile in your project root:

# Use official PHP image with Apache
FROM php:8.2-apache
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
mysql-client \
postgresql-client \
curl \
git \
zip \
unzip \
libzip-dev \
libjpeg-dev \
libpng-dev \
libfreetype6-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) \
gd \
mysqli \
pdo \
pdo_mysql \
pdo_pgsql \
zip \
bcmath \
intl \
opcache \
&& rm -rf /var/lib/apt/lists/*
# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Enable Apache modules
RUN a2enmod rewrite \
&& a2enmod headers \
&& a2enmod expires
# Set working directory
WORKDIR /var/www/html
# Copy Apache configuration
COPY apache.conf /etc/apache2/sites-available/000-default.conf
# Copy entrypoint script
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
# Create necessary directories
RUN mkdir -p /var/www/html/application/files \
&& mkdir -p /var/www/html/packages \
&& mkdir -p /var/www/html/updates
# Set permissions
RUN chown -R www-data:www-data /var/www/html
# Expose port 80
EXPOSE 80
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD curl -f http://localhost/ || exit 1
# Use entrypoint script
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["apache2-foreground"]

Step 4: Create Apache Configuration

Create apache.conf for proper URL rewriting:

<VirtualHost *:80>
ServerAdmin admin@localhost
DocumentRoot /var/www/html
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Enable mod_rewrite for pretty URLs
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# Logging
ErrorLog ${APACHE_LOG_DIR}/concrete5-error.log
CustomLog ${APACHE_LOG_DIR}/concrete5-access.log combined
# Performance headers
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"
</IfModule>
# Security headers
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
</VirtualHost>

Step 5: Create Entrypoint Script

Create docker-entrypoint.sh for initialization:

#!/bin/bash
set -e
echo "Starting Concrete5 initialization..."
# Wait for database to be ready
if [ ! -z "$DB_HOST" ]; then
echo "Waiting for database at $DB_HOST:$DB_PORT..."
until nc -z "$DB_HOST" "${DB_PORT:-3306}" 2>/dev/null; do
echo "Database is unavailable - sleeping"
sleep 2
done
echo "Database is available"
fi
# Download and install Concrete5 if not already present
if [ ! -f "/var/www/html/concrete/bootstrap.php" ]; then
echo "Installing Concrete5..."
cd /var/www/html
# Use Composer to create new Concrete5 project
# This installs Concrete5 from composer
if [ -f "composer.json" ]; then
composer install --no-interaction --prefer-dist --optimize-autoloader
fi
fi
# Set correct permissions
echo "Setting permissions..."
chown -R www-data:www-data /var/www/html/application
chown -R www-data:www-data /var/www/html/packages
chown -R www-data:www-data /var/www/html/updates
# Create config directory if needed
mkdir -p /var/www/html/application/config
chown -R www-data:www-data /var/www/html/application/config
echo "Concrete5 initialization complete. Starting Apache..."
# Execute the main command
exec "$@"

Make it executable:

Terminal window
chmod +x docker-entrypoint.sh

Step 6: Create .dockerignore

Create .dockerignore to exclude unnecessary files:

.git
.gitignore
.env
.env.local
*.log
node_modules
npm-debug.log
.DS_Store
.vscode
.idea
README.md
docs/
tests/
updates/

Step 7: Create .gitignore

Create .gitignore to prevent committing sensitive files:

# Environment
.env
.env.local
.env.*.local
# Concrete5 uploads
application/files/*
application/config/database.php
application/config/site.php
# Composer
composer.lock
vendor/
# Logs
*.log
logs/
# Cache
tmp/
cache/
updates/
# OS
.DS_Store
Thumbs.db
# IDE
.vscode/
.idea/
*.swp
*.swo
# Node
node_modules/
npm-debug.log

Step 8: Create Composer Configuration

Create composer.json for Concrete5:

{
"name": "concrete5/concrete5",
"description": "Concrete5 CMS Installation",
"require": {
"php": ">=7.4",
"concrete5/core": "^9.1"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"config": {
"platform": {
"php": "8.2"
},
"optimize-autoloader": true
},
"scripts": {
"post-install-cmd": [],
"post-update-cmd": []
}
}

Step 9: Local Testing (Optional)

Test your Concrete5 setup locally:

Terminal window
# Build the image
docker build -t concrete5-test .
# Create a test network
docker network create concrete5-network
# Run MySQL for testing
docker run -d \
--name concrete5-mysql \
--network concrete5-network \
-e MYSQL_ROOT_PASSWORD=root_password \
-e MYSQL_DATABASE=concrete5 \
-e MYSQL_USER=concrete5_user \
-e MYSQL_PASSWORD=concrete5_pass \
mysql:8.0
# Wait for MySQL
sleep 30
# Run Concrete5
docker run -d \
--name concrete5-app \
--network concrete5-network \
-p 8080:80 \
-e DB_HOST=concrete5-mysql \
-e DB_USER=concrete5_user \
-e DB_PASSWORD=concrete5_pass \
-e DB_NAME=concrete5 \
-e DB_PORT=3306 \
-v $(pwd)/application:/var/www/html/application \
concrete5-test
# Access the application
# Open http://localhost:8080 in your browser
# View logs
docker logs -f concrete5-app
# Cleanup
docker stop concrete5-app concrete5-mysql
docker rm concrete5-app concrete5-mysql
docker network rm concrete5-network

Step 10: Commit to GitHub

Push your configuration to GitHub:

Terminal window
git add Dockerfile docker-entrypoint.sh apache.conf composer.json .dockerignore .gitignore
git commit -m "Add Concrete5 Docker configuration"
git branch -M main
git remote add origin https://github.com/yourusername/concrete5-deployment.git
git push -u origin main

Deploying to Klutch.sh

Now let’s deploy Concrete5 to Klutch.sh with proper database configuration and persistent storage.

Deployment Steps

  1. Access Klutch.sh Dashboard

    Navigate to klutch.sh/app and sign in with your GitHub account.

  2. Create a New Project

    In the Projects section, click “Create Project” and name it something like “Concrete5 Website” or “CMS Platform”.

  3. Create a New App

    Within your project, click “Create App” to begin configuring your Concrete5 deployment.

  4. Connect Your Repository
    • Select GitHub as your Git source
    • Choose your repository with the Concrete5 Dockerfile
    • Select the branch to deploy (typically main)

    Klutch.sh will automatically detect the Dockerfile in your repository root.

  5. Configure Traffic Settings
    • Traffic Type: Select HTTP (Concrete5 serves web traffic via HTTP)
    • Internal Port: Set to 80 (Apache’s default port)
  6. Configure Environment Variables

    Add the following environment variables to configure your Concrete5 instance:

    Database Configuration:

    Terminal window
    # MySQL configuration
    DB_HOST=your-mysql-host.com
    DB_PORT=3306
    DB_USER=concrete5_user
    DB_PASSWORD=your-secure-database-password
    DB_NAME=concrete5
    # Or PostgreSQL
    DB_DRIVER=postgres
    DB_HOST=your-postgres-host.com
    DB_PORT=5432
    DB_USER=concrete5_user
    DB_PASSWORD=your-secure-database-password
    DB_NAME=concrete5

    Application Configuration:

    Terminal window
    # Site URL (your Klutch.sh app URL)
    APP_URL=https://example-app.klutch.sh
    # Application environment
    APP_ENV=production
    # Debug mode (disable in production)
    APP_DEBUG=false
    # Security key for sessions and encryption
    APP_KEY=your-random-security-key-here
    # Generate with: php -r "echo bin2hex(random_bytes(32));"

    Email Configuration (SMTP for notifications):

    Terminal window
    MAIL_DRIVER=smtp
    MAIL_HOST=smtp.example.com
    MAIL_PORT=587
    MAIL_USERNAME=your-email@example.com
    MAIL_PASSWORD=your-email-password
    MAIL_ENCRYPTION=tls
    MAIL_FROM_ADDRESS=noreply@yourdomain.com
    MAIL_FROM_NAME="Concrete5 Site"

    Additional Configuration:

    Terminal window
    # Logging
    LOG_LEVEL=warning
    LOG_CHANNEL=stack
    # Cache configuration
    CACHE_DRIVER=file
    # Session settings
    SESSION_DRIVER=file
    SESSION_LIFETIME=120
    # File upload limits (in bytes)
    MAX_UPLOAD_SIZE=104857600
    # 100MB
    # PHP settings
    PHP_MEMORY_LIMIT=512M
    PHP_MAX_EXECUTION_TIME=300

    Security Recommendations:

    • Generate a strong, unique APP_KEY
    • Use a strong database password
    • Never commit .env files to Git
    • Keep APP_DEBUG=false in production
    • Use HTTPS for your site (Klutch.sh provides this automatically)
  7. Configure Persistent Storage

    Concrete5 needs persistent volumes for user uploads, theme files, and application data:

    Volume 1 - Application Files:

    • Mount Path: /var/www/html/application/files
    • Size: 10-50 GB (depending on expected uploads)

    Volume 2 - Themes and Packages:

    • Mount Path: /var/www/html/packages
    • Size: 5-10 GB

    Important: Persistent volumes are essential. Without them, all user uploads and customizations will be lost when the container restarts.

  8. Configure Compute Resources

    Choose appropriate resources based on expected traffic:

    Small Site (< 1,000 monthly visitors):

    • CPU: 1 core
    • RAM: 1 GB
    • Suitable for: Personal blogs, small business sites

    Medium Site (1,000-10,000 monthly visitors):

    • CPU: 2 cores
    • RAM: 2 GB
    • Suitable for: Growing businesses, community sites

    Large Site (10,000-100,000 monthly visitors):

    • CPU: 4 cores
    • RAM: 4 GB
    • Suitable for: Large organizations, popular sites

    Enterprise (100,000+ monthly visitors):

    • CPU: 8+ cores
    • RAM: 8+ GB
    • Suitable for: Enterprise deployments, high-traffic sites

    You can scale up or down based on actual usage patterns.

  9. Deploy the Application

    Click “Create” to start the deployment. Klutch.sh will:

    1. Clone your repository
    2. Build the Docker image
    3. Configure environment variables
    4. Set up persistent volumes
    5. Start the Concrete5 container
    6. Assign a public URL (e.g., example-app.klutch.sh)
    7. Configure automatic HTTPS with SSL certificates

    Deployment typically takes 3-5 minutes.

  10. Monitor Deployment Progress

    Track the deployment:

    • Go to the Deployments tab
    • View real-time build logs
    • Wait for status to show “Running”
    • Check for any errors or warnings
  11. Complete Concrete5 Installation

    Once deployed, complete the Concrete5 setup wizard:

    1. Navigate to your app URL: https://example-app.klutch.sh
    2. You should see the Concrete5 installation wizard
    3. Follow the setup steps:
      • Accept the license
      • Verify database configuration
      • Create admin user account
      • Configure basic site settings
    4. The wizard will initialize the database with required tables
    5. Complete the setup to access the dashboard
  12. Verify Installation

    After setup completes, verify everything is working:

    1. Access the admin dashboard: https://example-app.klutch.sh/dashboard
    2. Log in with your admin credentials
    3. Check that the home page loads
    4. Test creating a page
    5. Verify file uploads work (try uploading an image)
    6. Check that the theme loads properly
    7. Test the website from a different browser to confirm it works

Database Configuration

Concrete5 requires a database for storing content, users, and configuration. You have several options:

Option 1: External Database Service

Use a managed database service for ease of management:

Recommended Providers:

Setup Process:

  1. Create database instance with your provider
  2. Create database named concrete5
  3. Create user with full permissions
  4. Note connection details (host, port, user, password)
  5. Add to environment variables in Klutch.sh

Option 2: MySQL/PostgreSQL on Klutch.sh

Deploy the database separately on Klutch.sh:

  1. Create a new app using MySQL or PostgreSQL image
  2. Configure with persistent storage
  3. Set a secure root password
  4. Use TCP traffic on port 8000
  5. Connect Concrete5 app to database via internal URL

Database Setup

Create Database and User (if using manual setup):

-- For MySQL
CREATE DATABASE concrete5 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'concrete5_user'@'%' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON concrete5.* TO 'concrete5_user'@'%';
FLUSH PRIVILEGES;
-- For PostgreSQL
CREATE DATABASE concrete5;
CREATE USER concrete5_user WITH PASSWORD 'secure_password';
GRANT ALL PRIVILEGES ON DATABASE concrete5 TO concrete5_user;

Connection String Format:

  • MySQL: mysql://user:password@host:3306/concrete5
  • PostgreSQL: postgresql://user:password@host:5432/concrete5

Database Requirements:

  • MySQL 5.7+ or PostgreSQL 10+
  • At least 100MB initial storage (scales with content)
  • SSL/TLS encryption recommended for production
  • Regular backups essential

Concrete5 automatically creates all necessary tables during installation.

Getting Started with Concrete5

First Login and Site Setup

  1. Access the Dashboard

    Navigate to https://example-app.klutch.sh/dashboard and log in with your admin credentials.

  2. Understand the Dashboard

    The Concrete5 dashboard shows:

    • Site pages and structure
    • User management
    • System settings
    • Page attributes and metadata
    • Add-ons and extensions
  3. Configure Basic Settings

    Go to DashboardSystem & SettingsSite:

    • Set site name and tagline
    • Configure timezone
    • Set default language
    • Configure canonical URLs for SEO

Creating and Managing Content

Creating a Page:

  1. Click “Add Page” in the Dashboard
  2. Select a template (or use default)
  3. Enter page name and description
  4. Set URL slug for SEO-friendly URLs
  5. Click “Create”
  6. You’ll be taken to edit the new page

In-Context Editing:

This is where Concrete5 really shines. When you click on any editable block on the page:

  • A floating toolbar appears above it
  • You can edit content directly in context
  • Click elsewhere to save changes
  • No need to visit a separate admin page

Working with Blocks:

Concrete5 organizes content into blocks:

  • Text block: Simple paragraphs and formatted text
  • Image block: Single image with alt text
  • Content block: Full WYSIWYG editor
  • File block: Downloadable documents
  • Video block: YouTube, Vimeo, or self-hosted
  • Feature block: Showcase items with images
  • Automated list: Dynamic content from pages

To add a block:

  1. Click the ”+” icon on the page
  2. Select block type
  3. Configure block settings
  4. Click to add content

User Management

Creating Users:

  1. Go to DashboardUsers & GroupsUsers
  2. Click “Add User”
  3. Enter email, username, and password
  4. Select user group (determines permissions)
  5. Assign roles: Admin, Editor, Member, Guest
  6. User receives welcome email

User Groups and Permissions:

  • Administrators: Full system access
  • Editors: Can create/edit pages and content
  • Members: Limited editing permissions
  • Guests: View-only access

Site Structure and Navigation

Managing the Page Tree:

Concrete5 uses a hierarchical page structure:

Home
├── About
│ ├── Team
│ └── History
├── Products
│ ├── Product A
│ └── Product B
├── Blog
│ ├── Post 1
│ └── Post 2
└── Contact

Modify Page Structure:

  1. Right-click any page in the page tree
  2. Options: Add Sibling, Add Child, Edit, Delete
  3. Drag-and-drop to reorganize
  4. Click expand/collapse arrows to view children

Page Properties:

For each page, set:

  • Page Type: Determines which blocks can be used
  • Template: Controls the layout
  • Attributes: Custom metadata (author, date, category, etc.)
  • Publishing: Schedule publication dates
  • Versions: Track and restore previous versions

Working with Themes

Installing a Theme:

  1. Go to DashboardThemes
  2. Click “Browse Marketplace” or upload custom theme
  3. Select theme and click “Install”
  4. Click “Activate” to use it site-wide
  5. Preview changes before applying

Customizing a Theme:

  1. Go to MarketplaceFind Themes
  2. Browse available themes
  3. Each theme has:
    • Live preview
    • Documentation
    • Customization options
    • User reviews

Popular Themes:

  • Elemental Pro: Modern, highly customizable
  • Supreme: Feature-rich, professional
  • Radiance: Lightweight, responsive
  • Auberge: Design-focused

Add-ons and Extensions

Concrete5 has a rich ecosystem of add-ons for extended functionality:

Installing Add-ons:

  1. Go to DashboardExtend Concrete5Find More Add-ons
  2. Browse the marketplace
  3. Click “Install” on desired add-on
  4. Review requirements and permissions
  5. Confirm installation
  6. Activate from Installed Add-ons

Popular Add-ons:

  • Page List: Display dynamic lists of pages
  • Social Media: Add social media integrations
  • Email Forms: Create contact forms
  • Advanced Custom Attributes: Custom page fields
  • Calendar: Event management
  • Blog: Structured blog functionality
  • E-commerce: Simple store capabilities
  • Member Registration: User account registration
  • Newsletter: Email subscription management

Content Editing Tips

Bulk Page Updates:

  1. Select multiple pages in the tree
  2. Right-click and choose “Bulk Edit”
  3. Apply changes to multiple pages at once
  4. Useful for updating templates or attributes

Version Control:

  • Concrete5 maintains version history
  • Click “Version History” on any page
  • Restore previous versions if needed
  • Useful for content rollback

Scheduling:

  • Set publish dates for future content
  • Schedule page removal
  • Automatic publishing/unpublishing
  • Useful for planned releases

Search and Metadata:

  • Configure page metadata for SEO
  • Set canonical URLs
  • Add custom meta tags
  • Configure XML sitemap

Performance Optimization

Caching

Concrete5 includes multiple caching strategies:

Full-Page Caching:

  • Cache entire HTML output
  • Dramatically speeds up page load
  • Automatically clears when content changes
  • Most effective for content-heavy sites

Block Cache:

  • Cache individual blocks
  • Reduces database queries
  • Fine-grained control
  • Configure per-block

Enable Caching:

  1. Go to DashboardSystem & SettingsOptimizationCaching
  2. Select caching method: File, Database, Redis, Memcached
  3. Configure cache lifetime
  4. Enable all cache types

Cache Configuration:

Terminal window
# In environment variables
CACHE_DRIVER=file
CACHE_LIFETIME=3600

Image Optimization

Concrete5 automatically handles image optimization:

Automatic Thumbnails:

  • Generates thumbnails when uploading
  • Responsive images for different screen sizes
  • Reduces bandwidth usage
  • Improves page load times

Image Attributes:

  • Set image quality
  • Configure thumbnail sizes
  • Enable WEBP format support
  • Set maximum dimensions

Configure Image Settings:

  1. Go to DashboardSystem & SettingsFile Management
  2. Set thumbnail sizes
  3. Configure image quality
  4. Enable optimization options

Database Optimization

Regular Maintenance:

-- Analyze tables for query optimization
ANALYZE TABLE pages;
ANALYZE TABLE areas;
ANALYZE TABLE blocks;
-- Optimize tables to free space
OPTIMIZE TABLE pages;
-- Check for errors
CHECK TABLE pages;

Indexing:

Concrete5 comes with appropriate indexes. Avoid adding indexes without understanding query patterns.

Query Performance:

  • Monitor slow query log
  • Review Concrete5 logs for database errors
  • Profile heavy pages
  • Optimize custom code

Server-Side Optimization

PHP Settings:

Configure in environment variables:

Terminal window
PHP_MEMORY_LIMIT=512M
PHP_MAX_EXECUTION_TIME=300
PHP_POST_MAX_SIZE=100M
PHP_UPLOAD_MAX_FILESIZE=100M

Opcode Caching:

PHP 8.2 includes OPcache by default. Enable aggressive caching:

Terminal window
OPCACHE_ENABLE=1
OPCACHE_MEMORY_CONSUMPTION=256
OPCACHE_MAX_ACCELERATED_FILES=4000
OPCACHE_REVALIDATE_FREQ=60

Compression:

Enable GZIP compression in Apache (configured in apache.conf).

Security Best Practices

User Authentication

Strong Passwords:

  • Enforce minimum length (12+ characters)
  • Require complexity (uppercase, numbers, symbols)
  • Implement password expiration
  • Prevent password reuse

Two-Factor Authentication:

  • Enable 2FA for admin users
  • Use authenticator apps (Google, Authy)
  • Backup recovery codes required

Session Management:

  • Configure session timeout (recommended 30-60 minutes)
  • Secure session cookies (HttpOnly, Secure flags)
  • Implement concurrent session limits

Access Control

Role-Based Permissions:

Assign appropriate roles:

  • Administrators: Full system access
  • Editors: Content management only
  • Authors: Create/edit own content
  • Viewers: Read-only access

Granular Permissions:

Configure page-level permissions:

  • Set who can view specific pages
  • Restrict editing to specific users
  • Control publishing permissions
  • Manage file access

Audit Logging:

  1. Enable audit logs in System & Settings
  2. Track user actions
  3. Monitor failed logins
  4. Review permission changes

Data Security

Backups:

Regular backups are critical:

  • Database backups (daily recommended)
  • File uploads backup
  • Configuration files backup
  • Test restore procedures regularly

SSL/TLS:

Klutch.sh provides automatic HTTPS. Ensure:

  • All traffic uses HTTPS
  • Redirect HTTP to HTTPS
  • Valid SSL certificate installed
  • HSTS headers enabled

File Uploads:

Control what users can upload:

  • Whitelist safe file types
  • Limit file size
  • Store uploads outside web root
  • Scan uploads for malware

Regular Updates

Keep Concrete5 secure:

Check for Updates:

  1. Go to DashboardSystem & SettingsUpdate
  2. Review available updates
  3. Read release notes for security issues
  4. Update core and extensions

Backup Before Updating:

  1. Backup database
  2. Backup application files
  3. Note current version
  4. Document custom modifications
  5. Test in staging environment first

Update Process:

  1. Navigate to Updates section
  2. Click “Update” on core or extensions
  3. Monitor update progress
  4. Verify site works after update
  5. Clear all caches

Troubleshooting

Issue 1: Installation Wizard Won’t Load

Symptoms: Blank page or 500 error on first access

Solutions:

  1. Check Database Connection:

    • Verify database host is correct
    • Test credentials with another tool
    • Ensure database user has all permissions
    • Check database exists
  2. Review Logs:

    • Check Klutch.sh application logs
    • Look for PHP errors
    • Review database connection errors
  3. Verify Permissions:

    • Check file permissions on /var/www/html/application
    • Should be writable by www-data user
    • Run: chown -R www-data:www-data /var/www/html
  4. Check PHP Configuration:

    • Verify required PHP extensions are loaded
    • Check memory limit is sufficient
    • Ensure extensions are installed in Dockerfile

Issue 2: Pages Return 404 Errors

Symptoms: Valid pages show 404 “not found”

Solutions:

  1. Check .htaccess and URL Rewriting:

    • Verify Apache mod_rewrite is enabled
    • Check .htaccess file exists in webroot
    • Verify Apache configuration allows rewriting
  2. Verify Page Settings:

    • Check page is published
    • Verify page has correct URL slug
    • Ensure page isn’t restricted by permissions
  3. Clear Cache:

    • Go to DashboardOptimizationCaching
    • Clear all caches
    • Rebuild cache
  4. Check Database:

    • Verify pages exist in database
    • Review database tables for corruption
    • Check page publish status

Issue 3: File Uploads Fail

Symptoms: “Upload failed” errors, files not saved

Solutions:

  1. Check Permissions:

    • Verify /var/www/html/application/files is writable
    • Check ownership is www-data:www-data
    • Verify persistent volume is mounted
  2. Check File Size Limits:

    • Set in environment: MAX_UPLOAD_SIZE=104857600
    • Verify PHP max upload in .htaccess
    • Check server upload limits
  3. Verify Storage:

    • Check persistent volume has free space
    • Monitor volume usage in Klutch.sh dashboard
    • Expand volume if approaching capacity
  4. Review Logs:

    • Check Apache error logs
    • Review PHP error logs
    • Look for permission or disk space errors

Issue 4: Site Is Slow

Symptoms: Slow page load times, delays in admin

Solutions:

  1. Enable Caching:

    • Enable full-page cache
    • Enable block cache
    • Configure cache lifetime
  2. Check Resource Usage:

    • Monitor CPU and memory in Klutch.sh dashboard
    • Identify resource-intensive operations
    • Upgrade instance if consistently maxed out
  3. Optimize Database:

    • Run database optimization queries
    • Check for slow queries in logs
    • Verify appropriate indexes exist
  4. Reduce Page Complexity:

    • Audit page blocks
    • Remove unnecessary blocks
    • Optimize images (use appropriate sizes)
    • Minimize database queries per page
  5. Review Add-ons:

    • Disable unused add-ons
    • Check add-on performance
    • Remove poorly-optimized extensions

Issue 5: Memory Errors

Symptoms: “Fatal error: allowed memory size exhausted”, “Out of memory”

Solutions:

  1. Increase Memory Limit:

    Terminal window
    PHP_MEMORY_LIMIT=512M
    # Or higher if needed
    PHP_MEMORY_LIMIT=1024M
  2. Identify Memory Leaks:

    • Review error logs
    • Check for specific operations that cause errors
    • Profile memory usage with PHP tools
  3. Optimize Code:

    • Avoid loading large datasets into memory
    • Use pagination for large lists
    • Unset variables after use
    • Avoid infinite loops
  4. Upgrade Resources:

    • Increase instance RAM in Klutch.sh
    • More memory allows larger operations
    • Prevents timeout errors

Issue 6: Database Connection Issues

Symptoms: “Could not connect to database”, connection errors

Solutions:

  1. Verify Credentials:

    • Check DB_HOST, DB_USER, DB_PASSWORD
    • Ensure credentials are correct
    • Try connecting with MySQL client
  2. Check Network:

    • Verify database host is reachable
    • Test connectivity from Klutch.sh instance
    • Check firewall rules
    • Verify database port is correct
  3. Database Status:

    • Confirm database service is running
    • Check for database errors in logs
    • Verify database user has proper permissions
    • Ensure database exists
  4. Connection Pool:

    • Check max connections limit
    • Monitor active connections
    • Restart application if stalled

Issue 7: Theme or Add-on Errors

Symptoms: Broken styling, missing functionality, blank pages

Solutions:

  1. Revert to Default Theme:

    • Go to DashboardThemes
    • Select default theme
    • Verify site works
  2. Disable Problematic Add-ons:

    • Go to DashboardAdd-ons
    • Disable recently installed add-ons
    • Test if issue resolves
  3. Clear Cache:

    • Clear all caches in OptimizationCaching
    • Refresh browser cache (Ctrl+Shift+R)
    • Rebuild all caches
  4. Check Compatibility:

    • Verify theme/add-on supports your PHP version
    • Check Concrete5 version compatibility
    • Review marketplace reviews for issues
  5. Review Logs:

    • Check error logs for PHP errors
    • Look for JavaScript errors in browser console
    • Review Concrete5 logs

Issue 8: Admin Dashboard Unresponsive

Symptoms: Dashboard loads slowly, timing out, freezes

Solutions:

  1. Check Resource Usage:

    • Upgrade instance CPU/RAM
    • Monitor resource usage patterns
    • Identify peak usage times
  2. Disable Cache:

    • Temporarily disable full-page cache
    • Test dashboard responsiveness
    • Re-enable if dashboard works
  3. Clear Cache:

    • Go to OptimizationCaching
    • Clear all caches
    • Clear browser cache
  4. Reduce Operations:

    • Close unnecessary browser tabs
    • Disable real-time preview
    • Limit simultaneous admin users
  5. Profile Performance:

    • Check slow query logs
    • Identify expensive operations
    • Optimize or defer heavy operations

Issue 9: Email Delivery Issues

Symptoms: Password reset emails not received, notifications not sending

Solutions:

  1. Verify SMTP Configuration:

    • Check MAIL_HOST, MAIL_PORT, MAIL_USERNAME, MAIL_PASSWORD
    • Verify credentials with email provider
    • Test SMTP connection manually
  2. Check Email Settings:

    • Go to System & SettingsEmail
    • Verify from address and name
    • Test send functionality
  3. Review Logs:

    • Check application logs for email errors
    • Review SMTP server logs
    • Look for authentication failures
  4. Spam Filters:

    • Check spam/junk folder
    • Verify SPF, DKIM, DMARC records
    • Use reputable SMTP provider
  5. Port and Security:

    • Verify correct SMTP port (587 or 465)
    • Check TLS/SSL configuration
    • Ensure firewall allows SMTP

Issue 10: Unexpected Downtime

Symptoms: Site unavailable, returns 502 or 503 errors

Solutions:

  1. Check Application Status:

    • Verify app is running in Klutch.sh dashboard
    • Check deployment status
    • Review logs for errors
  2. Restart Application:

    • Restart from Klutch.sh dashboard
    • Monitor restart progress
    • Check logs after restart
  3. Check Database:

    • Verify database connection
    • Check database service is running
    • Review database logs
  4. Review Logs:

    • Check Klutch.sh application logs
    • Look for fatal errors
    • Review system logs
  5. Increase Resources:

    • Upgrade instance if running out of resources
    • Monitor CPU and memory usage
    • Plan capacity for expected growth

Custom Domains

Using a custom domain makes your site professional and brand-friendly.

Step 1: Add Domain in Klutch.sh

  1. Go to your app in Klutch.sh dashboard
  2. Navigate to Domains section
  3. Click “Add Custom Domain”
  4. Enter your domain (e.g., www.yourdomain.com)
  5. Save the configuration

Step 2: Update DNS

Configure DNS with your domain provider:

Type: CNAME
Name: www (or leave empty for root)
Value: example-app.klutch.sh
TTL: 3600

DNS Examples:

www.yourdomain.com. CNAME example-app.klutch.sh.
yourdomain.com. CNAME example-app.klutch.sh.

Step 3: Update Concrete5 Configuration

Update the site URL setting:

  1. Go to DashboardSystem & SettingsSite
  2. Set “Site URL” to https://www.yourdomain.com
  3. Save changes

Also set in environment variables:

Terminal window
APP_URL=https://www.yourdomain.com

Step 4: Verify Setup

  1. Wait for DNS propagation (5-60 minutes)

  2. Test DNS resolution:

    Terminal window
    nslookup yourdomain.com
    # Should show example-app.klutch.sh
  3. Access https://yourdomain.com in browser

  4. Verify SSL certificate is valid

  5. Check site loads correctly

Production Best Practices

Backup Strategy

What to Backup:

  1. Database: Core of your site
  2. Uploads: User files and images
  3. Custom Code: Themes and add-ons
  4. Configuration: Environment settings

Backup Schedule:

  • Daily: Database backups
  • Weekly: Complete system backup
  • Monthly: Archival backup

Backup Implementation:

Terminal window
# Automated database backup
0 2 * * * mysqldump -h $DB_HOST -u $DB_USER -p$DB_PASSWORD $DB_NAME | gzip > /backups/concrete5-$(date +%Y%m%d).sql.gz
# Backup uploads
0 3 * * * tar -czf /backups/uploads-$(date +%Y%m%d).tar.gz /var/www/html/application/files/
# Verify backups
0 5 * * * ls -lh /backups/

Backup Testing:

  • Monthly restore tests
  • Verify backup integrity
  • Document recovery procedures
  • Practice disaster recovery

Monitoring and Logging

Key Metrics to Monitor:

  • CPU usage
  • Memory usage
  • Disk space (especially uploads)
  • Database connection count
  • Page load times
  • Failed logins
  • Database errors

Logging Configuration:

Terminal window
LOG_LEVEL=warning
LOG_CHANNEL=stack

Monitor logs for:

  • PHP errors
  • Database errors
  • Failed authentication
  • Permission issues
  • Deployment errors

Scaling Strategy

Identify Bottlenecks:

  1. Monitor CPU usage during peak times
  2. Check memory utilization
  3. Review database query performance
  4. Measure page load times

Vertical Scaling (Recommended First):

  • Increase CPU cores
  • Increase RAM
  • Upgrade storage
  • Simplest approach for most sites

Horizontal Scaling (Advanced):

  • Multiple application instances
  • Load balancer distribution
  • Shared database
  • Shared storage (S3 or NFS)
  • More complex setup

Cache Optimization:

  • Aggressive caching strategy
  • CDN for static assets
  • Browser caching headers
  • Reduced database queries

Security Maintenance

Regular Tasks:

Daily:

  • Monitor error logs
  • Check failed logins
  • Verify backups completed

Weekly:

  • Review user accounts
  • Check for suspicious activity
  • Test critical functionality

Monthly:

  • Security audit
  • Verify permissions
  • Review access logs
  • Update documentation

Quarterly:

  • Full security scan
  • Penetration testing (if applicable)
  • Compliance audit
  • Disaster recovery test

Annually:

  • Major version updates
  • Security assessment
  • Capacity planning
  • Strategy review

Additional Resources

Conclusion

Deploying Concrete5 on Klutch.sh gives you a powerful, flexible content management system with complete control over your infrastructure. You’ve learned how to build a production-ready Dockerfile with proper Apache configuration, set up the application with persistent storage for uploads and files, configure database connectivity, optimize performance through caching and code optimization, implement security best practices for user authentication and data protection, troubleshoot common deployment issues, and scale resources as your site grows.

Concrete5’s in-context editing makes content management intuitive for your team. Unlike traditional CMSs that separate editing from viewing, Concrete5 lets content creators edit pages directly in context—reducing training time and improving efficiency.

With Klutch.sh’s straightforward deployment process, you can focus on creating great content rather than managing infrastructure. Your site is now running on reliable, globally-distributed infrastructure with automatic HTTPS, scalable resources, and professional-grade hosting.

The flexibility of Concrete5 combined with Klutch.sh’s ease of deployment creates an excellent foundation for websites of any size—from small business sites to large enterprise deployments. Start small, scale as needed, and adjust your approach based on actual usage patterns and performance data.

For questions, community support, or marketplace add-ons, check out the Concrete5 website and active community forums. The passionate community and extensive marketplace ensure you can find solutions for virtually any requirement.