Deploying CiviCRM
Introduction
CiviCRM is a powerful, open-source constituent relationship management (CRM) platform designed specifically for nonprofits, advocacy groups, and civic organizations. It provides comprehensive tools for managing contacts, donations, memberships, events, email campaigns, case management, and grant tracking—all in one unified platform. Built on PHP and supporting multiple database backends, CiviCRM integrates seamlessly with popular content management systems like WordPress, Drupal, and Joomla.
Deploying CiviCRM on Klutch.sh gives you a reliable, scalable platform for hosting your nonprofit’s CRM infrastructure with production-grade performance, persistent storage for critical constituent data, and streamlined deployment workflows. Whether you’re managing donor relationships, coordinating volunteers, organizing advocacy campaigns, or tracking program outcomes, this guide walks you through deploying CiviCRM using Docker to ensure a reproducible, secure, and maintainable setup.
This comprehensive guide covers everything you need to deploy CiviCRM successfully on Klutch.sh: from creating your Dockerfile to configuring database connections, setting up persistent volumes for uploads and data, managing environment variables for security, and implementing production best practices for reliable nonprofit operations.
Prerequisites
Before you begin deploying CiviCRM on Klutch.sh, ensure you have the following:
- A Klutch.sh account (sign up here)
- A GitHub account and repository for your CiviCRM project
- Basic familiarity with Docker, environment variables, and database management
- A MySQL 5.7+ or MariaDB 10.2+ database (you can provision one on Klutch.sh or use an external managed database service)
- Understanding of PHP applications and web servers (helpful but not required)
What You’ll Deploy
By the end of this guide, you’ll have:
- A fully functional CiviCRM installation running on Klutch.sh
- Persistent storage for file uploads, attachments, custom data, and application assets
- Database connectivity to MySQL or MariaDB for storing constituent and organizational data
- Secure environment variable configuration for credentials and API keys
- Production-ready setup with proper permissions and security configurations
- A Docker-based deployment that’s reproducible and easy to maintain
Understanding CiviCRM Architecture
CiviCRM is built on PHP and requires:
- PHP 7.3 or higher (PHP 7.4+ recommended) with required extensions (MySQLi/PDO, Multibyte String, SOAP, cURL, Zip, GD, DOM, XML)
- Web server (Apache with mod_rewrite or Nginx)
- MySQL 5.7+ or MariaDB 10.2+ database for storing all CRM data
- File storage for uploads, attachments, templates, and custom data
- Composer for dependency management (when building from source)
CiviCRM typically runs on port 80 (HTTP) when using Apache, which we’ll configure for routing on Klutch.sh. For this deployment, we’ll use the internal port 80 for HTTP traffic routing.
1. Prepare Your CiviCRM Repository
-
Create a new GitHub repository for your CiviCRM deployment. This will house your Dockerfile and any custom configuration.
-
In your repository root, you’ll create a
Dockerfilethat defines the container image for CiviCRM. This ensures reproducible builds and consistent deployments. -
Keep sensitive data (database credentials, API keys, SMTP passwords) out of your repository. We’ll use Klutch.sh environment variables to manage secrets securely.
-
Organize your repository structure:
civicrm-deployment/├── Dockerfile├── .dockerignore├── docker-compose.yml (for local development only)├── config/│ └── civicrm.settings.php.template (optional)└── README.md -
Create a
.dockerignorefile to exclude unnecessary files from the Docker build:.git.github.env.env.localnode_modules*/temp/**/cache/**/logs/*
For more details on setting up your repository and connecting to GitHub, refer to the Klutch.sh Quick Start Guide.
2. Sample Dockerfile for CiviCRM
Below is a production-ready Dockerfile that sets up CiviCRM with Apache, all required PHP extensions, and proper permissions. This Dockerfile uses the official CiviCRM installation method with WordPress as the base CMS (you can adapt this for Drupal or standalone installations).
Option 1: CiviCRM with WordPress
FROM wordpress:php8.1-apache
# Set working directoryWORKDIR /var/www/html
# Install system dependencies and required PHP extensionsRUN apt-get update && apt-get install -y \ wget \ unzip \ libpng-dev \ libjpeg-dev \ libfreetype6-dev \ libzip-dev \ libxml2-dev \ libonig-dev \ libcurl4-openssl-dev \ git \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j$(nproc) \ gd \ mysqli \ pdo_mysql \ zip \ curl \ soap \ mbstring \ xml \ dom \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*
# Enable Apache modules required for CiviCRMRUN a2enmod rewrite headers expires ssl
# Set recommended PHP settings for CiviCRMRUN { \ echo 'memory_limit = 256M'; \ echo 'upload_max_filesize = 32M'; \ echo 'post_max_size = 32M'; \ echo 'max_execution_time = 300'; \ echo 'max_input_time = 300'; \ echo 'max_input_vars = 3000'; \} > /usr/local/etc/php/conf.d/civicrm.ini
# Set proper file permissionsRUN chown -R www-data:www-data /var/www/html
# Expose port 80 for HTTP trafficEXPOSE 80
# Start ApacheCMD ["apache2-foreground"]Option 2: Standalone CiviCRM with Nginx and PHP-FPM
For a more lightweight deployment without a CMS:
FROM php:8.1-fpm
# Set working directoryWORKDIR /var/www/html
# Install system dependenciesRUN apt-get update && apt-get install -y \ nginx \ wget \ unzip \ libpng-dev \ libjpeg-dev \ libfreetype6-dev \ libzip-dev \ libxml2-dev \ libonig-dev \ libcurl4-openssl-dev \ git \ supervisor \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j$(nproc) \ gd \ mysqli \ pdo_mysql \ zip \ curl \ soap \ mbstring \ xml \ dom \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*
# Download and install CiviCRMARG CIVICRM_VERSION=5.69.2RUN cd /tmp && \ wget https://download.civicrm.org/civicrm-${CIVICRM_VERSION}-wordpress.zip && \ unzip civicrm-${CIVICRM_VERSION}-wordpress.zip -d /var/www/html/ && \ rm civicrm-${CIVICRM_VERSION}-wordpress.zip
# Configure NginxCOPY nginx.conf /etc/nginx/sites-available/default
# Set PHP configuration for CiviCRMRUN { \ echo 'memory_limit = 256M'; \ echo 'upload_max_filesize = 32M'; \ echo 'post_max_size = 32M'; \ echo 'max_execution_time = 300'; \ echo 'max_input_time = 300'; \ echo 'max_input_vars = 3000'; \} > /usr/local/etc/php/conf.d/civicrm.ini
# Configure supervisor to run both PHP-FPM and NginxCOPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Set proper permissionsRUN chown -R www-data:www-data /var/www/html
EXPOSE 80
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]3. Required Configuration Files
nginx.conf (for Option 2)
server { listen 80; server_name _; root /var/www/html; index index.php index.html;
client_max_body_size 32M;
location / { try_files $uri $uri/ /index.php?$args; }
location ~ \.php$ { include fastcgi_params; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires max; log_not_found off; }}supervisord.conf (for Option 2)
[supervisord]nodaemon=trueuser=root
[program:php-fpm]command=/usr/local/sbin/php-fpmautostart=trueautorestart=truestdout_logfile=/var/log/php-fpm.logstderr_logfile=/var/log/php-fpm-error.log
[program:nginx]command=/usr/sbin/nginx -g "daemon off;"autostart=trueautorestart=truestdout_logfile=/var/log/nginx.logstderr_logfile=/var/log/nginx-error.log4. Persistent Storage and Volumes
CiviCRM requires persistent storage for several critical directories:
- File uploads and attachments:
/var/www/html/wp-content/uploads/civicrm(WordPress) or/var/www/html/sites/default/files/civicrm(Drupal) - Templates cache: CiviCRM template compilation directory
- Custom data and extensions: Custom PHP extensions and configurations
-
In the Klutch.sh dashboard at klutch.sh/app, navigate to your project and go to the Volumes section.
-
Create a new persistent volume with an appropriate size (start with 10GB, adjust based on your expected data growth).
-
For WordPress-based CiviCRM, attach the volume to mount path:
/var/www/html/wp-content/uploads -
For standalone installations, attach to:
/var/www/html/sites/default/files -
You may also want separate volumes for:
- Configuration files:
/var/www/html/sites/default(mount path) - Size: 1GB
- Configuration files:
Important: Ensure the directories within the container have proper permissions (www-data:www-data ownership) after mounting volumes.
For more details on managing persistent storage, see the Klutch.sh Volumes Guide.
5. Database Configuration
CiviCRM requires a MySQL or MariaDB database. You have two options:
Option A: Use Klutch.sh Managed MySQL
- In the Klutch.sh dashboard, navigate to the Databases section
- Create a new MySQL instance
- Note the connection details (host, port, username, password, database name)
- The internal database host will be accessible from your CiviCRM app
See the MySQL deployment guide for detailed instructions.
Option B: Use External Managed MySQL
Use a managed MySQL service from your cloud provider (AWS RDS, Google Cloud SQL, Azure Database for MySQL) and note the connection credentials.
6. Environment Variables and Configuration
Set these environment variables in your Klutch.sh app settings at klutch.sh/app:
Required Database Variables
WORDPRESS_DB_HOST=your-mysql-hostWORDPRESS_DB_USER=civicrm_userWORDPRESS_DB_PASSWORD=your-secure-passwordWORDPRESS_DB_NAME=civicrm_dbCiviCRM-Specific Variables
CIVICRM_DB_HOST=your-mysql-hostCIVICRM_DB_USER=civicrm_userCIVICRM_DB_PASSWORD=your-secure-passwordCIVICRM_DB_NAME=civicrm_db
# Site configurationCIVICRM_SITE_KEY=generate-a-random-32-character-keyCIVICRM_SITE_URL=https://example-app.klutch.sh
# Email/SMTP Configuration (optional but recommended)CIVICRM_SMTP_SERVER=smtp.example.comCIVICRM_SMTP_PORT=587CIVICRM_SMTP_USERNAME=your-smtp-userCIVICRM_SMTP_PASSWORD=your-smtp-passwordCIVICRM_SMTP_AUTH=trueOptional Performance and Security Variables
# Memory and resource limitsPHP_MEMORY_LIMIT=256MPHP_MAX_EXECUTION_TIME=300PHP_UPLOAD_MAX_FILESIZE=32M
# Cron configurationCIVICRM_CRON_KEY=generate-another-random-key
# LoggingCIVICRM_LOG_LEVEL=errorSecurity Note: Always mark sensitive variables (passwords, API keys, SMTP credentials) as secrets in the Klutch.sh dashboard. Never commit secrets to your repository.
7. Deploying to Klutch.sh
-
Push your repository (including
Dockerfileand any configuration files) to GitHub. -
Log in to the Klutch.sh dashboard at klutch.sh/app.
-
Create a new project (if you haven’t already) and give it a descriptive name like “CiviCRM Production”.
-
Within your project, create a new app:
- Connect your GitHub repository
- Klutch.sh will automatically detect the Dockerfile in the root directory
- Set the app name (e.g., “civicrm-app”)
-
Configure the traffic settings:
- Select HTTP traffic type
- The internal port for traffic routing should be set to 80 (this is where Apache or Nginx listens inside the container)
-
Attach persistent volumes:
- Add the volume you created earlier
- Set the mount path to
/var/www/html/wp-content/uploads(or your configured path) - Specify the volume size as configured earlier
-
Configure environment variables:
- Add all the database, CiviCRM, and optional variables from section 6
- Mark all passwords and sensitive keys as secrets
-
(Optional) Configure custom domain:
- If you want to use your own domain instead of
example-app.klutch.sh - See the Custom Domains Guide
- If you want to use your own domain instead of
-
Review your configuration and click Create to deploy.
-
Klutch.sh will build your Docker image and start the container. Monitor the build logs for any errors.
-
Once deployed, visit your app URL (e.g.,
https://example-app.klutch.sh) to access CiviCRM.
8. Post-Deployment: CiviCRM Installation
After your container is running, complete the CiviCRM installation:
-
Navigate to your app URL in a web browser:
https://example-app.klutch.sh -
If using WordPress, first complete the WordPress installation:
- Follow the WordPress setup wizard
- Create an admin account
- Complete the basic site configuration
-
Install the CiviCRM plugin:
- For WordPress: Download the CiviCRM plugin from civicrm.org
- Upload and activate the plugin through the WordPress admin interface
- Navigate to the CiviCRM installer URL:
https://example-app.klutch.sh/wp-admin/admin.php?page=civicrm-install
-
Run the CiviCRM installer:
- Verify that all system requirements are met (PHP extensions, file permissions)
- Enter your database credentials (these should match your environment variables)
- Set the site name and default language
- Complete the installation
-
Configure CiviCRM settings:
- Set up your organization information
- Configure email settings (SMTP)
- Set up payment processors if accepting donations
- Configure user permissions and roles
-
Test core functionality:
- Create a test contact
- Send a test email
- Test file uploads
- Verify database connectivity
9. Getting Started with CiviCRM
Once installation is complete, here are some essential first steps:
Create Your First Contact
- Navigate to Contacts → New Individual
- Fill in basic contact information (name, email, phone)
- Save the contact
Set Up Custom Fields
- Go to Administer → Custom Data and Screens → Custom Fields
- Create custom field sets for your organization’s specific needs
- Add fields for donor information, volunteer data, or program-specific details
Configure Email Settings
- Navigate to Administer → System Settings → Outbound Email
- Enter your SMTP server details
- Send a test email to verify configuration
Import Existing Data
- Go to Contacts → Import Contacts
- Upload a CSV file with your existing contact data
- Map CSV columns to CiviCRM fields
- Complete the import process
10. Production Best Practices
Security
- Always use HTTPS for your CiviCRM deployment (Klutch.sh provides this automatically)
- Keep PHP, CiviCRM, and all extensions up to date
- Implement strong password policies for admin users
- Regularly review user permissions and roles
- Enable two-factor authentication for admin accounts
- Restrict access to sensitive data and financial information
- Use secure SMTP with TLS/SSL for email delivery
Backups
- Implement regular database backups (daily recommended for production)
- Back up persistent volumes containing file uploads and custom data
- Test restore procedures regularly
- Store backups in a separate location from your production environment
- Consider automated backup solutions for critical data
Performance Optimization
- Enable CiviCRM caching mechanisms
- Optimize database queries and indexes
- Use a CDN for static assets if serving a large user base
- Monitor resource usage (CPU, memory, disk) in the Klutch.sh dashboard
- Consider scaling up instance size for larger organizations
- Implement database connection pooling for high-traffic deployments
Monitoring and Maintenance
- Set up monitoring for database connections and application health
- Monitor disk usage for persistent volumes and expand as needed
- Review CiviCRM logs regularly for errors or warnings
- Schedule regular maintenance windows for updates
- Test updates in a staging environment before production deployment
Data Management
- Implement data retention policies
- Archive old records and activities periodically
- Clean up duplicate contacts regularly
- Optimize database tables monthly
- Export critical data for offline backup
11. Customizing CiviCRM
Installing Extensions
- Navigate to Administer → System Settings → Extensions
- Browse available extensions or upload custom ones
- Install extensions that meet your organization’s needs
- Configure extension settings as required
Custom Templates and Themes
For WordPress-based installations:
- Customize the WordPress theme to match your branding
- Use CiviCRM’s template override system for custom layouts
- Store custom templates in your persistent volume
API Access
CiviCRM provides a robust REST API for integrations:
- Generate API keys in Administer → Users and Permissions → API Keys
- Use the API for custom integrations with other systems
- Implement webhooks for real-time data synchronization
12. Troubleshooting Common Issues
Database Connection Errors
Symptoms: Error messages about database connectivity or “Cannot connect to database”
Solutions:
- Verify database credentials in environment variables match your MySQL instance
- Ensure the CiviCRM app can reach the database host (check network connectivity)
- Confirm the database user has proper permissions
- Check MySQL logs for connection attempts and errors
File Permission Issues
Symptoms: Unable to upload files, “Permission denied” errors, cache errors
Solutions:
- Verify persistent volumes are properly mounted
- Ensure the web server user (
www-data) owns the upload directories - Run
chown -R www-data:www-data /var/www/html/wp-content/uploadsinside the container - Check that volume mount points have proper read/write permissions
Memory Limit Exceeded
Symptoms: “Allowed memory size exhausted” errors, especially during large imports
Solutions:
- Increase
PHP_MEMORY_LIMITenvironment variable to 512M or higher - Use the Nixpacks runtime environment variable:
NIXPACKS_PHP_MEMORY_LIMIT=512M - For very large operations, temporarily increase limits and scale back after completion
Email Delivery Issues
Symptoms: Emails not being sent, timeout errors, SMTP authentication failures
Solutions:
- Verify SMTP credentials and server settings
- Test SMTP connection using the CiviCRM email settings page
- Ensure SMTP port is accessible from your Klutch.sh deployment
- Check spam/junk folders for test emails
- Review email logs in CiviCRM for detailed error messages
Application Performance Issues
Symptoms: Slow page loads, timeouts, unresponsive interface
Solutions:
- Enable CiviCRM caching in Administer → System Settings → Cleanup Caches and Update Paths
- Review and optimize custom reports and searches
- Consider upgrading instance size in Klutch.sh dashboard
- Optimize database queries and add appropriate indexes
- Clear CiviCRM caches regularly
13. Scaling and Advanced Configurations
Horizontal Scaling
For organizations with high traffic or large user bases:
- Consider separating the database onto a dedicated instance
- Use external object storage (S3-compatible) for file uploads
- Implement read replicas for the database to distribute query load
- Use Redis or Memcached for session and cache storage
Advanced Database Configuration
For optimal performance with large datasets:
- Configure database connection pooling
- Implement regular database optimization and VACUUM operations
- Set up database monitoring and slow query logging
- Consider partitioning large tables for better performance
Custom Buildtime Configuration
If you need to customize the build process, use Nixpacks environment variables:
NIXPACKS_PHP_VERSION=8.1- Specify PHP versionNIXPACKS_BUILD_CMD=custom-build-script.sh- Custom build commandNIXPACKS_START_CMD=custom-start-script.sh- Custom start command
14. Integration Examples
WordPress Integration
CiviCRM integrates seamlessly with WordPress:
- Use CiviCRM shortcodes in WordPress pages
- Create custom contribution pages
- Display upcoming events on your website
- Synchronize WordPress users with CiviCRM contacts
Drupal Integration
For Drupal-based deployments:
- Use CiviCRM Views integration for custom displays
- Implement Drupal Rules for automation
- Leverage Drupal’s permissions system with CiviCRM
- Create custom content types linked to CiviCRM entities
External Service Integrations
- Payment Processors: PayPal, Stripe, Authorize.Net
- Email Marketing: Mailchimp, SendGrid
- Accounting: QuickBooks, Xero
- Communication: Twilio for SMS, Zoom for virtual events
15. Migrating Existing CiviCRM Installation
If you’re migrating from an existing CiviCRM installation:
-
Export existing data:
- Create a full database backup using
mysqldump - Archive all file uploads and custom extensions
- Export any custom templates or configurations
- Create a full database backup using
-
Prepare your Klutch.sh environment:
- Set up the database instance
- Create persistent volumes for uploads
- Configure environment variables
-
Import database:
- Restore the database backup to your new MySQL instance
- Update site configuration paths in
civicrm.settings.php - Update database connection strings
-
Upload files:
- Transfer file uploads to the persistent volume
- Ensure proper permissions on all directories
-
Update configuration:
- Run CiviCRM’s configuration update utility
- Clear all caches
- Verify all paths and URLs are correct
-
Test thoroughly:
- Verify contact data integrity
- Test email functionality
- Confirm payment processing works
- Check custom reports and searches
Resources
- CiviCRM Official Documentation
- CiviCRM GitHub Repository
- CiviCRM Installation Guide
- Klutch.sh Quick Start Guide
- Klutch.sh Volumes Guide
- Klutch.sh MySQL Deployment Guide
- Klutch.sh Custom Domains Guide
Deploying CiviCRM on Klutch.sh provides your nonprofit organization with a robust, scalable platform for constituent relationship management. With Docker-based deployment, persistent storage, and production-grade infrastructure, you can focus on your mission while Klutch.sh handles the hosting complexity. For questions or support, reach out to the Klutch.sh community or consult the CiviCRM forums for application-specific guidance.