Published May 20th, 2009 by kabir
We use BackupPC and have a love-hate relationship with it. We love that it works most of the time, and hate that it uses CGI Web interface and also outputs cryptic error messages when backup fails. But never the less, we have not found a better deal so far. Hence we continue to use it.
Here is our installation quick-guide:
Category: Uncategorized | Tags: | 1 Comment »
Published May 19th, 2009 by kabir
As we are moving to Ruby on Rails platform and only maintaining PHP 5 projects until they are
replaced with RoR versions, we are deploying RoR on our development network. Here is our quick guide to RoR installations
on CentOS 5.3.
Setting up Ruby on Rails with friends
- Download Ruby source and compile using: ./configure && make && make install
- Download RubyGems source and install using ruby setup.rb
- Upgrade RubyGems using gem install rubygems-update
- Install Rails using gem install rails
- Install JSON using gem install json
- Install SQLite3 using gem install sqlite3-ruby
- Install MySQL support using gem install mysql or gem install dbd-mysql
fails so here is what works:
- Download MySQL extension for ruby using wget http://rubyforge.org/frs/download.php/51087/mysql-ruby-2.8.1.tar.gz
- After extracting it run: ruby extconf.rb –with-mysql-config && make && make install
- To find out what extensions were installed using gem, run: gem list
Setting up Phusion Passenger for Apache
We want to use the Phusion Passenger with Enterprise Ruby so here how to install these goodies.
To install Phusion Passenger run:
-
gem install passenger
- By default, the passenger installer looks for Apache in /usr/sbin/httpd which is not where we install our custom Apache
server so we created a symbolic link that points /usr/sbin/httpd to /home/apache/bin/httpd
- Also, we installed few Apache tools that the installer needs using yum -y install httpd-devel apr-devel
-
Run: passenger-install-apache2-module
- After the Apache 2 module was successfully installed, we edited the Apache configuration file, and added these
lines:
LoadModule passenger_module /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.2/ext/apache2/mod_passenger.so
PassengerRoot /usr/local/lib/ruby/gems/1.9.1/gems/passenger-2.2.2
PassengerRuby /usr/local/bin/ruby
- Restart Apache
- After restarting Apache, deploy any number of Ruby on Rails applications on Apache by pointing DocumentRoot to the public directory
of the RoR project
Going Enterprise with Ruby on Rails
To install Enterprise Ruby do the following
- Download Enterprise Ruby source and extract in /usr/local/src
- From the newly created directory, run
./installer
- Follow the prompts
- After installing Enterprise Ruby, reinstall Phusion Passenger as requested by the Enterprise Ruby installer
- You are now ready to use Enterprise Ruby
Category: Ruby on Rails | Tags: | Be the First to Comment »
Published May 18th, 2009 by kabir
It was time for us to upgrade our development center’s gateway server and we needed to redo our caching DNS server setup that permits local LAN users to enjoy a local DNS server with a split mindset — to support local non-routable domains for internal development teams and cached DNS service for external resources.
Our last BIND install was long time ago and it was willingly forgotten. So before I started with BIND I decided to give a little thought on BIND replacement. My BIND installation started with a Google search for ‘BIND replacement’ and djbdns surfaced. I am big fan of DJB’s (Daniel J. Bernstein) work on cryptography and generally admire his approaches to solving real problems and a very big fan of qmail. But I hardly recommend his wares for scenarios where inexperienced (1-5 years) engineering staff is in charge of network services. Therefore, even though I loved how djbdns works and the security it provides, I had to stick with the latest version of BIND for this installation. In case you want to ponder some more on the merits of BIND vs djbdns, check out the following document:
BIND versus DJBDNS: A Comparison of Performance,
Ease of Configuration, and Security
If you read the above article, you will notice that BIND only wins against djbdns when it comes to ease of installation: 6 steps for BIND vs 17 steps for djbdns. If djbdns could be had using yum, it would have a bigger install base. Too many steps in installing and configuring makes lazy people (like me) want to stick with what they already have or know.
Although I was quite accustomed to setting up BIND, I found myself into two interesting problems that I like to write here so that next time one of my staff can avoid them without pulling his hair out or wasting hours and hours.
LAN clients can connect to BIND but nothing more happens
I created a view in /etc/named.conf file to allow internal LAN clients connected to localnets to be able to use the DNS server and also see a special internal zone. However, the clients were able to connect fine but they would not resolve anything and timeout.
After an hour+ investigation, I gave up and returned home and later reviewed the problem and discovered that our IPTABLE settings were the cause of the problem. I had only enabled domain port (53) to be open for LAN clients but did not allow the UDP port! So after adding the following two lines in /etc/sysconfig/iptables and restarting the iptables service, we were in business!
-A RH-Firewall-1-INPUT -m state –state NEW -m tcp -p tcp –dport domain -j ACCEPT
-A RH-Firewall-1-INPUT -m state –state NEW -m udp -p udp –dport domain -j ACCEPT
The internal view looked like below:
options {
listen-on port 53 { 127.0.0.1; 192.168.8.254; };
directory "/var/named";
allow-query { any; localhost; localnets; };
};
view internal {
match-clients { localnets; };
recursion yes;
include "/etc/named.rfc1912.zones";
zone "evoknow.net" { type master; file "evoknow.net"; };
};
Weird Problem with CentOS 5.3 Resolver
One of the strangest thing that I have noticed on CentOS 5.3 is that even if I do not provide any nameservers in /etc/resolv.conf and have a caching DNS server running on the same machine or its default route, it is able to resolve names! I do not understand how that works. Normally, if you have an name server entry in /etc/resolv.conf, it uses it and if you don’t name service fails unless you are trying to resolve hosts defined in /etc/hosts. So I am bit puzzled by the fact that on this new CentOS 5.3 installation, it works without any valid entries in /etc/resolv.conf. I did not bother with this much as it works either way for me now. I will investigate this later or perhaps you can find out more.
Cheers.
Category: DNS | Tags: | 1 Comment »
Published May 18th, 2009 by kabir
Recently, we were upgrading the development environment to CentOS 5.3 wih PHP 5.2.9 and ran across the following issues. This might help you save some times if you are trying the same so we are sharing the details here.
When trying to compile PHP 5.2.9 on CentOS 5.3 with the following configuration options:
#! /bin/sh
#
# Created by configure
'./configure' \
'--with-apxs2=/home/apache/bin/apxs' \
'--with-mysql=/usr/lib' \
'--with-mysqli=/usr/bin/mysql_config' \
'--with-gd' \
'--with-jpeg-dir=/usr/local' \
'--with-png-dir=/usr/lib' \
'--with-zlib' \
'--with-freetype-dir=/usr' \
'--enable-gd-native-ttf' \
'--with-ttf' \
'--with-curl' \
'--with-pspell' \
'--enable-mbstring' \
'--with-mcrypt=/usr/local' \
'--with-mhash=/usr/local' \
'--with-libxml-dir=/usr' \
'--enable-soap' \
'--enable-ftp' \
'--enable-zip' \
'--enable-pcntl' \
"$@"
we got buncha errors related to MySQL as we wanted both mysql tradtional interface and the mysqi (improved) interface for PHP.
After investigating a bit, we figured out that libtool-ltdl and libtool-ltdl-devel packages were not installed on the server. So after running yum -y install libtool-ltdl libtool-ltdl-devel to install the packages, we were able to move further in the compilation process but when linking the binaries with libraries in the system, we found the following error:
gcc: /usr/lib/mysql/libmysqlclient.so: No such file or directory
To fix this, here is what we did, tried to find where the library is currently seating at using locate libmysqlclient.so, which showed:
/usr/lib/libmysqlclient.so
/usr/lib/libmysqlclient.so.16
/usr/lib/libmysqlclient.so.16.0.0
Since the PHP make script is looking for them in /usr/lib/mysql/libmysqlclient.so directory, it made sense to simply create symbolic link using ln -s /usr/lib/libmysqlclient.so
Category: PHP5 | Tags: | 1 Comment »
Published May 8th, 2009 by admin
Today we found out one of our customers office cannot connect to their mail server, which we host in our data center. They use comcast in their offices and comcast all of a sudden decided to not allow customers use comcast mail server for outgoing mail. Wonderful, no one told us that comcast did that so customer found out the hard way.
Customer configured their outlooks and thunderbirds to point to their mail server on port 25. Alas, nothing works. Our tech support was exhausted from pulling in a near 12 hour shift on some other unrelated non-network tasks. So I decided to investigate this from Bangladesh (as I am in our dev center upgrading our dev network), I found out that outbound port 25 is blocked by comcast. So I decided to run postfix on a non-standard port (587) by adding the following lines in the /etc/postfix/master.cf:
# Standard port
smtp inet n - n - - smtpd
# Non-standard port
587 inet n - n - - smtpd
After adding telling postfix to listen to the new non-standard port, I reloaded postix and also told IPTABLES to allow incoming traffic on this port. Then had the customer’s email client configured to send using the new port and we were back in business!
Category: Uncategorized | Tags: | Be the First to Comment »
Published April 23rd, 2009 by admin
Today, one of our customer mail server decided to panic; we can understand — it has been a busy week for the server — lots of emails going in and out — it just decided to throw a kennel panic; normally, we would panic when a kernel does it before us. However, this one had been panicking so much that only thing we can think of is retiring this old one-eyed (1U) beast as soon possible. However, the customer is not ready to fork out big bucks to change it any time soon in this wonderful economy.
So we tried to give it the fingers but the remote kvm was not reachable; more panic on our end. However, we finally got the remote RPC to filp the power and got the server back up and running. Sounds all very typical and simple, right?
Well, mail services (SMTP, POP3, IMAP) all came up fast and only problem we noticed is when users tried to send mail out, they were getting relay access denied message.
Since we use pop-before-smtp for authenticating the IP addresses that connects to the POP3 server (dovecot) as valid SMTP client, we figured restarting the pop-before-smtp, would just do us good on this wonderful Thursday afternoon.
Too bad, we were wrong. The pop-before-smtp script, which is written in Perl, uses BerkeleyDB which is not very good at handling a “CRASH”. It corrupted the existing /etc/postfix/pop-before-smtp.db file and even after deleting it and recreating by flipping the pop-before-smtp service, it turns out the file shows no IP whatsoever when we ran pop-before-smtp --list.
So that is when we starting pulling hair out and decided that we need to do things in baby steps. We did the following to make it all work:
- Stopped the
pop-before-smtp service
- Manually removed the /etc/postfix/pop-before-smtp.db file
- Manually created an empty file called /etc/postfix/pop-before-smtp (without the .db ext)
- Manually ran
postmap /etc/postfix/pop-before-smtp to create an empty Berkeley DB that postfix would love to read
- Manually ran the
file /etc/postfix/pop-before-smtp.db to see if the file is really BerkeleyDB at all
- Manually deleted the /etc/postfix/pop-before-smtp file
- Manually restarted the pop-before-smtp service
Bang!, everything worked. So the lesson here is that, when your server crashes and you have pop-before-smtp running, the BerkeleyDB file might be corrupt and you might want to totally clear the server’s memory by creating empty file, empty BerkeleyDB file and then restarting the service. Just removing the file and restarting pop-before-smtp does not work because we think the BerkeleyDB backend dumps the old data or file bits that corrupts the file again.
So be aware. Better yet, dump pop-before-smtp totally and go with a different solution, which we will discuss in an upcoming post. So stay tuned.
Category: annoyance | Tags: | Be the First to Comment »
Published April 3rd, 2009 by kabir
Most of the time, I use putty for terminal sessions and the very first thing I end up doing is running unalias ls because I just cannot stand colored output from ls. I had been telling myself to do something about it for awhile but I never do as it is such a simple matter.
But finally, I got bugged enough that I decided to permanently remove the colored output from ls for me and the rest of the staff who have the same issue. Here is how:
- Login as root on your CentOS server
- Edit the
/etc/profile.d/colors.sh
- Comment out the line:
alias ls='ls --color=tty' 2>/dev/null
Change to:
## DISABLED alias ls='ls --color=tty' 2>/dev/null
- Now logout and log back in again and you should not see colors for
ls any more
-
- Of course, if you do not want to logout this time, you can also run
source /etc/profile.d/colors.sh to rerun this file, which gets run when you login and use bash shell.
Now from time to time if you have color cravings, you always execute ls --color=tty manually or create a temporary alias using alias ls='ls --color=tty' if you really, really need colors bad!
Cheers!
Kabir
Category: annoyance, shell | Tags: | 1 Comment »
Published January 31st, 2009 by kabir
Problem Statement
Say you found out that a Web crawler from an unsavory spam organization is crawling your Web site for harvesting information such a email addresses and captcha-free Web forms. You have to take action and disable such a beast from using up your bandwidth and server resources. There are many options to fight such a low-life but the easiest one is to block the IP address of the offender. Here in this article, we will show you how to use a simple shell script that you can use to do so.
Step 1: Creating a simple shell script called block_ip.sh
The purpose of this shell script is to read a text file that has a list of IP address or IP networks and block them using iptables. Here is a simplified version of this shell script:
#!/bin/sh
# Filename: block_ip.sh
# Purpose: blocks all IP address/network found in a text file
# The text file must have one IP address or network per line
#################################################################
# Change the following path/filename to match yours
IP_LIST_FILE=/path/to/bad.ip.txt
#################################################################
# Don't change anything below unless you are a smarty pant!
#################################################################
IPTABLES_BIN=/sbin/iptables
# Get the IP address/network from the file and ignore any line starting with # (comments)
BAD_IP_ADDR_LIST=$(grep -Ev "^#" $IP_LIST_FILE)
# Now loop through the IP address/network list and ban them using iptabels
for i in $BAD_IP_ADDR_LIST
do
echo -n "Blocking $i ...";
$IPTABLES_BIN -A INPUT -s $i -j DROP
$IPTABLES_BIN -A OUTPUT -d $i -j DROP
echo "DONE.";
done
##################################################################
# END OF SCRIPT - NOTHING TO SEE HERE - THAT'S ALL FOLKS!
##################################################################
Make sure you make this script executable by changing the permission using chmod 750 block_ip.sh command.
Step 2: Creating your IP address or network block data file
Now create a text file with the same filename in the path you stated in IP_LIST_FILE line in the above-mentioned script. An example of such a file is shown below:
# Block a bogus IP address
200.100.1.100
# Block a bogus IP network
130.86.1.0/24
After creating the file, you are ready to block the IP addresses/networks by running the shell script as follows:
# sh /path/to/block_ip.sh
This will block the IP addresses/network mentioned in the file using iptables.
Verifying the IP blocks
To verify that these IP addresses/networks are blocked, run:
# iptables -L -n
You should see the blocked IP addresses/networks in your INPUT and OUTPUT chains, which basically tells CentOS to ignore incoming or outgoing packets to the named IP addresses or networks.
Category: Security | Tags: | 2 Comments »
Published January 30th, 2009 by kabir
Problem Statement
The APC caching backend is awesome. It speeds up PHP execution by a factor that is worth the trouble of installing it in few minutes. The biggest benefit is that your dumb (or smart) PHP developers do not have to know anything about it. So here is how you can speed up PHP without any help from your superstar PHP programmers.
Step 1: Make Sure APXS is in your current path
Since we install Apache on /home/apache, the APXS (apxs) tool gets installed in /home/apache/bin directory which is not typically in our standard BASH path. So we have to add it by exporting the environment variable called PATH as follows:
# export PATH=$PATH:/home/apache/bin
This appends the /home/apache/bin/ to existing path and thus makes it available to any program looking for apxs.
Step 2: Install APC via PECL
The rest of the APC install is as simple as running the following command:
# pecl install APC
Step 3: Check if APC is bringing in the beacon
Once APC installs, you need to test if it is functional.
Category: Performance | Tags: | 4 Comments »
Published January 6th, 2009 by kabir
Problem Statement
By laws of the universe, Linux systems such as CentOS will not allow a non-root user to change file ownership using the chown command. It is restricted for good reasons. However, in Web production environment where you need other admins to work on files that are often created by multiple users such as the Web server itself or another user, it becomes problematic as root access is often the only way to go. However, in this hack we will demonstrate how you can create a relatively safe (nothing is ever safe) shell script that can be executed by a non-root user using the sudo facility.
Step 1: Configuring the chroot_chown script for your system
Follow the steps below:
- Download the chroot_chown shell script and rename it to
chroot_chown. Next, using your favorite editor (of course, vi) open the file for editing. Review the following lines:
ROOT_DIR='\/mnt\/www\/production\/'
SAFE_ROOT_DIR=/mnt/www/production
USER=production
GROUP=httpd
- Change the
ROOT_DIR value so that it set to the root directory from which the non-root user is allowed access to change ownership. If you set this to /, user will be able to change ownership from anywhere, which would defeat the entire purpose of chrooting the script! So BE CAREFUL when you set this variable. Also, you have to escape the forward-slash characters as we have shown above.
- Set the
SAFE_ROOT_DIR to the same directory as ROOT_DIR without escaping the forward-slash characters
- Set the
USER and GROUP variables to desired username and group name that you want to allow. This username and group will be set for any directory for which the non-root user attempts to change ownership. This is extra protection since we do not want the non-root user to intentionally or unintentionally change the ownership of a file to say ‘root’ and take over the server. :)
- Save the file with your changes
Step 2: Installing the script and setting its permissions
Follow the steps below:
- Copy the
chroot_chown script to /usr/bin directory
- Run
chmod 755 /usr/bin/chroot_chown
- Run
chown root:root /usr/bin/chroot_chown to ensure that the script is owned by root and cannot be altered by any other users
Step 3: Configuring sudo to allow a non-root user to run the chroot_chown script
Follow the steps below:
- Edit the
/etc/sudoers file and a line such as the one shown below:
%groupname ALL=/usr/bin/chroot_chown
- Change the %groupname to desired group name of the non-root users who can run the
chroot_chown script. For example:
%ops ALL=/usr/bin/chroot_chown
This allows the users in ops group to run the script.
- Save your changes.
Step 4: Testing the chroot_chown script
Now as a non-root user in the group who can run the chroot_chown do the following:
$ sudo chroot_chown /path/you/want/to/change/ownership
For example:
$ sudo chroot_chown /mnt/www/production/tmp
The user will be asked to enter her password once and if the password is correct, she will be allowed to change the ownership of the named file or directory to the username and group set in USER and GROUP variables in the /usr/bin/chroot_chown script.
Now if you think that one of your users can trick the script in changing a critical file permission, yes we thought about it and thought about it for awhile and took some measures that should stop such an effort. For example:
$ sudo chroot_chown /etc/passwd
This will fail as the script will automatically set the prefix of the path to $SAFE_ROOT_DIR/etc/passwd which does not exists. So if someone is a bit more interested and tries:
$ sudo chroot_chown /mnt/www/production/../../../etc/passwd
This will fail as the script will catch the .. pattern and print a message like:
Don't be a smarty pant! You cannot have .. in your path.
Category: Security | Tags: | Be the First to Comment »