How to Install OroCRM on Ubuntu 20.04
Introduction
OroCRM is enterprise-ready open-source Customer Relationship Management (CRM) software that offers:
- Out-of-the-box features to meet various business requirements,
- Flexibility for companies of all sizes, and
- Extensions to integrate with third-party applications, such as Microsoft 365, Google Data Studio, and MailChimp.
This article walks you through deploying OroCRM Community Edition 4.2.8, the latest stable release of OroCRM Community Edition for now, on a Vultr Ubuntu 20.04 LTS server instance in the production environment.
Prerequisites
- A newly created Vultr Ubuntu 20.04 LTS server instance with at least 4GB of RAM. Say its IPv4 address is 203.0.113.100.
- A domain name crm.example.com for accessing the internal CRM system, leaving example.com and www.example.com for the public portal.
1. Setup DNS Records
If you are hosting the apex domain name example.com on Vultr, set up DNS records as follows to bind crm.example.com to your Vultr server's IPv4 address 203.0.113.100:
Record #1
- Type: A
- Name: crm
- Data: 203.0.113.100
- TTL (seconds): 300
Record #2
- Type: MX
- Name: [blank]
- Data: example.com
- TTL (seconds): 300
- Priority: 10
Record #3
- Type: NS
- Name: [blank]
- Data: ns1.vultr.com
- TTL (seconds): 300
Record #4
- Type: NS
- Name: [blank]
- Data: ns2.vultr.com
- TTL (seconds): 300
Learn more about managing DNS through Vultr in another article on Vultr DNS.
Instructions on setting up DNS records on other platforms may vary.
2. Harden the System
Use your favorite terminal application on your desktop machine, such as the OpenSSH client, to log in to the server instance as root.
On Windows 10 or 11:
PS > ssh -p22 root@203.0.113.100
On a modern Linux or macOS desktop:
$ ssh -p22 root@203.0.113.100
After you log in, execute the tasks listed in this section to harden the system.
Find if any swap space resides on the system:
# swapon -s
If so, feel free to move to the next task. If not, set up a swap file of 2GB as follows:
# fallocate -l 2g /swap
# chmod 600 /swap
# mkswap /swap
# swapon /swap
# echo '/swap none swap defaults 0 0' >> /etc/fstab
# free -m
Change the preset password of root to a new, private password NewPassword4Root, and then delete the history entry which shows the password in plain text:
# echo 'root:NewPassword4Root' | chpasswd && history -d -1
Create a normal user named orosa with sudo privileges as a designated system administrator, along with its password SudoUserPassword:
# useradd -ms /bin/bash orosa
# echo 'orosa:SudoUserPassword' | chpasswd && history -d -1
# echo 'orosa ALL=(ALL) NOPASSWD: ALL' | tee -a /etc/sudoers.d/designated
# chmod 0440 /etc/sudoers.d/designated
Setup firewall rules to allow only SSH, HTTP, and HTTPS traffic:
# ufw default deny
# ufw allow ssh
# ufw allow http
# ufw allow https
# ufw enable
# ufw status
Update and then restart the system:
# apt update
# apt upgrade -y
# apt autoremove -y
# shutdown -r now
Now turn to your desktop machine to generate an SSH key pair consisting of a public key named crm.key.pub and a private key named crm.key, and then upload the public key to the server instance.
On Windows 10 or 11:
PS > ssh-keygen -t rsa -b 4096 -f C:\Users\$env:UserName\.ssh\crm.key -P YourPassphrase -C 'orosa@crm.example.com'
PS > scp C:\Users\$env:UserName\.ssh\crm.key.pub orosa@203.0.113.100:/home/orosa/.ssh/
On a modern Linux or macOS desktop:
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/crm.key -P YourPassphrase -C 'orosa@crm.example.com'
$ scp ~/.ssh/crm.key.pub orosa@203.0.113.100:/home/orosa/.ssh/
Log in to the server instance as orosa for follow-on tasks. Input the password SudoUserPassword when prompted.
On Windows 10 or 11:
PS > ssh -p22 orosa@203.0.113.100
On a modern Linux or macOS desktop:
$ ssh -p22 orosa@203.0.113.100
Continue setting up key-based SSH authentication:
$ cat /home/orosa/.ssh/crm.key.pub >> /home/orosa/.ssh/authorized_keys
$ chmod 600 /home/orosa/.ssh/authorized_keys
$ rm /home/orosa/.ssh/crm.key.pub
Disallow password authentication for SSH:
$ sudo sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
As a security routine, prohibit root from remotely logging in through SSH:
$ sudo sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
Reload the SSH service and then exit the current SSH session:
$ sudo systemctl reload sshd.service
$ exit
From now on, you must log in as orosa using the private key crm.key for system administration. Input the passphrase YourPassphrase when prompted.
On Windows 10 or 11:
PS > ssh -p22 orosa@203.0.113.100 -i C:\Users\$env:UserName\.ssh\crm.key
On a modern Linux or macOS desktop:
$ ssh -p22 orosa@203.0.113.100 -i ~/.ssh/crm.key
3. Install MySQL Community Edition 8.0.28
For OroCRM Community Edition 4.2.8, MySQL 8.0 is the required Database Management System (DBMS). Do not choose MariaDB because OroCRM is not tested with it.
Download the latest MySQL Community Edition 8.0 Advanced Packaging Tool (APT) repository package from the official MySQL APT Repository Download Page:
$ cd
$ wget https://dev.mysql.com/get/mysql-apt-config_0.8.22-1_all.deb
Verify the MD5 checksum of the package:
$ md5sum mysql-apt-config_0.8.22-1_all.deb
If the above command outputs a value different than ade43b291d4b8db2a00e292de7307745, delete the downloaded .deb file and then re-download it.
Setup the MySQL Community Edition 8.0 APT repository:
$ sudo dpkg -i mysql-apt-config_0.8.22-1_all.deb
In the Package configuration window, use Up and Down to highlight an option, and then use Enter to select the highlighted one. The final result should be:
MySQL Server & Cluster (Currently selected: mysql-8.0)
MySQL Tools & Connectors (Currently selected: Enabled)
MySQL Preview Packages (Currently selected: Disabled)
Ok
Highlight the fourth row Ok, and press Enter to confirm your configuration.
Update the APT repository on the system:
$ sudo apt update
Install the latest stable release of mysql-server 8.0 package:
$ sudo apt install mysql-server -y
During the installation, make sure to input a strong password (say it is @5tr0ngPassw0rd!
) for the root account when prompted, and then choose Use Strong Password Encryption (RECOMMENDED) for the default authentication plugin option to improve security.
Confirm the installation of MySQL 8.0:
$ mysql -V
mysql Ver 8.0.28 for Linux on x86_64 (MySQL Community Server - GPL)
Start the MySQL service:
$ sudo systemctl start mysql.service
$ sudo systemctl enable mysql.service
Run an official script named mysql_secure_installation to secure the installation of MySQL:
$ sudo mysql_secure_installation
When prompted, reply to questions (abridged) as follows:
- Enter password for user root:
@5tr0ngPassw0rd!
- Would you like to setup VALIDATE PASSWORD component? `y'
- For password validation policy, please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG:
2
- Estimated strength of the password: 100. Change the password for root ?
n
- Remove anonymous users? `y'
- Disallow root login remotely? `y'
- Remove test database and access to it? `y'
- Reload privilege tables now? `y'
Note: Make sure the password you set up reads a 100 strength score.
Because MySQL reads settings from various configuration files, find possible locations of MySQL configuration files as follows:
$ mysql --help | grep "Default options" -A 1
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf
Create a global MySQL configuration file:
$ sudo nano /etc/my.cnf
Populate the file to optimize MySQL performance:
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
optimizer_search_depth = 0
Press Ctrl+O, Enter, and Ctrl+X to save and quit.
Restart the MySQL service to load updated configurations:
sudo systemctl restart mysql.service
4. Install PHP 8.0.14
OroCRM Community Edition 4.2.8 works with PHP 7.4.14+ or PHP 8.0.x. This article prefers the latest stable release of PHP 8.0, which is PHP 8.0.14 for now.
Set up a third-party Personal Package Archives (PPA) repository:
$ LC_ALL=C.UTF-8 sudo add-apt-repository ppa:ondrej/php -y
$ sudo apt update
$ sudo apt upgrade -y
Install PHP 8.0 and required PHP 8.0 extensions for OroCRM Community Edition 4.2.8, including the FastCGI Process Manager (FPM) extension for working with Nginx:
$ sudo apt install php8.0 php8.0-bcmath php8.0-common php8.0-curl php8.0-fpm php8.0-gd php8.0-imap php8.0-intl php8.0-ldap php8.0-mbstring php8.0-mysql php8.0-mongodb php8.0-opcache php8.0-soap php8.0-tidy php8.0-xml php8.0-zip -y
$ php -v
PHP 8.0.14 (cli) (built: Dec 20 2021 21:22:57) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.14, Copyright (c) Zend Technologies
with Zend OPcache v8.0.14, Copyright (c), by Zend Technologies
As required by OroCRM Community Edition 4.2.8, change PHP settings for PHP-FPM and PHP-CLI as follows.
Specify the timezone the server is in for both PHP-FPM and PHP-CLI, such as America/Los_Angeles:
$ sudo sed -i 's#;date.timezone =#date.timezone = America/Los_Angeles#' /etc/php/8.0/fpm/php.ini
$ sudo sed -i 's#;date.timezone =#date.timezone = America/Los_Angeles#' /etc/php/8.0/cli/php.ini
For other timezones, refer to the PHP Timezones List page.
Change the memory limit for PHP-FPM to 1Gb:
$ sudo sed -i 's/memory_limit = 128M/memory_limit = 1G/' /etc/php/8.0/fpm/php.ini
Increase execution time to 60 seconds for both PHP-FPM and PHP-CLI:
$ sudo sed -i 's/max_execution_time = 30/max_execution_time = 60/' /etc/php/8.0/fpm/php.ini
$ sudo sed -i 's/max_execution_time = 30/max_execution_time = 60/' /etc/php/8.0/cli/php.ini
Disallow detecting Unicode for both PHP-FPM and PHP-CLI:
$ echo 'detect_unicode = Off' | sudo tee -a /etc/php/8.0/fpm/php.ini
$ echo 'detect_unicode = Off' | sudo tee -a /etc/php/8.0/cli/php.ini
Enable OPcache for PHP-FPM:
$ sudo nano /etc/php/8.0/fpm/php.ini
Press F6 to search for [opcache], and then add the following lines right under the [opcache] line:
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=512
opcache.max_accelerated_files=65407
opcache.interned_strings_buffer=32
realpath_cache_size=4096K
realpath_cache_ttl=600
opcache.save_comments=1
opcache.validate_timestamps=0
Press Ctrl+O, Enter, and Ctrl+X to save and quit.
Disable OPcache for PHP-CLI:
$ sudo nano /etc/php/8.0/cli/php.ini
Press F6 to search for [opcache], and then add the following line right under the [opcache] line:
opcache.enable_cli=0
Press Ctrl+O, Enter, and Ctrl+X to save and quit.
Optimize PHP-FPM performance as follows while keeping the default pm = dynamic setting:
$ sudo sed -i 's/pm.max_children = 5/pm.max_children = 128/' /etc/php/8.0/fpm/pool.d/www.conf
$ sudo sed -i 's/pm.start_servers = 2/pm.start_servers = 8/' /etc/php/8.0/fpm/pool.d/www.conf
$ sudo sed -i 's/pm.min_spare_servers = 1/pm.min_spare_servers = 4/' /etc/php/8.0/fpm/pool.d/www.conf
$ sudo sed -i 's/pm.max_spare_servers = 3/pm.max_spare_servers = 8/' /etc/php/8.0/fpm/pool.d/www.conf
$ sudo sed -i 's/;pm.max_requests = 500/pm.max_requests = 512/' /etc/php/8.0/fpm/pool.d/www.conf
$ sudo sed -i 's/;catch_workers_output = yes/catch_workers_output = yes/' /etc/php/8.0/fpm/pool.d/www.conf
Start the PHP-FPM service:
$ sudo systemctl start php8.0-fpm.service
$ sudo systemctl enable php8.0-fpm.service
5. Install Nginx 1.20.2 and its PageSpeed Module
OroCRM Community Edition 4.2.8 needs to work with a web server, such as Apache or Nginx. This article prefers the latest stable release of Nginx, which is Nginx 1.20.2 for now. To increase performance, this article builds both Nginx and its PageSpeed module from source.
Install dependencies for compiling Nginx and the PageSpeed module:
$ sudo apt install git unzip build-essential openssl libssl-dev libpcre3 libpcre3-dev zlib1g zlib1g-dev libgd-dev libxml2 libxml2-dev uuid-dev -y
Compile and install Nginx 1.20.2 and the latest stable release of PageSpeed:
$ bash <(curl -f -L -sS https://ngxpagespeed.com/install) --nginx-version 1.20.2 -a '--prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module' -y
Add the nginx user for running the Nginx service:
$ sudo useradd -M nginx
Make working directories for Nginx:
$ sudo mkdir -p /var/cache/nginx/{client_temp,proxy_temp,fastcgi_temp,uwsgi_temp,scgi_temp}
$ sudo chown -R nginx:nginx /var/cache/nginx
$ sudo mkdir /etc/nginx/{conf.d,sites-available,sites-enabled}
$ sudo mkdir /var/www/
$ sudo mkdir /var/www/crm.example.com
$ sudo chown nginx:nginx /var/www/crm.example.com
Setup a systemd configuration file for Nginx:
$ sudo nano /lib/systemd/system/nginx.service
Populate the file as follows:
[Unit]
Description=nginx - high performance web server
Documentation=https://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/sh -c "/bin/kill -s HUP $(/bin/cat /var/run/nginx.pid)"
ExecStop=/bin/sh -c "/bin/kill -s TERM $(/bin/cat /var/run/nginx.pid)"
[Install]
WantedBy=multi-user.target
Press Ctrl+O, Enter, and Ctrl+X to save and quit.
Confirm the installation of Nginx:
$ nginx -V
nginx version: nginx/1.20.2
built by gcc 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)
built with OpenSSL 1.1.1f 31 Mar 2020
TLS SNI support enabled
configure arguments: ...
Start the Nginx service:
$ sudo systemctl start nginx.service
$ sudo systemctl enable nginx.service
Configure and test the installation of the PageSpeed module:
$ sudo mkdir /var/cache/ngx_pagespeed_cache/
$ sudo chown nginx:nginx /var/cache/ngx_pagespeed_cache/
Edit the main Nginx configuration file:
$ sudo nano /etc/nginx/nginx.conf
Insert the following settings into the server{ }
segment, under the server_name localhost;
line:
pagespeed on;
pagespeed FileCachePath "/var/cache/ngx_pagespeed_cache/";
pagespeed RewriteLevel OptimizeForBandwidth;
pagespeed EnableFilters collapse_whitespace;
pagespeed Disallow "*.svg*";
location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" {
add_header "" "";
}
location ~ "^/pagespeed_static/" { }
location ~ "^/ngx_pagespeed_beacon$" { }
Press Ctrl+O, Enter, and Ctrl+X to save and quit.
Restart the Nginx service:
$ sudo systemctl restart nginx.service
Use the curl utility to confirm the installation of the PageSpeed module:
$ curl -I -X GET http://203.0.113.100
HTTP/1.1 200 OK
Server: nginx/1.20.2
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Date: Sun, 23 Jan 2022 13:42:35 GMT
X-Page-Speed: 1.13.35.2-0
Cache-Control: max-age=0, no-cache
Update PHP-FPM configurations to work with Nginx:
$ sudo sed -i 's/user = www-data/user = nginx/' /etc/php/8.0/fpm/pool.d/www.conf
$ sudo sed -i 's/group = www-data/group = nginx/' /etc/php/8.0/fpm/pool.d/www.conf
$ sudo sed -i 's/listen.owner = www-data/listen.owner = nginx/' /etc/php/8.0/fpm/pool.d/www.conf
$ sudo sed -i 's/listen.group = www-data/listen.group = nginx/' /etc/php/8.0/fpm/pool.d/www.conf
$ sudo systemctl restart php8.0-fpm.service
6. Get Let's Encrypt TLS Certificates
To enable the HTTPS protocol in the production environment, follow the instructions below to get free Let's Encrypt TLS certificates for crm.example.com using the Certbot Automatic Certificate Management Environment (ACME) client.
Update the system-provided snapd program:
$ sudo snap install core; sudo snap refresh core
To avoid potential conflicts, remove any existing Certbot programs installed from other sources:
$ sudo apt-get remove certbot
$ sudo sed -i '/certbot-auto/d' /etc/crontab
$ sudo rm -f /usr/local/bin/cert-bot
$ sudo rm -rf /opt/eff.org
Install Certbot through snapd:
$ sudo snap install --classic certbot
For convenience, create a symbolic link pointing to Certbot in the /usr/bin directory:
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Get Let's Encrypt certificates for the designated domain name crm.example.com through Certbot and its Nginx plugin:
$ sudo certbot certonly --nginx --email admin@example.com --agree-tos --no-eff-email -d crm.example.com
By default, the Let's Encrypt TLS certificates expire in 90 days, but the Certbot program has setup automatic certificate renewal to prevent that from happening. Use commands below to confirm those renewals are in schedule:
$ sudo certbot renew --dry-run
$ sudo systemctl list-timers | grep snap.certbot.renew.service
7. Enable HTTPS on the Nginx Site
Follow instructions in this section to enable HTTPS on the Nginx site in a production environment, including:
- Redirecting HTTP traffic to HTTPS, and
- Forbidding direct access to the server's IPv4 address 203.0.113.100.
Backup the existing Nginx configuration file:
$ sudo mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
Generate a 2048-bit Diffie-Hellman parameters file for Nginx to enhance security:
$ sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048
Create the main Nginx configuration file:
$ sudo nano /etc/nginx/nginx.conf
Populate the file as follows:
user nginx;
pid /run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 65535;
events {
multi_accept on;
worker_connections 65535;
}
http {
charset utf-8;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
log_not_found off;
types_hash_max_size 2048;
types_hash_bucket_size 64;
client_max_body_size 16M;
# MIME
include mime.types;
default_type application/octet-stream;
# Logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
# SSL
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites
ssl_dhparam /etc/nginx/dhparam.pem;
# Mozilla Intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
resolver_timeout 2s;
# Load configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Press Ctrl+O, Enter, and Ctrl+X to save and quit.
Create the Nginx configuration file for crm.example.com:
$ sudo nano /etc/nginx/sites-available/crm.example.com.conf
Populate the file as follows:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name crm.example.com;
set $base /var/www/crm.example.com;
root $base/public;
#PageSpeed
pagespeed on;
pagespeed FileCachePath "/var/cache/ngx_pagespeed_cache/";
pagespeed RewriteLevel OptimizeForBandwidth;
pagespeed EnableFilters collapse_whitespace;
pagespeed Disallow "*.svg*";
pagespeed SslCertDirectory "/etc/letsencrypt/live/crm.example.com/";
pagespeed SslCertFile "/etc/letsencrypt/live/crm.example.com/fullchain.pem";
pagespeed FetchHttps enable;
location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" {
add_header "" "";
}
location ~ "^/pagespeed_static/" { }
location ~ "^/ngx_pagespeed_beacon$" { }
# SSL
ssl_certificate /etc/letsencrypt/live/crm.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/crm.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/crm.example.com/chain.pem;
# . files
location ~ /\.(?!well-known) {
deny all;
}
# index.php
index index.php;
# favicon.ico
location = /favicon.ico {
log_not_found off;
access_log off;
}
# robots.txt
location = /robots.txt {
log_not_found off;
access_log off;
}
# One week for CSS and JavaScript
location ~* \.(?:css(\.map)?|js(\.map)?)$ {
expires 1w;
access_log off;
add_header Cache-Control public;
}
# Three weeks for media
location ~* \.(?:jpg|jpeg|gif|png|webp|ico|cur|tif|tiff|woff|woff2|heic|eot|ttc|otf|ttf|svg|svgz|mpg|mpeg|mp3|mp4|wmv|avi|mov|m4a|mid|midi|wav|aac|ogg|ogv|webm|swf|flv)$ {
if ( -f $request_filename ) { expires 3w; add_header "Cache-Control" "public"; }
try_files $uri /index.php$is_args$args;
access_log off;
}
# gzip
gzip on;
gzip_vary on;
gzip_buffers 16 8k;
gzip_proxied any;
gzip_comp_level 5;
gzip_disable "msie6";
gzip_min_length 1000;
gzip_http_version 1.0;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/x-javascript application/rss+xml application/atom+xml image/svg+xml;
try_files $uri $uri/ @rewrite;
location @rewrite {
rewrite ^/(.*)$ /index.php/$1;
}
location ~ /\.ht {
deny all;
}
# handle .php
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
fastcgi_index index.php;
fastcgi_intercept_errors on;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffers 4 256k;
fastcgi_buffer_size 128k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS on;
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$base/:/usr/lib/php/:/tmp/";
}
location /ws {
reset_timedout_connection on;
# Prevent 502 bad gateway error
proxy_buffers 8 32k;
proxy_buffer_size 64k;
# Redirect all HTTP traffic to localhost:8080;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8080/;
proxy_redirect off;
proxy_read_timeout 86400;
# Enable WS support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
error_log /var/log/nginx/crm.example.com_wss_error.log;
access_log /var/log/nginx/crm.example.com_wss_access.log;
}
}
# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name crm.example.com;
# ACME-challenge
location ^~ /.well-known/acme-challenge/ {
root /var/www/_letsencrypt;
}
location / {
return 301 https://crm.example.com$request_uri;
}
}
# Restrict direct access to server's IPv4 and Ipv6 addresses
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name "";
return 444;
}
Press Ctrl+O, Enter, and Ctrl+X to save and quit.
Create a symbolic link to enable the configuration file for crm.example.com:
$ sudo ln -s /etc/nginx/sites-available/crm.example.com.conf /etc/nginx/sites-enabled/
Setup a temporary PHP file for test:
$ sudo mkdir -p /var/www/crm.example.com/public
$ sudo chown nginx:nginx /var/www/crm.example.com/public
$ echo '<?php phpinfo();?>' | sudo tee /var/www/crm.example.com/public/index.php
$ sudo chown nginx:nginx /var/www/crm.example.com/public/index.php
Restart Nginx and PHP-FPM to load new settings:
$ sudo systemctl restart nginx.service
$ sudo systemctl restart php8.0-fpm.service
Test updated Nginx configurations:
$ sudo nginx -t
Then point your favorite web browser to http://crm.example.com
. The URL should become https://crm.example.com
, and the webpage should display all PHP-related information.
Delete the test file and then move on:
$ sudo rm /var/www/crm.example.com/public/index.php
$ sudo rmdir /var/www/crm.example.com/public
8. Install Node.js 14.18.3
OroCRM Community Edition 4.2.8 requires Node.js (>=12.0, <15.0) for JavaScript assets minification and SCSS assets build. Follow the instructions below to install Node.js 14.18.3, the latest stable release of the Node.js 14 series for now.
$ curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash -
$ sudo apt-get install -y nodejs
$ node -v
v14.18.3
9. Install Composer 2.2.5
Use commands listed below to install Composer 2.2.5, the latest stable release of Composer for now:
$ cd
$ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
$ php -r "if (hash_file('sha384', 'composer-setup.php') === '906a84df04cea2aa72f40b5f787e49f22d4c2f19492ac310e8cba5b96ac8b64115ac402c8cd292b8a03482574915d1a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
$ php composer-setup.php
$ php -r "unlink('composer-setup.php');"
$ sudo mv composer.phar /usr/local/bin/composer
$ composer -V
Composer version 2.2.5 2022-01-21 17:25:52
Notice: The above instructions are only suitable for installing Composer 2.2.5. Be sure to get the latest release of Composer by following the instructions on the official Composer Download page.
10. Install Supervisor 4.1.0
OroCRM requires a process managing program, such as Supervisor, to manage its background processes. Use commands below to install Supervisor 4.1.0, the latest stable version of distribution-provided Supervisor:
$ sudo apt install supervisor
$ supervisord -v
4.1.0
11. Install Image Processing Tools for Optimizing Image Size
As required by OroCRM, install two image processing tools, pngquant and jpegoptim, for optimizing image size in storage:
$ sudo apt install pngquant -y
$ sudo apt install jpegoptim -y
12. Install OroCRM Community Edition 4.2.8
To prepare a MySQL database for OroCRM, log in to the MySQL shell as root, typing the password @5tr0ngPassw0rd! when prompted:
$ sudo mysql -u root -p
In the MySQL shell, create a database named orocrm and a database user named orocrm along with a strong password Pa55word40r0crm!:
mysql> CREATE DATABASE orocrm CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
mysql> CREATE USER 'orocrm'@'localhost' IDENTIFIED BY 'Pa55word40r0crm!';
mysql> GRANT ALL PRIVILEGES ON orocrm.* TO 'orocrm'@'localhost';
mysql> FLUSH PRIVILEGES;
mysql> EXIT;
Download the OroCRM Community Edition 4.2.8 files:
$ cd && git clone -b 4.2.8 https://github.com/oroinc/crm-application.git crm.example.com
$ sudo rmdir /var/www/crm.example.com
$ sudo mv /home/orosa/crm.example.com /var/www/
$ sudo chown -R orosa:orosa /var/www/crm.example.com
Use the acl utility to grant proper permissions on the existing and future OroCRM files for both the designated system administrator named orosa and the user of the Nginx service named nginx:
$ sudo apt install acl
$ sudo mkdir /var/www/crm.example.com/var/sessions
$ sudo chown orosa:orosa /var/www/crm.example.com/var/sessions
$ sudo setfacl -dR -m u:nginx:rwX -m u:orosa:rwX /var/www/crm.example.com/var/{sessions,cache,data,logs}
$ sudo setfacl -R -m u:nginx:rwX -m u:orosa:rwX /var/www/crm.example.com/var/{sessions,cache,data,logs}
$ sudo setfacl -dR -m u:nginx:rwX -m u:orosa:rwX /var/www/crm.example.com/public/{media,js}
$ sudo setfacl -R -m u:nginx:rwX -m u:orosa:rwX /var/www/crm.example.com/public/{media,js}
Use Composer to install all dependencies for OroCRM Community Edition in production:
$ cd /var/www/crm.example.com
$ composer install --prefer-dist --no-dev
During the process, input required parameters as follows:
- database_driver (pdo_mysql):
pdo_mysql
- database_host ('%env(ORO_DB_HOST)%'):
127.0.0.1
- database_port ('%env(ORO_DB_PORT)%'):
3306
- database_name ('%env(ORO_DB_NAME)%'):
orocrm
- database_user ('%env(ORO_DB_USER)%'):
orocrm
- database_password ('%env(ORO_DB_PASSWORD)%'):
Pa55word40r0crm!
- database_server_version ('%env(ORO_DB_VERSION)%'):
8.0.28
- database_driver_options ({ }): Enter
- mailer_transport ('%env(ORO_MAILER_DRIVER)%'): Enter
- mailer_host ('%env(ORO_MAILER_HOST)%'): Enter
- mailer_port ('%env(ORO_MAILER_PORT)%'): Enter
- mailer_encryption ('%env(ORO_MAILER_ENCRYPTION)%'): Enter
- mailer_user ('%env(ORO_MAILER_USER)%'): Enter
- mailer_password ('%env(ORO_MAILER_PASSWORD)%'): Enter
- websocket_bind_address (0.0.0.0):
127.0.0.1
- websocket_bind_port (8080):
8080
- websocket_frontend_host ('*'):
'*'
- websocket_frontend_port (8080):
443
- websocket_frontend_path (''):
ws
- websocket_backend_host ('*'):
'*'
- websocket_backend_port (8080):
8080
- websocket_backend_path (''):
''
- websocket_backend_transport (tcp):
tcp
- websocket_backend_ssl_context_options ({ }): Enter
- web_backend_prefix (''):
''
- session_handler (session.handler.native_file): Enter
- secret ('%env(ORO_SECRET)%'):
aiXaefalo8Hadee7zooquiehe2QuenahviekieFeaPa5eij4aithoa8kee7eipoh
- installed (null): Enter
- assets_version (null): Enter
- assets_version_strategy (time_hash): Enter
- message_queue_transport (dbal): Enter
- message_queue_transport_config (null): Enter
- deployment_type (null): Enter
- liip_imagine.jpegoptim.binary (null):
/usr/bin/jpegoptim
- liip_imagine.pngquant.binary (null):
/usr/bin/pngquant
- env(ORO_DB_HOST) (127.0.0.1):
127.0.0.1
- env(ORO_DB_PORT) (null):
3306
- env(ORO_DB_NAME) (oro_crm):
orocrm
- env(ORO_DB_USER) (root):
orocrm
- env(ORO_DB_PASSWORD) (null):
Pa55word40r0crm!
- env(ORO_DB_VERSION) (null):
8.0.28
- env(ORO_MAILER_DRIVER) (smtp): Enter
- env(ORO_MAILER_HOST) (127.0.0.1): Enter
- env(ORO_MAILER_PORT) (null): Enter
- env(ORO_MAILER_ENCRYPTION) (null): Enter
- env(ORO_MAILER_USER) (null): Enter
- env(ORO_MAILER_PASSWORD) (null): Enter
- env(ORO_SECRET) (ThisTokenIsNotSoSecretChangeIt):
aiXaefalo8Hadee7zooquiehe2QuenahviekieFeaPa5eij4aithoa8kee7eipoh
Note:
By pressing Enter, you choose to use the default value shown in parentheses.
The above demonstration ignores email-related settings because Vultr blocks the SMTP port by default. A rational email sending solution is to work with a third-party email sending vendor.
For the secret entry, you need to input a long and complicated string, such as the 64-bit random string shown above. Use the pwgen utility to generate one of your own:
$ sudo apt install pwgen $ pwgen 64 1
If necessary, review or update those parameters by editing a newly-generated .yml configuration file after running the above composer install command. And remember to save the file before you quit if you make any changes.
$ nano /var/www/crm.example.com/config/parameters.yml
Having finished the installation of dependencies, use the command below to optimize the automatic load process of Composer:
$ composer dump-autoload --optimize --no-dev --classmap-authoritative
For security purposes, disable the PHP Phar module before installing and running OroCRM Community Edition in production:
$ sudo phpdismod phar
Note: In the future, if you need to use Composer to install extensions or update OroCRM, enable the PHP Phar module again as follows:
$ sudo phpenmod phar
Set up an environment variable for Symfony:
$ export SYMFONY_ENV=prod
$ echo 'export SYMFONY_ENV=prod' | sudo tee -a /etc/profile
Install OroCRM Community Edition in a production environment:
$ php bin/console oro:install --env=prod --timeout=2000
During the installation, input administrative information as follows:
- Application URL (http://localhost):
https://crm.example.com
- Organization name (OroCRM):
EXAMPLE.COM
- Username (admin):
admin
- Email:
admin@example.com
- First name:
John
- Last name:
Doe
- Password: (not echo)
- Formatting Code (en):
en
- Language (en):
en
- Load sample data (y/n):
n
After the installation, run the following command to warm up the API documentation cache:
$ php bin/console oro:api:doc:cache:clear
As required by OroCRM, set up a cron job to run the oro:cron program once per minute:
$ crontab -e
When prompted, press Enter to select the default nano editor. And then add the following entry to the end of the file:
*/1 * * * * php /var/www/crm.example.com/bin/console oro:cron --env=prod > /dev/null
Press Ctrl+O, Enter, and Ctrl+X to save and quit.
If necessary, use crontab -l
to review the current user's cron jobs.
Besides, use the Supervisor program to execute OroCRM background processes as follows:
$ sudo nano /etc/supervisor/conf.d/orocrm.conf
Populate the file with:
[program:oro_web_socket]
command=php ./bin/console gos:websocket:server --env=prod
numprocs=1
autostart=true
autorestart=true
directory=/var/www/crm.example.com/
user=nginx
redirect_stderr=true
[program:oro_message_consumer]
command=php ./bin/console oro:message-queue:consume --env=prod
process_name=%(program_name)s_%(process_num)02d
numprocs=5
autostart=true
autorestart=true
directory=/var/www/crm.example.com/
user=nginx
redirect_stderr=true
Press Ctrl+O, Enter, and Ctrl+X to save and quit.
Start the Supervisor service:
$ sudo systemctl daemon-reload
$ sudo systemctl start supervisor.service
$ sudo systemctl enable supervisor.service
Check if OroCRM processes are running as scheduled:
$ sudo supervisorctl status
If all goes well, you should find similar output shown below:
oro_message_consumer:oro_message_consumer_00 RUNNING pid 4040, uptime 0:00:34
oro_message_consumer:oro_message_consumer_01 RUNNING pid 4041, uptime 0:00:34
oro_message_consumer:oro_message_consumer_02 RUNNING pid 4042, uptime 0:00:34
oro_message_consumer:oro_message_consumer_03 RUNNING pid 4043, uptime 0:00:34
oro_message_consumer:oro_message_consumer_04 RUNNING pid 4044, uptime 0:00:34
oro_web_socket RUNNING pid 4045, uptime 0:00:34
That's all for installing OroCRM Community Edition 4.2.8 on Ubuntu 20.04 LTS. Now it's time to point your favorite web browser to https://crm.example.com
to navigate the OroCRM site. Use the administrator's credentials you set up earlier to log in.
Next Steps
Having finished the installation of OroCRM Community Edition, you need to fulfill the contents on the site and consider if it's necessary to integrate with other platforms or services. Use the Oro Go-live Checklist to find more details.