Post

I Built An Open-Source Crm That You Can Self-Host - Relaticle

I Built An Open-Source Crm That You Can Self-Host - Relaticle

I Built An Open-Source CRM That You Can Self-Host - Relaticle

Introduction

In an era where SaaS solutions dominate the CRM landscape, DevOps engineers and system administrators face an uncomfortable truth: every proprietary platform we adopt means surrendering control of critical business data while accumulating recurring costs. The 2023 Flexera State of the Cloud Report reveals that 82% of enterprises cite cloud cost management as a primary challenge, with SaaS subscriptions being a major contributor. This is where self-hosted solutions shine.

Relaticle emerges as a modern answer to these challenges. Built with Laravel and Filament PHP, this open-source CRM gives you complete ownership of your customer data while eliminating per-seat pricing. For DevOps professionals managing on-premises infrastructure or private cloud environments, Relaticle represents more than just a CRM - it’s a statement about data sovereignty and infrastructure control.

In this comprehensive guide, we’ll explore:

  • The technical architecture enabling self-hosted CRM operations
  • Production-grade deployment strategies for enterprise environments
  • Security hardening techniques for customer data protection
  • Performance optimization for high-load scenarios
  • Maintenance workflows that ensure long-term reliability

Understanding Relaticle

Technical Architecture

Relaticle employs a classic LEMP stack architecture with modern DevOps twists:

1
Client → Nginx → PHP-FPM (Laravel) → MySQL/PostgreSQL → Redis (Optional Caching)

Key components:

  1. Laravel 10: MVC framework providing core application logic
  2. Filament PHP 3: Admin panel and CRM interface builder
  3. Livewire: Reactive frontend components
  4. Alpine.js: Lightweight JavaScript interactions

Feature Breakdown

Core capabilities relevant to infrastructure management:

FeatureTechnical ImplementationDevOps Impact
Custom FieldsDatabase schema morphingRequires DB migration planning
Data ExportLaravel Excel integrationStorage I/O considerations
API AccessLaravel Sanctum tokensRate limiting needed
Audit LogsDatabase table trackingRetention policy management
User RolesSpatie Permission packageRBAC implementation

Comparison Matrix: Self-Hosted CRM Options

SolutionStackDB RequirementsScalabilityMaintenance Complexity
RelaticlePHP/MySQLModerateVertical scalingMedium
SuiteCRMPHP/MySQLHeavyRequires clusteringHigh
EspoCRMPHP/MySQLLightLimitedLow
OdooPython/PostgreSQLVery HeavyHorizontal scalingVery High

Security Model

Relaticle inherits Laravel’s security features but adds:

  1. Automatic password policy enforcement
  2. Configurable session timeout
  3. Optional 2FA via Time-based One-Time Password (TOTP)
  4. IP allowlisting at application layer

Prerequisites

Hardware Requirements

Production deployment recommendations:

ComponentDevelopmentSmall Business (50 users)Enterprise (500+ users)
CPU2 cores4 cores8+ cores
RAM4GB16GB64GB+
Storage40GB200GB (SSD)1TB+ NVMe RAID
Network1Gbps1Gbps10Gbps bonded

Software Requirements

Officially supported stack:

1
2
3
4
5
- PHP 8.2+ with extensions: ctype, curl, dom, fileinfo, gd, json, mbstring, openssl, pdo, tokenizer, xml, zip
- MySQL 8.0+ or PostgreSQL 15+
- Redis 6+ (optional but recommended)
- Node.js 18+ (for build processes)
- Composer 2.5+

Security Pre-Checks

Before installation:

  1. Verify OS hardening (SSH config, firewall rules)
  2. Create dedicated service account with restricted privileges
  3. Configure separate database credentials with least-privilege access
  4. Validate TLS certificate availability
  5. Implement network segmentation for database tier

Installation & Setup

Deployment Options

Option 1: Docker Deployment (Recommended)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Clone repository
git clone https://github.com/relaticle/relaticle.git
cd relaticle

# Copy environment template
cp .env.example .env

# Build containers
docker compose build --no-cache

