Thursday, May 9, 2019

Enhance Apache and Lighttpd on Centos Linux: increasing file descriptors limit

Centos Linux servers typically have the maximum file descriptors at 1024. Other Linux distributions may have the same settings, but what is this file descriptor and how to increase the value? Please use linux man pages to get further details of the commands in this document. These are information for educational purposes.

Some web servers that have to work harder, may need to multitask more than others. This is when there will be warnings in /var/log/messages related to

can't have more connections than fds/2:  1024 1024

or Apache error logs showing

ulimit:error setting limit(Operation not permitted)

Another situation is when a software runs into an infite loop of process, such that is increase resource usage until the server comes to a complete stand still. Causing no other users to have access to the server. On a production server, this would be a disaster. What is really affected by these limits? Its the application performances such as database and web servers that are under heavy usage. Typical linux terminal users wont really need to concern with the limits.

View limits
Users can view file limits with the command;

$ ulimit 
$ ulimit -aH

Value of unlimited is common for development servers.

To view limit for current BASH open files of the user;

$ ulimit -n

To view max user processes

$ ulimit -Hn
$ ulimit -u

To view limits of any running process, identify the process ID ($PID) then run command;
$ grep 'open files' /proc/{$PID}/limits

Replace {$PID} with the PID to be checked.

Any user can reduce their file descriptor limit. This is useful to test problematic applications. Example to reduce to 1024.

$ ulimit -u 1024

Configuration file sysctl
This sysctl.conf and files in /etc/sysctl.d is an interface that allows you to make changes to a running Linux kernel. This file is extensively configured to harden a production Centos Linux server. Example, to reboot the linux after a kernel panic, the following values is used;


With /etc/sysctl.conf you can configure various Linux networking and system settings. To view current values;

$ sudo sysctl -A
$ sudo sysctl fs.file-max
fs.file-max = 994255

Centos Linux

Check the current value of the file descriptor
$ ulimit -aHS
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 39253
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 4096
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

To view system configured default limit on file descriptors.

$ cat /etc/security/limits.d/20-nproc.conf
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.

*          soft    nproc     4096
root       soft    nproc     unlimited

Here, the plan is to increase limits to 65530.

Change the hard and soft limits in configuration file.

Edit /etc/security/limits.conf with these values. The * refers to any user.

* soft nproc 65535
* hard nproc 65535

* soft nofile 65535
* hard nofile 65535

In cases where the fs.file-max is below the 65535 value, then it can be set by editing /etc/sysctl.conf

fs.filemax = 65535

In both cases above, apply changes with the command;

$ sudo sysctl -p


Edit /etc/lighttpd/lighttpd.conf

server.max-fds = 2048

Apache Httpd

The Centos, this document referring is with httpd version 2.4.6 (CentOS) and is using httpd compiled as preforked (non threaded).

Edit the file /etc/httpd/conf/httpd.conf

<IfModule prefork.c>
StartServers       4
MinSpareServers    3
MaxSpareServers   10
ServerLimit      256
MaxClients       256

MaxRequestsPerChild  10000

Refer details at


When selinux is in mode Enforcing, it needs to allow changes. Check the status with

$ sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          permissive
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Max kernel policy version:      31

$ getsebool httpd_setrlimit
httpd_setrlimit --> off

Temporary turn it on, then later view the status again;

$ setsebool httpd_setrlimit on

To make this change permanent;

$ sudo setsebool -P httpd_setrlimit on

MYSQL database

Edit /usr/lib/systemd/system/mysqld.service


Edit /etc/my.cnf


Apply the changes;

$ sudo systemctl daemon-reload
$ sudo systemctl restart mysqld.service

Friday, October 19, 2018

Show user permission to MySQL and MariaDb databases

User permission levels in MySQL (and MariaDb) can be drilled down into many layers. From database permission, table permission, column permission and routine permission. There could be more that I don't know of. Its great to have greater control over who have access to the database;

How do I show user permission just at database level? First step is to know where such information is stored, followed by how to retrieve the information.

Access MySQL login as admin OR root.

