CloudLinux OS components

Reseller limits

General information and requirements

Reseller limits is a feature that allows hosters to set limits for the resources each reseller can operate with. Hoster also provides controls to the reseller on what resources each reseller’s end user will have. Reseller limits set by a hoster limit the total amount of resources resellers’ end users can consume altogether.

When a hoster has set reseller limits for the particular reseller he provides the reseller with an ability to set limits for his end users within the Reseller Interface.

Types of Users

Starting from the version 3.0-18, LVE Manager operates with four types of users and their resource usage limits.

The types of users are as follows:

  • End User is a type of user that purchases hosting directly from a hoster and uses it for his own purposes;
  • Reseller is a type of user that buys hosting from a hoster and resells it to his end users;
  • Reseller’s End User is a type of user that purchases hosting from a reseller and uses it for his own purposes.
  • Reseller’s End User (no Reseller limit) is a type of user that purchases hosting from a reseller and uses it for his own purposes but does not have limits set by a reseller. These limits are set by the hoster.

Types of Limits

See the comparison Table with types of limits.

Limits Reseller limits Reseller’s end user limits Hoster’s end user limits
[SPEED Yes Yes Yes
[PMEM Yes Yes Yes
[IO Yes Yes Yes
[IOPS Yes Yes Yes
[EP Yes Yes Yes
[NPROC Yes Yes Yes
Inodes Yes (default for all users) No Yes
MySQL Limits Yes (supported only for MySQL Governor ALL mode) Yes (supported only for MySQL Governor ALL mode) Yes

What happens when reseller or reseller's end user hits the limit?

Note

Reseller is a virtual entity. So, he cannot hit the limit. There is reseller's end user with the same name as reseller. This end user is limited as any other reseller's end user. When hoster sets Reseller limits he limits the group of resellers' end users including reseller's end user with the same name as the reseller.

  • Reseller's end user can hit reseller limit when end user's limit is bigger than reseller's limit. In such case end user will be limited by reseller limit.
  • Reseller limit can be hit when all resellers’ end users in total use as much resources as reseller limit.
  • Reseller's end user can hit his limit when end user limit is lower than reseller limit. In such case end user will be limited by his limit.

Requirements

Note

Reseller Limits are only supported in kernel starting with the version 3.10.0-714.10.2.lve1.5.3.el7 for CloudLinux 7 kernel and 3.10.0-714.10.2.lve1.5.3.el6h for CloudLinux 6 Hybrid kernel .

Note

If you are using CloudLinux 6 kernel you would have to migrate to CloudLinux 6 Hybrid kernel first in order to be able to use new Reseller Limits functionality.

Installation, enabling, and disabling

Use the detailed instruction below:

  1. Install CloudLinux 7 or CloudLinux 6 Hybrid on a new server. Follow the instructions described here. Or you can convert your CentOS 6.x or CentOS 7.x system to CloudLinux 6 or CloudLinux 7 respectively. To do this, follow the instructions described on the link.

  2. If you have installed the CloudLinux 6, please convert it to the CloudLinux 6 Hybrid Kernel. Follow the instructions described here.

  3. Install LVE Manager with Reseller Limit support or update it up to version 3.0-18 (or later) by running the following commands:

    yum install kernel lve cagefs lvemanager lve-utils lve-stats --disableexcludes=main
    
    yum update
    
    reboot
    

    For CloudLinux 6 Hybrid kernel with Reseller Limit support, please run the following commands:

    yum install kernel lve cagefs lvemanager lve-utils lve-stats --disableexcludes=main
    
    yum update
    
    reboot
    

How to enable and disable Reseller limits

To start using a new feature Reseller limits you would have to enable reseller limits for a particular reseller first.

To enable Reseller access, please do the following:

  1. Log in with a Hoster access.
  2. You can create a new account or give privileges to an existing account.
  3. For new account tick a checkbox Make this account a reseller in the Reseller Settings box.

Note

If checkbox Make the account own itself (i.e., the user can modify the account) is not selected when creating Reseller in cPanel WHM, then user account Reseller will belong to root, not to reseller Reseller. In such case, the user Reseller will be managed by the root. So, LVE limits specified by the root will be applied to the user Reseller. User Reseller will not be limited by Reseller limits.

When the checkbox is selected, user Reseller will be limited by Reseller limits (in addition to personal user limits set by Reseller).

  1. Give privileges to the proper Reseller account to make all features work.
  2. Go to the Users tab and choose a particular reseller you want to enable Reseller limits for and click on the pencil icon.
  3. In the pop-up move the slider Manage Limits. Click AGREE for the question Are you sure you want to enable limits, set limits for that reseller if you you want them to be different from the default limits, otherwise default server limits will be applied. Than click the Save.

Note

Resellers’ end users can use as much resources in total as it is provided for that particular reseller by a hoster. The summary usage of all end users that belong to that particular reseller will not exceed the amount of resources provided to reseller by a hoster. If no Reseller Limits are set, reseller’s end user will be limited by default limits set by a hoster.

How to disable Reseller limits

To disable Reseller limits, please do the following:

  1. Go to the Users tab, choose a particular reseller and click on the pencil icon.
  2. In the pop-up move the slider Manage Limits. Click AGREE for the question Are you sure you want to disable limits. Than click Save.

Note

If you disable Reseller limits everything will work the same as before. All the end user limits set by the reseller will be saved. But all custom default reseller limits will be disabled.

See also Reseller limits UI.

LVE-Stats 2

General information and requirements

Why is it needed?

  • Old LVE-statistics store averages as integer numbers, as % of CPU usage. If user used 100% of CPU for 1 second within an hour, it is only 1-2% for a minute, and 0 for 5 minutes. Data in old LVE-statistics is aggregated to 1-hour intervals. So, such peak load will noExat be recorded and we need to store data with much higher precision.
  • 100% CPU usage in old lve statistics means “all cores”. On 32 core servers usage is not visible for most users (as they are limited to 1 core).
  • Old LVE-statistics does not provide a way to determine a cause of LVE faults, i.e. what processes are running when user hits LVE limits.Example
  • Notifications in old LVE-statistics are not accurate because they are based on average values for CPU, IO, IOPS.
  • Old LVE-statistics functionality is hard to extend.

Major improvements and features

  • increased precision of statistics;
  • CPU usage is calculated  in terms of % of a single core (100% usage means one core);
  • lvestats-server emulates and tracks faults for CPU, IO, IOPS;
  • lvestats-server saves “snapshots” of user’s processes and queries for each “incident” - added new lve-read-snapshot utility;
  • improved notifications about hitting LVE limits (more informative and without false positives);
  • implemented ability to add custom plugins;
  • MySQL and PostGreSQL support;
  • more pretty, scalable, interactive charts;
  • snapshots include HTTP-requests.

What features will be implemented in the future?

  • Notifications for control panels other than CPanel.
  • Burstable Limits/server health: We are monitoring server health ( LA , memory , idle CPU ) and automatically decreasing/increasing limits based on server health.
  • Reseller Limits: plugin would analyze usage per group of users (reseller’s usage), and do actions.
  • Suspend/notify plugin: would detect that user is being throttled for 10 minutes, and suspend him (just because), or notify, or increase limits.

Installation and update

To install, please execute:

yum install lve-stats

To update:

yum update lve-stats

Settings of old lve-stats (ver. 0.x) are imported automatically on the first install/update of a new lve-stats package.

SQLite database file is located in /var/lve/lvestats2.db, data from old lve-stats (ver. 0.x) are being migrated automatically in the background. Migrating process can last 2-8 hours (during this time lags are possible when admin is trying to check statistics, at the same time users will not be affected). Migrating the latest 30 days, SQLite DB stable migration is provided.

Currently, the new lve-stats supports all databases available in CloudLinux.

Note

You can also use LVE-stats 2 CLI

Downgrade

If you have any problems after update, downgrade lve-stats2 to the previous stable version by running:

yum downgrade lve-stats

and contact CloudLinux support at https://cloudlinux.zendesk.com/hc/requests/new

Note

You may need to rename *.rpmsave files to original ones in order to restore settings for old lve-stats (/etc/sysconfig/lvestats, /etc/sysconfig/cloudlinux-notify).

Note

You can also use LVE-stats 2 CLI

Configuration

Main configuration file /etc/sysconfig/lvestats2 contains the following options:

  • db_type - selects appropriate database type to use;

  • connect-string - connection string for PostGreSQL and MySQL database, has the following form:

    connect_string = USER:PASSWORD@HOST[:PORT]/DATABASE
    

    Default port is used for specific database, if port is not specified (typical port is 3306 for MySQL and 5432 for PostGreSQL). Connection string is not used for sqlite database.

  • server_id - sets the name of the server (at most 10 characters). This option is to use with centralized database ( PostGreSQL or MySQL). For use with sqlite database, value of this option should be "localhost" (without quotes).

  • plugins – path to directory containing custom plugins for lve-stats (default path /usr/share/lve-stats/plugins).

  • db_timeout - period of time to write data to database (in seconds); default value is 60 seconds.

  • timeout - timeout for custom plugins (seconds). If plugin execution does not finish within this period, plugin is terminated. Default value is 5 seconds.

  • interval - duration of one cycle of lvestats-server (seconds). This should be less than total duration of execution of all plugins. Default value is 5 seconds. Increasing this parameter makes precision of statistics worse.

  • keep_history_days - period of time (in days) to keep history in database. Old data is removed from database automatically. Default value is 60 days.

  • mode – sets compatibility output mode (compatibility with older lveinfo version

    • Value v1 enables compatibility with old version of lveinfo.
    • Value v2 enables extended output mode, but can break LVE plugins for control panels (statistics in LVE Manager, Resource Usage, etc). Support of v2 mode will be added to LVE plugins in the recent future. When mode parameter is absent, later version of lveinfo is implied.
  • disable_snapshots - disable snapshots and incidents. Possible values:

    • true
    • false

Configuration files for plugins are located in /etc/sysconfig/lvestats.config directory.

/etc/sysconfig/lvestats.config/SnapshotSaver.cfg contains the following options:

  • period_between_incidents - the minimal interval of time between incidents (in seconds). If minimal interval of time between LVE faults is greater than value specified, than new "incident" will begin and new snapshots will be saved. Default value is 300 seconds.
  • snapshots_per_minute - the maximum number of snapshots saved per minute for specific LVE id (default is 2).
  • max_snapshots_per_incident - the maximum number of snapshots saved for one "incident". Default is 10.

/etc/sysconfig/lvestats.config/StatsNotifier.cfg contains the following options:

  • NOTIFY_ADMIN – enables notification for admin (Y/N, default N);
  • NOTIFY_RESELLER – enables notification for reseller (Y/N, default N);
  • NOTIFY_CUSTOMER - enables notification for customers (Y/N, default N);
  • NOTIFY_INCLUDE_RESELLER_CUSTOMERY=notify all users, N=notify only hoster's users (whos reseller is root), default = N;
  • NOTIFY_CPU – notify about CPU faults when customer hits 100% of his CPU limit (Y/N, default N);
  • NOTIFY_IO - notify about IO faults when customer hits 100% of his IO limit (Y/N, default N);
  • NOTIFY_IOPS - notify about IOPS faults when customer hits 100% of his IOPS limit (Y/N, default N);
  • NOTIFY_MEMORY - notify about memory faults (Y/N, default N);
  • NOTIFY_EP – notify about entry processes faults (Y/N, default N);
  • NOTIFY_NPROC – notify about number of processes faults (Y/N, default N);
  • NOTIFY_MIN_FAULTS_ADMIN – minimum number of faults to notify admin (default 1);
  • NOTIFY_MIN_FAULTS_USER – minimum number of faults to notify customer (default 1);
  • NOTIFY_INTERVAL_ADMIN – period of time to notify admin (default 12h);
  • NOTIFY_INTERVAL_USER – period of time to notify customer (default 12h);
  • NOTIFY_FROM_EMAIL - sender email address. For example: NOTIFY_FROM_EMAIL=main_admin@host.com;
  • NOTIFY_FROM_SUBJECT - email message subject. For example: NOTIFY_FROM_SUBJECT=Message from notifier
  • NOTIFY_CHARSET_EMAIL – charset type for email. Available for lve-stats-2.9.4-1 and later. Default is us-ascii. For example: NOTIFY_CHARSET_EMAIL=utf-8

These values can also be set using cloudlinux-config CLI utility

Templates of notifications are located here:

  • /usr/share/lve/emails/en_US/admin_notify.txt
  • /usr/share/lve/emails/en_US/reseller_notify.txt
  • /usr/share/lve/emails/en_US/user_notify.txt
  • /usr/share/lve/emails/en_US/admin_notify.html
  • /usr/share/lve/emails/en_US/reseller_notify.html

Note

Notifications about LVE faults are implemented for CPanel, Plesk, and DirectAdmin.

After changing any options above, please restart lvestats service:

service lvestats restart

/etc/logrotate.d/lvestats - configuration file for /var/log/lve-stats.log rotation

Note

You can also use LVE-stats 2 CLI

LVE-stats2 and DB servers compatible work setup

LVE-stats2 and MySQL DB server compatible work setup

Note

Run all the commands below under root.

1. MySQL server setup

If MySQL Server is not installed, then install it according to control panel documentation.

For non-panel system:

  • CloudLinux 6

    yum install mysql mysql-server
    service mysqld start
    chkconfig mysqld on
    
  • CloudLinux 7

    yum install mariadb mariadb-server
    systemctl start mariadb.service
    systemctl enable mariadb.service
    

2. Database setup

  • Run MySQL administrative utility: mysql.

  • In utility run the commands:

    • creating server DB. Also, check Note below.
    CREATE DATABASE db_lvestats2;
    
    • creating a user for LVE Stats 2 server to work under. Also, check Note below.
    CREATE USER 'lvestats2'@'localhost' IDENTIFIED BY 'lvestats2_passwd';
    
    • granting all the privileges for all DB tables to the user. Use the username and DB name from the points above.
    GRANT ALL PRIVILEGES ON db_lvestats2.* TO 'lvestats2'@'localhost';
    
    • refreshing privileges information.
    FLUSH PRIVILEGES;
    
    • Exit administrative utility (Ctrl+d).

Note

DB name, username and their passwords above are given for an example - you can use any of your choices. Using old DB from LVE Stats version 1 is also acceptable as LVE Stats2 uses different tables and the old information will not be corrupted.

3. LVE-stats2 setup

  • Stop LVE Stats 2 server by running the command:
service lvestats stop
  • In server configuration file /etc/sysconfig/lvestats2, edit the following options:
    • db_type = mysql
    • connect_string = lvestats2:lvestats2_passwd@localhost/db_lvestats2

Note

connect_string option value is used in format: user:pass@host/database. Username, password and DB name must be the same as in point 2 of Database Setup above.

  • After making changes in configuration files run:
/usr/sbin/lve-create-db 

For DB primary initialization (creating tables, indexes, etc). There is no need to create anything in the DB manually.

  • When done, restart server by running:
service lvestats restart

4. Additional security settings

If you need to provide access to LVE Stats information utilities (lveinfo, lvechart, lve-read-snapshot) for different users, then we recommend creating one more DB user with read-only privilege to guarantee information security. It can be done by running the following commands in administrative utility:

  • creating a user (check Note above)
CREATE USER 'lvestats2_read'@'localhost' IDENTIFIED BY 'lvestats2_read_passwd';
  • granting read-only privilege to the user
GRANT SELECT ON db_lvestats2.* TO 'lvestats2_read'@'localhost';
  • refreshing privileges information
FLUSH PRIVILEGES;

If LVE Stats2 server is set correctly (see information below), the information utilities will work under this user.

If you need to provide access to information utilities to other users, then in order to guarantee information security you should do the following:

  • Assign permission 600 to the main configuration file (/etc/sysconfig/lvestats2), so that it could be read only by LVE Stats 2 server and by utilities that run under root.
  • Copy /etc/sysconfig/lvestats2 to /etc/sysconfig/lvestats2.readonly, assign permission 644 to the new file, so that it could be read by any user but could only be changed by root.
  • In /etc/sysconfig/lvestats2.readonly file, in the line connect_string, specify DB user with read-only permission, created above.

These steps allow hiding main DB user username/password from other system users.

If there is no need in such access differentiation, then /etc/sysconfig/lvestats2 file access permission should be 644, so that it could be read by all users and could be changed only by root.

5. Using special characters in database password

Since scheme ://user:password@host[:port]/database_name URI is used in connect_string config option, then usage of special characters in user DB password is not allowed.

To use special symbols in the password, it must be converted to escape-sequence. You can convert a password to escape-sequence in a console as follows:

echo -n '[You_P@$$]:' | perl -MURI::Escape -ne 'print uri_escape($_)."\n"'
%5BYou_P%40%24%24%5D%3A

Or replace the symbols manually:

!    #    $    &    '    (    )    *    +    ,    /    :    ;    =    ?    @   [    ]
%21  %23  %24  %26  %27  %28  %29  %2A  %2B  %2C  %2F  %3A  %3B  %3D  %3F  %40  %5B %5D

After that сonnect_string will look as follows:

сonnect_string=lvestats2:%5BYou_P%40%24%24%5D%3A@localhost/db_lvestats2

LVE-stats2 and PostgreSQL DB server compatible work setup

Note

Run all the commands below under root.

1. PostgreSQL server installation and setup

  • PostgreSQL installation and initialization

    For control panels use proper documentation for installation on the links: сPanel, Plesk.

    For non-panel CloudLinux run the following commands:

    • CloudLinux 6
    yum install postgresql-server postgresql
    service postgresql initdb
    service postgresql start
    chkconfig postgresql on
    
    • CloudLinux 7
    yum install postgresql-server postgresql
    postgresql-setup initdb
    systemctl start postgresql
    systemctl enable postgresql
    
  • Setup

    • In /var/lib/pgsql/data/pg_hba.conf config file change user authentication mode. Add the following lines (place before all other authentication parameters):

      # IPv4 local connections for lve-stats-2.x
      host dblvestat all 127.0.0.1/32 password
      # IPv6 local connections for lve-stats-2.x
      host dblvestat all ::1/128 password
      

      These lines enable user authentication by the password for IP4/IP6 connections. You can set other modes if needed.

    • Apply config changes by running:

      service postgresql restart
      

2. DB for LVE-stats-2.x - creating and setup

  • Run standard PostgreSQL psql administrative utility:
sudo -u postgres psql postgres 

OR for сPanel

psql -w -U postgres
  • In utility run:

    • creating server DB. Also, check Note below.

      CREATE DATABASE dblvestat;
      
    • creating a user for LVE Stats 2 server to work under. Also, check Note below.

      CREATE USER lvestat WITH password 'passw';
      
    • granting lvestat user all privileges for work with dblvestat DB.

      GRANT ALL privileges ON DATABASE dblvestat TO lvestat;
      
    • exit psql utility:

      \q
      

      OR alternatively:

      Ctrl+d
      

Note

DB name, username and their passwords above are given for an example - you can use any of your choices. Using old DB from LVE Stats version 1 is also acceptable as LVE Stats 2 uses different tables and the old information will not be corrupted

3. LVE-stats-2.x setup

  • Stop lve-stats2 server by running:
service lvestats stop
  • In server config file /etc/sysconfig/lvestats2 edit options for connecting to DB:
db_type = postgresql
connect_string=lvestat:passw@localhost/dblvestat
If DB is going to be used as centralized for multiple hosts then collect_usernames parameter must be changed:
collect_usernames=true

Note

connect_string option value is of the format: user:pass@host/database. Username, password and DB name must be the same as in Database Setup section above.

  • After making changes in configuration files, for DB primary initialization (creating tables, indexes, etc), run:
/usr/sbin/lve-create-db 
  • There is no need to create anything in the DB manually. When done, restart server by running:
service lvestats restart

4. Additional security settings

If you need to provide access to LVE Stats information utilities (lveinfo, lve-read-snapshot ) for other users (or if CageFS is disabled), then in order to guarantee DB security the following steps are required:

  • Create a DB user with read-only permission:
CREATE USER lvestat_read WITH password 'passw';
GRANT CONNECT ON DATABASE dblvestat to lvestat_read;
\connect dblvestat;
GRANT SELECT ON lve_stats2_history, lve_stats2_history_gov, lve_stats2_history_x60, lve_stats2_incident, lve_stats2_servers, lve_stats2_snapshot, lve_stats2_user TO lvestat_read;
  • Assign root ownership and permission 600 to the main configuration file (/etc/sysconfig/lvestats2), so that it could be read only by LVE Stats 2 server and by utilities that run under root.

  • Copy /etc/sysconfig/lvestats2 to /etc/sysconfig/lvestats2.readonly, assign permission 644 to the new file, so that it could be read by any user but could be changed only by root.

  • In /etc/sysconfig/lvestats2.readonly file, in the line connect_string, specify DB user with read-only permission, created above.

    These steps allow hiding main DB user username/password from other system users.

    If there is no need in such access differentiation, then /etc/sysconfig/lvestats2 file access permission should be 644, so that it could be read by all users and could be changed only by root.

  • When done, restart server by running:

service lvestats restart

5. Using special characters in database password

Since scheme ://user:password@host[:port]/database_name URI is used in connect_string config option, then usage of special characters in user DB password is not allowed.

To use special symbols in the password, it must be converted to escape-sequence. You can convert a password to escape-sequence in a console as follows:

echo -n '[You_P@$$]:' | perl -MURI::Escape -ne 'print uri_escape($_)."\n"'
%5BYou_P%40%24%24%5D%3A

OR replace the symbols manually:

!    #    $    &    '    (    )    *    +    ,    /    :    ;    =    ?    @    [    ]
%21  %23  %24  %26  %27  %28  %29  %2A  %2B  %2C  %2F  %3A  %3B  %3D  %3F  %40  %5B  %5D

After that сonnect_string will look as follows:

сonnect_string=lvestats2:%5BYou_P%40%24%24%5D%3A@localhost/db_lvestats2

Customize LVE-stats2 notifications

Jinja2 is used as a template engine for the notifications.

The templates for notifications are located in /usr/share/lve/emails/LOCALE, where LOCALE is the directory with localization name (language codes are formed according to ISO 639-1 and ISO 639-2).

By default the templates for English are set: /usr/share/lve/emails/en_US..

/usr/share/lve/emails/en_US contains the following templates:

  • admin_notify.html admin_notify.txt for administrator;
  • reseller_notify.html reseller_notify.txt for reseller;
  • user_notify.txt for user.

The notification is formed as Multipart content type RFC1341(MIME).

The plain text is taken from the .txt files, html version - from the .html template.

In case when only one template is present (.txt or .html) the notification is sent as a Non-multipart content type notification.

It is better to use Multipart content type notifications because when a mail client can not display an html-format message, then it will be displayed as plain text version.

To localize notifications, copy standard templates into directory with the proper locale name and translate the template. Also you can customize the main template making proper changes into it.

The list of variables that can be used in the template:

Variable Example Description
TONAME Customer Notification receiver user name. Taken from profile in the control panel, by default - Customer for user, Administrator for administrator, Reseller for reseller.
TOMAIL support@cloudlinux.com Notification receiver email address.
DOMAIN wordpress.test247.cloudlinux.com Main domain. Available only for user.
LOCALE en_US Locale in which the notification is sent. Available only for user.
RESELLER root User reseller. Available only for user.
PERIOD 12 hours Verification and notification sending period.
LOGIN wordpress User login in the system.
ID 500 User ID in the system.
lPMem lEP PMemF lVMem anyF IOf VMemF lCPU aIOPS aEP aPMem IOPSf lIO lIOPS aIO EPf aCPU aVMem NprocF aNproc lNproc CPUf See description in lveinfo --help output. Available only for users
STATS_HTML html table with the list of users that exceeded limits. Available for administrator and reseller.
STATS ASCII - table with the list of users that exceeded limits. Available only for admins and resellers.

Sender’s email address by default is administrator email address from control panel settings (root@{hostn_name} if there is no email in the control panel).

It can be changed with NOTIFY_FROM_EMAIL option in the config /etc/sysconfig/lvestats.config/StatsNotifier.cfg

For example:

NOTIFY_FROM_EMAIL=support@hostername.com

To apply changes restart lve-stats service:

service lvestats restart

for CloudLinux 7

systemctl restart lvestats.service

Default subject is Hosting account resources exceeded.  It can be changed for each template (and for localized templates as well). To change subject, in the very beginning of the file (no blank lines allowed in the beginning of the template) add the field Subject:, leave two blank lines after it and add template body.

Customized subjects can be taken only from the templates with the resolution *.txt (admin_notify.txt, reseller_notify.txt, user_notify.txt). Changes apply without lvestats restart.

For backward compatibility the subject can be also changed with the key NOTIFY_FROM_SUBJECT in the config /etc/sysconfig/lvestats.config/StatsNotifier.cfg.

Customized subjects have the higher priority than the key NOTIFY_FROM_SUBJECT.

Example for the file user_notify.txt

Subject: Customized subject example
Dear {{TONAME}},
 
Your {{DOMAIN}} web hosting account exceeded one or more of its resources within the last {{PERIOD}}.
{% if epf %}Exceeded the maximum of {{lep}} concurrent website connections. Your website was not available {{epf}} times because of this problem.
{% endif %}{% if pmemf %}Exceeded the physical memory limit of {{lpmem}}KB. Your website was not available {{pmemf}} times because of this problem.
{% endif %}{% if vmemf %}Exceeded the virtual memory limit of {{lvmem}}KB. Your website was not available {{vmemf}} times because of this problem.
{% endif %}{% if nprocf %}Exceeded the number of processes limit of {{lnproc}}. Your website was not available {{nprocf}} times because of this problem.
{% endif %}{% if cpuf %}You reached limit of {{lcpu}} of total server CPU usage {{cpuf}} times. Your website was forced to load slower to reduce its CPU usage.
{% endif %}{% if iof %}You reached limit of {{lio}}KB/s disk io rate {{iof}} times. The disk io speed for your account was slowed as a result of this problem.
{% endif %}{% if iopsf %}You reached limit of {{liops}} I/O operations {{iopsf}} times. The disk io speed for your account was slowed as a result of this problem.
{% endif %}
 
To view full details about your web hosting account's resource usage, including the time of each incident listed above, please click the link below and log into your cpanel hosting control panel, then click the "Resource Usage" link under the "Logs and Statistics" section.
http://{{DOMAIN}}:2083
 
If your account is regularly exceeding it's available resources, please consider upgrading to a higher level hosting plan that includes more resources. If you have any questions or need help with anything, just reply to this email and let us know.
 
Sincerely,
 
Your Friendly Web Hosting Support Team

Plugins

LVE-stats2 comes with a set of generic plugins:

Plugin Name Order Default Period (seconds) Description
LVECollector 1000 Y 5 Collects usage/limits data from /proc/lve/list
CPUInfoCollector 2000 Y 5 collents info about CPU - /proc/cpuinfo
LVEUsernamesCollector 3000 Y 3600 collects usernames & user ids to match uid <-> lve id later on
LVEUsageAnalyzer 4000 Y 5 analyzes usage of LVE
LveUsageAggregator 5000 Y 60 aggregates data by time periods
DBGovSaver 6000 Y 5 Saves data about database governor
FileSaver 7000 Y 5 Saves LVE data into /var/lve/info
CloudLinuxTopFileSaver 8000 Y 60 saves data used by cloudlinux-top to /var/lve/cloudlinux-top.json
DBSaver 9000 Y 60 save LVE data to database
DbUsernamesSaver 10000 Y 3600 saves users name to database
DBSaverX60 11000 Y 3600 saves aggregated hourly data into database
SnapshotSaver 12000 Y 30 collects & saves snapshots data
StatsNotifier 13000 Y varied notify user/admin based on usage
HistoryCleaner 14000 Y 3600 removes old usage
ResMEMCollector 1500 N 30 collects physical memory usage from processes RES field instead of /proc/lve/list
LVEDestroyer - N 5 destroys LVEs that weren't active for X iterations. Number of iterations is passed from config using iterations variable. iterations=0 means plugin disabled

To enable non-default plugin, copy or link it to /usr/share/lve-stats/plugins directory.

For example to enable ResMEMCollector plugin, do:

ln -s /usr/share/lve-stats/plugins.other/res_mem_collector.py /usr/share/lve-stats/plugins/
service lvestats restart

Creating a plugin for LVE-stats2

Introduction

LVE Stats 2 complex has scalable architecture, which allows to connect custom plugins.

LVE Stats server searches for plugins in the directory which is specified with plugins parameter of server’s /etc/sysconfig/lvestats2 configuration file. Default directory is /usr/share/lve-stats/plugins.

Each plugin must be of a Python class, must be written in Python language and its file must have .py extension. Files with all other extensions will be ignored. For normal server work access permission 400 is enough; owner – root .

Plugin classes can be of the same name, but better not, because classes' names can affect the set of parameters in set_config method. You can find detailed plugins' configuring information below, in appropriate chapter.

Plugin class must contain execute() method, which is invoked by the server every 5 seconds (by default, can be changed by interval parameter of configuration file). Also set_config method (configuration settings) can be available. You can find more info in Plugins Configuration chapter.

Additionally the following attributes can be set (plugin class instance variable):

  • order (integer) - defines plugin's position in the server's plugin list, (more info in Servers Plugin Arrangement ).
  • timeout (integer or float ) – the longest allowable duration of one launch of the plugin (execute method). Default value of timeout parameter is 5 seconds.
  • period (integer) – sets the interval between two launches of execute plugin method in seconds. If not defined, then plugin runs every 5 seconds ( interval parameter in configuration file).

When execute() method of the plugin is invoked, the server creates an attribute now in it, where launch time is recorded. This value is equal to what a standard Python function time.time() returns. All the plugins launched one after another receive the same  value of now attribute from the server. now is overwritten before execute() method is invoked.

The previous value of now attribute is not saved by the server. If plugin needs it, it has to save it by itself.

Plugin class can be inherited from LveStatsPlugin class, which is the part of the server itself. This is not obligatory, but inheritance can help to avoid different errors in servers work, particularly if a plugin doesn't contain required execute method.

LveStatsPlugin class is defined in the file: /opt/alt/python27/lib/python2.7/site-packages/lvestats/core/plugin.py .

Server plugin arrangement

When the server starts, it performs the search of plugins in the directory specified in /etc/sysconfig/lvestats2 configuration file. This directory is scanned only when the server starts, therefore if any plugin was added into the directory, the server has to be restarted with the following command:

service lvestats restart.

After successful restart, the plugins are graded and executed ascending by order attribute. If any plugin order attribute is not set, it is considered as a Python language constant sys.maxint (which is usually 9223372036854775807). This in fact means that such plugins will be executed in the last. If any plugins has similar order meanings, their execution order is unpredictable.

The server invokes execute method of all plugins one after another.

When the server invokes execute() method of any plugin, it transmits a data dictionary ( lve_data argument) into plugin. The dictionary is common for all the plugins. Any plugin can read, write and change any data in this dictionary. LVE Stats 2 server doesn't control this area. That is why one must be careful while developing new plugins, in order not to change or corrupt other plugins' data which can break their functionality.

If an exception occurs in execute() method, its text and python stack trace is recorded into server log /var/log/lve-stats and all the changes made to lve_data dictionary before the exception happened are lost.

The keys of the lve_data dictionary are recommended to look like PluginName_Key , in order the plugins do not corrupt other data accidentally.

Server contains some standard plugins which define and use the following keys in the common dictionary lve_data: LVE_VERSION, stats, old_stats, procs and lve_usage . User plugins can use data from these keys, but it is recommended not to change them if there is no special need, because it can break the next plugins in the execution queue.

Key Content
LVE_VERSION LVE version. The same as console command lvectl lve-version produces.
stats Dictionary, that contains lve id’s as keys and LVEStat class objects as values. Every LVEStat object contains values of usages and limits taken from /proc/lve/list file for every LVE Id . Dictionary keys – integer lve id , including 0 for “ default ” LVE. This dictionary is updated on each iteration of lvestats-server (every 5 seconds by default). LVEStat – is a standard server class, it can be imported with the command from lvestats.core.lvestat import LVEStat. The class is described in the file /opt/alt/python27/lib/python2.7/site-packages/lvestats/core/lvestat.py . Here you can find the whole list of data fields and their functions.
old_stats stats content from the previous iteration. Before the first iteration – empty dictionary.
totalHz When LVE_VERSION is 4, real CPU frequency in Hz multiplied by number of cores. When LVE_VERSION > 4, CPU speed is in conventional units and equals to 1000000000 * cores (1 GHz per core).
procs Quantity of CPU cores.
lve_usages Contains accumulated LVE statistics for each 5-seconds interval in current minute. Cleared each minute.
lve_usage Contains aggregated LVE Statistics for “previous” minute to store to database. Overwritten each minute.

Each plugin’s instance lifetime is from the moment it was loaded till the server stops working. But if execute() method working time exceeds timeout, the plugin will be terminated and restarted in the next iteration. All changes to the lve_data dictionary will be lost.

During servers graceful shutdown (restart, server shutdown, commands service lvestats stop, service lvestats restart ), each plugin receives SIGTERM signal. This is useful to correctly unload the plugin (terminate all subsidiary processes, save data to files etc.). If a plugin doesn't need to “finalize” its execution before termination, then there's no need to implement this signal handler. Below you can see an example of such handler.

Note

If a plugin implements handler for SIGTERM, then this handler must end with sys.exit(0) command. Otherwise plugin process will not be terminated correctly and will become orphaned.

Plugin configuration

LVE Stats 2 Server allows to configure each plugin separately.

On initialization stage the server invokes set_config() method of the plugin and locates there a dictionary which contains:

  • all parameters from file /etc/sysconfig/lvestats2 (global).
  • plugin's individual configuration file parameters (if one exists). Configuration files must be located in /etc/sysconfig/lvestats.config directory, have .cfg extension and be the same format as /etc/sysconfig/lvestats2 . Files in this directory are matched with the plugins by name. For instance, if plugin class is Plugin1_class , then server will try to find and download /etc/sysconfig/lvestats.config/Plugin1_class.cfg. Names are case sensitive. If any plugin doesn't have an individual configuration file, then it's not an error. In this case plugin will just receive parameters from /etc/sysconfig/lvestats2 .

Note

An individual configuration file of every plugin is loaded after server configuration file. That is why if it contains any parameters with names similar to ones of server config, then plugin will use parameters from its individual config rather than server config parameters.

If a plugin doesn't require any configuration to be done, then set_config method can be skipped.

In addition, plugins can use their own configuration methods.

Types of plugins

According to server architecture, plugins can be of the following types:

  • collectors
  • analyzers
  • persistors
  • notifiers

Collectors are designed to collect information; analyzers – to analyze it and form some other data on its basis; persistors – to save information from the common dictionary into files, databases, etc.; notifiers - to notify system users about any events.

This division is rather arbitrary. There is an opportunity to execute all the actions on collection, analysis and saving the information in one and only plugin. But at the same time the division into functionally independent parts allows to build flexible and easily configurable system for collecting and processing the data.

Also it is possible to implement the systems of lazy-write, planning of collecting/processing tasks and notifying users about different events.

Examples of plugins

Here is a practical example of a user plugin.

Specification:

  1. To trace specified file size changes. The name of file being traced must be specified in configuration file, which allows to change it without modifying the plugin itself. If file size has been changed, it has to be written as a message into our log. The name of log must be specified in configuration file as well.

  2. File size must be checked with default interval (5 seconds), and log notification must be held once a minute (to avoid resource expend for possibly regular write).

  3. System administrator must receive emails with file size at the moment the email was sent. These notifications must be sent even if the file size hasn’t been changed. Notification emails must be read periodicity from configuration file as well as sender/receiver emails .

As file size check, fixing the result and notification sending must be held with different periods, then it’s impossible to realize all the tasks by means of one plugin. The fact that one minute (60 seconds) is multiple to 5 seconds doesn’t matter in this case, because default period can be changed in server’s configuration file, but the condition of fixing the result once a minute is a part of the specification, which can not be violated. In addition, notification email period is known in advance, as it is specified by user in configuration file.

That is why we realize 4 plugins: collector, analyzer, persistor and notifier.

Collector

Collector's aim is to determine the size of a proper file.

# FSize_watcher_collector.py
# Example plugin for monitoring file size.
# Part 1. Collector

import os
from lvestats.core.plugin import LveStatsPlugin 

# Key name
COLLECTOR_KEY = 'FSizeWatcher_fsize'
COLLECTOR_KEY_FILENAME = 'FSizeWatcher_fname'  

class FSize_watcher_collector (LveStatsPlugin):
	# this plugin should be first in chain
	order = 0
	# File to monitoring
	file_to_monitoring = None 
	
	def __init__(self):
		pass 
		
	# Sets configuration to plugin
	def set_config(self, config):
		self.file_to_monitoring = config.get('file_to_monitoring', None)
		pass
	# Work method
	def execute(self, lve_data):
		try:
			# if monitoring file absent, do nothing
			if self.file_to_monitoring is None or not os.path.exists(self.file_to_monitoring):
		return 
		
			# Get file size
			stat_info = os.stat(self.file_to_monitoring)
			fsize = stat_info.st_size 
			
			# Place file name and file size to server data dictionary
			lve_data[COLLECTOR_KEY_FILENAME] = self.file_to_monitoring
			lve_data[COLLECTOR_KEY] = fsize
		except (OSError, IOError):
			# file absent or any other error - remove size from dictionary
			del lve_data[COLLECTOR_KEY]

Plugin algorithm is extremely simple – file size is read and written into data dictionary. Files name is read from set_config method configuration. If the name is not specified, then None is written into appropriate variable. All the errors are completely ignored (e.g. if specified file doesn't exist or there's no way to read any of it's information).

order attribute is specified as 0 to make this plugin go the first among three. Data collector must always be the first in plugins logical chain, because it provides all the necessary information for the analyzer which goes the next. Specific values of order can be of any kind, but what is important is that when the server starts, all the plugins line up in proper sequence: collector – analyzer – persistor .

In order to make plugin work, we have to create configuration file /etc/sysconfig/lvestats.config/FSize_watcher_collector.cfg with the following content:

# Config file for FSize_watcher_collector plugin
# Please define monitoring file here
# file_to_monitoring = /usr/local/cpanel/logs/error_log
file_to_monitoring = /usr/local/cpanel/logs/access_log

Note that file name FSize_watcher_collector without .cfg extension matches plugin class name.

file_to_monitoring option is read by plugin in set_config method and contains file’s full name for monitoring.

Files for monitoring, suggested in the actual example - /usr/local/cpanel/logs/error_log and /usr/local/cpanel/logs/access_log - are real, these are cPanel control panel logs.

The first file is errors log; the second is appeal log, is refreshed during common work with panel (e.g. if user email address is changed).

Errors log tracking is more important, but appeal log monitoring allows to illustrate plugins work more in details, because it is refreshed more often.

Note that plugin can monitor one file only.

Analyzer

Analyzer decides if the file's size has changed and gives a command to persistor to refresh log.

# FSize_watcher_analyzer.py
# Example plugin for monitoring file size.
# Part 2. Analyzer 

from lvestats.core.plugin import LveStatsPlugin 

# Key name from collector plugin
COLLECTOR_KEY = 'FSizeWatcher_fsize' 

# Key name 1 for saver plugin
SAVER_KEY = 'FSizeWatcher_fsize_to_store'
# Key name 2 for saver plugin
SAVER_DATA_PRESENCE = 'FSizeWatcher_fsize_present'  

class FSize_watcher_analyzer (LveStatsPlugin):
	# this plugin should be second in chain
	order = 1
	# Last file size
	file_last_size = 0
	# Plugin run period in secondsperiod = 60 
	
	def __init__(self):
		pass 
		
	# work method
	def execute(self, lve_data):
		# Default setting for saver
		lve_data[SAVER_DATA_PRESENCE] = 0
		# Check presence data
		if COLLECTOR_KEY not in lve_data:
		return 
		
		# Get file size from server data dictionary
		fsize = lve_data[COLLECTOR_KEY] 
		
		# Check, if file size changed, store it for saver plugin
		if fsize == self.file_last_size:
			return 
			
		# Put new size for saver plugin
		lve_data[SAVER_KEY] = fsize
		self.file_last_size = fsize
		lve_data[SAVER_DATA_PRESENCE] = 1

This plugin is extremely simple as well. It starts after collector (order=1) , searches for file size in the dictionary and compares it with the previous index. If it has changed, then it writes a sign of presence of a new size into the dictionary. If no changes seen, then sign resets. The previous file size is stored in the plugin itself in file_last_size variable. Note that they are stored during the whole server lve-stats lifetime.

If file size is not found in data dictionary, then plugin just ends.

All the errors are completely ignored.

Analyzer is unconfigurable, that is why it doesn’t require any configuration file and it doesn’t contain set_config method.

Plugin starts every 60 seconds (1 minute), because we need data fixation to be performed one time in a minute.

Persistor

Persistor saves information from the common dictionary into files, databases, etc.

# FSize_watcher_saver.py
# Example plugin for monitoring file size and last modification date-time.
# Part 3. Data saver 

import signal
import sys
import time
from lvestats.core.plugin import LveStatsPlugin 

# Key name 1 for saver plugin
SAVER_KEY = 'FSizeWatcher_fsize_to_store'
# Key name 2 for saver plugin
SAVER_DATA_PRESENCE = 'FSizeWatcher_fsize_present'
# Monitoring file name
COLLECTOR_KEY_FILENAME = 'FSizeWatcher_fname'  

class FSize_watcher_saver (LveStatsPlugin):
	# this plugin should be third in chain
	order = 2
	# Plugin run period in seconds
	period = 60
	# Log filename
	log_file_name = None
	# First run flag
	is_first_run = True 
	
	def __init__(self):
		signal.signal(signal.SIGTERM, self.sigterm_handler) 
		
	# Sets configuration to plugin
	def set_config(self, config):
		# Get log filename
		self.log_file_name = config.get('log_filename', None) 
		
	# work method
	def execute(self, lve_data):
		# do nothing, if log file not defined
		if not self.log_file_name:
			return
		try:
			# Check presence data
			if SAVER_DATA_PRESENCE not in lve_data or lve_data[SAVER_DATA_PRESENCE] == 0:
				# No data
				return
			# Get file size from server data dictionary
			fsize = lve_data[SAVER_KEY]
			
			# Store data to log
			f = open(self.log_file_name, 'a')
			if self.is_first_run:
				f.write('%s - FSize_watcher started. Monitoring file: %s, saving data period=%d sec\n' % (time.asctime(time.localtime()), lve_data[COLLECTOR_KEY_FILENAME], self.period))
				self.is_first_run = False
			f.write('%s - FSize_watcher: file size is %d bytes\n' % (time.asctime(time.localtime()), fsize))
			f.close()
		except:
			# Ignore all errors
			pass 
			
	# Terminate handler
	def sigterm_handler(self, signum, frame):
		if self.log_file_name:
			try:
				# Store data to log file
				f = open(self.log_file_name, 'a')
				f.write('%s - File watcher saver plugin: TERMINATE\n' % time.asctime(time.localtime()))
				f.close()
				pass
			except:
				# Ignore all errors
				pass
		# Terminate process
		sys.exit(0)

Configuration file /etc/sysconfig/lvestats.config/FSize_watcher_saver.cfg:

# Config file for FSize_watcher_saver.py plugin
# Please define log filename here
log_filename = /var/log/FSize_watcher.log

This plugin starts after analyzer (order=2) , checks new file size presence flag, and if positive – writes it into log. If the flag is cleared (which means the size hasn't changed), then plugin simply ends.

Starts once in a minute (period=60).

Also this plugin shows the work of signal handler.

Plugin constructor registers handler-function of a proper signal: signal.signal(signal.SIGTERM, self.sigterm_handler) . This means, that when the server finishes its work, then sigterm_handler method of plugin class will be invoked. In the actual example the function just writes a notification into log, tracing the fact of it's invocation.

Pay attention on sys.exit(0) command in the end of the handler. Find the information on it in Server Plugin Arrangement section.

In addition see into examples of file log /var/log/FSize_watcher.log formed by the plugins above:

Tue Feb  3 13:06:24 2015 - FSize_watcher started. Monitoring file: /usr/local/cpanel/logs/access_log, saving data period=60 sec
Tue Feb  3 13:06:24 2015 - FSize_watcher: file size is 122972890 bytes
Tue Feb  3 13:07:25 2015 - FSize_watcher: file size is 122975507 bytes
Tue Feb  3 13:08:25 2015 - FSize_watcher: file size is 122978124 bytes
Tue Feb  3 13:09:25 2015 - FSize_watcher: file size is 122978997 bytes
Tue Feb  3 13:10:25 2015 - FSize_watcher: file size is 122981033 bytes
Tue Feb  3 13:11:25 2015 - FSize_watcher: file size is 122982052 bytes
Tue Feb  3 13:13:25 2015 - FSize_watcher: file size is 122983798 bytes
Tue Feb  3 13:20:15 2015 - File watcher saver plugin: TERMINATE

and

Thu Feb  5 13:07:27 2015 - FSize_watcher started. Monitoring file: /usr/local/cpanel/logs/error_log, saving data period=60 sec
Thu Feb  5 13:07:27 2015 - FSize_watcher: file size is 14771849 bytes
Thu Feb  5 14:03:32 2015 - FSize_watcher: file size is 14771995 bytes
Thu Feb  5 15:01:36 2015 - FSize_watcher: file size is 14772434 bytes
Thu Feb  5 17:15:47 2015 - FSize_watcher: file size is 14772873 bytes
Thu Feb  5 18:47:54 2015 - FSize_watcher: file size is 14775213 bytes
Thu Feb  5 19:11:56 2015 - FSize_watcher: file size is 14775652 bytes
Thu Feb  5 21:09:05 2015 - FSize_watcher: file size is 14776091 bytes
Thu Feb  5 23:06:14 2015 - FSize_watcher: file size is 14776530 bytes
Fri Feb  6 00:47:23 2015 - FSize_watcher: file size is 14778870 bytes
Fri Feb  6 01:02:24 2015 - FSize_watcher: file size is 14779309 bytes
Fri Feb  6 02:00:28 2015 - FSize_watcher: file size is 14779434 bytes
Fri Feb  6 03:16:34 2015 - FSize_watcher: file size is 14779873 bytes
Fri Feb  6 05:04:42 2015 - FSize_watcher: file size is 14779998 bytes
Fri Feb  6 05:12:43 2015 - FSize_watcher: file size is 14780437 bytes
Fri Feb  6 05:56:50 2015 - FSize_watcher: file size is 14780551 bytes
Fri Feb  6 06:01:50 2015 - FSize_watcher: file size is 14780975 bytes
Fri Feb  6 06:03:51 2015 - FSize_watcher: file size is 14782183 bytes
Fri Feb  6 06:04:51 2015 - FSize_watcher: file size is 14782575 bytes
Fri Feb  6 06:18:52 2015 - FSize_watcher: file size is 14782647 bytes
Fri Feb  6 06:21:52 2015 - FSize_watcher: file size is 14782898 bytes
Fri Feb  6 06:48:54 2015 - FSize_watcher: file size is 14785238 bytes
Fri Feb  6 07:09:56 2015 - FSize_watcher: file size is 14785677 bytes
Tue Feb  6 08:03:15 2015 - File watcher saver plugin: TERMINATE

You can see that log record is being held once a minute (what we actually need), new file size is written.

Also we can notice that handler SIG_TERM was executed, signaling that plugin received the notification about server shut-down.

Notifier

Notifier informs system users about any events.

# FSize_watcher_saver.py
# Example plugin for monitoring file size and last modification date-time.
# Part 4. Notifier 

import time
import smtplib 

from lvestats.lib.commons import dateutil
from lvestats.core.plugin import LveStatsPlugin  


# Key name
COLLECTOR_KEY_FSIZE = 'FSizeWatcher_fsize'
COLLECTOR_KEY_FILENAME = 'FSizeWatcher_fname' 

# email message pattern
EMAIL_MESSAGE_PATTERN = """Hello, administrator!
Size of the file '%s' is %d bytes.
"""  


class FSize_watcher_notifier (LveStatsPlugin):
	# Default period
	DEFAULT_PERIOD_STR = '12h'
	# this plugin should be third in chainorder = 3
	# Timeout
	timeout = 20
	# Notifier Log filename
	log_file_name = '/var/log/FSize_watcher_notifier.log'
	# Email from address
	email_from = None
	# Email to address
	email_to = None
	# Email subject
	email_subject = None
	# Sets configuration to plugin
	def set_config(self, config):
		# Email settings
		self.email_from = config.get('notify_from_email', None)
		self.email_to = config.get('notify_to_email', None)
		self.email_subject = config.get('notify_from_subject', 'Message from FSize_watcher_notifier plugin')
		# Notify period
		s_period = config.get('notify_period', None)
		if s_period:
			self.period = dateutil.parse_period2(s_period)
		else:
			self.period = dateutil.parse_period2(FSize_watcher_notifier.DEFAULT_PERIOD_STR)
		f = open(self.log_file_name, 'a')
		f.write('%s - FSize_watcher_notifier plugin: configure\n' % time.asctime(time.localtime()))
		f.write('       - Period: %s\n' % self.period)
		f.write('       - From: %s\n' % self.email_from)
		f.write('       - To: %s\n' % self.email_to)
		f.write('       - Subject: \'%s\'\n' % self.email_subject)
		f.close() 
		
	# work method
	def execute(self, lve_data):
		if COLLECTOR_KEY_FSIZE not in lve_data or COLLECTOR_KEY_FILENAME not in lve_data:
			return
		if not self.email_from or not self.email_to:
			f = open(self.log_file_name, 'a')
			f.write('%s - FSize_watcher_notifier plugin error: email_from or email_to not set\n')
			f.close()
			return
		try:
			from email.mime.text import MIMEText
			# Send email
			msg = MIMEText(EMAIL_MESSAGE_PATTERN % (lve_data[COLLECTOR_KEY_FILENAME], lve_data[COLLECTOR_KEY_FSIZE]))
		msg['Subject'] = self.email_subject
		msg['From'] = self.email_from
		msg['To'] = self.email_to 
		
		s = smtplib.SMTP('localhost')
		s.sendmail(self.email_from, [self.email_to], msg.as_string())
			s.quit() 
			
		f = open(self.log_file_name, 'a')
			f.write('%s - FSize_watcher_notifier plugin: email message was successfully sent\n' % time.asctime(time.localtime()))
			f.close()
			except Exception as e:
			f = open(self.log_file_name, 'a')
			f.write('%s - FSize_watcher_notifier plugin error:\n%s\n' % (time.asctime(time.localtime()), str(e)))
			f.close()

Configuration file /etc/sysconfig/lvestats.config/FSize_watcher_notifier.cfg :

# Config file for FSize_watcher_notifier.py plugin
# Please define email options here 

NOTIFY_FROM_EMAIL=user@hostname
NOTIFY_FROM_SUBJECT=Message from FSize_watcher_notifier
NOTIFY_TO_EMAIL=admin@hostname
NOTIFY_PERIOD=12h

Plugin’s index number equals 3 ( order=3 ), that is why notifier starts after the rest. But since it uses only data formed by collector , then its order may equal any number bigger that collectors order (>0).

Notifier reads the necessary parameters from the configuration (email address, topic, period) and writes them into its own log as reference.

Plugin’s execute method checks the availability of all the necessary data (email parameters, collectors data) and sends the message. All the notifications are written into the notifier's own log.

If any data is missing, the message is not sent.

Log example:

Thu Feb  5 11:51:34 2015 - FSize_watcher_notifier plugin: configure
       - Period: 60.0
       - From: user@hostname
       - To: admin@hostname
       - Subject: 'Message from FSize_watcher_notifier'
Thu Feb  5 11:51:35 2015 - FSize_watcher_notifier plugin: email message was successfully sent
Thu Feb  5 11:52:35 2015 - FSize_watcher_notifier plugin: email message was successfully sent
Thu Feb  5 11:53:35 2015 - FSize_watcher_notifier plugin: email message was successfully sent
Thu Feb  5 11:54:35 2015 - FSize_watcher_notifier plugin: email message was successfully sent
Thu Feb  5 11:57:00 2015 - FSize_watcher_notifier plugin: configure
       - Period: 43200.0
       - From: user@hostname
       - To: admin@hostname
       - Subject: 'Message from FSize_watcher_notifier'
Thu Feb  5 11:57:00 2015 - FSize_watcher_notifier plugin: email message was successfully sent

File info and format for /var/lve/info file

This file is used by control panels to display to user their 'current' usage. The file is updated every 5 seconds by lve-stats.

When writing to this file we make sure that: average CPU/IOPS/MEM is never greater then LIMIT for that resource.

Example:

0,0,20,0,2500,0,262144,0,0,262144,0,0,100,0,0,0,0,1024,1024,0,0,0,0 600,1,20,2492,2500,70,262144,0,0,262144,33,0,100,1,0,0,0,1024,1024,0,5,0,0 200,0,20,0,2500,0,262144,0,0,262144,0,0,100,0,0,0,0,1024,1024,0,0,0,0 500,0,20,0,2500,0,262144,0,0,262144,0,0,100,0,0,0,0,1024,1024,0,0,0,0

First line of the file is ' default limits '.

Fields:

# 0 - id
# 1 - mep (average entry processes)
# 2 - lep  (limit ...)
# 3 - cpu_usage (average speed)
# 4 - lcpu (limit spped)
# 5 - mem_usage (average virtual memory)
# 6 - lmem (limit ...)
# 7 - mem_fault (number of virtual memory faults)
# 8 - mep_fault (number of entry processes faults)
LVE_VERSION >=6
# 9 - lmemphy (limit physical memory)
# 10 - memphy (average ...)
# 11 - memphy_fault (faults ...)
# 12 - lnproc (limit number of processes)
# 13 - nproc (average ...)
# 14 - nproc_fault (faults ...)
# 15 - lcpuw (CPU weight -- deprecated not used)
# 16 - io_usage (average IO usage)
# 17 - io_limit (limit ...)
LVE_VERSION >=8
#18 - liops  (limit IOPS)
#19 - iops (average IOPS)

Note

You can also use LVE-stats 2 CLI

Troubleshooting

lvestats service and utilities write fatal errors to system log.

There is /var/log/lve-stats.log file with additional information (warnings, tracebacks for errors).

CageFS

General information and requirements

CageFS is a virtualized file system and a set of tools to contain each user in its own 'cage'. Each customer will have its own fully functional CageFS, with all the system files, tools, etc.

The benefits of CageFS are:

  • Only safe binaries are available to user
  • User will not see any other users, and would have no way to detect presence of other users & their user names on the server
  • User will not be able to see server configuration files, such as Apache config files.
  • User's will have limited view of /proc file system, and will not be able to see other users' processes

At the same time, user's environment will be fully functional, and user should not feel in any way restricted. No adjustments to user's scripts are needed. CageFS will cage any scripts execution done via:

  • Apache (suexec, suPHP, mod_fcgid, mod_fastcgi)
  • LiteSpeed Web Server
  • Cron Jobs
  • SSH
  • Any other PAM enabled service

Note

mod_php is not supported, MPM ITK requires a custom patch

Note

CageFS is not supported for H-Sphere.

See also Compatibility Matrix.

Minimum Requirements:

  • kernel: CL6 with lve1.2.17.1 or later, CL7.
  • 7GB of disk space.

Depending on your setup, and number of users, you might also need:

  • Up to 8MB per customer in /var directory (to store custom /etc directory)
  • 5GB to 20GB in /usr/share directory (to store safe skeleton of a filesystem)

Warning

If at any time you decide to uninstall CageFS, please make sure you follow uninstall instructions

CageFS quirks

Due to the nature of CageFS, some options will not work as before or will require some changes:

  • lastlog will not work (/var/log/lastlog).
  • PHP will load php.ini from /usr/selector/php.ini. That file is actually a link to the real php.ini file from your system. So the same php.ini will be loaded in the end.
  • You have to run cagefsctl --update any time you have modified php.ini, or you want to get new/updated software inside CageFS.
  • CageFS installation changes jailshell to regular bash on cPanel - read why.

Installation and update

To install CageFS:

$ yum install cagefs
$ /usr/sbin/cagefsctl --init

That last command will create skeleton directory that might be around 7GB in size. If you don't have enough disk space in /usr/share, use following commands to have cagefs-skeleton being placed in a different location:

$ mkdir /home/cagefs-skeleton
$ ln -s /home/cagefs-skeleton /usr/share/cagefs-skeleton

WARNING

If you are placing skeleton in /home directory on cPanel servers, you must configure the following option in cPanel WHM: WHM -> Server Configuration -> Basic cPanel/WHM Setup -> Basic Config -> Additional home directories
Change the value to blank (not default Home ). Without changing this option, cPanel will create new accounts in incorrect places.

CageFS will automatically detect and configure all necessary files for:

  • cPanel
  • Plesk
  • DirectAdmin
  • ISPmanager
  • Interworx
  • MySQL
  • PostgreSQL
  • LiteSpeed

Web interface to manage CageFS is available for cPanel, Plesk 10+, DirectAdmin, ISPmanager & Interworx. Command line tool would need to be used for other control panels.

Once you initialized the template you can start enabling users. By default CageFS is disabled for all users.

Starting from cagefs-6.1-27 fs.proc_can_see_other_uid will be migrated (one time) from /etc/sysctl.conf into /etc/sysctl.d/90-cloudlinux.conf . If this variable is not set in either file, it will default to 0.

It is strongly advised against setting this variable in 90-cloudlinux.conf. Define it in /etc/sysctl.conf or in some other config file with an index number greater than 90-cloudlinux.conf, e.g. /etc/sysctl.d/95-custom.conf.

You can find more information on fs.proc_can_see_other_uid automatic migration in Kernel Config Variables.

Note

You can also use CageFS CLI

Uninstalling

To uninstall CageFS, start by disabling and removing all directories:

$ /usr/sbin/cagefsctl --remove-all

That command will: disable CageFS for all customers, unmount CageFS for all users, removes /usr/share/cagefs-skeleton & /var/cagefs directories. It will not remove /etc/cagefs directory.

Remove CageFS RPM:

$ yum remove cagefs

Managing users

CageFS provides for two modes of operations:

  1. Enabled for all, except those that are disabled.
  2. Disabled for all, except those that are enabled.

Mode #1 is convenient for production operation, where you want all new users to automatically be added to CageFS. Mode #2 is convenient while you test CageFS, as it allows you to enable it on one by one for your customers.

To start using CageFS you have to select one of the mode of operations:

$ /usr/sbin/cagefsctl --enable-all
or
$ /usr/sbin/cagefsctl --disable-all
or
$ /usr/sbin/cagefsctl --toggle-mode
That will switch the operation mode, preserving current disabled/enabled users.

To enable individual user do:

$ /usr/sbin/cagefsctl --enable [username]
To disable individual user:
$ /usr/sbin/cagefsctl --disable [username]
To list all enabled users:
$ /usr/sbin/cagefsctl --list-enabled
To list all disabled users:
$ /usr/sbin/cagefsctl --list-disabled
To see current mode of operation:
$ /usr/sbin/cagefsctl --display-user-mode

Note

You can also use CageFS CLI

Configuration

File system templates

CageFS creates a filesystem template in /usr/share/cagefs-skeleton directory. CageFS template will be mounted for each customer.  The template is created by running:

# /usr/sbin/cagefsctl --init

To update the template, you should run:

$ /usr/sbin/cagefsctl --update

The behavior of the commands (and the files copied into /usr/share/cagefs-skeleton directory) depends on the configuration files in /etc/cagefs/conf.d
You can add additional files, users, groups and devices into CageFS template by adding .cfg file, and running:

$ /usr/sbin/cagefsctl --update

To delete files from CageFS template, remove corresponding .cfg file, and run:

$ /usr/sbin/cagefsctl --update

Here is an example openssh-clients.cfg file:

[openssh-clients]

comment=OpenSSH Clients

paths=/etc/ssh/ssh_config, /bin/hostname, /usr/bin/scp, /usr/bin/sftp, /usr/bin/slogin, /usr/bin/ssh, /usr/bin/ssh-add, /usr/bin/ssh-agent, /usr/bin/ssh-copy-id, /usr/bin/.ssh.hmac, /usr/bin/ssh-keyscan, /usr/libexec/openssh/sftp-server, /etc/environment, /etc/security/pam_env.conf

devices=/dev/ptmx

Example mail.cfg file:

[mail]

comment=Mail tools

paths=/bin/mail, /etc/aliases.db, /etc/mail, /etc/mailcap, /etc/mail.rc, /etc/mime.types, /etc/pam.d/smtp.sendmail, /etc/rc.d/init.d/sendmail, /etc/smrsh, /etc/sysconfig/sendmail, /usr/bin/hoststat, /usr/bin/Mail, /usr/bin/mailq.sendmail, /usr/bin/makemap, /usr/bin/newaliases.sendmail, /usr/bin/purgestat, /usr/bin/rmail.sendmail, /usr/lib64/sasl2/Sendmail.conf, /usr/lib/mail.help, /usr/lib/mail.tildehelp, /usr/lib/sendmail.sendmail, /usr/sbin/mailstats, /usr/sbin/makemap, /usr/sbin/praliases, /usr/sbin/sendmail.sendmail, /usr/sbin/smrsh, /var/log/mail, /var/spool/clientmqueue, /var/spool/mqueue

users=smmsp

groups=smmsp

There is an easy way to add/delete files from particular RPMs into CageFS. That can be done by using --addrpm and --delrpm options in cagefsctl . Like:

$ cagefsctl --addrpm ffmpeg
$ cagefsctl --update

Note

ffmpeg RPM should be installed on the system already.

Excluding files

To exclude files and directories from CageFS, edit file:
/etc/cagefs/custom.black.list
And add files or directories in there, one per line.

Execute the following command to apply changes:

cagefsctl --force-update

Please do not edit /etc/cagefs/black.list file because it is replaced during the update of CageFS package.

Excluding users

To exclude users from CageFS, create a file (any name would work) inside /etc/cagefs/exclude folder, and list users that you would like to exclude from CageFS in that file (each user in separate line).

Then execute the following command to apply changes:

cagefsctl --user-status USER

And check that the command shows Disabled.

Mount points

CageFS creates individual namespace for each user, making it impossible for users to see each other's files and creating high level of isolation. The way namespace is organized:

  1. /usr/share/cagefs-skeleton with safe files is created
  2. Any directory from the server that needs to be shared across all users is mounted into /usr/share/cagefs-skeleton (a list of such directories is defined in /etc/cagefs/cagefs.mp)
  3. /var/cagefs/[prefix]/username directory for each user. Prefix is defined as last two digits of user id. User id is taken from /etc/passwd file.
  4. Separate /etc directory is created and populated for each user inside /var/cagefs/[prefix]/username
  5. /tmp directory is mounted for each user separately into ~username/.cagefs-tmp directory
  6. Additional custom directories can be mounted for each user by defining them in /etc/cagefs/cagefs.mp
  7. You can define custom directories per user using virt.mp files [CageFS 5.1 and higher]

To define individual custom directories in /etc/cagefs/cagefs.mp following format is used:

@/full/path/to/directory,permission notation

This is useful when you need to give each user its own copy of a particular system directory, like:

@/var/run/screen,777

Such entry would create separate /var/run/screen for each user, with permissions set to 777

To modify mount points, edit /etc/cagefs/cagefs.mp. Here is an example of cagefs.mp:

/var/lib/mysql
/var/lib/dav
/var/www/cgi-bin
/var/spool
/dev/pts
/usr/local/apache/domlogs
/proc
/opt
@/var/spool/cron,700
@/var/run/screen,777

If you want to change mount points, make sure you re-initialize mount points for all customers:

$ cagefsctl --remount-all
This command will kill all current processes and reset mount points.

Per user virtual mount points

[CageFS 5.1 and higher]

  • Please, see Split by username feature, as it might be simpler to implement in some cases.

Starting with CageFS 5.1 you can specify additional directories to be mounted inside user's CageFS. This can be specified for each user. To specify virtual mount points for a user, create a file:

/var/cagefs/[prefix]/[user]/virt.mp

Inside that file, you can specify mount points in the following format:

virtdir1,mask
@subdir1,mask
@subdir2,mask
virdir2,mask
@subdir3,mask
@subdir4,mask
>virtdir3,mask
@subdir5,mask
@subdir6,mask
# comments
  • mask is always optional, if missing 0755 is used
  • Create virtual directory subdir/virtdir , mount it to:
    • skeleton jaildir/virtdir
    • inside virtual directory, create directories subdir1, subdir2
    • mount virtdir1/subdir1 to subdir/virtdir/subdir1
    • if virtdir is started with >, create directory subdir/virtdir , but don't mount it into jaildir . This is needed for cases when virtdir is inside home base dir.
  • if file /var/cagefs/[prefix]/[user]/virt.mp is missing -- no virt directories are loaded for that user.

Note that CageFS will automatically create those files for Plesk 10 & higher.

For example if we have Plesk 11.5 with two users cltest1, and cltest2:

cltest1 uid 10000 has domains: cltest1.com, cltest1-addon.com and sub1.cltest1.com
cltest2 uid 10001 has domains: cltest2.com, cltest2-addon.com

In such case we would have file /var/cagefs/00/cltest1/virt.mp :

>/var/www/vhosts/system,0755
@cltest1-addon.com,0755
@cltest1.com,0755
@sub1.cltest1.com,0755

and file: /var/cagefs/01/cltest2/virt.mp:

>/var/www/vhosts/system
@cltest2-addon.com
@cltest2.com

Split by username

[CageFS 5.3.1+]

Sometimes you might need to make sure that directory containing all users would show up as containing just that user inside CageFS. For example, if you have directory structure like:

/home/httpd/fcgi-bin/user1
/home/httpd/fcgi-bin/user2

Then we can add the following line to /etc/cagefs/cagefs.mp file:

%/home/httpd/fcgi-bin

and execute:

cagefsctl --remount-all

After that each subdirectory of /home/httpd/fcgi-bin will be mounted for appropriate user in CageFS: /home/httpd/fcgi-bin/user1 will be mounted for user1 and /home/httpd/fcgi-bin/user2 will be mounted for user2 .

Mounting user’s home directory inside CageFS

CageFS 6.1-1 (and later) has improved mounting user’s home directory that is applied for users with home directories like /home/user or /homeN/user (where N = 0,1,..9).

In such case, earlier versions of CageFS always mount user’s home directory to /home/user and create symlink /homeN -> /home when needed, so user’s home directory can be accessed both via /home/user and /homeN/user . This quirk leads to some rare incompatibilities between CageFS and other software (for example OpenCart), because real path of user’s home directory in CageFS and in real file system can differ.

New CageFS mounts user’s home directory in a way that its real path in CageFS is always the same as in real file system. Additionally, CageFS searches for symlinks like /homeX -> /homeY and /homeX/user -> /homeY/user in real system and creates such symlinks in user’s CageFS when found.

This new mounting mode is enabled by default. You can switch to old mounting mode by executing the following commands:

# touch /etc/cagefs/disable.home.dirs.search
# cagefsctl --force-update
# cagefsctl --remount-all

Note

New mounting mode will be disabled automatically when "mounting base home directory" mode is enabled (mount_basedir=1 setting in /etc/cagefs/cagefs.base.home.dirs file).

Base home directory

If you have a custom setup where home directories are in a special format, like: /home/$USERNAME/data , you can specify it using regular expressions. This is needed by CageFS to create safe home space for end user, where no other users are visible.

We will create empty: /var/cagefs/[prefix]/$USERNAME/home , and then mount /home/$USERNAME in that directory

To do that, create a file: /etc/cagefs/cagefs.base.home.dirs

With content like:

^/home/
^/var/www/users/

If there is no such file, the home directory without last component will be considered as a base dir, like with /home/$USERNAME we would create /var/cagefs/[prefix]/$USERNAME/home , and then mount /home/$USERNAME in there

With /home/$USERNAME/data as a home dir, we would assume that /home/$USERNAME is the base directory, and we would create /var/cagefs/[prefix]/$USERNAME/home/$USERNAME/data and then we would mount /home/$USERNAME/data -- which would cause each user to see empty base directories for other users, exposing user names.

Sharing home directory structure among users

When you want to share directory structure among multiple users, you can add following line at the top of the /etc/cagefs/cagefs.base.home.dirs file. This is useful on the systems that support sites with multiple users, with different home directories inside the main 'site' directory.

mount_basedir=1

For example:

user1 has home directory /var/www/vhosts/sitename.com/web_users/user1 user2 has home directory /var/www/vhosts/sitename.com/web_users/user2 site admin has home directory /var/www/vhosts/sitename.com

So, content of /etc/cagefs/cagefs.base.home.dirs should be the following:

mount_basedir=1
^/var/www/vhosts/[^/]+

Directory structure in /var/www/vhosts/sitename.com will be mounted in CageFS for appropriate users.
Each user will have access to whole directory structure in /var/www/vhosts/sitename.com (according to their permissions).

Note

You should execute cagefsctl --remount-all in order to apply changes to CageFS (i.e. remount home directories).

PostgreSQL support

CloudLinux 7:

CageFS works with any PostgreSQL version installed from CloudLinux or CentOS repositories. PostgreSQL packages for CloudLinux 7 come from the upstream (CentOS) unmodified. PostgreSQL’s socket is located in /var/run/postgresql directory. This directory is mounted to CageFS by default (in cagefs-5.5-6.34 or later).

When PostgreSQL has been installed after CageFS install, please add line:

/var/run/postgresql

/etc/cagefs/cagefs.mp file and then execute:

cagefsctl --remount-all 

The steps above are enough to configure CageFS to work with PostgreSQL.

CloudLinux 6:

CageFS provides separate /tmp directory for each end user. Yet, PostgreSQL keeps its Unix domain socket inside server's main /tmp directory. In addition to that, the location is hard coded inside PostgreSQL libraries.

To resolve the issue, CloudLinux provides a version of PostgreSQL with modified start up script that can store PostgreSQL's socket in /var/run/postgres. The script automatically creates link from /tmp to that socket to prevent PostgreSQL dependent applications from breaking.

In addition to that, CageFS knows how to correctly link this socket inside end user's /tmp directory.

To enable PostgreSQL support in CageFS:

  1. Make sure you have updated to latest version of PostgreSQL.

  2. Edit file /etc/sysconfig/postgres, and uncomment SOCK_DIR line.

  3. Update CageFS configuration by running:

cagefsctl  --reconfigure-cagefs
  1. Restart PostgreSQL by running:
$ service postgresql restart 

If you are using cPanel, you would also need to modify file: /etc/cron.daily/tmpwatch

And update line:

flags=-umc 

to:

flags=-umcl

to prevent symlink from being removed.

PAM configuration

CageFS depends on pam_lve module tor PAM enabled services. When installed, the module is automatically installed for following services:

  • sshd
  • crond
  • su

The following line is added to corresponding file in /etc/pam.d/:

session    required     pam_lve.so      100     1

Where 100 stands for minimum UID to put into CageFS & LVE , and 1 stands for CageFS enabled.

Filtering options for commands executed by proxyexec

You can disallow a user in CageFS to execute specific commands with some specific dangerous options via proxyexec.

To do so, you should create <command>.json file in the /etc/cagefs/filters directory and specify the names of options you want to disable.

For example, to disable some options of sendmail command, /etc/cagefs/filters/sendmail.json is created with the following content:

{
  "default": {
    "deny": [
      "-be",
      "-bem"
    ],
    "restrict_path": [
      "-C",
      "-D"
    ]
  },
  "/usr/sbin/sendmail": {
    "deny": [
      "-be",
      "-bem"
    ],
    "restrict_path": [
      "-C",
      "-D"
    ]
  },
  "/var/qmail/bin/sendmail": {
    "deny": [
      "-be",
      "-bem"
    ],
    "restrict_path": [
      "-C",
      "-D"
    ]
  },
  "/usr/sbin/sendmail.sendmail": {
    "deny": [
      "-be",
      "-bem"
    ],
    "restrict_path": [
      "-C",
      "-D"
    ]
  },
  "/usr/local/cpanel/bin/sendmail": {
    "deny": [
      "-be",
      "-bem"
    ],
    "restrict_path": [
      "-C",
      "-D"
    ]
  }
}

You can specify options for different paths separately (for example, /usr/sbin/sendmail or /var/qmail/bin/sendmail).

If the path to the program being executed does not match any path specified in the config file, then default parameters are used.

  • deny list should contain options that should be disallowed for use by users (the black list of options, all other options will be allowed).
  • You can specify the white list of options in the allow list (all other options will be denied).
  • You cannot specify both white and black list (allow and deny).

It is possible to verify that a path specified as a parameter for an option does not refer outside of the user’s home directory. This check is performed for options specified in the restrict_path list. All issues are reported in /var/log/secure log file.

Executing by proxy

Some software has to run outside CageFS to be able to complete its job. This includes such programs as passwd, sendmail, etc.

CloudLinux uses proxyexec technology to accomplish this goal. You can define any program to run outside CageFS, by specifying it in /etc/cagefs/custom.proxy.commands file. Do not edit existing /etc/cagefs/proxy.commands as it will be overwritten with next CageFS update.

Once program is defined, run this command to populate the skeleton:

$ cagefsctl --update

All the cPanel scripts located in /usr/local/cpanel/cgi-sys/ that user might need to execute should be added to proxy.commands.

The syntax of /etc/cagefs/*.proxy.commands files is as follows:
ALIAS:wrapper_name=username:path_to_executable

Mandatory parameters are ALIAS and path_to_executable.

  • ALIAS - any name which is unique within all /etc/cagefs/*.proxy.commands files;

  • wrapper_name - the name of wrapper file, which is used as a replacement for executable file path_to_executable_ inside CageFS. Wrapper files are located in /usr/share/cagefs/safeprograms. If wrapper name is not specified, then default wrapper /usr/share/cagefs/safeprograms/cagefs.proxy.program is used. Also, a reserved word noproceed can be used, it will intend that wrapper is not in use (installed before) - applied for the commands with several ALIAS, as in the example below.

  • username - the name of a user on whose behalf path_to_executable will run in the real system. If username is not specified, then path_to_executable will run on behalf the same user that is inside CageFS.

  • path_to_executable - the path to executable file which will run via proxyexec.

Example of a simple command executed via proxyexec:

SENDMAIL=/usr/sbin/sendmail

Example of crontab command execution with custom wrapper under root (privilege escalation). The command uses two ALIAS , that is why in the second line noproceed is specified instead of wrapper name.

CRONTAB_LIST:cagefs.proxy.crontab=root:/usr/bin/crontab
CRONTAB_SAVE:noproceed=root:/usr/bin/crontab

Users with duplicate UIDs

Sometimes hosters may have users with non unique UIDs. Thus, proxyexec may traverse users directory to find a specific one. That behavior turns into inappropriate if users directory is not cached locally (for example LDAP is in use).

To turn this feature off:

touch /etc/cagefs/proxy.disable.duid

Or to activate it back:

rm /etc/cagefs/proxy.disable.duid

Custom /etc files per customer

[4.0-5 and later]

To create a custom file in /etc directory for end user, create a directory:
/etc/cagefs/custom.etc/[username]

Put all custom files, and sub-directories into that direcotry.

For example, if you want to create custom /etc/hosts file for USER1 , create a directory:
/etc/cagefs/custom.etc/USER1

Inside that directory, create a hosts file, with the content for that user.

After that execute:

$ cagefsctl --update-etc USER1

If you are making changes for multiple users, you can run:

$ cagefsctl --update-etc

To remove a custom file, remove it from /etc/cagefs/custom.etc/[USER] directory, and re-run:

$ cagefsctl --update-etc

Moving cagefs-skeleton directory

Sometimes you might need to move cagefs-skeleton from /usr/share to another partition.

There are two ways:

  1. If /usr/share/cagefs-skeleton is not created yet ( cagefsctl --init wasn't executed), then execute:
$ mkdir /home/cagefs-skeleton 
$ ln -s /home/cagefs-skeleton /usr/share/cagefs-skeleton 
$ cagefsctl --init
  1. If /usr/share/cagefs-skeleton already exists:
$ cagefsctl --disable-cagefs 
$ cagefsctl --unmount-all
# To ensure that the following command prints empty output: 
$ cat /proc/mounts | grep cagefs 
# if you see any cagefs entries, execute "cagefsctl --unmount-all" again.
$ mv /usr/share/cagefs-skeleton /home/cagefs-skeleton 
$ ln -s /home/cagefs-skeleton /usr/share/cagefs-skeleton
$ cagefsctl --enable-cagefs

On cPanel servers, if you place skeleton into /home directory, then you should configure the following option:

In cPanel WHM choose Server Configuration and go to Basic cPanel/WHM Setup , then in Basic Config change Additional home directories default value to blank (not "home" ).

Note

If this option is not set, then cPanel will create new accounts in incorrect places.

Moving /var/cagefs directory

To move /var/cagefs to another location:

$ cagefsctl --disable-cagefs
$ cagefsctl --unmount-all

Verify that /var/cagefs.bak directory does not exist (if it exists - change name "cagefs.bak" to something else)

$ cp -rp /var/cagefs /new/path/cagefs
$ mv /var/cagefs /var/cagefs.bak
$ ln -s /new/path/cagefs /var/cagefs
$ cagefsctl --enable-cagefs
$ cagefsctl --remount-all

Verify that the following command gives empty output:

$ cat /proc/mounts | grep cagefs.bak

Then you can safely remove /var/cagefs.bak:

$ rm -rf /var/cagefs.bak

TMP directories

CageFS makes sure that each user has his own /tmp directory, and that directory is the part of end-user's quota.

The actual location of the directory is $USER_HOME/.cagefs/tmp

Once a day, using cron job, CageFS will clean up user's /tmp directory from all the files that haven't been accessed during 30 days.

This can be changed by running:

$ cagefsctl --set-tmpwatch='/usr/sbin/tmpwatch -umclq 720'

Where 720 is the number of hours that the file had to be inaccessible to be removed.

By default this is done at 03:37 AM, but you can also force the clean up outdated files that match 'chosen period' of all user's /tmp directories without waiting for a job to be launched by cronjob . Just run:

$ cagefsctl --tmpwatch

The following path will be cleaned as well:

/var/cache/php-eaccelerator (actual location $USER_HOME/.cagefs/var/cache/php-eaccelerator )

You can configure tmpwatch to clean custom directories inside CageFS .

Create /etc/cagefs/cagefs.ini configuration file and specify tmpwatch_dirs directive as follows:

tmpwatch_dirs=/dir1,/dir2

After that directories /dir1 and /dir2 inside CageFS  will be cleaned automatically.

Note that actual location of those directories in real file system is $USER_HOME/.cagefs/dir1 and $USER_HOME/.cagefs/dir2 .

Cleanup PHP sessions

For cPanel servers, CageFS version 6.0-42 or higher performs cleaning of PHP sessions based on session.gc_maxlifetime and session.save_path directives specified in proper php.ini files.

session.gc_maxlifetime directive default value is 1440 seconds. Those session files will be deleted, that were created or had metadata (ctime) changes more time ago than it is specified in session.gc_maxlifetime .

For Alt-PHP versions session.save_path value is normally /tmp .

Note

For new installations of Alt-PHP packages, session.save_path will be changed from /tmp to /opt/alt/phpNN/var/lib/php/session, where NN corresponds to Alt-PHP version.

This applies to the following Alt-PHP versions (or later):

  • alt-php44-4.4.9-71;
  • alt-php51-5.1.6-81;
  • alt-php52-5.2.17-107;
  • alt-php53-5.3.29-59;
  • alt-php54-5.4.45-42;
  • alt-php55-5.5.38-24;
  • alt-php56-5.6.31-7;
  • alt-php70-7.0.23-5;
  • alt-php71-7.1.9-5;
  • alt-php72-7.2.0-0.rc.2.2.

When using EasyApache 3, session.save_path value is normally /var/cpanel/php/sessions/ea3 or /tmp . Seettings for EasyApache 3 are usualy taken from the file /usr/local/lib/php.ini .

When using EasyApache 4, session.save_path value is normally /var/cpanel/php/sessions/ea-phpXX , where XX corresponds to PHP version.

Cleaning is started by cron /etc/cron.d/cpanel_php_sessions_cron , which starts the script /usr/share/cagefs/clean_user_php_sessions twice within one hour.

The settings for ea-php are located in /opt/cpanel/ea-phpXX/root/etc/php.d/local.ini or in /opt/cpanel/ea-phpXX/root/etc/php.ini , where XX corresponds to the PHP version.

The settings for alt-php are located in /opt/alt/phpXX/etc/php.ini files, where XX corresponds to PHP version.

The cleaning script cleans php sessions for all PHP versions ( ea-php and alt-php ) regardless of whether a version is used or selected via MultiPHP Manager or PHP Selector . When different session.gc_maxlifetime values are specified for the same session.save_path (for different php versions), the cleaning script will use the least value for cleaning session.save_path . So, it is recommended to specify different session.save_path for each PHP version.

Users can define custom value of session.gc_maxlifetime via PHP Selector in order to configure PHP's garbage collector, but that will not affect the script for cleaning PHP sessions. The script cleans PHP sessions based on global values of session.gc_maxlifetime and session.save_path directives taken from files mentioned above. Settings in custom users’ php.ini files are ignored.

Cleanup PHP session files in Plesk

For Plesk servers, CageFS version 6.0-52 or higher is provided with a special cron job for removing obsolete PHP session files. Cleanup script runs once an hour (similar to how it is done in Plesk).

Each time the script runs, it performs the cleanup of the paths:

  1. set by session.save_path directive in /opt/alt/phpXX/etc/php.ini files. If session.save_path is missing, then /tmp is used. Session files lifetime is set by session.gc_maxlifetime directive. If it is not found, then 1440 seconds value is used (24 minutes, as in Plesk). Lifetime set in the file is only taken into consideration if it is longer than 1440 seconds, otherwise 1440 seconds is used. All the installed Alt-PHP versions are processed.

  2. /var/lib/php/session . Files lifetime is only defined by Plesk script /usr/lib64/plesk-9.0/maxlifetime . If the script is missing or returns errors, then this directory is not processed.

The following features are applied during the cleanup:

  • all the users with UID higher than specified in /etc/login.defs are processed. Each user is processed independently from one another.
  • only directories inside CageFS are being cleaned. The paths of the same name in the physical  file system are not processed.
  • in all the detected directories, all the files with the names that correspond to sess_ search mask are removed, the rest of the files are ignored.
  • the files older than specified lifetime are removed.
  • all non-fatal errors (lack of rights, missing directory) are ignored and do not affect the further work of the script.

Disable PHP sessions cleanup on cPanel and Plesk

Here is a possible workaround for PHP session expiration problem (session lives longer than it is possible in a control panel). To use your own custom PHP sessions cleanup scripts - you can turn off built-in sessions cleanup implementation in the following way: add clean_user_php_sessions=false line to /etc/sysconfig/cloudlinux .

Syslog

By default, /dev/log should be available inside end user's CageFS . This is needed so that user's cronjobs and other things that user dev/log would get recorded in the system log files.

This is controlled using file /etc/rsyslog.d/schroot.conf with the following content:

$AddUnixListenSocket /usr/share/cagefs-skeleton/dev/log

To remove presence of dev/log inside CageFS, remove that file, and restart rsyslog service.

Excluding mount points

How to exclude mounts from namespaces for all LVEs

By default, all mounts from the real file system is inherited by namespaces of all LVEs . So, destroying all LVEs may be required in order to unmount some mount in real file system completely. Otherwise, mount point remains busy after unmounting it in the real file system because this mount exists in namespaces of LVEs .

lvectl start command saves all mounts from real file system as “default namespace” for later use in all LVEs . lve_namespaces service executes lvectl start command during startup.

In lve-utils-2.0-26 (and later) there is an ability to exclude specific mounts from namespaces for all LVEs . In order to do so, please create a file /etc/container/exclude_mounts.conf with list of mounts to exclude (one mount per line) as regular expressions, and then execute lvectl start :

# cat /etc/container/exclude_mounts.conf    
^/dir1/
^/dir2$
# lvectl start

After that, all new created LVEs will be without /dir2 mount and without mounts that start with /dir1/ (like /dir1/x , /dir1/x/y , etc). To apply changes to existing LVEs you should recreate LVEs :

# lvectl destroy all   
# lvectl apply all

Note

You should recreate all LVEs only once after creating /etc/container/exclude_mounts.conf file. After that the configuration changes will be applied to all new LVEs automatically.

Shared memory (/dev/shm) isolation in CageFS

Note

Requires cagefs-6.2.1-1 or later

The /dev/shm in a real file system directory is “world-writable”. This directory from the real file system is mounted to CageFS by default, so /dev/shm directory is common for all users by default. However, it is possible to improve security and isolate /dev/shm (shared memory) for each user in CageFS.

To enable /dev/shm isolation, do the following steps:

  1. Delete /dev/shm line from the /etc/cagefs/cagefs.mp file
sed -i -e '/^\/dev\/shm/d' /etc/cagefs/cagefs.mp
  1. Create a configuration file with mount options for shared memory
echo 'mode=0777' > /etc/cagefs/dev.shm.options
  1. Remount CageFS to apply changes
cagefsctl --remount-all

You can also specify additional mount options.

For example, you can specify the size of shared memory in megabytes:

echo 'mode=0777,size=1m' > /etc/cagefs/dev.shm.options
cagefsctl --remount-all

Or you can specify the size of user’s physical memory limit (PMEM) in percentage:

echo 'mode=0777,size=50%' > /etc/cagefs/dev.shm.options
cagefsctl --remount-all

To disable /dev/shm isolation, do the following steps:

  1. Delete configuration file
rm -f /etc/cagefs/dev.shm.options
  1. Validate /etc/cagefs/cagefs.mp file
cagefsctl --check-mp
  1. Add /dev/shm line to /etc/cagefs/cagefs.mp file
echo '/dev/shm' >> /etc/cagefs/cagefs.mp
  1. Remount CageFS to apply changes
cagefsctl --remount-all

Note

you should specify mode=0777. It is required for the proper operation of shared memory inside CageFS. This is not a security issue because the /dev/shm directory is isolated for each user and visible inside a user’s CageFS only.

Note

/dev/shm is mounted with nosuid,nodev,noexec mount options always (both in “isolated /dev/shm” mode and not). You cannot change this behavior.

Note

“isolated /dev/shm” mode will become the default in the future CageFS releases.

Note

when the size of the /dev/shm is specified in percentage of user’s physical memory limit (PMEM), you should remount CageFS after changing PMEM limit in order to change the size of shared memory allocated for the /dev/shm in user’s CageFS. To do so, execute cagefsctl --remount-all

Integration with control panels

CageFS comes with a plugin for various control panels.

The plugin allows to:

  • Initialize CageFS;

  • Select mode of operation;

  • See and modify the list of enabled/disabled users;

  • Update CageFS skeleton.

cPanel

CageFS plugin for cPanel is located in Plugins section of WHM.

It allows to initialize CageFS, select users CageFS will be enabled for, as well as update CageFS skeleton.

To enable CageFS for a proper user (users), in CageFS User Manager choose a user from the list on the right ( Disabled users) and click Toggle . The user will move to the list on the left ( Enabled users).

To disable a user (users), choose a user from the list on the left ( Enabled users) and click Disable CageFS . The user will move to the list on the right ( Disabled users).

To update CageFS skeleton, click Update CageFS Skeleton .

Plesk

CageFS comes with a plugin for Plesk 10.x. It allows initializing and updating CageFS template, as well as managing users and mode of operation for CageFS.

In modules section choose CageFS:

To enable CageFS for a proper user (users), in CageFS User Manager choose a user from the list on the right ( Disabled users) and click Toggle . The user will move to the list on the left ( Enabled users).

To disable a user (users), choose a user from the list on the left ( Enabled users) and click Disable CageFS . The user will move to the list on the right ( Disabled users).

To update CageFS skeleton, click Update CageFS Skeleton .

ISPManager

CageFS comes with plugin for ISP Manager to enable/disable CageFS on per user base. In edit user section chose Permission tab. Mark CageFS User Mode checkbox and click OK to apply.

Or you can manage global CageFS settings via CageFS menu

See also CageFS CLI tools.

MySQL Governor

General information and requirements

Note

MySQL Governor 0.8-32+

MySQL Governor is software to monitor and restrict MySQL usage in shared hosting environment. The monitoring is done via resource usage statistics per each MySQL thread.

MySQL Governor can also kill off slow SELECT queries.

MySQL Governor has multiple modes of operations, depending on the configuration. It can work in monitor-only mode, or it can use different throttling scenarious.

MySQL Governor allows to restrict customers who use too much resources. It supports following limits:

CPU % CPU speed relative to one core. 150% would mean one and a half cores
READ bytes bytes read. Cached reads are not counted, only those that were actually read from disk will be counted
WRITE bytes bytes written. Cached writes are not counted, only once data is written to disk, it is counted

You can set different limits for different periods: current, short, med, long. By default those periods are defined as 1 second, 5 seconds, 1 minute and 5 minutes. They can be re-defined using configuration file. The idea is to use larger acceptable values for shorter periods. Like you could allow a customer to use two cores (200%) for one second, but only 1 core (on average) for 1 minute, and only 70% within 5 minutes. That would make sure that customer can burst for short periods of time.

When customer is restricted, the customer will be placed into special LVE with ID 3. All restricted customers will be placed into that LVE, and you can control amount of resources available to restricted customers. Restricted customers will also be limited to only 30 concurrent connections. This is done so they wouldn't use up all the MySQL connections to the server.

Installation and update

Installation

IMPORTANT

Please make full database backup (including system tables) before you upgrade MySQL or switch to MariaDB. This action will prevent data loss in case if something goes wrong.

MySQL Governor is compatible only with MySQL 5.x, 8.0; MariaDB & Percona Server 5.6.

To install MySQL Governor on your server install governor-mysql package at first:

$ yum remove db-governor db-governor-mysql  # you can ignore errors if you don't have those packages installed
$ yum install governor-mysql

Then configure MySQL Governor properly.

The installation is currently supported only on cPanel, Plesk, DirectAdmin, ISPmanager, InterWorx , as well as on servers without control panel.

If you are installing CloudLinux on a server running MySQL already, set your current MySQL version before calling installation script:

$ /usr/share/lve/dbgovernor/mysqlgovernor.py --mysql-version=mysqlXX
$ /usr/share/lve/dbgovernor/mysqlgovernor.py --install

Please make sure to specify your current MySQL version instead of XX as follows:

  • 55 — MySQL v5.5
  • 56 — MySQL v5.6
  • 57 — MySQL v5.7
  • 80 — MySQL v8.0 [requires MySQL Governor 1.2-37+; database packages are available in Beta only, so, please use --install-beta flag instead of --install ]

If you are installing CloudLinux on a server running MariaDB already, do instead:

$ /usr/share/lve/dbgovernor/mysqlgovernor.py --mysql-version=mariadbXX
$ /usr/share/lve/dbgovernor/mysqlgovernor.py --install

Please make sure to specify your current MariaDB version instead of XX as follows:

  • 55 — MariaDB v5.5
  • 100 — MariaDB v10.0
  • 101 — MariaDB v10.1
  • 102 — MariaDB v10.2
  • 103 — MariaDB v10.3 [requires MySQL Governor 1.2-36+; for cPanel - MySQL Governor 1.2-41+]

Installation for Percona Server 5.6 [requires MySQL Governor 1.1-22+ or 1.2-21+]:

$ /usr/share/lve/dbgovernor/mysqlgovernor.py --mysql-version=percona56
$ /usr/share/lve/dbgovernor/mysqlgovernor.py --install

Please note that MySQL/MariaDB/Percona will be updated from CloudLinux repositories.

If you are installing MySQL Governor on a server without MySQL at all, you have an opportunity to choose desired MySQL version to be installed with MySQL Governor installation script. Use --mysql-version flag before calling the installation script:

$ /usr/share/lve/dbgovernor/mysqlgovernor.py --mysql-version=MYSQL_VERSION
$ /usr/share/lve/dbgovernor/mysqlgovernor.py --install

MYSQL_VERSION could be chosen from the list of versions currently supported by MySQL Governor :

mysql51 MySQL v5.1
mysql55 MySQL v5.5
mysql56 MySQL v5.6
mysql57 MySQL v5.7
mysql80 MySQL v8.0 [requires MySQL Governor 1.2-37+; database packages available in beta only, so use --install-beta flag instead of --install]
mariadb55 MariaDB v5.5
mariadb100 MariaDB v10.0
mariadb101 MariaDB v10.1
mariadb102 MariaDB v 10.2
mariadb103 MariaDB v 10.3 [requires MySQL Governor 1.2-36+; for cPanel - MySQL Governor 1.2-41+]
percona56 Percona Server v 5.6

Generally, stable and beta channels contain different version of MySQL packages - beta contains newer version than stable or the same one. If you would like to install beta packages, use --install-beta flag instead of --install when calling installation script:

$ /usr/share/lve/dbgovernor/mysqlgovernor.py --install-beta

Starting with MySQL Governor version 1.2 when installing MySQL/MariaDB MySQL Governor asks for a confirmation of a database version to be installed. To avoid such behavior for the automatic installations, please use --yes flag.

For example:

$ /usr/share/lve/dbgovernor/mysqlgovernor.py --install --yes

Please note that restore of previous packages in case of failed installation would also be confirmed with --yes flag.

IMPORTANT

Use --yes flag on your own risk, because it confirms installation in any case - even in case if there are troubles during installation (for example, network problems causing incomplete download of packages), everything would be confirmed.

Note

See also MySQL Governor CLI

Upgrading database server

In order to change MySQL version you should run the following commands:

$ /usr/share/lve/dbgovernor/mysqlgovernor.py --mysql-version=MYSQL_VERSION
$ /usr/share/lve/dbgovernor/mysqlgovernor.py --install

where MYSQL_VERSION is the target database server version that should be replaced with the value from the table above.

IMPORTANT

Make sure you have full database backup (including system tables) before you switch. This action will prevent data loss in case if something goes wrong.

Uninstalling

To remove MySQL Governor:

$ /usr/share/lve/dbgovernor/mysqlgovernor.py --delete

The script will install original MySQL server, and remove MySQL Governor.

Configuration and operation

Configuration

MySQL Governor configuration is located in /etc/container/mysql-governor.xml

It is best to modify it using dbctl tool.

Once configuration file is updated, please, restart the MySQL Governor using:

$ service db_governor restart
Example configuration:
<governor> 

<!--  'off' - do not throttle anything, monitoring only -->
<!--  'abusers' - when user reaches the limit, put user's queries into LVE for that user -->
<!--  'all' - user's queries always run inside LVE for that user -->
<!--  'single' - single LVE=3 for all abusers. -->
<!-- 'on' - deprecated (old restriction type) -->
<!-- To change resource usage of restricted user in LVE mode use command /usr/sbin/lvectl set 3 --cpu=<new value> --ncpu=<new value> --io=<new value> --save-all-parameters -->
<lve use="on|single|off|abusers|all"/> 

<!-- connection information -->
<!-- If host, login and password are not present, this information is taken from /etc/my.cnf and ~root/.my.cnf -->
<!-- Use symbol specified in prefix to figure out hosting accounts (mysql username will be split using prefix_separator, and first part will be used as account name). If prefix is not set, or empty -- don’t use prefixes/accounts --> 

<!-- db governor will try to split MySQL user names using prefix separator (if present)and statistics will be aggregated for the prefix (account name) -->
<connector host="..." login="..." password=".." prefix_separator="_"/> 

<!-- Intervals define historical intervals for burstable limits. In seconds -->
<intervals short="5" mid="60" long="300"/> 

<!-- log all errors/debug info into this log -->
<log file=”/var/log/dbgovernor-error.log” mode=”DEBUG|ERROR”/> 

<!-- s -- seconds, m -- minutes, h -- hours, d -- days -->
<!-- on restart, restrict will disappear -->
<!-- log file will contain information about all restrictions that were take -->
<!-- timeout - penalty period when user not restricted, but if he hit his limit during this period he will be restricted with higher level of restrict (for more long time) -->
<!- level1, level2, level3, level4 - period of restriction user for different level of restriction. During this period all user's requests will be placed into LVE container -->

<!-- if user hits any of the limits during period of time specified in timeout, higher level of restrict will be used to restrict user. If user was already on level4, level4 will be applied again -->
<!-- attribute format set an restrict log format:
SHORT -  restrict info only
MEDIUM - restrict info, _all_tracked_values_
LONG - restrict info, _all_tracked_values_, load average and vmstat info
VERYLONG - restrict info, _all_tracked_values_, load average and vmstat info, slow query info -->
<!-- script -- path to script to be triggered when account is restricted -->
<!-- user_max_connections - The number of simultaneous connections of blocked user (in LVE mode) --> 

<!-- restriction levels/format are deprecated -->
<restrict level1="60s" level2="15m" level3="1h" level4="1d" timeout="1h"
log="/var/log/dbgovernor-restrict.log" format="SHORT|MEDIUM|LONG|VERYLONG"
script="/path/to/script"
user_max_connections="30"/> 

<!-- period (deprecated) - period based restriction that has multiple levels (see above) -->
<!-- limit (by default) - when user hits limits, the account will be marked as restricted and if user does not hit  limit again during "unlimit=1m" account will be unrestricted. This mode doesn't have any additional levels/penalties. -->
<restrict_mode use="period|limit" unlimit="1m"/>

<!-- killing slow SELECT queries (no other queries will be killed) -->
<!-- if "log" attribute was set all killed queries will be saved in log file -->
<!-- slow parameter in the <limit name="slow" current="30"/> will no be applied without enabling slow_queries --> 
<slow_queries run="on|off" log="/var/log/dbgovernor-kill.log"/> 
<!-- Enable or disable saving of statistics for lve-stats - On - enabled, Off-disabled -->
<statistic mode="on|off"></statistic>
<!-- Enable logging user queries on restrict, can be On or Off -->
<!-- Files are saved in /var/lve/dbgovernor-store and being kept here during 10 days -->
<logqueries use="on|off"></logqueries>
<default>
<!-- -1 not use limit(by default, current - required) -->
<limit name="cpu" current="150" short="100" mid="90" long="65"/>
<limit name="read" current="100000000" short="90000000" mid="80000000" long="70000000"/>
<limit name="write" current="100000000" short="90000000" mid="80000000" long="70000000"/>
<!-- Time to kill slow SELECT queries for account, can be different for accounts in seconds(but unit can be specified) -->
<!-- enabled only when slow_queries run="on" -->
<!-- s -- seconds, m -- minutes, h -- hours, d -- days -->
<limit name="slow" current="30"/>
</default>
<!-- name will matched account name, as extracted via prefix extraction --> 

<!-- mysql_name will match exact MySQL user name. If both name and mysql_name are present, system will produce error -->
<!-- mode restrict -- default mode, enforcing restrictions -->
<!-- mode norestrict -- track usage, but don’t restrict user --> 
<!-- mode ignore -- don’t track and don’t restrict user -->
<user name=”xxx” mysql_name=”xxx” mode=”restrict|norestrict|ignore”>
<limit...>
</user> 

<!-- debug mode for particular user. The information logged to restrict log. -->
<debug_user name="xxx"/> 

</governor>

These values can also be set using cloudlinux-config CLI utility

Modes of operation

Note

MySQL Governor 1.0+

MySQL Governor has multiple modes of operation. Some of them are experimental at this moment.
Mode:
off -- Monitor Only : In this mode MySQL Governor will not throttle customer's queries, instead it will let you monitor the MySQL usage to see the abusers at any given moment in time (and historically). This mode is good when you are just starting and want to see what is going on
single -- Single restricted's LVE for all restricted customers (deprecated) : In that mode once customer reaches the limits specified in the MySQL Governor , all customer's queries will be running inside LVE with id 3. This means that when you have 5 customers restricted at the same time, all queries for all those 5 customers will be sharing the same LVE. The larger the number of restricted customers - the less resources per restricted customer will be available
abusers - Use LVE for a user to restrict queries (default mode) : In that mode, once user goes over the limits specified in the MySQL Governor , all customer's queries will execute inside that user's LVE. We believe this mode will help with the condition when the site is still fast, but MySQL is slow (restricted) for that user. If someone abuses MySQL, it will cause queries to share LVE with PHP processes, and PHP processes will also be throttled, causing fewer new queries being sent to MySQL. Requires dbuser-map file
all - Always run queries inside user's LVE : This way there is no need for separate limits for MySQL. Depending on overhead we see in the future, we might decide to use it as a primary way of operating MySQL Governor . The benefit of this approach is that limits are applied to both PHP & MySQL at the same time, all the time, preventing any spikes whatsoever. Requires dbuser-map file

If dbuser-map file is absent on the server, " abusers " mode emulates " single ".

With single and abusers mode, once user is restricted, the queries for that user will be limited as long as user is using more than limits specified. After a minute that user is using less, we will unrestricted that user.

You can specify modes of operation using dbctl or by changing configuration file. dbuser-map file is located in /etc/container/dbuser-map.

Starting and stopping

To start:

$ service db_governor start

To stop:

$ service db_governor stop

Mapping a user to a database

[ MySQL Governor 1.x]

Traditionally MySQL Governor used prefixes to map user to database. With the latest version, we automatically generate user -> database user mapping for cPanel , Plesk and DirectAdmin control panels.

The mapping file is located in: /etc/container/dbuser-map

The format of the file:

[dbuser_name1] [account_name1] [UID1]
...
[dbuser_nameN] [account_nameN] [UIDN]
For example:
pupkinas_u2 pupkinas 502
pupkinas_u1 pupkinas 502
pupkinas_u3 pupkinas 502
pupkin2a_uuu1 pupkin2a 505
pupkin10_p10 pupkin10 513
pupkin5a_u1 pupkin5a 508
pupkin3a_qq1 pupkin3a 506
pupkin3a_test22 pupkin3a 506
pupkin3a_12 pupkin3a 506

This would specify that db users: pupkinas_us2, pupkinas_u1, pupkinas_u3 belong to user pupkinas with uid (lve id) 502 db user pupkin2a_uuu1 belongs to user pupkin2a with uid 505, etc...

This file is checked for modifications every 5 minutes.

If you need to force reload of that file, run:

service db_governor restart

Log files

Error_log

MySQL Governor error log is used to track any problems that MySQL Governor might have

Restrict_log

Restrict log is located in /var/log/dbgovernor-restrict.log

Restrictions:

_timestamp_ _username_ LIMIT_ENFORCED _limit_setting_ __current_value_                         _restrict_level__ SERVER_LOAD TRACKED_VALUES_DUMP
 ... 
  • TRACKED_VALUES_DUMP=busy_time:xx,cpu_time:xx,...
  • SERVER_LOAD = load averages followed by output of vmstat
  • TRACKED_VALUES_DUMP is available with MEDIUM & LONG format
  • SERVER_LOAD is available with LONG format

Change MySQL version

If you would like to change to a different MySQL version, or switch to MariaDB you have to start by backing up existing databases.

Note

For experienced users only. Changing MySQL version is a quite complicated procedure, it causes system table structural changes which can lead to unexpected results. Think twice before proceeding.

IMPORTANT

Please make full database backup (including system tables) before you will do upgrade of MySQL or switch to MariaDB. This action will prevent data losing in case if something goes wrong.

$ /usr/share/lve/dbgovernor/mysqlgovernor.py --mysql-version=MYSQL_VERSION
$ /usr/share/lve/dbgovernor/mysqlgovernor.py --install
  • If you are using cPanel or DirectAdmin - recompile Apache .

To install beta version of MySQL:

$ /usr/share/lve/dbgovernor/mysqlgovernor.py --install-beta

MYSQL_VERSION can be one of the following:

auto default version of MySQL for given OS release (or cPanel settings)
mysql50 MySQL v5.0
mysql51 MySQL v5.1
mysql55 MySQL v5.5
mysql56 MySQL v5.6
mysql57 MySQL v5.7
mysql80 MySQL v8.0 [requires MySQL Governor 1.2-37+; database packages are available in Beta only, so, please use --install-beta flag instead of --install ]
mariadb55 MariaDB v5.5
mariadb100 MariaDB v10.0
mariadb101 MariaDB v10.1
mariadb102 MariaDB v 10.2
mariadb103 MariaDB v 10.3 [requires MySQL Governor 1.2-36+; for cPanel - MySQL Governor 1.2-41+ ]
percona56 Percona v 5.6
  • We don't recommend to downgrade from MySQL v5.6, MariaDB 10.x

Note

Starting from cPanel & WHM version 70, cPanel supports MySQL 5.7: https://blog.cpanel.com/being-a-good-open-source-community-member-why-we-hesitated-on-mysql-5-7/

Note

Starting from cPanel & WHM version 78, cPanel supports MariaDB 10.3: https://documentation.cpanel.net/display/78Docs/MySQL+or+MariaDB+Upgrade

Note

cPanel does not officially support MySQL 8.0, that is why we don’t recommend to use it on cPanel servers. Use on your own risk for DirectAdmin and Plesk servers, because downgrade can corrupt your databases.

Note

See also MySQL Governor CLI

Backing up MySQL

On cPanel server disable MySQL service monitoring before doing the job:

$ whmapi1 configureservice service=mysql enabled=1 monitored=0

Execute as root :

$ mkdir -p ~/mysqlbkp
$ service mysql restart --skip-networking --skip-grant-tables
$ mysql_upgrade
$ mysqldump --all-databases --routines --triggers > ~/mysqlbkp/dbcopy.sql
$ service mysql stop
$ cp -r /var/lib/mysql/mysql ~/mysqlbkp/
$ service mysql start

On cPanel server enable monitoring back:

$ whmapi1 configureservice service=mysql enabled=1 monitored=1

Note

This operation may take some time.

abrt plugin

We have created a plugin for abrt tool to automatically upload core dumps in case MySQL Governor crashes.

To install the plugin:

$ yum install cl-abrt-plugin --enablerepo=cloudlinux-updates-testing

It will monitor crash reports for /usr/sbin/db_governor, /usr/sbin/dbtop and /usr/sbin/dbctl

You can modify /etc/libreport/plugins/dropbox.conf to monitor other software as well by adding them to AppList.

AppLists=/usr/sbin/db_governor,/usr/sbin/dbtop,/usr/sbin/dbctl

See also MySQL Governor CLI tools.

Troubleshooting

MariaDB 5.5 and MariaDB 10.0: How to set LimitNOFILE correctly for systemd.

MariaDB 5.5 and MariaDB 10.0 have only file for managing the service, but the file has LSB functions, so it is supported by systemd .

For adding extra limits, do the following:

  1. Run:
mkdir /etc/systemd/system/mariadb.service.d/
  1. Run:
touch /etc/systemd/system/mariadb.service.d/limits.conf
  1. Add the following content to the the file /etc/systemd/system/mariadb.service.d/limits.conf :
[Service] 
LimitNOFILE=99999

MySQL Governor lost connection to MySQL - “Can't connect to mysql” messages in /var/log/dbgovernor-error.log (Plesk and DirectAdmin)

This may be caused by changing root/administrator credentials without updating MySQL Governor configuration file.

When you change root or administrator credentials in Plesk or DirectAdmin, you also need to update MySQL Governor configuration file. This could be done with the following command (available since governor-mysql 1.2-38):

/usr/share/lve/dbgovernor/mysqlgovernor.py --update-config-auth

The command updates credentials in MySQL Governor configuration file and restarts db_governor service afterwards.

After applying the command MySQL Governor successfully connects to MySQL.

PHP Selector

General information and requirements

Note

To PHP Selector proper operation, make sure you have installed and configured mod_suexec package. You can find installation instruction here.

PHP Selector is a CloudLinux component that sits on top of CageFS. It allows each user to select PHP version and module based on their needs. PHP Selector requires account to have CageFS enabled to work.

PHP Selector is compatible with the following technologies: suPHP, mod_fcgid, CGI (suexec), LiteSpeed .

It is not compatible with mod_php/DSO, including mod_ruid2 and MPM ITK

Note

PHP Selector is not supported for H-Sphere.

See also Compatibility Matrix.

Installation and update

The installation of PHP Selector presumes that you already have CageFS & LVE Manager installed.

Use compatibility matrix to check if your Web Server/PHP mode is supporting PHP Selector. If not, you need a change to one of the supported models.

Installation of different versions of PHP & modules:

$ yum groupinstall alt-php

Update CageFS & LVE Manager with support for PHP Alternatives:

$ yum update cagefs lvemanager

cPanel/WHM: Make sure 'Select PHP version' is enabled in Feature Manager .

IMPORTANT

Please, do not use settings like SuPHP_ConfigPath, PHPRC, PHP_INI_SCAN_DIR. Do not redefine path to php.ini and ini-files for PHP modules. Doing that can break PHP Selector functionality.

For example, alternative php5.2 versions should load /opt/alt/php52/etc/php.ini file and scan /opt/alt/php52/etc/php.d directory for modules:

Configuration File (php.ini) Path         /opt/alt/php52/etc
Loaded Configuration File                 /opt/alt/php52/etc/php.ini
Scan this dir for additional .ini files   /opt/alt/php52/etc/php.d
additional .ini files parsed              /opt/alt/php52/etc/php.d/alt_php.ini

Those are default locations for alt-php.

If you need custom PHP settings per user, please change them via "Edit PHP settings" feature of PHP Selector .

If a list of default modules is absent on the server in the /etc/cl.selector/defaults.cfg file for some alt-PHP version and there is nd_mysqli extension in this version, then on installation/update of the LVE Manager the mysqli extension will be disabled and nd_mysqli extension will be enabled automatically.

  • If nd_mysqli module is absent or a list of enabled modules is available, then they won't be changed automatically.
  • If alt-PHP is not installed on LVE Manager installation/update, then they won’t be changed automatically.

To change the modules status (enabled/disabled) manually, run the following command in a console:

# /usr/sbin/cloudlinux-selector make-defaults-config --json --interpreter=php

Update

To update PHP Selector, run the following command:

yum groupupdate alt-php

This command allows to install newly released versions in PHP Selector.

Note

See also PHP Selector CLI

LiteSpeed support

Note

LiteSpeed detects CloudLinux OS and applies all settings out-of-the-box.

If the settings were not applied, you can use the following steps to set up LiteSpeed to use PHP Selector.

How to set up LiteSpeed version lower than 5.3 to use PHP Selector

To enable PHP Selector with LiteSpeed Web Server follow PHP Selector installation guide , and then adjust following settings in LiteSpeed :

  1. CloudLinux (Admin Console | Configuration | Server | General): CageFS
  2. Enable SuExec: Server | General | PHP SuEXEC | Yes
  3. Go to External App tab, the new lsphp_selector is here.

Note

You can select any other application or create a custom one.

  1. The Command line should be /var/www/cgi-bin/cgi_wrapper/cloudlinux_wrapper on Plesk . For other control panels, Command line should be /usr/local/bin/lsphp .

Run On Start Up line must contain Yes or No.

For Plesk:

For other control panels:

Settings in text format:

Name lsphp_selector
Address uds://tmp/lshttpd/lsphp_selector.sock
Notes Not Set
Max Connections 35
Environment PHP_LSAPI_MAX_REQUESTS=5000
PHP_LSAPI_CHILDREN=35
Initial Request Timeout (secs) 60
Retry Timeout (secs) 0
Persistent Connection Yes
Connection Keepalive Timeout Not Set
Response Buffering No
Auto Start Through CGI Daemon (Async)
Command * For Plesk /var/www/cgi-bin/cgi_wrapper/cloudlinux_wrapper
* For other control panels /usr/local/bin/lsphp
Back Log 100
Instances 1
suEXEC User Not Set
suEXEC Group Not Set
umask Not Set
Run On Start Up Yes
Max Idle Time 70
Priority 0
Memory Soft Limit (bytes) 2047M
Memory Hard Limit (bytes) 2047M
Process Soft Limit 400
Process Hard Limit 500
  1. Go to Script Handler tab. For required suffixes change the Handler Name to lsphp_selector .

Additional settings for LiteSpeed version 5.3 +

Go to Server --> PHP tab. Click Edit in the PHP Handler Defaults section. We recommend to set up the following settings:

  • Set Yes in the Run On Startup
  • Make sure to set Max Idle Time

Note

In order to use PHP Selector and custom php.ini, lsphp5 needs to be in SuEXEC non-daemon mode.

Note

Some PHP configurations require more memory for SuExec to work properly. If you are getting error 500 after switching suEXEC to non-daemon mode, try to increase Memory Soft Limit and Memory Hard Limit for external App to at least 650/800M.

Note

If you have LiteSpeed installed not in standard location path, please create a symlink: 'ln -s /path/to/custom/lsws /usr/local/lsws' then run 'cagefsctl --setup-cl-selector'.

ISPmanager support

As of July 2013, PHP Selector support for ISPmanager is limited to command line utilities. You should still be able to use it.

As always, PHP Selector requires CGI, FCGI or suPHP to work.

You will need to do following modifications:

Create new file /usr/local/bin/php-cgi-etc:

#!/bin/bash
/usr/bin/php-cgi -c /etc/php.ini "$@"
Make that file executable:
$ chmod +x /usr/local/bin/php-cgi-etc
Edit file /usr/local/ispmgr/etc/ispmgr.conf

Add a line:

path phpcgibinary /usr/local/bin/php-cgi-etc

Make sure there is no other lines with path phpcgibinary defined in the file.

Restart ISPmanager :

$ killall ispmgr

After that FCGID wrappers (/var/www/[USER]/data/php-bin/php) for new users will be like this:

#!/usr/local/bin/php-cgi-etc

You might need to edit/modify wrappers for existing users if you want them to be able to use PHP Selector. You can leave them as is for users that don't need such functionality.

Uninstalling

It is not possible to remove PHP Selector from the system completely as it is an essential part of LVE Manager and CageFS packages. However, you can make PHP Selector unavailable for cPanel and Plesk users.

To do so, go to LVE Manager → PHP Selector and check Disabled as PHP Selector status. Doing so allows you to disable web-interface of the PHP Selector in the user interface but does not reset custom settings (choosing a version of PHP and modules).

To disable PHP Selector and make it has no effect on a PHP version on the sites, run the following command:

  • this command resets PHP versions to Native:
cagefsctl --cl-selector-reset-versions
  • this command resets PHP modules to Default:
cagefsctl --cl-selector-reset-modules

WARNING

These commands can affect PHP version of your clients’ web sites. Use them with caution as improper usage might cause your clients’ web sites down.

Disabling PHP extension globally

If you want to disable PHP extension globally, you don't need to remove file /opt/alt/phpXX/etc/php.d.all/$EXTENSION.ini . You should just comment out "extension=" directives in it.

The extension will be visible in PHP Selector interface, but selecting it in users's interface will take no effect - extension will be disabled in fact.

Reinstalling of alt-php packages will not reset settings (will not enable extension again).

Configuration and using

Setting default version and modules

Administrator can set default interpreter version and extensions for all users. All file operations are actually done by CageFS. CageFS takes settings from /etc/cl.selector/defaults.cfg. Currently the /etc/cl.selector/defaults.cfg is created and handled by CloudLinux PHP Selector scripts. It has the following format:

[global]
selector=enabled

[versions]
php=5.4

[php5.4]
modules=json,phar

[php5.3]
modules=json,zip,fileinfo

Individual PHP.ini files

For each customer, inside CageFS, file alt_php.ini is located in /etc/cl.php.d/alt-phpXX (XX - version of PHP, like 52 or 53). The file contains PHP extension settings and extension directives selected by customer. This file exists for each customer, for each PHP version.

Note, that this is 'local' to CageFS, and different users will have different files. The file is not visible in /etc/cl.php.d outside CageFS. If you would like to view that file, use:

# cagefsctl -e USERNAME 

to enter into CageFS for that user. Then type: exit ; to exit from CageFS

This file has to be updated using cagefsctl --rebuild-alt-php-ini after updating alt-php RPMs

Admin can change individual settings for PHP extensions by changing that extension's ini file, like editing /opt/alt/php54/etc/php.d.all/eaccelerator.ini and then running:

cagefsctl --rebuild-alt-php-ini
to propagate the change.

How to add additional php.ini file for a user inside CageFS

If you want to create additional php.ini file for a user inside CageFS in order to change some specific PHP options for that user, you can execute the following:

# su -s /bin/bash - USER
# cd /etc/cl.php.d/alt-php72/
# echo "upload_tmp_dir=/tmp" >> custom.ini

The commands above create custom.ini file that will be used for alt-php72. By default this approach is valid only for alt-php version selected via PHP Selector. When /etc/cl.selector/symlinks.rules file contains php.d.location = selector line, then the approach is valid for all alt-php versions regardless whether it is selected in PHP Selector or not.

You can find more details here.

But the recommended way is to modify PHP options via PHP Selector web or CLI interfaces, as described here.

Substitute global php.ini for individual customer

Sometimes you might want to have a single customer with a different php.ini, than the rest of your customers.

To do that, you will use custom.etc directory functionality

  1. Move default php.ini into /etc directory and create a symlink to it:
$ mv /usr/local/lib/php.ini /etc/php.ini
$ ln -fs /etc/php.ini /usr/local/lib/php.ini
  1. Change path to php.ini in /etc/cl.selector/native.conf file to:
php.ini=/etc/php.ini
  1. For each user that needs custom file, create directory /etc/cagefs/custom.etc/USER_NAME/php.ini .

For example if you want to create custom for USER1 and USER2 you would create files:
/etc/cagefs/custom.etc/USER1/php.ini
/etc/cagefs/custom.etc/USER2/php.ini

Create such files for each user that should have custom file.

  1. Execute:
$ cagefsctl --force-update 

Notes

  1. Make sure that php.ini load path is set to /etc/php.ini

  2. Users will be able to override settings of those php.ini files (global or custom) via PHP Selector. If you want to prevent that, you should disable PHP Selector feature.

  3. Even if PHP Selector is disabled, user can override PHP settings by using ini_set() php function in PHP script, or by php -c command line option.

  4. If you modify anything in /etc/cagefs/custom.etc directory, you should execute:

$ cagefsctl --update-etc

in order to apply changes to CageFS for all users.

OR

$ cagefsctl --update-etc user1 user2

to apply changes to CageFS for specific users.

How to substitute global php.ini for individual customer on cPanel server with EasyApache4

Note

It is enough to put php.ini in the directory where PHP script is located in order to run the PHP script with a custom php.ini when using SuPHP. Also, you can use cPanel MultiPHP Manager to create user’s custom php.ini file, and this approach should work for CGI, FCGI, and LSAPI. Recommended ways to manage php.ini settings per user are to use cPanel MultiPHP or CloudLinux PHP Selector interfaces.

  1. For each user that needs custom file, create directory /etc/cagefs/custom.etc/USER_NAME/php.ini.

    For example, if you want to create a custom file for USER1 and USER2 you would create files:

    /etc/cagefs/custom.etc/USER1/php.ini
    /etc/cagefs/custom.etc/USER2/php.ini
    

    Create such files for each user that should have a custom file.

  2. Execute the following command:

    $ cagefsctl --force-update
    
  3. Configure php.ini load path for user’s domains.

  • When using suphp handler, you should use SuPHP_ConfigPath directive in virtual host configuration for these domains, or use this directive in .htaccess files: suPHP_ConfigPath/etc.

  • When using mod_lsapi, you should use lsapi_phprc directive in virtual host configuration: lsapi_phprc/etc/. You can find the detailed description of mod_lsapi directives here.

  • When using FCGI or CGI, you should implement custom PHP wrapper and redefine the path to php.ini via -c command line option, like below:

    #!/bin/bash
    [ -f /etc/php.ini ] && exec /usr/bin/php -c /etc/php.ini
    exec /usr/bin/php
    

Notes:

  1. You should restart Apache web server after modifying virtual host configuration for the domains.

  2. Custom php.ini may break switching PHP version via CloudLinux PHP Selector or cPanel MultiPHP Manager for the appropriate users or domains.

  3. When using cPanel ea-php for the domains, additional php.ini files may not be loaded, so you should load all needed PHP extensions in custom /etc/php.ini file:

  4. When using CloudLinux alt-php, additional php.ini files will be loaded:

  5. If you have modified anything in /etc/cagefs/custom.etc directory, you should execute one of the following:

    • to apply changes to CageFS for all users, run:
    $ cagefsctl --update-etc
    
    • to apply changes to CageFS for specific users, run:
    $ cagefsctl --update-etc user1 user2
    

Managing interpreter version

Managing interpreter versions is done by means of manipulating a set of symbolic links that point to different versions of interpreter binaries. For example, if default PHP binary is /usr/local/bin/php :

  • First we move the default binary inside CageFS to /usr/share/cagefs-skeleton/usr/selector , and make /usr/local/bin/php a symlink pointing to /etc/cl.selector/php . This operation is done as part of CageFS deployment.
  • Next suppose we have additional PHP version, say 7.2.5. The information about all additional interpreter binaries and paths for them is kept in /etc/cl.selector/selector.conf . This config file is updated by RPM package manager each time alternative PHP package is added, removed or updated
  • /usr/bin/selectorctl --list --interpreter=php will get us list of all available PHP interpreter versions out of /etc/cl.selector/selector.conf file . Next we want to know which PHP version is active for a given user (to supply a selected option in options list). We type:
  • /usr/bin/selectorctl --user USERNAME --interpreter=php --user-current will retrieve PHP version set for a particular user. The script gets the path from /var/cagefs/LAST_TWO_DIGITS_OF_UID/USERNAME/etc/cl.selector/php symlink, compares it with contents of /etc/cl.selector/selector.conf file and if path is valid, prints out the current interpreter version.
  • /usr/bin/selectorctl --user USERNAME --interpreter=php --set-user-current=7.2 sets the current PHP version for particular user by creating symlink in /var/cagefs/LAST_TWO_DIGITS_OF_UID/USERNAME/etc/cl.selector directory. All old symlinks are removed, and new symlinks are set.

Including PHP Selector only with some packages (cPanel)

cPanel has a ' Feature Manager ' in WHM that allows you to disable PHP Selector for some of the packages that you offer.

In reality it only disables the icon in cPanel interface. Yet, in most cases it should be enough in shared hosting settings.

You can find more info on ' Feature Manager ' here: http://docs.cpanel.net/twiki/bin/view/11_30/WHMDocs/FeatureManager

Once PHP Selector is enabled, you can find it in the Feature Manager . Disabling it in Feature Manager , will remove the icon for users that are using that particular 'Feature List'

PHP extensions

Configuring Alt-PHP modules loading

CloudLinux PHP Selector and Alt-PHP can be used in conjunction with Plesk PHP Selector and cPanel MultiPHP . To be compatible, CloudLinux PHP Selector works as follows: modules that are selected in CloudLinux PHP Selector are loaded for Alt-PHP version selected in CloudLinux PHP Selector only. For the rest Alt-PHP versions default module set is loaded ( /opt/alt/phpXX/etc/php.d/default.ini ) . Described above is default behavior.

Note

If system default PHP version selected in cPanel MultiPHP Manager is not ea-php, then default module set is loaded for all Alt-PHP versions by default (/opt/alt/phpXX/etc/php.d/default.ini).

When "php.d.location = selector" option is in effect, modules selected via PHP Selector will be loaded for all alt-php versions.

This behavior is implemented in CageFS-6.1-10 and later.

In LVE Manager 1.0-9.40+ this behavior can be modified so that modules selected in CloudLinux PHP Selector would be loaded for all Alt-PHP versions (with CageFS enabled), which can be quite useful if you use  ‘ per directory ’ or ‘ per domain ’ Alt-PHP configuration and want to select modules using CloudLinux PHP Selector .

To modify it, create a file /etc/cl.selector/symlinks.rules (read-only for regular users) with the following content: php.d.location = selector

And run the command to apply changes:

/usr/bin/selectorctl --apply-symlinks-rules
To revert to the default behavior:
  • Delete /etc/cl.selector/symlinks.rules file.
  • Alternatively remove php.d.location option from the file.
  • Alternatively set default value for php.d.location option.

And run the command to apply changes:

/usr/bin/selectorctl --apply-symlinks-rules

FFmpeg

Due to possible patent issues CloudLinux does not provide FFmpeg libraries ( https://ffmpeg.org/legal.html ). We highly recommend researching if you can legally install FFmpeg extension on your server. This might differ based on where you and your servers are located. More information can be found on the link: https://ffmpeg.org/legal.html

For your convenience we provide FFMPEG PHP binding. For them to work, you need to install FFmpeg package from the “ Nux Dextop ” repository following the instructions.

Once FFmpeg is installed you can install PHP bindings, by running:

yum install alt-php*ffmpeg 

Enable PHP-FFmpeg extension via PHP Selector :

selectorctl --enable-extensions=ffmpeg --user USERNAME --version X.Y

Native PHP configuration

PHP Selector requires access to the native PHP version for proper work. It is specified in the file /etc/cl.selector/native.conf of the following content (example):

php=/usr/bin/php-cgi
php-cli=/usr/bin/php
php.ini=/etc/php.ini
lsphp=/usr/local/bin/lsphp
php-fpm=/usr/local/sbin/php-fpm

Then execute the following command to apply changes.

cagefsctl --setup-cl-selector

The file is created when installing CageFS on the servers with cPanel, Plesk, DA, Interworx and ISP Manager , if it is missing. On all other servers the file is not being created at all.

That is why, if the file is not created automatically, then it must be created manually and correct paths must be written to its directives.

Access permission 644 must be set:

chmod 0644 /etc/cl.selector/native.conf

How to configure alt-php72-zts to use with PHP Selector

Requirements

To use alt-php72-zts with PHP Selector you need the following:

  • cagefs-6.1.8-1 or later
  • alt-php72-zts-7.2.21-4 or later

Using zts PHP

  1. Install alt-php72-zts with the following command:
yum install alt-php72-zts
  1. Make sure that /etc/cl.selector/selector.conf file contains correct paths to the PHP zts binaries.

You should remove the old lines:

php 7.2 7.2.20 /opt/alt/php72/usr/bin/php-cgi
php-cli 7.2 7.2.20 /opt/alt/php72/usr/bin/php

And replace them with the lines with the new paths:

php 7.2 7.2.20 /opt/alt/php72/usr/bin/zts-php-cgi
php-cli 7.2 7.2.20 /opt/alt/php72/usr/bin/zts-php
  1. Make sure that /opt/alt/php72/etc/php.d.all path refers to the directory containing ini files for zts PHP extensions:
cd /opt/alt/php72/etc
ln -fsn php.d.all.zts php.d.all
  1. Execute the following command:
cagefsctl --setup-cl-selector

Using non-zts PHP

  1. Make sure that /etc/cl.selector/selector.conf file contains correct paths to the non-zts PHP binaries.

You should remove the old lines:

php 7.2 7.2.20 /opt/alt/php72/usr/bin/zts-php-cgi
php-cli 7.2 7.2.20 /opt/alt/php72/usr/bin/zts-php

And replace them with the lines with the new paths:

php 7.2 7.2.20 /opt/alt/php72/usr/bin/php-cgi
php-cli 7.2 7.2.20 /opt/alt/php72/usr/bin/php
  1. Make sure that /opt/alt/php72/etc/php.d.all path refers to the directory containing ini files for non-zts PHP extensions:
cd /opt/alt/php72/etc
ln -fsn php.d.all.def php.d.all
  1. Execute the following command:
cagefsctl --setup-cl-selector

Using

Once PHP Selector is installed, you will see the Selector tab in the LVE Manager.

PHP Selector lets you select default PHP version, as well as modules that will be available to user out of the box.

Inside cPanel , User will be able to change PHP version they would have:

as well as extensions that they want to use:

and php.ini settings

All changes are saved automatically.

Custom PHP.ini options

Note

Requires LVE Manager 0.6+

PHP Selector allows customer to edit php.ini settings. Admin has a full control over which settings can be modified.

To allow settings to be modifiable, it has to be whitelisted in /etc/cl.selector/php.conf .

Here are some of the examples of allowed directives:

Directive = safe_mode
Default   = Off
Type      = bool
Remark    = <5.4.0
Comment   = Enables PHP safe mode. This mode puts a number of restrictions on scripts (say, access to file system) mainly for security reasons.
Directive = safe_mode_include_dir
Type      = value
Remark    = <5.4.0
Comment   = If PHP is in the safe mode and a script tries to access some files, files from this directory will bypass security (UID/GID) checks. The directory must also be in include_path. For example: /dir/inc
Directive php.ini setting
Default Default value
Type bool, value (any text), list
Range list of values for list Type
Comment explanation of the setting to display in UI

Default values, that are shown in PHP Selector web interface, are taken from '/opt/alt/phpXX/usr/bin/php -i' runtime values, if directive is not there, it will use ' default ' value that was set in php.conf . So, if you wish to change default value of any option for "alternative" php version, please modify /opt/alt/phpXX/etc/php.ini files (where XX = 55, 54, 53, etc according to php version).

Admin can modify the settings using selectorctl command.

Users can use web interface to modify php.ini settings:

End user files and directories

The following files and directories are created inside CageFS for each customer:

/etc/cl.selector - PHP binaries symbolic links.

/usr/selector/php - Native PHP binaries.

/etc/cl.php.d/alt-php* - Links to enabled modules.

/home/user/.cl.selector/alt_phpXX.cfg - Config file for custom PHP options.

like:

/etc/cl.php.d/alt-php54/fileinfo.ini - /opt/alt/php54/etc/php.d.all/fileinfo.ini

Compiling your own extensions

Sometimes you might want to compile your own PHP extension for your users to use. In most cases, it is better to contact our support by sending us a support ticket . We will try to provide such extension for you via regular updates within 5-7 days.

If you have decided that you want to build it on your own, you would need to build it for each and every supported version of PHP that you have installed. The module installation process is a bit different from standard - you would need to use the version of phpize and php-config binaries that come with particular Alt-PHP version.

The full process for PHP 5.X and 7.X looks as follows:

  1. Download and unpack extension, cd into it's directory.

  2. Execute our version of phpize if necessary:

/opt/alt/phpXX/usr/bin/phpize
  1. Execute configure with our binary:
./configure --with-php-config=/opt/alt/phpXX/usr/bin/php-config
  1. Make the .so file:
make
  1. Copy it to the modules directory (on 32-bit server, use usr/lib/php/modules ).
cp -rp modules/*.so /opt/alt/phpXX/usr/lib64/php/modules/
  1. Add ini file for module to /opt/alt/phpXX/etc/php.d.all .

  2. Register new Alt-PHP version with:

$ cagefsctl --setup-cl-selector

Roll your own PHP

To add your own PHP version in PHP Selector :

  • Create directory in (like: /opt/alt/php51), and mimic directory structure inside to be similar to the one of PHP versions bundled by CloudLinux .
  • Put all the ini files for all the modules into /opt/alt/php51/etc/php.d.all
  • Create a symbolic link /opt/alt/php51/etc/php.d -> /etc/cl.php.d/alt-php51

Place all such files into /opt/alt/php51/usr/lib/php/modules

Add an absolute path to PHP binaries into /etc/cl.selector/selector.conf using the following format:

php     5.1 5.1.2 /opt/alt/php51/usr/bin/php-cgi 
php-cli 5.1 5.1.2 /opt/alt/php51/usr/bin/php 
php-fpm 5.1 5.1.2 /opt/alt/php51/usr/sbin/php-fpm
   ^     ^    ^                ^----- absolute path
   |     |    |---------------------- real version
   |     | -------------------------- version to display
   |--------------------------------- binary to 'substitute'

Execute:

cagefsctl --setup-cl-selector

The new PHP version must be available now for selection in PHP Selector.

Detect user's PHP version

Note

LVE Manager 0.5-63 or higher

PHP Selector provides an easy way to figure out which versions are available and selected for end user from the command line. You can get this information by running:

$ selectorctl --interpreter=php --user-summary --user=USERNAME
The output:
5.2 e - -
5.3 e - s
5.4 e - -
5.5 e - -
native e d -

The first column defines the PHP version. Native means native PHP version, like the one installed by cPanel with EasyApache.

The second column will contain either e or -. If e is present, it means that given version is enabled, and can be selected by the end user.

The third column can have values d or -. If d is present, that version is considered a 'default' version. Only one PHP version will have d indicator.

The fourth column can have values s or -. If s is present, that is the selected version, currently being used by the end user. Only one PHP version will have s indicator.

In case a user is not inside CageFS, and as such doesn't use PHP Selector , you will see the following error message:

ERROR:User USERNAME not in CageFS

PHP Selector without CageFS

[LVE Manager 2.0-11.1 or higher]

PHP Selector can now be used with CageFS turned off (in case when there is only one user account on the server).

To install run:

yum groupinstall alt-phpyum install cagefs lvemanager

(no need to initialize or turn on CageFS)

selectorctl --setup-without-cagefs USER

( USER - the name of a user who is using selector. If not specified, the first available cPanel account username will be used).

When executing --setup-without-cagefs, the following actions are performed:

  • Creating symlinks to the user modules and options for each Alt-PHP version:
    /opt/alt/php55/link/conf/alt_php.ini -> /home/USER/.cl.selector/alt_php55.ini

  • In user home directory creating:
    .cl.selector/

“Backup” settings files (selected version, modules, options):
.cl.selector/defaults.cfg
.cl.selector/alt_php44.cfg

Symlinks to the selected version:
.cl.selector/lsphp -> /opt/alt/php44/usr/bin/lsphp
.cl.selector/php.ini -> /opt/alt/php44/etc/php.ini
.cl.selector/php-cli -> /opt/alt/php44/usr/bin/php
.cl.selector/php -> /opt/alt/php44/usr/bin/php-cgi

Additional symlinks for environment variable $PATH (search path) in the file ~/.bashrc :
.cl.selector/selector.path/
.cl.selector/selector.path/php-cgi -> ../php
.cl.selector/selector.path/php -> ../php-cli

Generated ini files with selected modules and options for each version: .cl.selector/alt_php44.ini
.cl.selector/alt_php51.ini
.cl.selector/alt_php52.ini
.cl.selector/alt_php53.ini
.cl.selector/alt_php54.ini
.cl.selector/alt_php55.ini
.cl.selector/alt_php56.ini
.cl.selector/alt_php70.ini
.cl.selector/alt_php71.ini

Symlinks above are being created according to the settings in ~/.cl.selector/defaults.cfg and ~/.cl.selector/alt_php44.cfg files (44 - corresponding PHP version), which are storing PHP Selector settings for the user. These files are usually taken from user home directory backup or when migrating account from another server. Thus, when migrating account from server to server, PHP Selector settings are saved.

If no PHP Selector settings backup files are found when running selectorctl --setup-without-cagefs, then default settings from /etc/cl.selector/defaults.cfg global file are applied (as in selector normal mode). If the file is absent, then native PHP version will be selected for the user.

  • The following line: PATH=$HOME/.cl.selector/selector.path:$HOME/.cl.selector:$PATH

is being added to the user file ~/.bashrc

Apache PHP handlers settings are not changed.

  • Also selectorctl --setup-without-cagefs command does the following:

    • Turns off link traversal protection (linksafe);
    • Turns off cagefs service.

To get back to the selector normal mode (“with CageFS”) run:

selectorctl --revert-to-cagefs

(CageFS should be initialized by using cagefsctl --init command before running the command above)

This command removes symlinks:
/opt/alt/php55/link/conf/alt_php.ini -> /home/USER/.cl.selector/alt_php55.ini turns on link traversal protection (linksafe) and cagefs service.

Note

See also PHP Selector CLI

Configuring "global” php.ini options for all Alt-PHP versions

Note

CageFS 6.0-33 or higher, LVE Manager 2.0-11.2 or higher

There is /etc/cl.selector/global_php.ini file, where you can specify values of PHP options that should be applied for all Alt-PHP versions that are installed on a server. These settings will also be automatically applied to the new Alt-PHP versions that will be installed later.

Example:
# cat /etc/cl.selector/global_php.ini
[Global PHP Settings]
date.timezone = Europe/Warsaw
error_log = error_log
memory_limit = 192M
Sections are ignored. Only name of an option and a value have meaning.

When an option is absent in /etc/cl.selector/global_php.ini file, than it is not changed (applied) to php.ini for Alt-PHP versions.

date.timezone and error_log options are handled differently than the others. When these options are not in /etc/cl.selector/global_php.ini file, than values for the options will be taken from "native" php.ini file. And when the option is in php.ini for some Alt-PHP version already (and its value is not empty), than value from /etc/cl.selector/global_php.ini will be NOT applied.

Note

CageFS version 6.1.5-1 or later

The behavior above is changed for cPanel servers with EasyApache 4. The /usr/local/lib/php.ini file is removed for new installations of cPanel v80 and later.

  • When /usr/local/lib/php.ini file exists, error_log and date.timezone options will be taken from that php.ini file.
  • When /usr/local/lib/php.ini file does not exist, error_log and date.timezone options will be taken from the php.ini file for system default PHP version selected in MultiPHP Manager.

This functionality works when the system default PHP version is ea-php only. When the system default PHP version is alt-php, error_log and date.timezone directives will be NOT taken from that php.ini file.

To confirm changes (not affecting "date.timezone" and "error_log" options) please run:

/usr/sbin/cagefsctl --setup-cl-selector

To confirm changes (including date.timezone and error_log options) please run:

/usr/bin/selectorctl --apply-global-php-ini
or
/usr/sbin/cagefsctl --apply-global-php-ini
(two commands above work the same way).

If you don't want to change error_log, but want to change date.timezone, you can execute:

selectorctl --apply-global-php-ini date.timezone

Similarly, command selectorctl --apply-global-php-ini error_log applies error_log and all other options specified in /etc/cl.selector/global_php.ini file, except date.timezone .

So, you can specify 0, 1 or 2 parameters from the list: error_log, date.timezone .

Using --apply-global-php-ini without arguments applies all global PHP options including two above.

Example:

selectorctl --apply-global-php-ini error_log
selectorctl --apply-global-php-ini date.timezone
selectorctl --apply-global-php-ini date.timezone error_log

The latter command has the same effect as /usr/bin/selectorctl --apply-global-php-ini.

Note

See also PHP Selector CLI

Integration with control panels

This is the list of commands that we use to integrate PHP Selector with control panels. If you need to integrate PHP Selector with a custom control panel, you might find all the commands here:

PHP summary:

Command:

/usr/bin/selectorctl --summary
Result:
4.4 e -
5.1 e -
5.2 e -
5.3 e -
5.4 e -
5.5 e -
5.6 e -
7.0 e -
7.1 e -
native e d
When native PHP version needs to be displayed:

Command:

/usr/bin/selectorctl --summary --show-native-version

Result:

4.4 e -
5.1 e -
5.2 e -
5.3 e -
5.4 e -
5.5 e -
5.6 e -
7.0 e -
7.1 e -
native(5.6) e d

The first column: PHP version
The second column: enabled or not ( e - enabled)
The third column: if selected as default ( d - default)

Set default version:

/usr/bin/selectorctl --set-current=_VERSION_

Disable version:

/usr/bin/selectorctl --disable-alternative=_VERSION_

Enable version:

/usr/bin/selectorctl --enable-alternative=_VERSION_

List extensions for a version:

/usr/bin/selectorctl --list-extensions --version=5.6

Result:

- apc
- bcmath
- big_int
- bitset
- bloomy
~ bz2
- bz2_filter
~ calendar
- coin_acceptor
- crack
~ ctype
+ curl

+: enabled
~: included in php binary (cannot be disabled)
-: disabled

Select default extensions (enable comma-separated list of extensions globally for a version):

/usr/bin/selectorctl --version=5.6 --enable-extensions=pdo,json,mysql

Deselect default extensions (disable comma-separated list of extensions globally for a version):

/usr/bin/selectorctl --version=5.6 --disable-extensions=pdo,json,mysql

Replace extensions with comma-separated list of extensions for a version globally:

/usr/bin/selectorctl --version=5.6 --replace-extensions=pdo,json,mysql

Select PHP version for a user:

/usr/bin/selectorctl --set-user-current=_VERSION_ --user=_USER_

List enabled extensions for a user:

/usr/bin/selectorctl --list-user-extensions --user=_USER_ --version=_VERSION_

Enable comma-separated list of extensions for a user:

/usr/bin/selectorctl --enable-user-extensions=pdo,json,mysql --user=_USER_ --version=_VERSION_

Reset user’s extensions to defaults:

/usr/bin/selectorctl --reset-user-extensions --user=_USER_ --version=_VERSION_

Replace user extensions with comma-separated list of extensions:

/usr/bin/selectorctl --replace-user-extensions=EXT_LIST --user=_USER_ --version=_VERSION_

EXT_LIST a is comma separated list of PHP extensions (for example: pdo,json,mysql )

List available options for php.ini editing:

/usr/bin/selectorctl --print-options --user=_USER_ --version=_VERSION_ [--json]

List available options for php.ini editing (print safe strings):

/usr/bin/selectorctl --print-options-safe --user=_USER_ --version=_VERSION_ [--json]

Set php.ini options for end user:

/usr/bin/selectorctl --user=_USER_ --version=_VERSION_ --replace-options=_OPTIONS_ --base64 [--json]

Here is an example of how you can generate OPTIONS in base64 format:

OPTIONS=`echo disable_functions:exec,syslog|base64 -w 0`,`echo display_errors:off|base64 -w 0`,`echo post_max_size:128M|base64 -w 0`
echo $OPTIONS

PHP Selector integration with cPanel’s MultiPHP Manager

Note

Requires CageFS 5.5-6.18+

Overview

Earlier, when EasyApache 3 was in trend, CloudLinux with PHP Selector would work seamlessly; you would set up the EasyApache profile which is compatible with PHP Selector, and you are ready to go. However, with EasyApache 4 cPanel introduced the built-in MultiPHP Manager which changed everything.

The main advantage of MultiPHP Manager is allowing users to select different PHP versions for each domain. With CloudLinux, you can also make use of a similar feature: PHP Selector. PHP Selector has an important advantage over MultiPHP Manager: it allows a single cPanel user to manage PHP extensions without the need to contact his/her hoster. The user can enable/disable PHP extensions as he pleases. PHP Selector also leaves the choice of PHP version to the end user, but the switch is made for the whole user, not for a separate website (as with MultiPHP Manager).

Note

The main question a hoster should answer is which of the above features he will provide for his clients: MultiPHP Manager or PHP Selector. Using both can be confusing for the end users. You can manage which features to show to your cPanel end-users in WHM Home » Packages » Feature Manager » Feature Lists.

If you'd like to use PHP Selector on a cPanel server, continue reading this document to understand how to integrate MultiPHP Manager and PHP Selector.

Prerequisites

Before integrating PHP Selector with cPanel, make sure that you have the following components installed:

  • LVE Manager
  • CageFS
  • CloudLinux alt-php package

Configuration

Once you’re done with PHP Selector installation, there are a few things that you need to check on cPanel servers. You need to make sure that MultiPHP Manager settings are correct and that CageFS is enabled for the users. Let us cover the steps in detail.

Go to WHM -> MultiPHP Manager -> PHP Versions tab.

  1. Make sure that the System PHP Version is set to one of the ea-phpXX ones.

    Attention

    Selecting the alt-phpXX (as a “System PHP Version”) will break the PHP Selector.

  2. Switch the PHP-FPM to Off; the PHP Selector is not compatible with it.

    Note

    If you have PHP-FPM enabled for existing websites, you need to disable it for them.

  3. Last but not least, make sure that the domains/accounts (where you'd like to use the PHP Selector) use the Inherited version. You need to do that because MultiPHP Manager has higher priority than PHP Selector. So, if any other PHP version is set in this menu, it will overwrite the PHP version selected in PHP Selector for that domain.

That’s it! You are all set. The only thing that’s left is to make sure that you use the “Enable for all users” mode for CageFS if you’d like to keep PHP Selector for all users.

See also: FAQ on PHP Selector integration with cPanel’s MultiPHP Manager.

More about PHP Selector’s configuration

Setting up the PHP version on customer’s end (in cPanel)

It is possible to change the current PHP Version for MultiPHP Manager on the user’s end. Here’s how the settings would look like by default:

As end-user can change that and select any version, other than Inherited one. Just like with WHM’s MultiPHP Manager, the PHP Selector won’t work correctly in this case. We recommend leaving either PHP Selector or MultiPHP Manager enabled for the end-user. That way, your end users will have only one place where to configure PHP which will make things easier.

PHP directives and their priorities

Given the way cPanel handles the PHP versions, it could be quite confusing to understand which PHP.ini directive will get higher priority over another. Let's discuss it here.

Directives priority - if PHP Selector is enabled

If the PHP Selector is configured properly, its options would have the highest priority. You can find them in cPanel -> Select PHP Version -> Switch to PHP Options.

You can add custom php.ini options here too! Check this article to find out how to do that. The lower priority would have the php.ini (or .user.ini for some of the PHP handlers) configuration file, but you could also type in the PHP values there.

Directives priority - if PHP Selector isn’t used

If you haven’t configured the PHP Selector, and you’d like to simply change PHP.ini parameters for particular alt-phpXX or ea-phpXX versions, you could manage them in WHM -> MultiPHP INI Editor. cPanel end-user can also customize php.ini directives in cPanel -> MultiPHP INI Editor. For more information, read the official documentation here and here.

PHP version in the command-line interface (CLI)

Shell commands, starting with /usr/bin/php and /usr/local/bin/php would use the same version that you select in the PHP Selector (if it’s already set up). That PHP will also load PHP directives selected in PHP Selector. For example, if we have a setup like this:

We should get the 7.2 version in the php -v output if nothing was changed in the PHP Selector. This is exactly what we get:

/usr/local/bin/php -v
PHP 7.2.14 (cli) (built: Feb 10 2019 18:20:08) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.14, Copyright (c) 1999-2018, by Zend Technologies

But if we change the PHP version in the PHP Selector, the php -v output will change as well.

/usr/local/bin/php -v
PHP 7.3.2 (cli) (built: Feb  7 2019 13:36:44) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.2, Copyright (c) 1998-2018 Zend Technologies

However, PHP version chosen in MultiPHP Manager can also be applied to console commands /usr/bin/php and /usr/local/bin/php. Whether it will be applied or not depends on the current working directory. .htaccess file search is performed in the current directory and in parent directories. If the file is found, then the PHP version specified in it is applied, if not found, then System default PHP version is applied. System default PHP version for a specific user can be changed via PHP Selector.

See also PHP Selector CLI tools.

Bundled PHP extensions

Large number of PHP extensions are bundled with each version of PHP.

PHP 4.4 extensions

bcmath
bz2
calendar
ctype
curl
dba
dbase
dbx
domxml
exif
fileinfo
ftp
gd
gettext
gmp
iconv
imap
interbase
ioncube_loader
ioncube_loader_4
json
ldap
mbstring
mcrypt
mhash
mysql
ncurses
odbc
openssl
overload
pcntl
pcre
pgsql
posix
pspell
readline
recode
session
shmop
snmp
sockets
sourceguardian
standard
sybase_ct
sysvmsg
sysvsem
sysvshm
tokenizer
wddx
xml
xmlrpc
zlib

PHP 5.1 extensions

bcmath
big_int
bitset
bz2
bz2_filter
calendar
coin_acceptor
crack
ctype
curl
date
dba
dbase
dom
doublemetaphone
exif
ftp
gd
geoip
gettext
gmagick
gmp
gnupg
haru
hash
huffman
iconv
idn
igbinary
imagick
imap
inclued
inotify
interbase
ioncube_loader
ioncube_loader_4
ldap
libxml
lzf
mbstring
mcrypt
memcache
msgpack
mysql
mysqli
ncurses
odbc
openssl
pcntl
pcre
pdo
pdo_firebird
pdo_mysql
pdo_odbc
pdo_pgsql
pdo_sqlite
pgsql
posix
pspell
quickhash
radius
readline
redis
reflection
session
shmop
simplexml
snmp
soap
sockets
sourceguardian
spl
ssh2
standard
stats
stem
sybase_ct
sysvmsg
sysvsem
sysvshm
tidy
timezonedb
tokenizer
translit
wddx
xdebug
xml
xmlreader
xmlrpc
xmlwriter
xsl
zlib

PHP 5.2 extensions

apc
apm
ares
bcmath
bcompiler
big_int
bitset
bloomy
bz2
bz2_filter
calendar
coin_acceptor
crack
ctype
curl
date
dba
dbase
dbx
dom
doublemetaphone
eaccelerator
enchant
exif
ffmpeg
fileinfo
filter
ftp
gd
gender
geoip
gettext
gmagick
gmp
gnupg
haru
hash
hidef
htscanner
huffman
iconv
idn
igbinary
imagick
imap
inclued
inotify
interbase
intl
ioncube_loader
ioncube_loader_4
json
ldap
libxml
lzf
magickwand
mailparse
mbstring
mcrypt
memcache
memcached
mhash
mongo
msgpack
mssql
mysql
mysqli
ncurses
oauth
odbc
opcache
openssl
pcntl
pcre
pdf
pdo
pdo_dblib
pdo_firebird
pdo_mysql
pdo_odbc
pdo_pgsql
pdo_sqlite
pgsql
phar
posix
pspell
quickhash
radius
rar
readline
recode
redis
reflection
rsync
session
shmop
simplexml
snmp
soap
sockets
sourceguardian
spl
spl_types
sqlite
ssh2
standard
stats
stem
stomp
suhosin
sybase_ct
sysvmsg
sysvsem
sysvshm
tidy
timezonedb
tokenizer
translit
uploadprogress
uuid
wddx
xcache_3
xdebug
xml
xmlreader
xmlrpc
xmlwriter
xrange
xsl
yaf
yaz
zend_optimizer
zip
zlib

PHP 5.3 extensions

apc
apcu
apm
ares
bcmath
bcompiler
big_int
bitset
bloomy
brotli
bz2
bz2_filter
calendar
clamav
coin_acceptor
core
crack
ctype
curl
date
dba
dbase
dbx
dom
doublemetaphone
eaccelerator
eio
enchant
ereg
exif
ffmpeg
fileinfo
filter
ftp
functional
gd
gender
geoip
gettext
gmagick
gmp
gnupg
haru
hash
hidef
htscanner
http
huffman
iconv
idn
igbinary
imagick
imap
inclued
inotify
interbase
intl
ioncube_loader
ioncube_loader_4
jsmin
json
ldap
libevent
libxml
lzf
magickwand
mailparse
mbstring
mcrypt
memcache
memcached
mhash
mongo
msgpack
mssql
mysql
mysqli
mysqlnd
ncurses
nd_mysql
nd_mysqli
nd_pdo_mysql
oauth
odbc
opcache
openssl
pcntl
pcre
pdf
pdo
pdo_dblib
pdo_firebird
pdo_mysql
pdo_odbc
pdo_pgsql
pdo_sqlite
pgsql
phalcon
phar
posix
propro
pspell
quickhash
radius
raphf
rar
readline
recode
redis
reflection
rsync
session
shmop
simplexml
snmp
soap
sockets
sourceguardian
spl
spl_types
sqlite
sqlite3
ssh2
standard
stats
stem
stomp
suhosin
sybase_ct
sysvmsg
sysvsem
sysvshm
tidy
timezonedb
tokenizer
trader
translit
uploadprogress
uri_template
uuid
wddx
weakref
xcache
xcache_3
xdebug
xml
xmlreader
xmlrpc
xmlwriter
xrange
xsl
yaf
yaml
yaz
zend_guard_loader
zip
zlib
zmq

PHP 5.4 extensions

apc
apcu
apm
ares
bcmath
big_int
bitset
brotli
bz2
bz2_filter
calendar
clamav
core
ctype
curl
date
dba
dbase
dbx
dom
doublemetaphone
eaccelerator
eio
enchant
ereg
exif
ffmpeg
fileinfo
filter
ftp
functional
gd
gender
geoip
gettext
gmagick
gmp
gnupg
haru
hash
hidef
htscanner
http
iconv
igbinary
imagick
imap
inclued
inotify
interbase
intl
ioncube_loader
ioncube_loader_4
jsmin
json
ldap
libevent
libsodium
libxml
lzf
magickwand
mailparse
mbstring
mcrypt
memcache
memcached
mhash
mongo
mongodb
msgpack
mssql
mysql
mysqli
mysqlnd
ncurses
nd_mysql
nd_mysqli
nd_pdo_mysql
oauth
oci8
odbc
opcache
openssl
pcntl
pcre
pdf
pdo
pdo_dblib
pdo_firebird
pdo_mysql
pdo_odbc
pdo_pgsql
pdo_sqlite
pgsql
phalcon
phar
posix
propro
pspell
quickhash
radius
raphf
rar
readline
recode
redis
reflection
rsync
session
shmop
simplexml
snmp
soap
sockets
sourceguardian
spl
spl_types
sqlite3
ssh2
standard
stats
stem
stomp
suhosin
sybase_ct
sysvmsg
sysvsem
sysvshm
tidy
timezonedb
tokenizer
trader
translit
uploadprogress
uri_template
uuid
wddx
weakref
xcache
xcache_3
xdebug
xml
xmlreader
xmlrpc
xmlwriter
xrange
xsl
yaf
yaml
yaz
zend_guard_loader
zip
zlib
zmq

PHP 5.5 extensions

apcu
apm
ares
bcmath
big_int
bitset
brotli
bz2
bz2_filter
calendar
clamav
core
ctype
curl
date
dba
dbase
dbx
dom
doublemetaphone
eio
enchant
ereg
exif
ffmpeg
fileinfo
filter
ftp
gd
gender
geoip
gettext
gmagick
gmp
gnupg
gRPC
haru
hash
hidef
htscanner
http
iconv
igbinary
imagick
imap
inotify
interbase
intl
ioncube_loader
ioncube_loader_4
jsmin
json
ldap
libevent
libsodium
libxml
lzf
magickwand
mailparse
mbstring
mcrypt
memcache
memcached
mhash
mongo
mongodb
msgpack
mssql
mysql
mysqli
mysqlnd
ncurses
nd_mysql
nd_mysqli
nd_pdo_mysql
oauth
oci8
odbc
opcache
openssl
pcntl
pcre
pdf
pdo
pdo_dblib
pdo_firebird
pdo_mysql
pdo_odbc
pdo_pgsql
pdo_sqlite
pgsql
phalcon
phalcon3
phar
posix
propro
pspell
quickhash
radius
raphf
rar
readline
recode
redis
reflection
rsync
session
shmop
simplexml
snmp
soap
sockets
sourceguardian
spl
spl_types
sqlite3
ssh2
standard
stats
stem
stomp
suhosin
sybase_ct
sysvmsg
sysvsem
sysvshm
tidy
timezonedb
tokenizer
trader
translit
uploadprogress
uri_template
uuid
wddx
weakref
xcache_3
xdebug
xml
xmlreader
xmlrpc
xmlwriter
xrange
xsl
yaf
yaml
yaz
zend_guard_loader
zip
zlib
zmq

PHP 5.6 extensions

apcu
apm
ares
bcmath
big_int
bitset
brotli
bz2
bz2_filter
calendar
core
ctype
curl
date
dba
dbx
dom
doublemetaphone
eio
enchant
ereg
exif
ffmpeg
fileinfo
filter
ftp
gd
gender
geoip
gettext
gmagick
gmp
gnupg
gRPC
haru
hash
htscanner
http
iconv
igbinary
imagick
imap
inotify
interbase
intl
ioncube_loader
ioncube_loader_4
jsmin
json
ldap
libevent
libsodium
libxml
lzf
mailparse
mbstring
mcrypt
memcache
memcached
mhash
mongo
mongodb
msgpack
mssql
mysql
mysqli
mysqlnd
ncurses
nd_mysql
nd_mysqli
nd_pdo_mysql
oauth
oci8
odbc
opcache
openssl
pcntl
pcre
pdf
pdo
pdo_dblib
pdo_firebird
pdo_mysql
pdo_odbc
pdo_pgsql
pdo_sqlite
pgsql
phalcon
phalcon3
phar
posix
propro
pspell
quickhash
radius
raphf
rar
readline
recode
redis
reflection
rsync
session
shmop
simplexml
snmp
soap
sockets
sourceguardian
spl
spl_types
sqlite3
ssh2
standard
stats
stem
stomp
suhosin
sybase_ct
sysvmsg
sysvsem
sysvshm
tidy
timezonedb
tokenizer
trader
translit
uploadprogress
uri_template
uuid
wddx
weakref
xcache_3
xdebug
xml
xmlreader
xmlrpc
xmlwriter
xrange
xsl
yaml
yaz
zend_guard_loader
zip
zlib
zmq

PHP 7.0 extensions

apcu
bcmath
bitset
brotli
bz2
calendar
core
ctype
curl
date
dba
dbase
dom
eio
enchant
exif
fileinfo
filter
ftp
gd
gender
geoip
gettext
gmagick
gmp
gnupg
gRPC
hash
htscanner
http
iconv
igbinary
imagick
imap
inotify
interbase
intl
ioncube_loader
json
ldap
libsodium
libxml
lzf
mailparse
mbstring
mcrypt
memcached
mongodb
mysqli
mysqlnd
nd_mysqli
nd_pdo_mysql
newrelic
oauth
oci8
odbc
opcache
openssl
pcntl
pcre
pdf
pdo
pdo_dblib
pdo_firebird
pdo_mysql
pdo_odbc
pdo_pgsql
pdo_sqlite
pdo_sqlsrv
pgsql
phalcon3
phar
posix
propro
pspell
raphf
rar
readline
redis
reflection
session
shmop
simplexml
snmp
soap
sockets
sourceguardian
spl
sqlite3
sqlsrv
ssh2
standard
stats
suhosin
sysvmsg
sysvsem
sysvshm
tidy
timezonedb
tokenizer
trader
uploadprogress
uuid
vips
wddx
xdebug
xml
xmlreader
xmlrpc
xmlwriter
xsl
yaml
yaz
zip
zlib
zmq
  • Please note that to use newrelic extension you should set your own New Relic License Key in your own /opt/alt/php7*/etc/php.ini file. Please find more info about New Relic License Key in the New Relic documentation.

PHP 7.1 extensions

apcu
bcmath
brotli
bz2
calendar
core
ctype
curl
date
dba
dbase
dom
eio
enchant
exif
fileinfo
filter
ftp
gd
gender
geoip
gettext
gmagick
gmp
gnupg
gRPC
hash
htscanner
http
iconv
igbinary
imagick
imap
inotify
interbase
intl
ioncube_loader
json
ldap
libsodium
libxml
lzf
mailparse
mbstring
mcrypt
memcached
mongodb
mysqli
mysqlnd
nd_mysqli
nd_pdo_mysql
newrelic
oauth
oci8
odbc
opcache
openssl
pcntl
pcre
pdo
pdo_dblib
pdo_firebird
pdo_mysql
pdo_odbc
pdo_pgsql
pdo_sqlite
pdo_sqlsrv
pgsql
phalcon3
phar
posix
propro
pspell
raphf
rar
readline
redis
reflection
session
shmop
simplexml
snmp
soap
sockets
sourceguardian
spl
sqlite3
sqlsrv
ssh2
standard
stats
suhosin
sysvmsg
sysvsem
sysvshm
tidy
timezonedb
tokenizer
trader
uploadprogress
uuid
vips
wddx
xdebug
xml
xmlreader
xmlrpc
xmlwriter
xsl
yaml
zip
zlib
zmq
  • Please note that to use newrelic extension you should set your own New Relic License Key in your own /opt/alt/php7*/etc/php.ini file. Please find more info about New Relic License Key in the New Relic documentation.

PHP 7.2 extensions

apcu
bcmath
brotli
bz2
calendar
core
ctype
curl
date
dba
dom
eio
enchant
exif
fileinfo
filter
ftp
gd
gender
geoip
gettext
gmagick
gmp
gnupg
gRPC
hash
http
iconv
igbinary
imagick
imap
inotify
interbase
intl
ioncube_loader
json
ldap
libxml
lzf
mailparse
mbstring
memcached
mongodb
mysqli
mysqlnd
nd_mysqli
nd_pdo_mysql
newrelic
oauth
oci8
odbc
opcache
openssl
pcntl
pcre
pdo
pdo_dblib
pdo_firebird
pdo_mysql
pdo_odbc
pdo_pgsql
pdo_sqlite
pdo_sqlsrv
pgsql
phalcon3
phar
posix
propro
pspell
raphf
readline
redis
reflection
session
shmop
simplexml
snmp
soap
sockets
spl
sqlite3
sqlsrv
ssh2
standard
stats
sysvmsg
sysvsem
sysvshm
tidy
timezonedb
tokenizer
trader
uploadprogress
uuid
vips
wddx
xml
xmlreader
xmlrpc
xmlwriter
xsl
yaml
zip
zlib
zmq
  • Please note that to use newrelic extension you should set your own New Relic License Key in your own /opt/alt/php7*/etc/php.ini file. Please find more info about New Relic License Key in the New Relic documentation.

PHP 7.3 extensions

apcu
bcmath
dba
dbase
dom
eio
enchant
fileinfo
gd
gender
geoip
gmagick
gnupg
grpc
http
igbinary
imagick
imap
inotify
interbase
intl
json
ldap
lzf
mailparse
mbstring
memcached
mongodb
mysqlnd
nd_mysqli
nd_pdo_mysql
newrelic
oauth
oci8
odbc
opcache
pdf
pdo
pdo_dblib
pdo_firebird
pdo_oci
pdo_odbc
pdo_pgsql
pdo_sqlite
pdo_sqlsrv
pgsql
phar
posix
propro
pspell
raphf
redis
snmp
soap
sockets
sqlsrv
ssh2
stats
sysvmsg
sysvsem
sysvshm
tidy
timezonedb
trader
uploadprogress
uuid
vips
wddx
xdebug
xmlreader
xmlrpc
xmlwriter
xsl
yaf
yaml
zip
zmq

Note

To use newrelic extension you should set your own New Relic License Key in your own /opt/alt/php7*/etc/php.ini file. You can find more info about New Relic License Key in the New Relic documentation.

Python Selector

Note

This documentation is for the new version of Python Selector. You can find documentation for the old Python Selector here

General information and requirements

Python Selector is a CloudLinux component that allows each user to easily deploy and manage Python applications via application server.

Requirements

Important!

Do not downgrade LVE Manager to versions lower than 4.2.2 if you have already migrated Python applications because it will break migrated applications.

  • Python Selector supports the following Alt-Python versions:
    • alt-python27 2.7.16, supported by CloudLinux 6, CloudLinux 7
    • alt-python33 3.3.7, supported by CloudLinux 6, CloudLinux 7
    • alt-python34 3.4.9, supported by CloudLinux 6, CloudLinux 7
    • alt-python35 3.5.6, supported by CloudLinux 6, CloudLinux 7
    • alt-python36-3.6.8, supported by CloudLinux 6, CloudLinux 7
    • alt-python36-3.7.2, supported by CloudLinux 6, CloudLinux 7
  • This feature is available for CloudLinux 7, CloudLinux 6 hybrid and CloudLinux 6.
  • New Python Selector requires LVE Manager version 4.2 or later.
  • It supports cPanel and DirectAdmin servers. On DirectAdmin only on Apache. Plesk will not be supported.
  • Python Selector uses mod_passenger to host Python. For more details about mod_passenger, please read documentation.
  • Python Selector works with EasyApache 3 (note EOL at 1st September 2019), EasyApache 4 and LiteSpeed Web Server. Or Apache on DirectAdmin.

Migration to the new Python Selector

The new Python Selector has a bunch of new features:

  • the ability to set environment variables for the application
  • the ability to set dependencies from the file requirements
  • the ability to start and stop applications as in Node.js Selector
  • the ability to add and edit custom configurations
  • the ability to install modules from the custom configurations

All existing Python applications (created before the update of LVE Manager to version 5.0.1-1) will work the same as before. You do not need to migrate them unless you’d like to use new features. These applications we define as old applications.

Important!

There are some risks during the migration process and the migration can fail. To avoid such issues and make it possible to solve them if any, only user who created a particular application is allowed to initiate the migration process.

You do not need to migrate the new applications that will be created after the update to the LVE Manager 5.0.1-1. All new features are available for them.

Important!

You cannot migrate back to the old application. If you face any issue during the migration, please contact our support team.

How to migrate an application to the new Python Selector

Note

Only user who created an application can migrate it.

To migrate a Python application:

  • Log in to your control panel.
  • Open Python Selector user interface.
  • Choose an application to migrate and click in the Actions section. You will see the popup.
  • Click Migrate in the popup.
  • After successful migration, you will see the confirmation popup.

If you face any issue during the migration, please contact our support team.

Installation and update

New clients can install Python Selector using the CloudLinux Installation Wizard.

cPanel

To use Python Selector, it is required to install the following:

  • alternative Python packages by running the following command:

    yum groupinstall alt-python
    
  • LVE Manager, LVE Utils and Phusion Passenger to create isolated Python environments by running the following command:

    yum install lvemanager lve-utils alt-python-virtualenv ea-apache24-mod-alt-passenger
    

For EasyApache 3:

yum install lve-utils lvemanager alt-python-virtualenv alt-mod-passenger

DirectAdmin

To use Python Selector, it is required to install the following:

  • alternative Python packages by running the following command:

    yum groupinstall alt-python
    
  • LVE Manager, LVE Utils and Phusion Passenger to create isolated Python environments by running the following command:

    yum install lve-utils lvemanager alt-python-virtualenv alt-mod-passenger
    
  • CageFS for better security. See CageFS documentation for details.

Note

After installation, please make sure that you have unmarked appropriate checkboxes in LVE Manager Options tab to show Python App in the web-interface.

Note

Adding Python module requires executing permissions to gcc/make binaries. Please enable compilers in Compiler Access section of WHM, then run:

cagefsctl --force-update

Deploying Trac using Python Selector

  1. In Setup Python App create an application. Trac project WSGI script will be located in App Directory (e.g. trac).

App URI – is a URL where web-interface is located (e.g. Trac – web-interface is located in YOUR_DOMAIN/trac).

Trac needs Python version from 2.5 to 3.0, in the actual example version 2.7 is used.

  1. When the App is created, add the following modules: Trac, Genshi, MySQL-python.

2.1. Alternatively, connect to the server via SSH and perform the following steps:

source ~/virtualenv/trac/2.7/bin/activate

then:

~/virtualenv/trac/2.7/bin/easy_install Trac mysql-python (using easy_install)

or

~/virtualenv/trac/2.7/bin/pip install trac mysql-python

(using pip).

  1. In cPanel create MySQL database and a user. Add user to database.

In this example DB tractest_trac and user tractest_trac were created.

  1. Connect to the server via SSH using your cPanel account.

Create Trac project:

~/virtualenv/trac/2.7/bin/trac-admin
~/trac_project initenv

For the Database connection string parameter enter the following: mysql://user:password@localhost/database_name – here the data for connecting MySQL database are specified.

Note

In case of ... The charset and collation of database are 'latin1' and 'latin1_swedish_ci' error the database must be created with one of (('utf8', 'utf8_bin'), ('utf8mb4', 'utf8mb4_bin')) ... while creating the project, you should change database encoding.

To change encoding, in cPanel run phpMyAdmin, choose DB, go to Operations, choose the necessary encoding in Collation section and click Go.

After that you have to repeat the procedure of creating a project. When done, the Trac project must appear: ~/trac_project

  1. To create project frontend run the following:
~/virtualenv/trac/2.7/bin/trac-admin ~/track_project deploy ~/trac

~/track_project — is the path to the project, ~/trac — is the path, that was specified while setting App Directory.

Create topic directory by default:

cd ~/public_html/trac
mkdir chrome 
cp -R ~/trac/htdocs/ ~/public_html/trac/chrome/

All project static files are located in this directory; the changes can be added here as well.

  1. To add path to WSGI file in the created application:

Go back to cPanel Setup Python App, change WSGI file location for your application to cgi-bin/trac.wsgi, click Update to apply changes and then click Restart.

Your existing application now must look like the following:

  1. Adding authorization:

In ~/public_html/trac/.htaccess after CLOUDLINUX PASSENGER CONFIGURATION section add the following lines:

AuthType Basic
AuthName "trac"
AuthUserFile /home/tractest/trac/passwd
Require valid-user
  1. Add new user and create password file /usr/local/apache/bin/htpasswd with ~/trac/passwd admin.

Enter password.

~/virtualenv/trac/2.7/bin/trac-admin  ~/track_project permission add admin TRAC_ADMIN

Add admin user to TRAC_ADMIN group.

Here the path trac directory is equal to App Directory in your project.

Now Trac is available via YOUR_DOMAIN/trac.

Trac with MySQL

To use Trac with MySQL database you should install alt-python27-devel package.

To install run:

yum install alt-python27-devel --enablerepo=cloudlinux-updates-testing 

EasyApache 4

CloudLinux has Python Selector, which allows creating applications with ea-apache24-mod-alt-passenger. However, it does not allow using cPanel application manager.

It is not correct to install both of those packages on the server because they contain the same passenger module for Apache web server.

The new ea-ruby24-mod_passenger is available for download from our updates-testing (beta) repository which allows you to run applications via cPanel application manager and CloudLinux Python Selector.

To install run:

# yum install lvemanager alt-python-virtualenv
# yum install ea-ruby24-mod_passenger --enablerepo=cl-ea4-testing

Python Selector (Old)

Note

This documentation is for the old version of Python Selector. You can find documentation for the new Python Selector here

We have the ability to deploy Python applications via application server. Python Selector uses mod_passenger to host Python.

This feature is available for CloudLinux 6 or later. It supports only cPanel servers.

You can find a list of supported alt-python versions using the following command.

yum grouplist | grep alt-python

Installation

Note

The instructions below are suitable only for EasyApache 3 and EasyApache 4. You should follow this instruction if you use LiteSpeed.

Install tools to create isolated Python environments and Passenger Apache module. For servers with EasyApache3:

yum install lvemanager alt-python-virtualenv alt-mod-passenger

for EasyApache4:

yum install lvemanager alt-python-virtualenv ea-apache24-mod-alt-passenger

To use Python Selector you should install alternative Python packages:

yum groupinstall alt-python

To use MySQL database you should install alt-python27-devel package:

yum install alt-python27-devel

Note

After installation, please make sure that you have unmarked appropriate checkboxes in LVE Manager Options tab to show Python App in web-interface.

Note

Adding Python modules requires executing permissions to gcc/make binaries. Please enable compilers in Compiler Access section of WHM, then run: cagefsctl --force-update

End user access

  1. In Software/Services area choose Select Python Environment.

  1. Create project form will appear. Choose interpreter version for your application, application folder name (project path) and URI for accessing your application. Click “Create project” to create an application.

After a little while a new application entry will be appended to the web-page.

  1. You can edit path (folder name of the project in the home directory, for example, /home/clman1/project_name ), uri for application, wsgi handler. If you click Edit - the value is converted to input field and thus becomes editable. When editing is complete, click Save .

  1. Wsgi entry is to specify python wsgi application entry point. It must be specified as filename, must be callable and separated by colon. If your app is running from file flask/run.py by calling callable app, set flask/run.py:app .

  1. When Show control is clicked, python extensions section will be expanded. It gives the ability to add or remove python modules. When start typing in input field, appropriate hints are shown in drop-down list. Choose the entry you want from drop-down and click Add .

If you click Delete , the corresponding module entry will disappear. In addition to setting path, uri and wsgi , the interpreter version can be changed as well by changing the value in select drop-down.

  1. No changes are applied to application environment until Update button is clicked. Before the Update button is clicked, all changes can be reverted with Reset button.

The newly created application will be supplied with stub only. A real application ought to be put into application folder. After application is placed into application folder, the wsgi parameter can be set.

Click Remove to delete the application - the application folder itself will remain unmoved.

Note. For LVE Manager version 0.9-10 and higher:

When creating an application you can use the key --domain , which attaches application to domain. If --domain key is not specified, then the main users domain will be used by default. To create application run:

/usr/bin/selectorctl --interpreter=python --version=VERSION[--user=USER] [--domain=DOMAIN] [--print-summary] [--json]–-create-webapp <FOLDER_NAME> <URI>

When changing application URI, --domain key can be used simultaneously, in this case not only URI will be changed, but also the application domain.

To change application URI run:

/usr/bin/selectorctl --interpreter=python [--user=USER][--domain=NEW_DOMAIN] [--print-summary] [--json] --transit-webapp<FOLDER_NAME> <NEW_URI> 

The possibility to choose domain when creating an application was added to web interface as well.

Also, you can run simple commands from web interface (e.g. you can install packages from specific repositories or control web applications by means of django -admin).

Hide Python Selector icon

It is possible to hide or show Python Selector icons by marking or unmarking proper checkbox in LVE Manager Options tab.

The same result can be accomplished in CLI by running:

cloudlinux-config set --json --data '{"options":{"uiSettings":{"hideRubyApp":false, "hidePythonApp":false}}}'

Note

If you are using cPanel/WHM, you can also configure hide/show CloudLinux Python Selectors in WHM | Feature Manager. For that, you’d need to first uncheck Hide Python App in web-interface in the LVE Manager. This will make the menu appear for all accounts. After that, you are free to disable this app in WHM | Feature Manager for the required feature lists.

Ruby Selector

General information and requirements

We have the ability to deploy Ruby applications via application server. Ruby Selector uses mod_passenger to host Ruby.

This feature is available for CloudLinux 6 or later. It supports only cPanel servers.

You can find a list of supported alt-ruby versions using the following commands.

yum grouplist | grep alt-ruby

Installation and update

Note

The instructions below are suitable only for EasyApache 3 and EasyApache 4. You should follow this instruction if you use LiteSpeed.

To use Ruby Selector install alternative Ruby packages:

yum groupinstall alt-ruby 

To use MySQL database you should install alt-python27-devel package:

yum install alt-python27-devel

Note

After installation, please make sure that you have unmarked appropriate checkboxes in VE Manager Options tab to show Ruby App in web-interface. Find the instructions on the link.

Note

Adding Ruby modules requires executing permissions to gcc/make binaries. Please enable compilers in Compiler Access section of WHM, then run: cagefsctl --force-update

Note

See also Ruby Selector CLI

Configuration and using

End user access

  1. In Software/Services area choose Select Ruby Environment.

  1. Create project form will appear. Choose interpreter version for your application, application folder name (project path) and URI for accessing your application. Click “Create project” to create an application.

After a little while a new application entry will be appended to the web-page.

  1. You can edit path (folder name of the project in the home directory, for example, /home/clman1/project_name), uri for application, wsgi handler. If you click Edit - the value is converted to input field and thus becomes editable. When editing is complete, click Save .

  1. Wsgi entry is to specify python wsgi application entry point. It must be specified as filename, must be callable and separated by colon. If your app is running from file flask/run.py by calling callable app, set flask/run.py:app.

  1. When Show control is clicked, python extensions section will be expanded. It gives the ability to add or remove python modules. When start typing in input field, appropriate hints are shown in drop-down list. Choose the entry you want from drop-down and click Add .

If you click Delete, the corresponding module entry will disappear.

In addition to setting path, uri and wsgi, the interpreter version can be changed as well by changing the value in select drop-down.

  1. No changes are applied to application environment until Update button is clicked. Before the Update button is clicked, all changes can be reverted with Reset button.

The newly created application will be supplied with stub only. A real application ought to be put into application folder. After application is placed into application folder, the wsgi parameter can be set.

Click Remove to delete the application - the application folder itself will remain unmoved.

Note

For LVE Manager version 0.9-10 and higher

When creating an application you can use the key --domain, which attaches application to domain. If --domain key is not specified, then the main users domain will be used by default.

To create application run:

/usr/bin/selectorctl --interpreter=<ruby> --version=VERSION[--user=USER] [--domain=DOMAIN] [--print-summary] [--json]–-create-webapp <FOLDER_NAME> <URI>
When changing application URI, `--domain` key can be used simultaneously, in this case not only URI will be changed, but also the application domain.

To change application URI run:

/usr/bin/selectorctl --interpreter=<ruby> [--user=USER][--domain=NEW_DOMAIN] [--print-summary] [--json] --transit-webapp<FOLDER_NAME> <NEW_URI> 
The possibility to choose domain when creating an application was added to web interface as well.

Also, you can run simple commands from web interface (e.g. you can install packages from specific repositories or control web applications by means of django -admin).

Note

See also Ruby Selector CLI

Hide Ruby Selector icon

It is possible to hide or show Ruby Selector icon by marking or unmarking proper checkboxes in LVE Manager Options tab.

The same result can be accomplished in CLI by running:

cloudlinux-config set --json --data '{"options":{"uiSettings":{"hideRubyApp":false}}}'

Note

If you are using cPanel/WHM, you can also configure hide/show CloudLinux Ruby Selectors in WHM | Feature Manager. For that, you’d need to first uncheck Hide Ruby App in web-interface in the LVE Manager. This will make the menu appear for all accounts. After that, you are free to disable this app in WHM | Feature Manager for the required feature lists.

Deploying Redmine using Ruby Selector

Note

Provided instructions are valid for older Redmine version 2.6.0. New versions guide could be found at http://kb.cloudlinux.com/2016/12/how-to-run-redmine-with-ruby-selector/

  1. In cPanel create MySQL database and add user to it. In the example given, the databace redminet_redmine was created and user redminet_redmine was added.

  2. In Setup Ruby App section create an application.

App Directory is the directory where all static files will be placed ( e.g. redmine). App URI is web-interface URL ( e.g. redmine web-interface will be located in YOUR_DOMAIN/redmine).

  1. After the application was created, add the following modules: bundle, i18n#0.6.11, builder#3.0.4, rails#3.2.19, mime-types#1.25.1, mocha#1.0.0, jquery-rails#3.1.2, coderay, fastercsv, request_store, rbpdf, mysql2, selenium-webdriver, rmagick, shoulda#3.3.2, ruby-openid#2.3.0, request_store#1.0.5, capybara#2.1.0, net-ldap#0.3.1, rack-openid, shoulda-matchers#1.4.1, redcarpet#2.3.0, yard, rake#10.4.2, bigdecimal.

Note : If error occurs while installing rmagic module, then you need to install ImageMagick-devel package on your server:

yum install ImageMagick-devel
The installation process takes quite along time, about 7-8 minutes. When done, click Restart button to restart the application.

3.1 Alternatively, after the application was created, you can add only one module - bundle .

  1. Enter the server via SSH, using your cPanel account.

Download the application http://www.redmine.org/projects/redmine/wiki/Download .

In the description given, the latest version Redmine (2.6.0) is assumed.

http://www.redmine.org/releases/redmine-2.6.0.tar.gz tar xzf redmine-2.6.0.tar.gz

Hereinafter 'redmine' is App Directory meaning which was specified while setting Ruby application.

cp -R ~/redmine-2.6.0/* ~/redmine
cd ~/redmine/config
cp database.yml.example database.yml
Edit config/database.yml - add MySQL database connection settings to Production section.
cp -R ~/redmine/public/* ~/public_html/redmine/
cd ~/public_html/redmine
cat htaccess.fcgi.example >> .htaccess
cp dispatch.fcgi.example dispatch.fcgi
Go to cd ~/redmine directory.

Add gem "bigdecimal" line into Gemfile file.

Run alternately:

source ~/rubyvenv/redmine/2.1/bin/activate
~/rubyvenv/redmine/2.1/bin/bundle install
(if running the alternative installation)
~/rubyvenv/redmine/2.1/bin/rake generate_secret_token
RAILS_ENV=production ~/rubyvenv/redmine/2.1/bin/rake db:migrate
- Database migration;

RAILS_ENV=production ~/rubyvenv/redmine/2.1/bin/rake redmine:load_default_data

  • Loading default data into database.

EasyApache 4

Since cPanel/WHM version 66 provides ea-ruby24-mod_passenger (more information on the link), this allows creating Ruby applications with cPanel application manager.

CloudLinux already has Python and Ruby Selector , which allows creating applications with ea-apache24-mod-alt-passenger . However, it does not allow using cPanel application manager .

It is not correct to install both of those packages on the server because they contain the same passenger module for Apache web server.

The new ea-ruby24-mod_passenger is available for download from our updates-testing (beta) repository which allows you to run applications via cPanel application manager and Ruby Selector.

To install run:

# yum install lvemanager alt-python-virtualenv
# yum install ea-ruby24-mod_passenger --enablerepo=cl-ea4-testing

See also Ruby Selector CLI tools.

Node.js Selector

General information and requirements

Node.js Selector is a CloudLinux component that allows each user to easily create Node.js applications, choose Node.js version and other parameters for applications based on their needs.

Requirements

  • Node.js Selector supports Node.js versions 6.x, 8.x, 9.x and later.
  • This feature is available for CloudLinux 7, CloudLinux 6 hybrid and CloudLinux 6.
  • Node.js Selector requires LVE Manager 4.0 or later.
  • It supports cPanel and DirectAdmin servers (Plesk is not supported as it already has Node.js support.) For more details, please go to Plesk & Node.js documentation here and here .
  • For more details about mod_passenger and Node.js, please read documentation here and here .
  • Node.js Selector is working with EasyApache 3 and EasyApache 4.

Installation and update

Note

Node.js Selector support is added to LiteSpeed Web Server starting from the 5.3RC1 release. See details here.

cPanel

To use Node.js Selector, install Node.js packages by running the following command:

yum groupinstall alt-nodejs6 alt-nodejs8 alt-nodejs9
Also, please install LVE Manager, LVE Utils and Fusion Passenger by running the following command:
yum install lvemanager lve-utils ea-apache24-mod-alt-passenger
For EasyApache 3:
yum install lvemanager lve-utils alt-mod-passenger
And we recommend to install CageFS for better security (not mandatory) by running the following command:
yum install cagefs

Note

If during Node.js Selector usage on cPanel servers you get "ENOMEM npm ERR! errno-12" error, try to increase Memory limit in cPanel WHM → Server Configuration → Tweak Settings → System → Max cPanel process memory, then restart cPanel service with the following command to apply changes.

CloudLinux 7:

systemctl restart cpanel.service

CloudLinux 6:

service cpanel restart

DirectAdmin

To use Node.js Selector, please install Node.js packages by running the following command:

yum groupinstall alt-nodejs6 alt-nodejs8 alt-nodejs9
Also, please install LVE Manager, LVE Utils and Fusion Passenger by running the following command:
yum install lvemanager lve-utils alt-mod-passenger
And we recommend to install CageFS for better security (not mandatory) by running the following command:
yum install cagefs

Node.js deployment

  • The first approach - remote usage of Node.js Interpreters of different versions
  • The second approach - remote usage of the cloudlinux-selector utility.

Remote usage of Node.js interpreters

  1. Create a Node.js project in IntelliJ IDEA/WebStorm . You can download this archive and use it as a basis.
  2. Install alt-nodejs packages on the server in use. See installation instructions.
  3. Create an application on the server. You can do it by three ways:
  • Via UI of the Node.js plugin.
  • Using the following command to create an application:
cloudlinux-selector create --interprete=nodejs --json --app-root=<USER_NAME> --app-uri=<APP_NAME> --app-mode=develompent --version=<VERSION> --domain=<DOMAIN>

Note

In the IntelliJ IDEA you can create and run any remote script (Preferences — Remote SSH External Tools — Add).

  • Choose a location of the application on the server and synchronize the files with the IntelliJ IDEA project.
  1. Set up Run/Debug Configurations in the project created.

  • Specify a path to the remote Node.js interpreter. To be able to specify the remote interpreter, you should install the Node.js Remote Interpreter plugin first. Please find more information here , using server access credentials for a user (Main menu → Run → Edit configurations...) .
  • Specify initial JavaScript file that will be run with the node command (it is the app.js file from the archive).
  • Specify Path Mappings between a local and a remote project (Preferences → Deployments → Add) . If you have created your application with the cloudlinux-selector utility or via plugin UI the Path Mappings should be as follows:
/home/<USER_NAME>/<APP_NAME>
  1. Synchronize the project directories on the local and the remote machine as per Path Mappings specified.
  2. Deploy the modules on the remote and the local machine with the npm install command (if there are dependent modules). In the UI you can click the Run NPM Install button.
  3. Run Node.js application with the configuration set at the 4th step (Main menu → Run → Run… → Select configuration) .

  1. If you are using the application from the archive attached, you can see the running application on port 3003 — http://DOMAIN:3003 .

Note

The port should be available to a server user.

The following information should be displayed on this page:

  • A version of the running Node.js interpreter;
  • Current environment variables;
  • The current time.

So that, you can be sure that deployed modules are used properly.

If you’d like to use a different version of Node.js to run an application, change a path to the interpreter in the configuration settings of the running.
To apply all changes to the project, synchronize all changes with the server and restart the running application.

  1. To debug a script, set breakpoints in the code and run the configuration via Main Menu (Main menu → Run → Debug… → Select configuration) .

Useful links:

Note

It is not required to install Passenger while working in IDE if you are using this approach.

Remote usage of the cloudlinux-selector utility

  1. Create an application via UI or with the command as described in the Remote Usage of Node.js Interpreters approach, step 3 (a,b).
  2. Set up project mapping on the local machine with the created remote application /home/<USER_NAME>/<APP_NAME> (Preferences → Deployments → Add).
  3. Set up the remote commands of cloudlinux-selector (Preferences → Remote SSH External Tools → Add) for the following actions:
  • Restart application;

  • Install packages;

  • Run script;

  • Change Node.js version for the application. You can see the running app at http://DOMAIN/APPLICATION_URL To apply all changes, restart the application.

  • See also Node.js Selector CLI tools.

  • See also Node.js Selector UI.

Troubleshooting

Debugging errors

Since alt-mod-passenger-5.3.7-2, directives such as PassengerFriendlyErrorPages and PassengerAppEnv are available for use from htaccess file. This allows end users to see errors from their application during the development process. For example, if you add one of the following lines to the htaccess file on the application page, you will see the information (if there was an error) similar to one on the picture.

PassengerAppEnv development
or
PassengerFriendlyErrorPages on

This is a much more convenient approach to developing an application and debugging errors. On the other hand, if these directives are turned off you will see:

In this case, there is no useful information for debugging errors and this is suitable for production mode. More information about PassengerFriendlyErrorPages and PassengerAppEnv.

Apache mod_lsapi PRO

General information and requirements

mod_lsapi PRO is an Apache HTTP Server module based on LiteSpeed Technologies API . It serves to execute PHP scripts on a web-server by analogy with other modules like mod_suphp, php-fpm, mod_php. However, mod_lsapi PRO usage offers excellent PHP performance, low memory footprint coupled with great security and support for opcode caching.

How does it work?

  1. Apache passes handling for PHP request to mod_lsapi PRO;
  2. mod_lsapi PRO use liblsapi to transfer request to lsphp parent process;
  3. lsphp is forking child process which executes the request and returns data to mod_lsapi PRO;
    mod_lsapi PRO integrates with Apache, allows to handle concurrent requests and manages the lsphp processes
  • If there are no requests for lsapi_backend_pgrp_max_idle seconds, lsphp parent process will be  terminated;
  • If there are no lsphp child processes available when a new request comes, the new lsphp child process will be created;
  • lsphp childs process concurrent requests simultaneously;
  • The maximum number of simultaneously running lsphp child processes can be set by the lsapi_backend_children directive.

What is lsphp?

lsphp - PHP + LSAPI. What is PHP LSAPI? LiteSpeed Server Application Programming Interface (LSAPI) is designed specifically for seamless, optimized communication between LiteSpeed Web Server and third-party web applications. Now with mod_lsapi PRO this protocol is available for Apache 2.2/2.4.

Using mod_lsapi PRO, we have seen the higher performance than Apache with mod_php, easier installation than php-fpm and easier integration with any control panel. mod_lsapi PRO means faster and more stable dynamic web pages.

Requirements

Currently, the mod_lsapi is not compatible with:

  • Apache mod_ruid2 - should be disabled;
  • Apache mod_itk - should be disabled;
  • PHP-FPM - should be disabled because PHP-FPM is also a PHP Handler just as mod_lsapi.

Optional requirements

  • Configured LVE containers for end-users ( recommended - higher security level );
  • Installed and configured mod_hostinglimitsfor Apache ( recommended - higher security level );
  • Installed mod_suexec for Apache and configured SuExecUserGroup directive for each virtual host ( recommended - higher security level );
  • Enabled CageFS for end-users ( recommended - higher security level );
  • PHP Selector with alt-php - an easy way to select different PHP versions for each end-user provided by CloudLinux;
  • ea-php - alternative to alt-php provided by cPanel (for cPanel only).

Installation

mod_lsapi PRO can be installed through YUM package manager, however, the installation process varies depending on the control panel.

Select the control panel you are using:

Note

See also mod_lsapi PRO.

Installing on cPanel servers with EasyApache 4

Install mod_lsapi PRO and related packages through YUM package manager as follows:

$ yum install liblsapi liblsapi-devel
$ yum install ea-apache24-mod_lsapi
After installing mod_lsapi PRO packages run the next command to setup mod_lsapi to cPanel:
$ /usr/bin/switch_mod_lsapi --setup
Now, when the module is installed, restart Apache to ensure that the mod_lsapi PRO is enabled:
$ service httpd restart
Now the lsapi handler is available for managing through cPanel MultiPHP Manager.

For more details about swith_mod_lsapi, please visit switch_mod_lsapi tool.

Installing on Plesk servers

Install mod_lsapi PRO and related packages through YUM package manager as follows:

$ yum install liblsapi liblsapi-devel
$ yum install mod_lsapi
Once completed, run the command to setup mod_lsapi PRO and register LSPHP handlers to Plesk Panel:
$ /usr/bin/switch_mod_lsapi --setup

Now, when the module is installed, restart Apache to ensure that mod_lsapi PRO is enabled:

$ service httpd restart

Now LSPHPXY alt-php PHP handlers are available for managing through Plesk PHP Settings.

For more details about swith_mod_lsapi, please visit switch_mod_lsapi tool.

Installing on DirectAdmin servers

Installation process is done with custombuild script:

$ cd /usr/local/directadmin/custombuild
$ ./build update
$ ./build set php1_mode lsphp
$ ./build php n
$ ./build apache
Restart Apache afterwards:
$ service httpd restart
Now all domains under php1_mode are using lsphp handler and no further actions are required to enable mod_lsapi PRO on DirectAdmin.

Installing on servers with no control panel

Install mod_lsapi PRO and related packages through YUM package manager as follows:

$ yum install liblsapi liblsapi-devel
$ yum install mod_lsapi
Once completed, run a command to setup mod_lsapi PRO:
$ /usr/bin/switch_mod_lsapi --setup
Now, when the module is installed, restart Apache to ensure that mod_lsapi PRO is enabled:
$ service httpd restart

If you are using an alternative Apache - httpd24 , then install mod_lsapi as follows:

$ yum install liblsapi liblsapi-devel
$ yum install httpd24-mod_lsapi
Once completed, run a command to setup mod_lsapi PRO:
$ /usr/bin/switch_mod_lsapi --setup
Now, when the module is installed, restart Apache to ensure that mod_lsapi PRO is enabled:
$ service httpd24 restart

For more details about swith_mod_lsapi, please visit switch_mod_lsapi tool.

Uninstalling

Uninstall mod_lsapi PRO is performed depending on your control panel.

Select the control panel you are using:

Uninstall procedure for cPanel servers with EasyApache 4

To remove lsapi handler from cPanel MultiPHP Manager and uninstall mod_lsapi PRO, run a command:

$ /usr/bin/switch_mod_lsapi --uninstall
Then remove packages with YUM package manager:
$ yum erase liblsapi liblsapi-devel ea-apache24-mod_lsapi
Restart Apache afterwards:
$ service httpd restart
Now mod_lsapi PRO is fully uninstalled.

Uninstall procedure for Plesk servers

To unregister LSPHP handlers and uninstall mod_lsapi PRO, run the command:

$ /usr/bin/switch_mod_lsapi --uninstall
Then remove packages with YUM package manager:
$ yum erase liblsapi liblsapi-devel mod_lsapi
Restart Apache afterwards:
$ service httpd restart
Now LSPHPXY alt-php PHP handlers and mod_lsapi PRO are fully uninstalled.

Uninstall procedure for DirectAdmin servers

Uninstall is done with custombuild script:

$ cd /usr/local/directadmin/custombuild
$ ./build update
$ ./build set php1_release [any other php mode]
$ ./build php n
$ ./build apache
The following PHP modes are available for DirectAdmin:
  • mod_php
  • fastcgi
  • php-fpm
  • suphp

Restart Apache afterwards:

$ service httpd restart
Now all domains under php1_mode are using the chosen handler and mod_lsapi PRO is fully uninstalled.

Uninstall procedure for servers with no control panel

To uninstall mod_lsapi PRO, run the command:

$ /usr/bin/switch_mod_lsapi --uninstall
Then remove packages with YUM package manager:
$ yum erase liblsapi liblsapi-devel mod_lsapi
$ rm [path to mod_lsapi.conf]
Restart Apache to restore the standard PHP handler:
$ service httpd restart

If you are using an alternative Apache: - httpd24, then uninstall mod_lsapi PRO as follows:

$ /usr/bin/switch_mod_lsapi --uninstall
Then remove packages with YUM package manager:
$ yum erase liblsapi liblsapi-devel httpd24-mod_lsapi
$ rm [path to mod_lsapi.conf]
Restart Apache afterwards:
$ service httpd24 restart
Now mod_lsapi PRO is fully uninstalled.

Configuration

In order to get mod_lsapi PRO work properly, you'll need to configure Apache. To do this, we use a separate lsapi.conf file.

First of all, for the mod_lsapi PRO work, you need to ensure that the module is loaded. In your lsapi.conf you need to make sure the LoadModule directive has not been commented out. A correctly configured directive may look like this:

LoadModule lsapi_module modules/mod_lsapi.so

In order to enable the module to process requests, you need to add the lsapi_engine directive to your lsapi.conf file as follows:

lsapi_engine On

The mod_lsapi PRO handler can be enabled using the AddType directive. The AddType directive tells Apache that a given filename extension should be handled by mod_lsapi PRO. Apache will assume that and will attempt to execute it when that particular resource is requested by a client.

AddType application/x-httpd-lsphp .php

If no handler is explicitly set for a request, the specified content type will be used as the handler name, therefore, please disable php.conf or any other PHP handler for using mod_lsapi PRO. In this example application/x-httpd-lsphp is a default handler by which mod_lsapi PRO process requests with lsphp binary from /usr/local/bin/ directory.

The final lsapi.conf configuration might look like this:

LoadModule lsapi_module modules/mod_lsapi.so


<IfModule lsapi_module>      
	lsapi_engine On      
	AddType application/x-httpd-lsphp .php      
	lsapi_backend_connect_timeout 100000
	lsapi_backend_connect_tries 10
	lsapi_backend_children 20
	lsapi_backend_pgrp_max_idle 30
	lsapi_backend_max_process_time 300
	lsapi_debug Off
</IfModule>

In order to mod_lsapi PRO work lsapi.conf should be loaded to Apache through Include directive.

For more detailed description of the module directives please visit Configuration reference.
For installation guide mod_lsapi PRO please visit Installation.

Configuration references

mod_lsapi customization:

Tuning LSPHP backend:

Connection pool mode:

CRIU support (CloudLinux 7 only):

PHP configuration management:

Security:

mod_lsapi customization

lsapi_engine

Syntax : lsapi_engine on/off
Default : lsapi_engine off
Context : httpd.conf, htaccess

Description :
Switching mod_lsapi handler on or off.


lsapi_socket_path

Syntax : lsapi_socket_path [path] Default : lsapi_socket_path /var/run/mod_lsapi
Context : httpd.conf

Description:
Path to backend lsphp sockets. By default /var/run/mod_lsapi


lsapi_poll_timeout

Syntax : lsapi_poll_timeout [number]
Default : lsapi_poll_timeout 300
Context : httpd.conf, htaccess

Description :
Time to wait for response from the lsphp daemon, in seconds. 0 stands for infinity. For preventing long running processes which can use EP (limit number of entry processes). Default value is 300. Should be more or equal to 0. In the case of wrong format, the default value will be used.


lsapi_per_user

Syntax : lsapi_per_user On/Off
Default : lsapi_per_user Off
Context : httpd.conf

Description :
Invoke master lsPHP process not per VirtualHost but per account. When On, invoke backend not per VirtualHost but per account. Default value is Off. It is possible, for example, to set it to On in global config file and to Off in config files of some particular Virtual Hosts. Then these Virtual Hosts will have a dedicated backend process, while others will have backend processes shared on account basis.


lsapi_output_buffering

Syntax : lsapi_output_buffering On/Off
Default : lsapi_output_buffering On
Context : httpd.conf, virtualhost, htaccess

Description :
Enable or disable output buffering on Apache level. Default value is On.


lsapi_disable_reject_mode

Syntax : lsapi_disable_reject_mode On/Off
Default : lsapi_disable_reject_mode Off
Context : httpd.conf, virtualhost

Description :
If a new HTTP request is coming to LSPHP daemon when all LSPHP workers are still busy, it can process this situation in two different ways. In REJECT mode LSPHP daemon will reject such request immediately. Otherwise, in legacy mode, LSPHP daemon will put this request into infinite queue, until one or more LSPHP daemon becomes free. When HTTP request is rejected in REJECT mode, mod_lsapi will write into Apache error_log the following message: Connect to backend rejected, and the client will receive 507 HTTP response. By default LSPHP daemon in CloudLinux uses REJECT mode. It can be switched off with this option.


lsapi_terminate_backends_on_exit

Syntax : lsapi_terminate_backends_on_exit On/Off
Default : lsapi_terminate_backends_on_exit On
Context : httpd.conf

Description :
httpd.conf, On - stop lsphp services on apache restart, Off - leave live started lsphp services on apache restart (for php+opcache). The lsphp will not restart, even if Apache gets restarted.


lsapi_avoid_zombies

Syntax : lsapi_avoid_zombies On/Off
Default : lsapi_avoid_zombies Off
Context : httpd.conf, virtualhost

Description :
Enable or disable a mechanism to avoid creation of zombie processes by lsphp. Default value is Off.


lsapi_use_req_hostname

Syntax : lsapi_use_req_hostname On/Off
Default : lsapi_use_req_hostname Off
Context : httpd.conf, virtualhosts

Description :
By default, we are using hostname from the server_rec structure (off), it means that mod_lsapi takes hostname from the VirtualHost section of the configuration file. Using hostname from the request_rec structure (On) means that mod_lsapi takes hostname from the HOST section of the request. It could be useful for those who use dynamically generated configs for virtual hosts for example with mod_lua.


lsapi_sentry

Syntax : lsapi_sentry On/Off
Default : lsapi_sentry On
Context : httpd.conf

Description :
When this option is enabled, errors that occur in the operation of the mod_lsapi will be sent to the remote sentry server. You can see the error messages that were sent to the sentry server in the directory /var/log/mod_lsapi. If you do not want to send error notifications from your server, you can disable this directive in lsapi.conf.


lsapi_debug

Syntax : lsapi_debug On/Off
Default : lsapi_debug Off
Context : httpd.conf, virtualhost

Description :
Extended debug logging.


Tuning LSPHP backend

lsapi_set_env

Syntax : lsapi_set_env VAR_NAME [VAR_VALUE]
Default : -
Context : httpd.conf

Description :
Pass env variable to lsphp. By default lsphp environment have only TEMP, TMP and PATH variables set.
Example: lsapi_set_env TMP "/var/lsphp-tmp"
Note: PATH env var default "/usr/local/bin:/usr/bin:/bin" cannot be changed because of security reasons.
To change it, use explicitly lsapi_set_env_path option.


lsapi_set_env_path

Syntax : lsapi_set_env_path [path(s)]
Default : lsapi_set_env_path /usr/local/bin:/usr/bin:/bin
Context : httpd.conf

Description :
Change PATH variable in the environment of lsPHP processes. Default path /usr/local/bin:/usr/bin:/bin will be used if not set.


lsapi_backend_children

Syntax : lsapi_backend_children [number]
Default : lsapi_backend_children [EP]
Context : httpd.conf

Description :
Sets env variable LSAPI_CHILDREN
Maximum number of simultaneously running child backend processes.
Optional, a default value is equal to EP.
min value is 2; max value is 10000. If var value is more, 10000 will be used.


lsapi_backend_connect_tries

Syntax : lsapi_backend_connect_tries [number]
Default : lsapi_backend_connect_tries 20
Context : httpd.conf

Description :
Number of retries to connects to lsPHP daemon.


lsapi_backend_connect_timeout

Syntax : lsapi_backend_connect_timeout [number]
Default : lsapi_backend_connect_timeout 500000
Context : httpd.conf

Description :
Number of usec to wait while lsPHP starts (if not started on request).


lsapi_backend_max_process_time

Syntax : lsapi_backend_max_process_time [number]
Default : lsapi_backend_max_process_time 300
Context : httpd.conf

Description :
Sets env variable LSAPI_MAX_PROCESS_TIME
Optional. Default value is 300.
Timeout to kill runaway processes.


lsapi_backend_pgrp_max_idle

Syntax : lsapi_backend_pgrp_max_idle [number]
Default : lsapi_backend_pgrp_max_idle 30
Context : httpd.conf

Description :
Sets env variable LSAPI_PGRP_MAX_IDLE, in seconds.
Controls how long a control process will wait for a new request before it exits. # 0 stands for infinite.
Optional, default value is 30.
Should be more or equal to 0.


lsapi_backend_use_own_log

Syntax : lsapi_backend_use_own_log On/Off
Default : lsapi_backend_use_own_log Off
Context : httpd.conf, virtualhost, htaccess

Description :
Redirecting log output of backend processes from Apache error_log to dedicated log file or files, depending on value of lsapi_backend_common_own_log option. If Off, use Apache error log file for backend output, or separate file otherwise.


lsapi_backend_common_own_log

Syntax : lsapi_backend_common_own_log On/Off
Default : lsapi_backend_common_own_log Off
Context : httpd.conf, virtualhost, htaccess

Description :
It will be used only when lsapi_backend_use_own_log set to On. On - backend processes of the all virtual hosts will share the common log file. Off - every virtual host will have its own backend log file.


lsapi_backend_coredump

Syntax : lsapi_backend_coredump On/Off
Default : lsapi_backend_coredump Off
Context : httpd.conf, htaccess

Description :
env variable LSAPI_ALLOW_CORE_DUMP (On or Off). Pass LSAPI_ALLOW_CORE_DUMP to lsphp or not. If it will be passed - core dump on lsphp crash will be created.
Off by default.
By default LSAPI application will not leave a core dump file when crashed. If you want to have LSAPI PHP dump a core file, you should set this environment variable. If set, regardless the value has been set to, core files will be created under the directory that the PHP script in.


lsapi_backend_accept_notify

Syntax : lsapi_backend_accept_notify On/Off
Default : lsapi_backend_accept_notify On
Context : httpd.conf, virtualhost

Description :
Switch LSAPI_ACCEPT_NOTIFY mode for lsphp. This option can be used both in Global and VirtualHost scopes.This mode is incompatible with PHP 4.4.


lsapi_backend_pgrp_max_reqs

Syntax : lsapi_backend_prgrp_max_reqs [number]
Default : lsapi_backend_max_reqs 0
Context : httpd.conf, virtualhost

Description :
Controls how many requests a control process will process before it exits. Should be more or equal to 0. In the case of wrong format, a default value will be used. Optional, the default value is 0, which means an unlimited number of requests.


lsapi_backend_pgrp_max_crashes

Syntax : lsapi_backend_prgrp_max_crashes [number]
Default : lsapi_backend_max_crashes 0
Context : httpd.conf, virtualhost

Description :
Controls how many crashes of its worker processes a control process will detect before it exits. Should be more or equal to 0. In the case of wrong format, a default value will be used. Optional, the default value is 0, which means an unlimited number of crashes.


Connection pool mode

lsapi_with_connection_pool

Syntax : lsapi_with_connection_pool On/Off
Default : lsapi_with_connection_pool Off
Context : httpd.conf

Description :
On/Off - disable enable connect pool, default is Off.


lsapi_backend_max_idle

Syntax : lsapi_backend_max_idle [number]
Default : lsapi_backend_max_idle 300
Context : httpd.conf

Description :
It is relevant only with lsapi_with_connection_pool option switched on. Controls how long a worker process will wait for a new request before it exits. 0 stands for infinite. Should be more or equal to 0. In the case of wrong format default value will be used. Optional, default value is 300.


lsapi_backend_max_reqs

Syntax : lsapi_backend_max_reqs [number]
Default : lsapi_backend_max_reqs 10000
Context : httpd.conf

Description :
It is relevant only with lsapi_with_connection_pool option switched on. Controls how many requests a worker process will process before it exits. Should be more than 0. In the case of wrong format default value will be used. Optional, default value is 10000.


CRIU support (CloudLinux 7 only)

lsapi_criu

Syntax : lsapi_criu On/Off
Default : lsapi_criu Off
Context : httpd.conf

Description :
Enable/disable CRIU for lsphp freezing. Default: Off.


lsapi_criu_socket_path

Syntax : lsapi_criu_socket_path [path]
Default : lsapi_criu_socket_path /var/run/criu/criu_service.socket
Context : httpd.conf

Description :
Set path to socket for communication with criu service. Default: /var/run/criu/criu_service.socket.


lsapi_criu_imgs_dir_path

Syntax : lsapi_criu_imgs_dir_path [path]
Default : lsapi_criu_imgs_dir_path /var/run/mod_lsapi/
Context : httpd.conf

Description :
Path to folder where images of freezed PHP will be stored. Should be path. Default: /var/run/mod_lsapi/


lsapi_backend_initial_start

Syntax : lsapi_backend_initial_start [number]
Default : lsapi_backend_initial_start 0
Context : httpd.conf

Description :
Number of requests to virtualhost, when lsphp will be freezed. Default: 0 - means disable freezing.


lsapi_criu_use_shm

Syntax : lsapi_criu_use_shm Off/Signals
Default : lsapi_criu_use_shm Off
Context : httpd.conf

Description :
Method of requests counting. Off - use shared memory. Signals - use signals from child processes to parent. Default: Off


lsapi_backend_semtimedwait

Syntax : lsapi_backend_semtimedwait On/Off
Default : lsapi_backend_semtimedwait On
Context : httpd.conf

Description :
Use semaphore for checking when lsphp process will be started. Speed of start lsphp increased with semaphore using. This method avoid cycles of waiting for lsphp start. Default: On.


lsapi_reset_criu_on_apache_restart

Syntax : lsapi_reset_criu_on_apache_restart On/Off
Default : lsapi_reset_criu_on_apache_restart Off
Context : httpd.conf, virtualhost

Description :
This option allows cleaning all CRIU images on Apache restart.
Setting lsapi_reset_criu_on_apache_restart to On means that on each Apache restart the CRIU images which are stored in directory specified by lsapi_criu_imgs_dir_path directive will be recreated on new request to domain(only after restart).
If this option set to Off then CRIU images won’t be recreated on Apache restart.


PHP configuration management

lsapi_process_phpini

Syntax : lsapi_process_phpini On/Off
Default : lsapi_process_phpini Off
Context : httpd.conf, virtualhost, directory

Description :
Enable or disable phpini_* directive processing. Default value is Off.


lsapi_phpini

Syntax : lsapi_phpini [path]
Default : lsapi_phpini -
Context : httpd.conf, virtualhost, htaccess

Description :
When lsapi_process_phpini option switched to Off, these values will be silently ignored. lsapi_phpini values with absolute filename of php.ini file can be inserted into .htaccess files in order to set custom php.ini which will override/complement settings from system default php.ini.


lsapi_phprc

Syntax : lsapi_phprc [No | Env | Auto | DocRoot]
Default : lsapi_phprc No
Context : httpd.conf, virtualhost

Description : The value of PHPRC env variable.
Special values are "No", "Env", "Auto" and "DocRoot".
Default value is "No" - without PHPRC at all.
"Auto" value stands for php.ini from DocumentRoot of the corresponding VirtualHost if it is present, or from user's home directory otherwise "DocRoot" value stands for php.ini from DocumentRoot of the corresponding VirtualHost.
"Env" value for using PHPRC from the environment, to set it with SetEnv config option, for example
lsapi_phprc No
lsapi_phprc Auto
lsapi_phprc DocRoot
lsapi_phprc Env
lsapi_phprc /etc/


lsapi_tmpdir

Syntax : lsapi_tmpdir [path]
Default : lsapi_tmpdir /tmp
Context : httpd.conf, virtualhost

Description :
Set alternate request body temporary files directory.


lsapi_enable_user_ini

Syntax : lsapi_enable_user_ini On/Off
Default : lsapi_enable_user_ini Off
Context : httpd.conf, virtualhost

Description :
Enable .user.ini files for backend. Same as suphp, php-fpm and fcgid mechanism of .user.ini. Default value is Off.


lsapi_user_ini_homedir

Syntax : lsapi_user_ini_homedir On/Off
Default : lsapi_user_ini_homedir Off
Context : httpd.conf, virtualhost

Description :
If lsapi_enable_user_ini option is set to On, then enable/disable processing .user.ini file in home directory also. Default value is Off.


lsapi_keep_http200

Syntax : lsapi_keep_http200 On/Off
Default : lsapi_keep_http200 Off
Context : httpd.conf, .htaccess

Description :
If set to On, always keep backend's response status as mod_php do. If set to Off, response status can be overridden by Apache as suphp do (in case of call via ErrorDocument directive).


lsapi_mod_php_behaviour

Syntax : lsapi_mod_php_behaviour On/Off
Default : lsapi_mod_php_behaviour On
Context : httpd.conf, virtualhost, directory

Description :
On/Off - disable php_* directives, default On.


php_value, php_admin_value, php_flag, php_admin_flag

Syntax : [php_value|php_admin_value|php_flag|php_admin_flag]
Default :
Context : httpd.conf, virtualhost, htaccess

Description :
mod_php emulation.


Security

lsapi_use_suexec

Syntax : lsapi_use_suexec On/Off
Default : lsapi_use_suexec On
Context : httpd.conf

Description :
Use or not suexec to a target user.


lsapi_user_group

Syntax : lsapi_user_group [user_name] [group_name]
Default : -
Context : httpd.conf, virtualhost, directory

Description :
Set user & group for requests.


lsapi_uid_gid

Syntax : lsapi_uid_gid [uid] [gid]
Default : -
Context : httpd.conf, virtualhost, directory

Description :
Set user & group for request.


lsapi_use_default_uid

Syntax : lsapi_use_default_uid On/Off
Default : lsapi_use_default_uid On
Context : httpd.conf

Description :
Use default Apache UID/GID if no uid/gid set. Values: On/Off. If Off, and no UID/GID set, error 503 will be returned.


lsapi_target_perm

Syntax : lsapi_target_perm On/Off
Default : lsapi_target_perm Off
Context : httpd.conf

Description :
Check target PHP script permissions. If set to On, lsapi will check that script is owned by the same user, as user under which it is being executed. Return 503 error if they don't match. Default: Off.


lsapi_paranoid

Syntax : lsapi_paranoid On/Off
Default : lsapi_paranoid Off
Context : httpd.conf

Description :
Check or not permissions of target php scripts. Optional, default value is Off.


lsapi_check_document_root

Syntax : lsapi_check_document_root On/Off
Default : lsapi_check_document_root On
Context : httpd.conf

Description :
Check or not owner of DOCUMENT_ROOT. Optional, default value is On.


lsapi_disable_forced_pwd_var

Syntax : lsapi_disable_forced_pwd_var On/Off
Default : lsapi_disable_forced_pwd_var Off
Context : httpd.conf, virtualhost

Description :
To disable addition of PWD variable. Default value is Off. If set to On, the PWD variable will not be added into a backend environment.


lsapi_max_resend_buffer

Syntax : lsapi_max_resend_buffer [number]tmp
Default : lsapi_max_resend_buffer 200
Context : httpd.conf, virtualhost

Description :
Maximum buffer in KiB to resend for request that has a body (like POST request body).

See also Apache mod_lsapi PRO CLI tools.

Troubleshooting

Debugging mod_lsapi issues: error_log & sulsphp_log

mod_lsapi errors will be located in error_log and sulsphp_log. Note that errors can appear in both logs at the same time, and you might need to refer to both of them to solve the issue.

See next table for more details:

error_log sulsphp_log Solution
Could not connect to lsphp backend: connect to lsphp failed: 111 Connection refused. Increase memory limit for LVE ID uid: (xxx/xxxxxxxx) gid: (xxx/xxxxxxxxxx) cmd: /usr/local/bin/lsphp Increase pmem or vmem limits for the user uid.
Error sending request: ReceiveLSHeader: nothing to read from backend socket No need to check this log. lsphp was killed. It can be due to apache restart or lfd. If you see this message too often - change lsapi_terminate_backends_on_exit to Off in lsapi.conf or add to /etc/csf/csf.pignore the following lines: exe:/usr/local/bin/lsphp pexe:/opt/alt/php.*/usr/bin/lsphp
Error sending request (lsphp is killed?): ReceiveLSHeader: nothing to read from backend socket, referer: http://XXXXXXX Child process with pid: XXXXX was killed by signal: 11, core dump: 0 No need to check this log. lsphp has crashed. Next slide will explain what to do (core dump creating). Also, check configuration options for apc and suhosin in php.ini. Once you have a core file generated at DocumentRoot contact https://cloudlinux.zendesk.com/ so we can investigate the cause.
Could not connect to lsphp backend: connect to lsphp failed: 111 Connection refused file is writable by others: (///usr/local/bin/lsphp) Incorrect lsphp file permissions. For fixing: chmod 755 /usr/local/bin/lsphp cagefsctl --force-update.
Could not determine uid/gid for request No need to check this log. UID/GID are not set in virtualhost. Set lsapi_use_default_uid On in lsapi.conf (it is On by default since 0.1-98 version, this solution is for older versions).
Own id for script file (/xxxx/xxx/xxxx) is xxx; should be xxxx No need to check this log. File is not owned by the user PHP executed by. To overwrite (insecure), set lsapi_target_perm Off in lsapi.conf.
Could not connect to lsphp backend: connect to lsphp failed: 111 Connection refused Entering jail error Check if СageFS enabled. Try running cagefsctl --remount-all.
connect_lsphp: connect to lsphp failed: tries XXX exceeded with timeout XXXXX Could not connect to lsphp backend: connect to lsphp failed: 111 Connection refused uid: (xxx/xxxxxxxx) gid: (xxx/xxxxxxxxxx) cmd: /usr/local/bin/lsphp Check if /tmp/lshttpd (global /tmp is not inside CageFS) exists and owner should be apache: apache for DirectAdmin, Plesk, iWorx, ISPManager and nobody for cPanel.
Backend error on sending request(GET /XXXX HTTP/1.1); uri(/XXXX) content-length(0) (lsphp is killed?): ReceiveAckHdr: backend process reset connection: errno 104 (possibly memory limit for LVE ID XXXX too small) uid: (xxx/xxxxxxxx) gid: (xxx/xxxxxxxxxx) cmd: /usr/local/bin/lsphp Increase PMEM limits for the user UID.
Reached max children process limit: XX, extra: 0, current: XX, please increase LSAPI_CHILDREN.

Backend error on sending request(GET /XXXX HTTP/1.1); uri(/XXXX) content-length(0) (lsphp is killed?): ReceiveAckHdr: backend process reset connection: errno 104 (possibly memory limit for LVE ID XXXX too small)
uid: (xxx/xxxxxxxx) gid: (xxx/xxxxxxxxxx) cmd: /usr/local/bin/lsphp Increase value of lsapi_backend_children for UID in vhost.conf or globally in lsapi.conf.
fork() failed, please increase process limit: Cannot allocate memory

Backend error on sending request(GET /XXXX HTTP/1.1); uri(/XXXX) content-length(0) (lsphp is killed?): ReceiveAckHdr: backend process reset connection: errno 104 (possibly memory limit for LVE ID XXXX too small)
uid:(xxx); gid:(xxx); uid limit warning: EP should be < than NPROC, current EP: XX, NPROC: XX

uid: (xxx/xxxxxxxx) gid: (xxx/xxxxxxxxxx) cmd: /usr/local/bin/lsphp
Increase NPROC limits for the UID. It should be greater than EP and lsapi_backend_children.
Child process with pid: XXXXXX was killed by signal: 9, core dump: 0

Backend error on sending request(GET /XXXX HTTP/1.1); uri(/XXXX) content-length(0) (lsphp is killed?): ReceiveAckHdr: nothing to read from backend socket (LVE ID XXXX
uid: (xxx/xxxxxxxx) gid: (xxx/xxxxxxxxxx) cmd: /usr/local/bin/lsphp These errors occurs when the amount of PMEM limits is incommensurable with the number of EP. Increase PMEM limits or decrease EP number for the user UID.
totBytesRead (X) != bodyLen (X), referer: XXXX

Backend error on sending request(POST /XXXX HTTP/1.1); uri(/XXXX) content-length(X) (lsphp is killed?): ReceiveAckHdr: nothing to read from backend socket (LVE ID XXXX)

lsphp(XXXX): Child process with pid: XXXX was killed by signal: 15, core dump: 0
No need to check this log. Increase LimitRequestBody (Apache) or/and SecRequestBodyNoFilesLimit (mod_security) configuration limits
Connect to backend failed: connect to lsphp failed: 13 No need to check this log. Check that mod_ruid2 is disabled
Connect to backend rejected on sending request(POST /XXXXX HTTP/1.1); uri(/XXXXX) No need to check this log. Set lsapi_disable_reject_mode On in your lsapi.conf and reload Apache. This way LSPHP daemon will put requests that cannot be served by LSPHP daemon right away into infinite queue, until one or more LSPHP daemon becomes free. Visit Configuration Reference for more info.

Non-standard apache user

If apache runs under a username other than "apache" or "nobody" , you should rebuild sulsphp (where username is built in for security reasons) with corresponding username:

$ yum install liblsapi liblsapi-devel   
$ cd ~$ wget [http://repo.cloudlinux.com/cloudlinux/sources/da/mod_lsapi.tar.gz](http://repo.cloudlinux.com/cloudlinux/sources/da/mod_lsapi.tar.gz)  
$ tar zxvf mod_lsapi.tar.gz  
$ cd mod-lsapi-0.1-37  
$ cmake -DHTTPD_USER=<new user name> .  
$ make
$ make install
This will:
- Install: /usr/lib/apache/mod_lsapi. so (or to another correct httpd modules path)
- Install: /usr/sbin/sulsphp

lsphp started under user apache/nobody

Check if SuExecUserGroup specified for virtual hosts. This parameter is used by mod_lsapi for user identification.

Could not connect to lsphp backend: connect(/tmp/lshttpd/lsapi_application-x-httpd-lsphp_XXX.sock) failed: 111 Connection refused

  • Switch in lsapi.conf or mod_lsapi.conf value to: lsapi_terminate_backends_on_exit Off

  • Check if empty: cat /etc/cron.d/kill_orphaned_php-cron | grep lsphp , then run:

yum install lve-utils
Then restart cron service.

Running PHP for users with UID < 99

If you need to run PHP using mod_lsapi using users with UID < 99, you would need to re-compile sulsphp:

$ yum install liblsapi liblsapi-devel
$ cd ~
$ wget [http://repo.cloudlinux.com/cloudlinux/sources/da/mod_lsapi.tar.gz](http://repo.cloudlinux.com/cloudlinux/sources/da/mod_lsapi.tar.gz)
$ tar zxvf mod_lsapi.tar.gz
$ cd mod-lsapi-0.1-XX
$ cmake -DUID_MIN=80 -DGID_MIN=80 .
$ make
$ make install
will be installed
- Installing: /usr/lib/apache/mod_lsapi.so (or another httpd modules path)
- Installing: /usr/sbin/sulsphp

Apache binary called not httpd (httpd.event, httpd.worker)

$ yum install liblsapi liblsapi-devel 
$ cd ~
$ wget http://repo.cloudlinux.com/cloudlinux/sources/da/mod_lsapi.tar.gz        
$ tar zxvf mod_lsapi.tar.gz
$ cd mod-lsapi-0.1-XX
$ cmake -DPARENT_NAME="<apache binary name>".
$ make
$ make install
Will be installed:
- Installing: /usr/lib/apache/mod_lsapi.so (or another httpd modules path)
- Installing: /usr/sbin/sulsphp

WHMCS Status page not accessible after installing CL and mod_lsapi (cPanel).

  • add user: useradd userstat
  • add to file (to the end of file before ) /usr/local/apache/conf/conf.d/lsapi.conf: <Directory /usr/local/apache/htdocs/> lsapi_user_group userstat userstat
  • service httpd restart

This is safe solution for easyapache rebuilding and cpanel-mod-lsapi updating.

PHP page with Suhosin return 503 error

Make php.ini for suhosin as recommended below:

[suhosin]
suhosin.simulation = Off
suhosin.mail.protect = 1
suhosin.cookie.disallow_nul = Off
suhosin.cookie.max_array_depth = 1000
suhosin.cookie.max_array_index_length = 500
suhosin.cookie.max_name_length = 500
suhosin.cookie.max_totalname_length = 500
suhosin.cookie.max_value_length = 200000
suhosin.cookie.max_vars = 16384
suhosin.get.disallow_nul = Off
suhosin.get.max_array_depth = 1000
suhosin.get.max_array_index_length = 500
suhosin.get.max_name_length = 500
suhosin.get.max_totalname_length = 500
suhosin.get.max_value_length = 1000000
suhosin.get.max_vars = 16384
suhosin.post.disallow_nul = Off
suhosin.post.max_array_depth = 1000
suhosin.post.max_array_index_length = 500
suhosin.post.max_name_length = 500
suhosin.post.max_totalname_length = 500
suhosin.post.max_value_length = 1000000
suhosin.post.max_vars = 16384
suhosin.request.disallow_nul = Off
suhosin.request.max_array_depth = 1000
suhosin.request.max_array_index_length = 500
suhosin.request.max_totalname_length = 500
suhosin.request.max_value_length = 1000000
suhosin.request.max_vars = 16384
suhosin.request.max_varname_length = 524288
suhosin.upload.max_uploads = 300
suhosin.upload.disallow_elf = Off
suhosin.session.cryptua = Off
suhosin.session.encrypt = Off
suhosin.session.max_id_length = 1024
suhosin.executor.allow_symlink = Off
suhosin.executor.disable_eval = Off
suhosin.executor.disable_emodifier = Off
suhosin.executor.include.max_traversal = 8

PHP page with APC return 503 error

Make php.ini for APC as recommended below:

[apc]...apc.shm_segments=1apc.shm_size=32...
shared memory should be not less than 32MB

Messages appearing in error_log: Child process with pid: XXXXX was killed by signal: 11, core dump: 0

This means that lsphp was crashed. The solution is:

  • Check if apc for user enabled. Tune its options as described in previous slide.
  • Check if suhosin is enabled for user. Tune its options as described in this article.
  • If previous items do not help, contact us at https://helpdesk.cloudlinux.com/

How to get lsphp core dump on crash

  • Configure mod_lsapi to allow lsphp to generate core dumps. In mod_lsapi.conf:
lsapi_backend_coredump On
  • Enable core file generation in sysctl:
sysctl -w ‘kernel.core_uses_pid=1’
sysctl -w ‘kernel.core_pattern=core.%p’
  • Configure system to change max size of core files. In /etc/security/limits.conf add:
user1 soft core unlimited
user1 hard core unlimited
where user1 is the username for which lsphp crashes.
  • If /etc/profile.d/limits.sh exists, look up for the following lines:
if [ "$LIMITUSER" != "root" ]; then
ulimit -n 100 -u 35 -m 200000 -d 200000 -s 8192 -c 200000 -v unlimited 2>/dev/null
Substring “-c 200000” must be replaced with “-c unlimited” .
  • Add line into ulimit -c unlimited into apachectl script just after another invokes of the ulimit command.

  • Do cold restart of Apache with the command like this:

service httpd stop; sleep 2; killall lsphp; service httpd start
  • You can make sure that ulimit for lsphp is changed to unlimited successfully with the following command:
cat /proc/PID/limits | grep ‘Max core file size’

where PID is a pid of any lsphp process. ps -u user1 | grep lsphp

  • Core dump of lsphp will be created in the DocumentRoot of the corresponding virtual server. On cPanel server it should map to

mod_lsapi is not included in output of httpd -M after installation and setup command for cPanel EasyApache 3

  1. Check if the file /usr/local/apache/conf/conf.d/lsapi.conf exists and not empty;

  2. Check if output of the command

cat /usr/local/apache/conf/httpd.conf | grep "/usr/local/apache/conf/conf.d/\*\.conf"
is not empty.

If it is empty:

  1. Add to "include" section of /var/cpanel/conf/apache/main string:

"include": '"/usr/local/apache/conf/conf.d/*.conf"'
 "include":
 "directive": 'include'
 "items":
 ...
 -
 "include": '"/usr/local/apache/conf/conf.d/*.conf"' 
 "listen":
  1. Do:
mkdir -p /usr/local/apache/conf/conf.d/;                                                                                 
cp /usr/share/lve/modlscapi/confs/lsapi.conf /usr/local/apache/conf/conf.d/lsapi.conf
  1. Call:
/scripts/rebuildhttpdconf/scripts/restartsrv_httpd

See also mod_lsapi PRO FAQ here.

CRIU Support

Note

CloudLinux 7 only

CRIU is Checkpoint/Restore In Userspace , (pronounced kree-oo ), is a software tool for Linux operating system. Using this tool, you can freeze a running application (or part of it) and checkpoint it as a collection of files on disk. You can then use the files to restore the application and run it exactly as it was during the time of freeze (more information on the link https://criu.org/Main_Page ).

mod_lsapi-1.1-1 is the first beta version with freezing PHP implemented. mod_lsapi now supports the following parameters:

Option name Description Values Default
lsapi_criu Enable/disable CRIU for lsphp freezing. On/Off Off
lsapi_criu_socket_path Set path to socket for communication with criu service. [path to socket] /var/run/criu/criu_service.socket
lsapi_backend_semtimedwait Enable/disable flag for notification about lsphp started. This method avoid cycles of waiting for lsphp start. On/Off On
lsapi_backend_initial_start Number of request when lsphp should be freezed. [number] 0 - no freezing 0
lsapi_criu_use_shm Method of requests counting. Off - use shared memory. Signals - use signals from child processes to parent. Off/Signals Off
lsapi_criu_imgs_dir_path Path to folder where imgs of freezed PHP will be stored. [path] /var/run/mod_lsapi/
lsapi_criu_debug Enable/Disable CRIU related debug logging. On/Off Off

Example:

lsapi_criu On
lsapi_criu_socket_path /var/run/criu/criu_service.socket
lsapi_backend_semtimedwait On
lsapi_backend_initial_start 15
lsapi_criu_use_shm Off
lsapi_criu_debug Off

When Apache module mod_lsapi detects CRIU enabled (lsapi_criu On) it prepares a directory for images (on the first request of virtualhost) to store ( lsapi_criu_imgs_dir_path /var/run/mod_lsapi/[dir_name] ), and starts lsphp process. Lsphp increases counter ( lsapi_criu_use_shm Off|Signals ) via shared memory or signals, when counter reaches limit ( lsapi_backend_initial_start 15 ), lsphp sends the request to CRIU for freezing. CRIU service makes images of requested processes. Lsphp will not be frozen if counter has not reached the limit. The next time when lsphp will be stopped, it will be unfrozen from the images.

The images of the processes will be saved even if Apache is restarted. But all images will be deleted after server restart by default configuration. This can be modified by setting the new path lsapi_criu_imgs_dir_path .

Important! If php.ini or configuration file from php.d is changed, the images must be deleted manually.

Note that CRIU (version lower than criu-lve-3.6-1) can't correctly freeze lsphp with PrivateTmp enabled. For correct work, PrivateTmp must be false in httpd.service file . For disabling:

Copy httpd.service to /etc/systemd/system and change there PrivateTmp:  

# cat httpd.service
[Unit]
Description=Apache web server managed by cPanel Easy
ApacheConditionPathExists=!/etc/httpddisable
ConditionPathExists=!/etc/apachedisable
ConditionPathExists=!/etc/httpdisable

[Service]Type=forking
ExecStart=/usr/local/cpanel/scripts/restartsrv_httpd --no-verbose
PIDFile=/var/run/apache2/httpd.pid
PrivateTmp=false 

[Install]
WantedBy=multi-user.target 
Or it would be technically better to provide a small override of service file rather than copying the whole new version in /etc/systemd/system

http://www.freedesktop.org/software/systemd/man/systemd.unit.html

mkdir /etc/systemd/system/httpd.service.d
echo "[Service]" >  /etc/systemd/system/httpd.service.d/nopt.conf
echo "PrivateTmp=false" >> /etc/systemd/system/httpd.service.d/nopt.conf

and

# systemctl daemon-reload

Installation

Criu is installed with dependency to mod_lsapi-1.1 package. To activate it:

  1. Enable service and start it:
systemctl enable criu
systemctl start criu
  1. Edit lsapi.conf file, turn CRIU On and set some defaults:
lsapi_criu On
lsapi_criu_socket_path /var/run/criu/criu_service.socket
lsapi_backend_semtimedwait On
lsapi_backend_initial_start 15
lsapi_criu_use_shm Off
  1. Restart apache:
service httpd restart
  1. An option added to the Apache configuration for cleaning all the images earlier saved by CRIU.
Option name Description Value Default
lsapi_reset_criu_on_apache_restart This option allows cleaning all CRIU images on Apache restart. On/Off Off

On the next restart of Apache all of the images will be cleaned.

It can be enabled by writing lsapi_reset_criu_on_apache_restart On in lsapi.conf (Virtual Host and .htaccess do not allow to use this option).

Note that this option works only if lsapi_terminate_backends_on_exit is On (default value is On , it is set in lsapi.conf too).

  1. If you need to clean CRIU images for one user you can simply add file to the user's directory with CRIU images (default /var/run/mod_lsapi/lsapi * criu_imgs ). On the next restart of lsphp the images will be cleaned.

  2. Global reset flag for cleaning all earlier saved images by CRIU.

Current mod_lsapi allows cleaning all images only with one flag file.

Create /usr/share/criu/mod_lsapi/lsphp.criu.reset file. Also don't forget to set such permissions [nobody:nobody] (or [apache:apache] for non cPanel) and access mode [700] to the /usr/share/criu/mod_lsapi directory.

Steps to do :

mkdir /usr/share/criumkdir /usr/share/criu/mod_lsapi
chown nobody:nobody /usr/share/criu/mod_lsapi
touch /usr/share/criu/mod_lsapi/lsphp.criu.reset

On the next requests to all virtual hosts images will be recreated (deleted first and created again later - it depends on lsapi_backend_initial_start value).

  1. Аdded possibility to clean CRIU images from user space.

If a user needs to clean CRIU images for lsphp, he should create a file: ~/mod_lsapi_reset_me_[vhost_name] . Where [vhost_name] is a ServerName from the VirtualHost block in the configuration file. On the next restart of lsphp, the images will be cleaned.

Example:

cd; touch mod_lsapi_reset_me_criu.test.com

where vhost.conf contains:
ServerName criu.test.com

This mode is enabled by default and creates a separate lsphp process for each virtual host.

mod_lsapi_reset_me[vhost_name] flag will not work for a user when lsapi_per_user option is On.

  1. There is (default off) option in mod_lsapi that creates only one lsphp process for a user, regardless of the number of his virtual hosts. We don't recommend to use this option with CRIU, but if you use it, make sure that your virtual hosts (under the same user) have the same environment configurations. If they are not the same, this may cause undesirable lsphp process operation.

Additional integration components

CloudLinux uses various ways to integrate with existing system.

LVE PAM module

pam_lve.so is a PAM module that sets up LVE environment. It provides easy way to setup LVE for SSH sessions, as well as other PAM enabled applications, such as crontab, su, etc.

pam_lve.so is installed by default when you convert existing server.

Installation:

# yum install pam_lve

After you install RPM , add the following line to the PAM config file for the required application:

session    required     pam_lve.so 500 1 wheel,other

In this line:

  • 500 stands for minimum UID for which LVE will be setup. For any user with UID < 500, LVE will not be setup. If CageFS is installed, use: cagefsctl --set-min-uid UID to setup minimum UID. The parameter in PAM files will be ignored in that case.
  • 1 stands for CageFS enabled (0 – CageFS disabled)
  • 3rd optional argument defines group of users that will not be placed into LVE or CageFS. Starting with pam_lve 0.3-7 you can specify multiple groups, comma separated.

Warning

It is crucial to place all users that su or sudo to root into that group. Otherwise, once such user gains root, user will be inside LVE, and all applications restarted by that user will be inside that user LVE as well.

For example, to enable LVE for SSH access, add that line to the /etc/pam.d/sshd. To enable LVE for SU, add that line to the /etc/pam.d/su.

By default, module will not place users with group wheel into lve. If you want to use different group to define users that will not be placed into LVE by pam_lve - pass it as the 3rd argument.

Warning

Be careful when you test it, as if you incorrectly add this line to the /etc/pam.d/sshd, it will lock you out ssh. Don't log out of your current SSH session, until you sure it works.

For preventing cases when user enters under usual user (using ssh) and then tries to enter as super user (via sudo or su) - pam_sulve was created, which tries to enter to LVE=1 and leaves it right away. If action fails, user gets message:

!!!!  WARNING: YOU ARE INSIDE LVE !!!!

To check if pam_sulve is enabled on the server:

grep pam_sulve.so /etc/pam.d/*

should not be empty.

LVE wrappers

LVE wrappers are the set of tools that allow system administrator to run various users, programs & daemons within Lightweight Virtual Environment. This allows system administrator to have control over system resources such program can have. Additionally it prevents misbehaving programs running within LVE to drain system resources and slow down or take down the whole system. The tools are provided by lve-wrappers RPM.

You can install them by running:

$ yum install lve-wrappers

Placing programs inside LVE

LVE Wrappers provide two tools for placing programs inside LVE: lve_wrapper and lve_suwrapper.

/bin/lve_wrapper can be used by any non-root user, as long as that user is in group lve (see /etc/groups file).

Syntax

lve_wrapper <command_to_run>

Example

$ lve_wrapper make install

The program will be executed within LVE with ID matching user's id.

/bin/lve_suwrapper can be used by root user or any user in group lve (see /etc/groups file) to execute command within specified LVE.

Syntax

lve_suwrapper LVE_ID <command_to_run>

Example

# lve_suwrapper 10000 /etc/init.d/postgresql start

Switches

  • -f - force namespace
  • -n - without namespace

MPM ITK

CloudLinux httpd RPM comes with MPM ITK built in. Yet, if you would like to build your own Apache, you need to apply our patch for MPM ITK

When running MPM ITK , you should disable mod_hostinglimits. All the functionality needed by MPM ITK is already built into the patch.

Directives which can be used by Apache with ITK patch:

  • AssignUserID - uses ID as LVE ID
  • LVEErrorCodeITK - error code to display on LVE error (508 by default)
  • LVERetryAfterITK - same as LVERetryAfter - respond with Retry-After header when LVE error 508 occurs
  • LVEId - ovverides id used for LVE ID instead of AssignUserID
  • LVEUser - overrides user to use to retrieve LVE ID, instead of AssignUserID

HostingLimits module for Apache

mod_hostinglimits works with existing CGI/PHP modules, to put them into LVE context. In most cases the CGI/PHP process will be placed into LVE with the ID of the user that sites belongs to. mod_hostinglimits detects the user from SuexecUserGroup (suexec module), SuPHP_UserGroup (from mod_suphp), AssignUserID (MPM ITK), RUidGid (mod_ruid2 ) directives.

This can be overwritten via LVEId or LVEUser parameter on the Directory level.

Note

Those parameters will not work with mod_fcgid and mod_cgid.

The order of detection looks as follows:

  • LVEId
  • LVEUser
  • SuexecUserGroup
  • suPHP_UserGroup
  • RUidGid
  • AssignUserID

Note

LVE doesn't work for mod_include #include due to its "filter" nature.

Example:

LoadModule hostinglimits_module modules/mod_hostinglimits.so
<IfModule mod_hostinglimits.c>
 AllowedHandlers cgi-script php5-script php4-script
 SecureLinks On
</IfModule>

Additional notes

mod_hostinglimits (since version 1.0-22) supports min-uid - cagefsctl --set-min-uid=600.

Min UID is read on Apache start/restart and stored in the memory during apache runtime.

If the min UID has changed, you should restart Apache for mod_hostinglimits applying new min UID value. Full min UID is supported only with APR.

The following message should appear:

[notice] mod_hostinglimits: found apr extention version 3.

This means that the correct APR is installed with mod_hostinglimits.

mod_hostinglimist has variable for Apache CustomLog format string %{LVE_ID}y.

How to use:

LogFormat

"%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i" req for lve "%{LVE_ID}y"

combined

shows in access_log the following info:

*.*.*.* - - [09/Apr/2015:07:17:06 -0400] "GET /1.php HTTP/1.1" 200 43435 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0" req for lve 500

*.*.*.* - - [09/Apr/2015:07:17:06 -0400] "GET /1.php?=PHPE9568F34-D428-11d2-A769-00AA001ACF42 HTTP/1.1" 200 2524 "************/1.php""Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0" req for lve 500

*.*.*.* - - [09/Apr/2015:07:17:06 -0400] "GET /1.php?=PHPE9568F35-D428-11d2-A769-00AA001ACF42 HTTP/1.1" 200 2146 "************/1.php""Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0" req for lve 500

Installation

cPanel

Installed by default during EasyApache build. Requires lve-stats & lve-utils packages to be installed.

DirectAdmin

Can be built using custombuild:

$ yum install liblve-devel
$ cd /usr/local/directadmin/custombuild
$ ./build update
$ ./build set cloudlinux yes
$ ./build apache
$ ./build rewrite_confs

If you run suphp, then run the following:

$ ./build suphp

Plesk

$ yum install mod_hostinglimits

ISPmanager

$ yum install mod_hostinglimits

InterWorx

$ yum install mod_hostinglimits

H-Sphere

Included by default in H-Sphere 3.5+

Standard Apache from RPM

$ yum install mod_hostinglimits

Custom Apache installation

Compile from the source: http://repo.cloudlinux.com/cloudlinux/sources/mod_hostinglimits.tar.gz

$ wget http://repo.cloudlinux.com/cloudlinux/sources/mod_hostinglimits.tar.gz
$ yum install cmake
$ tar -zxvf mod_hostinglimits*.tar.gz
$ cd mod_hostinglimits*
$ cmake .
$ make
$ make install
  • Apache Module Identifier: hostinglimits_module
  • Source Files: mod_hostinglimits.c
  • Compatibility: MPM prefork, worker, event, ITK

Directives

Description Makes sure that for any virtual hosts, only files owned by user specified via SuexecUserGroup or other ways as described above are served. For files owned by any other user apache will return Access Denied error. The directive will not affect VirtualHost without user id specified, or with uid < 100
Syntax SecureLinks On
Default SecureLinks Off
Context server config

Prevents apache from serving files not owned by user, stopping symlink attacks against php config files.

Example

SecureLinks On

SkipErrors

Description Allow apache to continue if LVE is not available
Syntax SkipErrors On
Default SkipErrors On
Context server config
Status deprecated

Prevents Apache from exiting if LVE is not available.

Example

SkipErrors Off

AllowedHandlers

Description List of handlers that should be placed into LVE, support regexp
Syntax AllowedHandlers cgi-script %^php% my-script
Default none
Context server config

This directive allows to list handlers which will be intercepted and placed into LVE.

Examples

  • Match requests handled by cgi-script handler:

    AllowedHandlers cgi-script 
    
  • Match all requests:

    AllowedHandlers *
    
  • Match all requests that handled by handler that contains PHP:

    AllowedHandlers %php%
    
  • Match all requests handled by handler that starts with PHP:

    AllowedHandlers %^php%
    

DenyHandlers

Description List of handlers that should not be placed into LVE, support regexp
Syntax DenyHandlers text/html
Default none
Context server config

This directive works together with AllowHandlers, to exclude some handlers from being allowed in LVE.

Example:

Match all requests, but text/*

AllowedHandlers *DenyHandlers %text/*%

LVEErrorCode

Description Error code to display once entry is rejected due to maxEntryProcs
Syntax values from 500 to 510
Default 508
Context directory config

Specifies ErrorCode to use on LVE error (like too many concurrent processes running).

The message that will be displayed by default is:

Resource Limit Is Reached.

The website is temporarily unable to serve your request as it exceeded resource limit. 

Please try again later.

You can redefine error message using ErrorDocument directive

Example:

LVEErrorCode 508ErrorDocument 508 508.html

LVEid

Description Allows to setup separate LVE ID on per directory level. If not set, user ID of a corresponding user is used.
Syntax LVEId number
Default User Id is used
Context directory config

Specifies LVE id for particular directory

Example:

<Directory "/home/user1/domain.com/forums">
 LVEId 10001
</Directory>

LVEUser

Description Allows to setup separate LVE ID on per directory level.
Syntax LVEUser username
Default none
Context directory config

Specifies LVE ID for particular directory.

Example:

<Directory "/home/user1/domain.com/forums">
       LVEUser user1
</Directory>

LVEUserGroupID

Description Use group ID instead of user ID for LVE container number.
Syntax LVEUserGroupID On/Off
Default User Id is used
Context global config only
  • If the option enabled, group ID will be used instead of a user ID. Apache will display the following string in error logs:
mod_hostinglimits: use GroupID instead of UID 
mod_hostinglimits: found apr extension version 2 
mod_hostinglimits: apr_lve_environment_init_group check ok
  • If a compatible apr library is not found, the following error message will be display in error logs.
mod_hostinglimits:  apr_lve_* not found!!!

Example:

<Directory "/home/user1/domain.com/forums">
       LVEUserGroupID On
</Directory>

LVERetryAfter

Description Returns Retry-After header when LVE error 508 occurs.
Syntax LERetryAfter MINUTES
Default 240 minutes
Context directory config

Specifies interval for Retry-After header. The Retry-After response-header field can be used to indicate how long the service is expected to be unavailable to the requesting client.

Example:

LVERetryAfter 180

LVESitesDebug

Description Provides extended debug info for listed sites.
Syntax LVESitesDebug test.com test2.com
Default none
Context directory config

Specifies virtual hosts to provide extra debugging information.

Example:

<Directory "/home/user1/domain.com/forums">
       LVESitesDebug abc.com yx.cnet
</Directory>

LVEParseMode

Description Determines the way LVE ID will be extraced. In Conf
Syntax LVEParseMode CONF PATH OWNER REDIS
Default: CONF
Context: directory config
  • In CONF mode, standard way to extract LVE ID is used (SuexecUserGroup, LVEId, or similar directives).

  • In PATH mode, username is extracted from the home directory path. The default way to match username is via the following regexp: /home/([^/]*)/ . Custom regexp can be specified in LVEPathRegexp.

  • In OWNER mode, the owner of the file is used as an LVE ID.

  • In REDIS mode, LVE ID is retrieved from Redis database.

Example:

LVEParseMode CONF

LVEPathRegexp

Description Regexp used to extract username from the path. Used in conjuction with LVEParseMode PATH
Syntax LVEPathRegexp regexp
Default /home/([^/]*)/
Context directory config

Used to extract usersname via path.

Example:

LVEPathRegexp /home/([^/]*)/

LVELimitRecheckTimeout

Description Timeout in milliseconds, a site will return EP without lve_enter for LA decreasing after this time
Syntax LVELimitRecheckTimeout number
Default 0
Context httpd.conf, virtualhost

Example:

LVELimitRecheckTimeout 1000

LVEUse429

Description Use 429 error code as code returned on max entry limits ( on/off ).
Syntax LVEUse429 on
Default off
Context httpd.conf, virtualhost

Example:

LVEUse429 on

Available for RPM based panels, EasyApache 4 and DirectAdmin.

Redis support for HostingLimits

Redis support provides a way to query Redis database for LVE id, based on domain in the HTTP request. Given a database like:

xyz.com 10001
bla.com  10002
....

The module will retrieve corresponding LVE id from the database.

To enable Redis support, compile from source: http://repo.cloudlinux.com/cloudlinux/sources/mod_hostinglimits.tar.gz

The compilation requires hiredis library.

$ wget http://repo.cloudlinux.com/cloudlinux/sources/da/mod_hostinglimits.tar.gz
$ yum install cmake
$ tar -zxvf mod_hostinglimits*.tar.gz
$ cd mod_hostinglimits*
$ cmake -DREDIS:BOOL=TRUE .
$ make
$ make install

To enable Redis mode, specify:

LVEParseMode REDIS

LVERedisSocket

Description Socket to use to connect to Redis database.
Syntax LVERedisSocket path
Default /tmp/redis.sock
Context server config

Used to specify location of Redis socket.

Example:

LVERedisSocket /var/run/redis.sock

LVERedisAddr

Description IP/port used to connect to Redis database instead of socket.
Syntax LVERedisAddr IP PORT
Default none
Context server config

Used to specify IP and port to connect to Redis instead of using Socket

Example:

LVERedisAddr 127.0.0.1 6993

LVERedisTimeout

Descriptin Number of seconds to wait before attempting to re-connect to Redis.
Syntax LERetryAfter SECONDS
Default 60 seconds
Context server config

Number of seconds to wait before attempting to reconnect to Redis after the last unsuccessful attempt to connect.

Example:

LVERedisTimeout 120

cPanel/WHM JSON API

CloudLinux offers JSON API for lvectl via WHM. You can access it using the following URL:

https:/IP:2087/cpsess_YOURTOKEN/cgi/CloudLinux.cgi?cgiaction=jsonhandler&handler=list

The output will look as follows:

{"data":[{"ID":"default","CPU":"30","NCPU":"1","PMEM":"1024M","VMEM":"1024M","EP":"28","NPROC":"0","IO":"2048"}]}

Parameters

cgiaction always jsonhandler
handler should match lvectl command

For commands like set, destroy & delete, where you need to specify LVE (user) ID, like lveid=500 (matches user ID 500).

Example:

https://IP:2087/cpsess_YOURTOKEN/cgi/CloudLinux.cgi?cgiaction=jsonhandler&handler=set&lveid=500&speed=30%&io=2048

https://IP:2087/cpsess_YOURTOKEN/cgi/CloudLinux.cgi?cgiaction=jsonhandler&handler=set&lveid=500&speed=300Mhz&io=2048

https://IP:2087/cpsess_YOURTOKEN/cgi/CloudLinux.cgi?cgiaction=jsonhandler&handler=set&lveid=500&speed=3Ghz&io=2048

Note

Speed limit can be specified in several units of measure - %, MHz, GHz . The figures will be different according to the unit of measure.

Output:

{"status":"OK"}

To do set default, use lveid=0, like:

https://IP:2087/cpsess_YOURTOKEN/cgi/CloudLinux.cgi?cgiaction=jsonhandler&handler=set&lveid=0&speed=30%&io=2048

For commands like apply all, destroy all, use:

handler=apply-all

handler=destroy-all

You can use the following commands that allow to specify user name instead of user ID:

set-user Set parameters for a LVE and/or create a LVE using username instead of ID.
list-user List loaded LVEs, display username instead of user ID.
delete-user Delete LVE and set configuration for that user to defaults.

If the limits for users are set with cPanel LVE Extension , then turnkey billing solutions can be applied (e.g. WHMCS).

mod_proctitle

mod_proctitle is a module for gathering URL information per request. It is available only for Apache 2.4 now.

For installation:

cPanel EasyApache 3 and non cPanel ( CloudLinux 7 only for non cPanel ):

# yum install mod_proctitle --enablerepo=cloudlinux-updates-testing
# service httpd restart

cPanel EasyApache 4:

# yum install ea-apache24-mod_proctitle
# service httpd restart
DirectAdmin:
# cd /usr/local/directadmin/custombuild
# ./build update
# ./build mod_procticle

How to read mod_proctitle information

How to read information gathered by the module

For reading information saved by module use the following script (the script is not in the package):

#!/bin/bash

httpd=httpd 

for pid in `/usr/bin/pgrep $httpd`; do
    for tid in `ls /proc/$pid/task`; do
		found=no
		for shm in `ls /dev/shm/apache_title_shm_${pid}_${tid}_* 2>/dev/null`; do
			found=yes
			title=`/usr/bin/tr -d '\0' < $shm`
			thread_id=`/bin/basename "${shm}" | sed "s/apache_title_shm_${pid}_${tid}_//"`
			echo "$pid.$tid - $thread_id - $title"
		break
		done
	if [ "$found" = "no" ]; then
		echo "$pid.$tid not found"
	fi
    done
done
Here are the examples of saved by module:
# sh proctitles_info.sh
571258.571258 NOT FOUND
571300.571300 NOT FOUND
571303.571303 - 000000000000000 - 1466513333.6 test.cloudlinux.com GET /1.php HTTP/1.1
571304.571304 - 000000000000000 - 1466513335.3 test.cloudlinux.com GET /1.php HTTP/1.1
571305.571305 - 000000000000000 - httpd
571306.571306 - 000000000000000 - httpd
571307.571307 - 000000000000000 - httpd
571372.571372 - 000000000000000 - httpd
571374.571374 - 000000000000000 - httpd

Item info:
[pid].[tid] - [posix thread id] - [request info]

Request information can contain:

NOT FOUND - means that process of Apache doesn't handle requests.
httpd - request is active and waiting for new connection.
[seconds].[tenths of second] [host] [METHOD] [URL] [PROTOCOL]

Tuning parameters

Module parameters for tuning

WatchHandlers List of handlers for monitoring (httpd.conf, virtualhost).
ProctitleUseFilter On/Off Use old method of cleaning information or new via filter (for prefork better to use Off )

alt-suexec

What is alt-suexec package needed for?

If you use standard httpd from our repository, but your users' sites do not match standard Apache location of /var/www, then you should use alt-suexec. alt-suexec package brings suEXEC binaries pre-compiled for specific locations, like /home .

How to switch suEXEC with alt-suexec

Based on httpd 2.2 basic for 6 and httpd 2.4 basic for CloudLinux 7, the package brings to server a set of suEXECs with different DOCUMENT ROOT s and MIN_UID/MIN_GID parameters. The first set of suEXECs is listed by such modes:

# switch_suexec -h
USE_BIZ - DOCUMENT ROOT /biz/ MIN_UID 500 MIN_GID 100 CALLER apache
USE_HOSTING - DOCUMENT ROOT /hosting/ MIN_UID 500 MIN_GID 100 CALLER apache
USE_HSPHERE - DOCUMENT ROOT /hsphere/local MIN_UID 100 MIN_GID 100 CALLER httpd
USE_HOME - DOCUMENT ROOT /home/ MIN_UID 500 MIN_GID 100 CALLER apache
USE_WWW - DOCUMENT ROOT /var/www/ MIN_UID 500 MIN_GID 100 CALLER apache
USE_FSROOT - DOCUMENT ROOT / MIN_UID 500 MIN_GID 100 CALLER apache
USE_STORAGE - DOCUMENT ROOT /storage/content/ MIN_UID 500 MIN_GID 100 CALLER apache
USE_DATAS - DOCUMENT ROOT /datas/ MIN_UID 500 MIN_GID 100 CALLER apache
The package also brings its own utility for installing specific suEXEC:
-l list of available suexec
-u update suexec according to /etc/sysconfig/alt-suexec
-s set new suexec and install it
-p set new suexec path and install it
-o set new suexec owners and install it
-r restore native apache suexec

There are two ways to set up new suEXEC binary:

  1. via config file /etc/sysconfig/alt-suexec
  2. via utility switch_suexec

Here are the examples of how to set up suEXEC with DOC_ROOT = "/home":

1.

  1. add string "USE_HOME" to /etc/sysconfig/alt-suexec
  2. run the command switch_suexec -u

2.

  1. switch_suexec -sUSE_HOME

Result of both methods:

# cat /etc/sysconfig/alt-suexec
USE_HOME

Here is standard suEXEC for CloudLinux 6 clean server:

# /usr/sbin/suexec -V
-D AP_DOC_ROOT="/var/www"
-D AP_GID_MIN=100
-D AP_HTTPD_USER="apache"
-D AP_LOG_EXEC="/var/log/httpd/suexec.log"
-D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
-D AP_UID_MIN=500
-D AP_USERDIR_SUFFIX="public_html"
-D AP_SAFE_DIRECTORY="/usr/local/safe-bin"

Here is output of new suEXEC after USE_HOME installtion:

# /usr/sbin/suexec -V
-D AP_DOC_ROOT="/home/"
-D AP_GID_MIN=100
-D AP_HTTPD_USER="apache"
-D AP_LOG_EXEC="/var/log/httpd/suexec.log"
-D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
-D AP_UID_MIN=500
-D AP_USERDIR_SUFFIX="public_html"
-D AP_SAFE_DIRECTORY="/usr/local/safe-bin"

Description of other switch_suexec parameters:

-p if suexec binary file will be placed not in standard way /usr/sbin - specify this new path with p-option
-o if suexec binary file not owned by root:apache - specify new owner with o-option

For most cases -p and -o options for standard Apache are useless.

Correct suEXEC will be restored even after httpd update or reinstall.

List of pre-built suEXEC binary files stored without suid bit and not executable.

How to install alt-suexec?

For installation run the command:

yum install alt-suexec

New suexec with custom parameters

If you need suEXEC with custom parameters absent in current set of alt-suexec, please submit a ticket on https://cloudlinux.zendesk.com and we will add new suEXEC with needed parameters.

cPanel Nginx and application selectors

Recently, cPanel added support for the Nginx web server and for Python and Node.js applications.

We have checked the compatibility of ea-nginx and cPanel application Selectors with CloudLinux LVE and CageFS. All tests passed successfully and all processes started by ea-nginx and cPanel selectors are launched inside LVE and CageFS.

Don’t forget, you can use Ruby/Python/Node.js Selectors from CloudLinux. Here you can find a large number of supported versions for Ruby/Python/Node.js applications.

Note

Nginx support is currently experimental.

Apache suexec module

General information and requirements

This module is used by the Apache HTTP Server to switch to another user before executing CGI programs. The suEXEC feature provides users of the Apache HTTP Server with the ability to run CGI and SSI programs under user IDs different from the user ID of the calling web server (apache/nobody). Normally, when a CGI or SSI program executes, it runs as the same user who is running the web server.

If we are talking about shared hosting where different accounts are launched on the same server, the installation of this module is necessary to ensure security.

How does it work with CloudLinux?

The DirectAdmin and CloudLinux (for httpd, httpd24-httpd and cPanel EasyApache 4) both provide a patched version of suexec. For other distributions you can use patches available here: http://repo.cloudlinux.com/cloudlinux/sources/da/cl-apache-patches.tar.gz

  1. Besides the ability to run CGI programs under user IDs, suexec with CloudLinux patch adds the ability to run that script under CageFS.

NOTE

Therefore, this module is necessary for the proper work of PHP Selector.

  1. This module is also necessary for the proper work of mod_hostinglimits. The SuexecUserGroup directive indicates for mod_hostinglimits in which LVE the user process should be put in.

Configuration

SuexecUserGroup Directive

Syntax: SuexecUserGroup User Group

Context: httpd.conf, virtualhost

Description: The SuexecUserGroup directive allows you to specify a user and a group for CGI programs to run as. Startup will fail if this directive is specified but the suEXEC feature is disabled.

Note

Control panels such as cPanel, Plesk, and DirectAdmin add this directive to the Apache configuration automatically when creating a domain. If you use the server without a control panel, make sure this directive is added for each virtual host.

Installation

The installation process varies depending on the control panel and Apache.

Installing on cPanel servers with EasyApache 4

  1. Install mod_suexec through YUM package manager as follows:
$ yum install ea-apache24-mod_suexec

NOTE

ea-apache24-mod_suexec conflicts with the mod_ruid2 therefore, before installing the module, remove ea-apache24-mod_ruid2 as follows: $ yum remove ea-apache24-mod_ruid2

  1. Now, when the module is installed, restart Apache:
$ service httpd restart

Installing on Plesk servers

This module is integrated into Apache for Plesk control panel by default.

Installing on DirectAdmin servers

This module is integrated into Apache for DirectAdmin control panel by default.

Installing on servers with no control panel

This module is integrated into httpd Apache rpm provided by Cloudlinux by default.

If you are using an alternative Apache - httpd24, nothing has to be done as this module is also integrated into httpd24-httpd Apache rpm provided by Cloudlinux by default.