# Generate application key
docker compose run --rm artisan key:generate

# Launch services
docker compose up -d

# Run migrations
docker compose exec artisan migrate --seed

Option 2: Bare Metal Installation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Install PHP extensions
sudo apt install php8.2-fpm php8.2-mysql php8.2-gd php8.2-mbstring php8.2-xml

# Clone repository
git clone https://github.com/relaticle/relaticle.git
cd relaticle

# Install dependencies
composer install --optimize-autoloader --no-dev
npm ci && npm run build

# Set permissions
chown -R www-data:www-data storage bootstrap/cache
chmod -R 775 storage bootstrap/cache

# Configure environment
vim .env # Set DB credentials, APP_URL, etc.

# Run migrations
php artisan migrate --seed

# Optimize
php artisan config:cache
php artisan route:cache
php artisan view:cache

Reverse Proxy Configuration (Nginx)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
server {
    listen 443 ssl http2;
    server_name crm.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/crm.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/crm.yourdomain.com/privkey.pem;

    root /var/www/relaticle/public;

    location / {
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/index\.php(/|$) {
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        internal;
    }

    location ~ \.php$ {
        return 404;
    }

    error_log /var/log/nginx/relaticle_error.log;
    access_log /var/log/nginx/relaticle_access.log;
}

Verification Checklist

After installation:

  1. Validate service statuses:
    1
    2
    
    docker compose ps # For Docker
    systemctl status php8.2-fpm nginx mysql # For bare metal
    
  2. Test HTTPS configuration:
    1
    
    curl -I https://crm.yourdomain.com
    
  3. Verify database connections:
    1
    2
    3
    
    docker compose exec artisan tinker # Docker
    php artisan tinker # Bare metal
    >>> DB::connection()->getPdo()
    
  4. Check queue workers (if enabled):
    1
    
    supervisorctl status
    

Configuration & Optimization

Critical .env Settings

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
APP_ENV=production
APP_DEBUG=false
APP_URL=https://crm.yourdomain.com

DB_CONNECTION=mysql
DB_HOST=db-cluster.example.com
DB_PORT=3306
DB_DATABASE=relaticle_prod
DB_USERNAME=relaticle_user
DB_PASSWORD=strong_password_here

CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis

REDIS_HOST=redis-cluster.example.com
REDIS_PASSWORD=redis_auth_password
REDIS_PORT=6379

SESSION_LIFETIME=43200 # 12 hours
SESSION_SECURE_COOKIE=true

Security Hardening

  1. Database Encryption
    CREATE DATABASE relaticle_prod
    ENCRYPTION='Y'
    DEFAULT ENCRYPTION='Y';
    
  2. File System Protections
    1
    2
    
    chattr +i storage/framework/sessions/*
    find storage -type d -exec chmod 750 {} \;
    
  3. Rate Limiting (In routes/api.php)
    1
    2
    3
    
    RateLimiter::for('api', function (Request $request) {
        return Limit::perMinute(300)->by($request->user()?->id ?: $request->ip());
    });
    

Performance Tuning

  1. PHP-FPM Optimization
    1
    2
    3
    4
    5
    6
    7
    
    ; /etc/php/8.2/fpm/pool.d/www.conf
    pm = dynamic
    pm.max_children = 100
    pm.start_servers = 20
    pm.min_spare_servers = 10
    pm.max_spare_servers = 30
    pm.max_requests = 1000
    
  2. OPcache Configuration
    1
    2
    3
    4
    5
    6
    
    ; /etc/php/8.2/fpm/conf.d/10-opcache.ini
    opcache.enable=1
    opcache.memory_consumption=256
    opcache.interned_strings_buffer=32
    opcache.max_accelerated_files=20000
    opcache.validate_timestamps=0
    
  3. Redis Caching
    1
    2
    3
    
    # In .env
    CACHE_STORE=redis
    SESSION_STORE=redis
    

Backup Strategy

Sample backup script (/usr/local/bin/relaticle-backup.sh):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
DATE=$(date +%Y%m%d)
BACKUP_DIR="/backups/relaticle"

# Database dump
mysqldump -h $DB_HOST -u $DB_USER -p$DB_PASSWORD $DB_DATABASE | gzip > $BACKUP_DIR/db-$DATE.sql.gz

# File backup
tar czf $BACKUP_DIR/files-$DATE.tar.gz /var/www/relaticle/storage

# Sync to remote
aws s3 sync $BACKUP_DIR s3://your-backup-bucket/relaticle/

# Retention (keep 30 days)
find $BACKUP_DIR -type f -mtime +30 -delete

Set cron job:

1
0 2 * * * /usr/local/bin/relaticle-backup.sh

Usage & Operations

Common Maintenance Commands

  1. Queue Management
    1
    2
    
    php artisan queue:restart # Graceful restart
    php artisan queue:failed # View failed jobs
    
  2. Cache Management
    1
    2
    3
    4
    
    php artisan config:cache
    php artisan route:cache
    php artisan view:cache
    php artisan event:cache
    
  3. User Management
    1
    2
    
    php artisan relaticle:create-user # Interactive user creation
    php artisan relaticle:deactivate-user [email]
    

Monitoring Recommendations

Recommended Prometheus exporters:

  1. MySQLd Exporter - Database metrics
  2. PHP-FPM Exporter - Application metrics
  3. Blackbox Exporter - HTTP checks
  4. Node Exporter - Host metrics

Sample Grafana dashboard metrics to track:

  • PHP-FPM active processes
  • MySQL query latency
  • Redis memory usage
  • Application response times
  • Queue backlog size

Scaling Approaches

Vertical Scaling:

  • Increase PHP-FPM pm.max_children
  • Add Redis persistent storage
  • Enable MySQL query caching

Horizontal Scaling:

  1. Separate web and database tiers
  2. Implement Redis clustering
  3. Add read replicas for MySQL
  4. Use load balancer with multiple app servers

Troubleshooting

Common Issues and Solutions

  1. Migrations Fail with Foreign Key Errors
    1
    2
    
    php artisan migrate:fresh --force
    php artisan db:seed
    
  2. High Memory Usage
    • Check PHP-FPM settings with systemctl status php8.2-fpm
    • Enable OPCache file cache
      1
      
      opcache.file_cache=/tmp/opcache
      
  3. Queue Workers Stalling
    1
    2
    
    supervisorctl restart all
    php artisan queue:retry all
    
  4. Mixed Content Warnings Ensure APP_URL in .env uses HTTPS
    1
    
    php artisan config:clear
    

Log Analysis Commands

  1. Error Log Tailing
    1
    
    tail -f storage/logs/laravel-$(date +%Y-%m-%d).log
    
  2. Database Slow Query Log
    SET GLOBAL slow_query_log = 'ON';
    SET GLOBAL long_query_time = 1;
    
  3. Nginx Request Analysis
    1
    
    awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr
    

Recovery Procedures

Full System Restoration:

  1. Restore database from backup:
    1
    
    zcat db-backup.sql.gz | mysql -u root -p relaticle_prod
    
  2. Extract files backup:
    1
    
    tar xzf files-backup.tar.gz -C /
    
  3. Clear caches:
    1
    
    php artisan optimize:clear
    

Conclusion

Relaticle represents more than just another CRM option - it’s a battle-tested solution for organizations prioritizing data control and infrastructure autonomy. By implementing the techniques covered in this guide, DevOps teams can deploy a production-grade CRM that meets enterprise security standards while maintaining full ownership of critical customer data.

Key takeaways:

  1. Self-hosted CRM solutions eliminate vendor lock-in and reduce long-term costs
  2. Properly configured Laravel applications can meet enterprise performance demands
  3. Infrastructure-as-Code principles apply equally to CRM deployments
  4. Comprehensive monitoring is non-negotiable for business-critical systems

For further exploration:

The future of business software lies in solutions that respect infrastructure autonomy while delivering modern user experiences. Relaticle’s open-source model demonstrates that these goals aren’t mutually exclusive when implemented with DevOps best practices.

This post is licensed under CC BY 4.0 by the author.