mysql.user and mysql.db Tables

Have a look at the following tables, as they contain the relevant information

mysql> describe * from mysql.user;
mysql> describe * from mysql.db;

Listing users

Let's say, you want to see which user to host have access

mysql> select user, host from mysql.user;

| user       | host        |
| oc_admin   | %           |
| auditor    | |
| auditor    | |
| root       |  |
| tbox       | localhost   |
| mysql.sys  | localhost   |
| oc_admin   | localhost   |
| pentaho    | localhost   |
| root       | localhost   |

List grants for users

mysql> show grants;
| Grants for root@localhost                                           |
| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION        |

List User Access to Databases, Tables and Columns

mysql> SELECT Host, Db, User from mysql.db

There are separate tables for each database, table or column specific access. Go thru and see what you need in the following tables.

mysql> SELECT Host, Db, User from mysql.db
mysql> SELECT * FROM mysql.db;
mysql> SELECT * FROM mysql.tables_priv;
mysql> SELECT * FROM mysql.columns_priv;

Wednesday, September 12, 2018

Git and undo last commit

Updating a remote git repository would mean all other users having a same source code. Sometimes, a local commit may be done and its found that there are changes that should not be push to the remote. The solution, remove not needed files then move to the previous commit on the local machine.

The command is
$ git reset --hard HEAD~1

Unstage any other files with the command
$ git reset

Wednesday, September 5, 2018

Howto install mcrypt for PHP 7.2

PHP extensions have always utilised reuse of applications to provide extra functionality to developers. One such is the use of mycrypt. As of PHP 7.1, the mcrypt is deprecated and totally removed in PHP 7.2. Unfortunately for those with application that rely on mcrypt, this means the end of the road. In my case, development of a Laravel application had dependencies on mcrypt when doing an update with the command;

$ composer update

The mcrypt is a replacement of Unix/Linux crypt( ) that encrypt files. The PHP extension is php-mcrypt, and this is used to interface between PHP application and the mcrypt utility.

However, there is a solution that use mcrypt found in the PHP Extension Community Library (PECL). In this example, its tested on

CentOS 7.5 
Apache 2.4.6 (CentOS)
PHP 7.2.5 (

Step 1. Install mcrypt utility.

$ pecl search mcrypt
WARNING: channel "" has updated its protocols, use "pecl channel-update" to update
Retrieving data...0%
.Matched packages, channel
Package       Stable/(Latest)  Local
mcrypt        1.0.1 (snapshot)       Bindings for the libmcrypt library
mcrypt_filter 0.1.0 (beta)           Applies mcrypt symmetric encryption using stream filters

Install mcrypt and its development library then update the pecl.

$ sudo pecl channel-update
$ sudo yum install libmcrypt
$ sudo yum install libmcrypt-devel

Step 2. Install php-devel (or php72w-devel if you use webtatic repo)

$ sudo yum install php72w-devel

Step 3. Install mcrypt extension

Either specify specifically a channel or use default
$ sudo /usr/bin/pecl install channel://
$ sudo /usr/bin/pecl install mcrypt-1.0.1

Create the file /etc/php.d/mcrypt.ini with the contents
; Enable mcrypt extension module from pecl

Restart Web server.

Note: If for some strange reason php still doesn't detect mcrypt extension, I would give a reboot.


Thursday, August 30, 2018

Laravel, Swiftmailer and Uncaught Swift_TransportException

Writing PHP applications that deliver email notification helps to build a versatile system that uses the most basic communication media on the Internet. The Email.

Getting the Email out would require knowledge of the Email server in use to deliver 1 or thousands of email notifications. Common Email use SMTP, sendmail, postfix or a custom Transport implementation for corporate use. There are security and reliability concerns when passing to any Email server. Some of which include protection from email header injection attacks, MIME compliant, HTML/multipart emails, inline or embedded images.

Swift Mailer helps to handle most of these things. Why reinvent the wheel? In order to use it, the application should support PHP 7.0 or higher. Installation through Composer simplifies the whole process.

$ composer require "swiftmailer/swiftmailer:^6.0"

More details are found at Swift Mailer.


Back to the original reason of this post. On a recent Laravel application, tested was carried out and checklist done on Centos Linux development server However when deployed to production Centos Linux server, email notification produced following error;

PHP Fatal error: Uncaught Swift_TransportException: Connection could not be established with host EMAILSERVER_NAME[Permission denied #13]

The full error is shown below.

[Thu Aug 30 14:35:54.225637 2018] [php7:error] [pid 18234] [client IPADDRESS:32852] PHP Fatal error: Uncaught Swift_TransportException: Connection could not be established with host EMAILSERVER_NAME[Permission denied #13] in /var/www/tboxmy/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php:277\nStack trace:\n#0 /var/www/tboxmy/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php(62): Swift_Transport_StreamBuffer->_establishSocketConnection()\n#1 /var/www/tboxmy/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php(113): Swift_Transport_StreamBuffer->initialize(Array)\n#2 /var/www/tboxmy/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Mailer.php(79): Swift_Transport_AbstractSmtpTransport->start()\n#3 /var/www/tboxmy/public/info/testemail.php(21): Swift_Mailer->send(Object(Swift_Message))\n#4 {main}\n thrown in /var/www/tboxmy/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php on line 277 


I am sure there are other possible ways to get this error, but in my case it was SELINUX. On the development selinux was on permissive and on production it was enforcing (quite strictly).

The next time this happens; here are the steps to take.

Determine selinux status and the booleans.

$ sestatus
. . .
$ getsebool httpd_can_sendmail
httpd_can_sendmail --> off
$ getsebool httpd_can_network_connect
httpd_can_network_connect --> off

Turn the permission to ON.

$ sudo setsebool -P httpd_can_sendmail 1
$ sudo setsebool -P httpd_can_network_connect 1

Restart the web server.

Thursday, July 12, 2018

Chinese Input on Linux Mint

Linux is flexible enough to support users from around the world with various types of input method.

On Linux Mint there are 2 approach or framework for input methods. They are Fcitx and Ibus. These enable users to switch between typing Latin (e.g. a b c) and others like Chinese Pin Yin (e.g. 平 阔). To get a details on these frameworks there is a 2012 article "GNOME and input method integration". Language models are developed on top of any of these frameworks, depending on the target user devices.

Do you need to have both input method frameworks? The short answer is No. Only one is needed for the operating system being used. On Linux where users can change their Desktop Managers, then all the preferred input method framework should be installed.

Sunpinyin is a popular utility for chinese input on Linux that is available on Fcitx and Ibus.It is open source licensed with LGPLv2 and CDDL dual-licenses.

I choose the approach of Ibus since doing a apt-cache search yielded the following;

ibus-sunpinyin - sunpinyin engine for ibus
libsunpinyin-dev - Simplified Chinese Input Method from SUN (development)
libsunpinyin3-dbg - Simplified Chinese Input Method from SUN (debug)
libsunpinyin3v5 - Simplified Chinese Input Method from SUN (runtime)
sunpinyin-data - Statistical language model data from open-gram
fcitx-sunpinyin - fcitx wrapper for Sunpinyin IM engine
python-sunpinyin - Simplified Chinese Input Method from SUN (Python binding)
sunpinyin-utils - Simplified Chinese Input Method from SUN (utilities)
ucimf-sunpinyin - ucimf wrapper for Sunpinyin IM engine
xsunpinyin - Standalone XIM server for Sunpinyin

Ibus was first on the list.

I might have missed some steps as I did this over several weeks. There wasn't any rush and there were other chores that needed to get done.

Here are the steps taken.

Step 1: Install Sunpinyin

Open a command line terminal and type

sudo apt-get install ibus-sunpinyin sunpinyin-utils

Step 2: Install the language

At Menubar click Applications ->Settings ->Input Method

Choose Language tab then click Install/Remove Languages...
Click Add.
Choose Chines, China (UTF8), then click Install.

Back to the Language Settings window, click "Input method" tab. In Input method, choose "IBus".

In Language support, Simplified Chinese click the Install button. Follow the instructions.

Step 3: Load it.

Logout and log back in.

At the Menubar, appears the Input Method applet with the text "EN".

Click on "EN" and select "Simplified Chinese".

Open a text editor or web browser and try out typing in Chinese.


Note: If this disrupts special keys on the keyboard, try to setup and use fcitx, instead. You can only use either one at a time.

Thursday, June 14, 2018

Install dwm window manager and C Programming on Centos 7

Here are notes on getting dwm and C programming to work with Centos 7. Started project on recompiling the kernel and dwm, a windows manager that required editing of C codes and the existing computer did not have C installed.

Its a good note on working with RPMS and how to get started in C programming.

What is DWM?

The dwm is a windows manager on Linux. Its advantage is having a window environment, without a mouse and allows easy rearranging of windows across the screen. Here is an example on Nautilus with 2 ST terminals.

DWM Window Manager Screen with 3 panels

Each window can be expanded across other windows as shown below.

DWM Window Manager Screen with 2 panels

Installation, build and finally creating the required rpm will create the minimum files and folders as shown below.
RPMBUILD folder structure

Step 1: Install C compiler and minimum libraries

$ sudo yum install gcc gcc-c++ kernel-devel kernel-header make rxvt-unicode

This will include the following packages;
  cpp.x86_64 0:4.8.5-28.el7_5.1                          
  gcc-gfortran.x86_64 0:4.8.5-28.el7_5.1                      
  gcc-gnat.x86_64 0:4.8.5-28.el7_5.1                        
  gcc-objc.x86_64 0:4.8.5-28.el7_5.1                        
  gcc-objc++.x86_64 0:4.8.5-28.el7_5.1                       
  libgcc.i686 0:4.8.5-28.el7_5.1                          
  libgcc.x86_64 0:4.8.5-28.el7_5.1                         
  libgfortran.x86_64 0:4.8.5-28.el7_5.1                      
  libgnat.x86_64 0:4.8.5-28.el7_5.1                        
  libgnat-devel.x86_64 0:4.8.5-28.el7_5.1                     
  libgomp.x86_64 0:4.8.5-28.el7_5.1                        
  libobjc.x86_64 0:4.8.5-28.el7_5.1                        
  libquadmath.x86_64 0:4.8.5-28.el7_5.1                      
  libquadmath-devel.x86_64 0:4.8.5-28.el7_5.1                   
  libstdc++.i686 0:4.8.5-28.el7_5.1                        
  libstdc++.x86_64 0:4.8.5-28.el7_5.1                       
  libstdc++-devel.x86_64 0:4.8.5-28.el7_5.1  

Alternatively is to install the whole development tools suite. This can be done with the command
yum groupinstall "Development Tools" --setopt=group_package_types=mandatory,default,optional

Step 2: Test C environment

Create a file hello.c with following contents

1:  #include<stdio.h>  
2:  int main()
3:  {  
4:      int a, b, c;  
5:      printf("Enter two numbers to add: ");  
6:      scanf("%d %d",&a,&b);  
7:      c = a + b;  
8:      printf("The sum is %d\n",c);  
9:      return 0;  
10: }  

Open the command line terminal (CLI), compile and run

$ gcc hello.c -o programSum
$ ./programSum

Hint: For larger projects, it will compile faster with ccache. E.g.
$ ccache gcc hello.c -o programSum

Step 3: Install graphical development libraries 

Applications that is graphical in nature mostly are group as X11. In order to create some sense of uniformity in the chaos world of Linux, LSB is a standard adopted and through which the use of these libraries ensure better compatibilities of an application across an Linux systems.

  • libXft is a runtime library. In this case to use the X Free Type Library where drawing of fonts and the application window is defined by LSBfor X11.
  • libXinerama is a library to support desktops that run across multiple displays on X11. It is more common to use RandR which does the similar work in more modern applications. In modern systems, libXinerama is an interface to RandR library.
  • fontpackages-devel contains templates and macros used to create font packages. The initial problem many years ago is that there were no standard to package fonts. This fedora project library reduces poor quality implementations and allow application developers to focus on their applications better.

sudo yum install -y libXft-devel libXinerama-devel fontpackages-devel

Step 4: Retrieve the source with SRPMS

Create a file with following contents
1:  # Download archives from Fedora 22 repository.  
2:  SOURCE=  
3:  F26=${SOURCE}/linux/releases/26  
4:  wget ${F26}/Everything/source/tree/Packages/d/dwm-6.1-4.fc26.src.rpm  
5:  wget ${F26}/Everything/source/tree/Packages/d/dmenu-4.7-1.fc26.src.rpm  
6:  wget ${F26}/Everything/source/tree/Packages/t/terminus-fonts-4.40-6.fc26.src.rpm  
7:  wget ${F26}/Everything/source/tree/Packages/s/st-0.7-2.fc26.src.rpm  

Save the file and execute.
$ chmod u+x
$ ./

Hint:  to edit the dwm source, extract the SRPMS then extract dwm-6.1.tar.gz
$ rpm -i dwm-6.1-4.fc26.src.rpm
$ cd ~/rpmbuild/SOURCES

The package dwm-6.1.tar.gz contain the files;
1:  BUGS  
2:  config.def.h  
4:  drw.c  
5:  drw.h  
6:  dwm.1  
7:  dwm.c  
8:  dwm.png  
10:  Makefile  
11:  README  
12:  TODO  
13:  transient.c  
14:  util.c  
15:  util.h  

Step 4. Build packages and install

$ rpmbuild --rebuild dwm-6.1-4.fc26.src.rpm
$ rpmbuild --rebuild dmenu-4.7-1.fc26.src.rpm
$ rpmbuild --rebuild terminus-fonts-4.40-6.fc26.src.rpm
$ rpmbuild --rebuild st-0.7-2.fc26.src.rpm

$ cd ~/rpmbuild/RPMS/SPECS/
$ rpmbuild -ba st.spec

$ cd ~/rpmbuild/RPMS/noarch/
$ sudo yum localinstall -y terminus-fonts-4.40-6.el7.centos.noarch.rpm terminus-fonts-console-4.40-6.el7.centos.noarch.rpm 

$ cd ~/rpmbuild/RPMS/x86_64/
$ sudo yum localinstall -y dwm-6.1-4.el7.centos.x86_64.rpm dwm-user-6.1-4.el7.centos.x86_64.rpm dmenu-4.7-1.el7.centos.x86_64.rpm st-0.7-2.el7.centos.x86_64.rpm st-user-0.7-2.el7.centos.x86_64.rpm

The dwm is installed at /usr/bin/dwm and the session is created in a file /usr/share/xsessions/dwm.desktop.

Logout and choose dwm as the window manager to login. Alternatively in xstartup, change the desktop manager to use dwm.

If any of the library is not detected during a run or build, ensure that its in the
linux system's path. This can be done by
  • Add a file to /etc/ that contains path to the library (mine defaults to /usr/lib64/)
Do a list of library dependencies comparison with what I have here;
1:  $ ldd `which dwm`  
2: => (0x00007ffd1b1b0000)  
3: => /lib64/ (0x00007fbf79baf000)  
4: => /lib64/ (0x00007fbf799ac000)  
5: => /lib64/ (0x00007fbf7976e000)  
6: => /lib64/ (0x00007fbf79558000)  
7: => /lib64/ (0x00007fbf79195000)  
8: => /lib64/ (0x00007fbf78f6c000)  
9: => /lib64/ (0x00007fbf78d68000)  
10: => /lib64/ (0x00007fbf78b56000)  
11: => /lib64/ (0x00007fbf788af000)  
12: => /lib64/ (0x00007fbf78685000)  
13: => /lib64/ (0x00007fbf78469000)  
14: => /lib64/ (0x00007fbf7825d000)  
15:       /lib64/ (0x000056545bb82000)  
16: => /lib64/ (0x00007fbf78059000)  


Blog Archive