Saturday, September 24, 2011

CSS Message Boxes for different message types

SkyHi @ Saturday, September 24, 2011
Can you believe this: Few days ago I went to my bank to check my credit score with the Credit Bureau. The bank official typed in my personal data and sent a request. Web application responded by displaying a yellow message box with an exclamation icon saying that data processing is still in progress. He checked several more times, but he didn't notice that at one moment the message changed to "Account available". But the message box hasn't changed. He continued to check a few more times and eventually he realized that the request was successful.
I don't know what was in the minds of developers and designers who created this application, but it certainly wasn't the user. This poor bank official was really frustrated. I can't imagine what the rest of the application looks like.
To prevent this, different message types should be displayed differently. My opinion is that every web application should handle four main message types: information, successful operation, warning and error. Each message type should be presented in a different color and different icon. A special message type represents validation messages.
I will show you a remake of CSS message boxes I used on my latest project. I changed them slightly just to make them simpler for this example. In next article, you will see how to create ASP.NET user control that can support different message types and how to style it using CSS. You will also see how to style ValidationSummary in a similar way.
Let's first take a quick look at message types.

1. Information messages

The purpose of information messages is to inform the user about something relevant. This should be presented in blue because people associate this color with information, regardless of content. This could be any information relevant to a user action.
Informational messagesInformational messages
For example, info message can show some help information regarding current user action or some tips.

2. Success messages

Success messages should be displayed after user successfully performs an operation. By that I mean a complete operation - no partial operations and no errors. For example, the message can say: "Your profile has been saved successfully and confirmation mail has been sent to the email address you provided". This means that each operation in this process (saving profile and sending email) has been successfully performed.
Success MessagesSuccess Messages
I am aware that many developers consider this as an information message type, but I prefer to show this message type using it's own colors and icons - green with a checkmark icon.

3. Warning messages

Warning messages should be displayed to a user when an operation couldn't be completed in a whole. For example "Your profile has been saved successfully, but confirmation mail could not be sent to the email address you provided.". Or "If you don't finish your profile now you won't be able to search jobs". Usual warning color is yellow and icon exclamation.
Warning MessagesWarning Messages

4. Error messages

Error messages should be displayed when an operation couldn't be completed at all. For example, "Your profile couldn't be saved." Red is very suitable for this since people associate this color with an alert of any kind.
Error MessagesError Messages

Design process

Now when we know the way to present messages to users, let's see how to implement a it using CSS. Let's take a quick look at the design process.
I will keep this as simple as I can. The goal is to have a single div that implements a single CSS class. So the HTML markup will look like this:
1.<div class="info">Info messagediv>
2.<div class="success">Successful operation messagediv>
3.<div class="warning">Warning messagediv>
4.<div class="error">Error messagediv>
CSS class will add a background image to the div that will be positioned top-left. It will also create a padding inside the div so that text can have enough white space around it. Note that left padding has to be wider to prevent text overlapping with the background image.
Design LayoutDesign Layout
And here are the CSS classes for all four (five with validation) different message types:
02.font-family:Arial, Helvetica, sans-serif;
04.}, .success, .warning, .error, .validation {
06.border: 1px solid;
07.margin: 10px 0px;
08.padding:15px 10px 15px 50px;
09.background-repeat: no-repeat;
10.background-position: 10px center;
11.} {
13.color: #00529B;
14.background-color: #BDE5F8;
15.background-image: url('info.png');
17..success {
18.color: #4F8A10;
19.background-color: #DFF2BF;
22..warning {
23.color: #9F6000;
24.background-color: #FEEFB3;
25.background-image: url('warning.png');
27..error {
28.color: #D8000C;
29.background-color: #FFBABA;
30.background-image: url('error.png');
Note: Icons used in this example are from Knob Toolbar icons collection.

Validation messages

I noticed that many developers can't distinguish between validation and other message types (such as error or warning messages). I saw many times that validation message is displayed as error message and caused confusion in the user's mind.
Validation is all about user input and should be treated that way. ASP.NET has built in controls that enable full control over user input. The purpose of validation is to force a user to enter all required fields or to enter fields in the correct format. Therefore, it should be clear that the form will not be submitted if these rules aren't matched. That's why I like to style validation messages in a slightly less intensive red than error messages and use a red exclamation icon.
Validation ErrorsValidation Errors
CSS class for validation message is almost identical to others (note that in some attributes are defined in previous code sample):
1..validation {
2.color: #D63301;
3.background-color: #FFCCBA;
4.background-image: url('validation.png');


Messages are an important part of the user experience that is often omitted. There are many articles that show nicely styled message boxes but it is not just a matter of design. It should provide a user with meaningful information, semantically and visually.
There are two other articles I would like to recommend you:
In my next article I will show you how to create ASP.NET user control that can wrap all of these message types and present it to a user. You will also see how to apply this style to a ValidationSummary control


switching from gnu screen to tmux (updated)

SkyHi @ Saturday, September 24, 2011

update #1: upstream accepted my patch, so the next tmux release will provide window-status-alert-{attr,fg,bg} ;)Only difference is the use of alert instead of flagged. It sounds better anyway ;) I’ll adjust my patch on 1.2 as well :)
update #2 [2010/05/17]: uploaded my updated config file, now using ` as my prefix key
I gave tmux a try yesterday.
Clean config file, thorough documentation and a few nice touches here and there (i.e. better, persistent window splitting) make it a nice alternative to screen, but the biggest difference lies in memory usage. Screen can easily eat up to 40-50mb with just a few windows open, but tmux has yet to reach the 10mb mark!
You may argue that ram is cheap these days, but when you’re on a 360mb VPS ram matters ;)
I did find a few bugs/annoyances, for instance if you add set-option -g default-terminal “screen-256color” in your config file, tmux stops evaluating the #T variable.
I hacked my way out of this one by adding the following in my .bash_profile instead:
[[ $TERM == "screen" ]] && export -p TERM="screen-256color"
Turns out that’s not tmux’s fault but bash’s, I’ll have to create a patch for that as well :) If you have the same issue, you can use the above hack as a temporary fix.

Also version 1.2 does not provide a way for you to customize the colors used on window titles with alerts (either monitored or when the bell is active), but I patched that and sent it upstream ;)
You can find an ebuild with the patch in my overlay, wirelay (layman -a wirelay ;) ).
The patch was accepted upstream so it’ll be in the next release.
My tmux looks like this:

and with some split panes:

finally, below is my (updated on 2010/05/17tmux.conf config file, used in the above screenshots.
I decided to use ` as my prefix key, its really better than hitting ctrl-a all the time

# ` is an interesting key for a prefix
set-option -g prefix `
# set-option -g prefix C-a

unbind-key C-b
bind-key C-a last-window
bind-key ` last-window
bind-key a send-prefix

# we might need ` at some point, allow switching
# we can also send the prefix char with `-a
bind-key F11 set-option -g prefix C-a
bind-key F12 set-option -g prefix `

# 0 is too far from ` 
set -g base-index 1

# set-option -g default-terminal "screen-256color"
set-option -g mouse-select-pane on
set-option -g status-keys vi
set-option -g bell-action any
set-option -g set-titles on
set-option -g set-titles-string '#H:#S.#I.#P #W #T' # window number,program name,active (or not)
set-option -g visual-bell on

setw -g mode-keys vi
setw -g mode-mouse on
setw -g monitor-activity on

bind e previous-window
bind f next-window
bind j up-pane
bind k down-pane

set-option -g status-utf8 on
# set-option -g status-justify centre
set-option -g status-justify left
set-option -g status-bg black
set-option -g status-fg white
set-option -g status-left-length 40

set-option -g pane-active-border-fg green
set-option -g pane-active-border-bg black
set-option -g pane-border-fg white
set-option -g pane-border-bg black

set-option -g message-fg black
set-option -g message-bg green

#setw -g mode-bg black

setw -g window-status-bg black
setw -g window-status-current-fg green
setw -g window-status-alert-attr default
setw -g window-status-alert-fg yellow

set -g status-left '#[fg=red]#h#[fg=green]:#[fg=white]#S #[fg=green]][#[default]'

# set -g status-right '#[fg=green]][#[fg=white] #T #[fg=green]][ #[fg=blue]%Y-%m-%d #[fg=white]%H:%M#[default]'
set -g status-right '#[fg=green]][ #[fg=blue]%Y-%m-%d #[fg=white]%H:%M#[default]'

set -g history-limit 4096

# `+r reloads the configuration, handy
bind r source-file ~/.tmux.conf

Thursday, September 22, 2011


SkyHi @ Thursday, September 22, 2011
# Make it use C-a, similar to screen..
unbind C-b
unbind l
set -g prefix C-a
bind-key C-a last-window

##Sane scrolling
set -g terminal-overrides 'xterm*:smcup@:rmcup@'

#Highlighting the active window in status bar
setw -g window-status-current-bg black
setw -g window-status-current-fg yellow
setw -g window-status-alert-bg black
setw -g window-status-alert-fg cyan  # backwards


tmux new-session -d -s hawkhost

tmux new-window -t hawkhost:1 -n 'Server1' 'ssh root@10.x.x.x'
tmux new-window -t hawkhost:2 -n 'Server2' 'ssh root@10.x.x.x'
tmux new-window -t hawkhost:3 -n 'Server3' 'ssh root@10.x.x.x'
tmux new-window -t hawkhost:4 -n 'Server4' 'ssh root@10.x.x.x'
tmux new-window -t hawkhost:5 -n 'Server5' 'ssh root@10.x.x.x'
tmux select-window -t hawkhost:1
tmux -2 attach-session -t hawkhost

Here is my current .tmux.conf:
# vi mode
set-window-option -g mode-keys vi
set-option -g status-keys vi

# misc settings
set-window-option -g utf8 on
set-window-option -g automatic-rename off
set-window-option -g mode-mouse on
set bell-action none

# statusbar
set-option -g status-bg black
set-option -g status-fg yellow
set-option -g status-right '#H %d.%m.%Y %H:%M'
set-window-option -g window-status-current-attr bold

and heres a example project file that i start, when i login to xmonad, that creates all my current project windows and panes:
# creates the environment for the project a

tmux start-server

if ! $(tmux has-session -t ProjectA) 

    cd /srv/www/ProjectA
    tmux new-session -d -s ProjectA -n terminal

    tmux new-window -t ProjectA:1 -n editor
    tmux set-window-option -t ProjectA:1 aggressive-resize on

    cd /srv/www/ProjectA/system/usr/share/doc/database
    tmux new-window -t ProjectA:2 -n database
    tmux split-window -t ProjectA:2
    tmux resize-pane -D -t ProjectA:2.0 20 
    tmux select-pane -t ProjectA:2.0

    tmux new-window -t ProjectA:3 -n log 
    tmux split-window -t ProjectA:3

    cd /srv/www/ProjectA/system/usr/share/doc/test
    tmux new-window -t ProjectA:4 -n test

    tmux send-keys -t ProjectA:1 'vim' C-m
    tmux send-keys -t ProjectA:2.0 'mysql -u root -pmypass ProjectA' C-m
    tmux send-keys -t ProjectA:3.0 'tail -f /srv/www/ProjectA/system/var/log/messages.log' C-m
    tmux send-keys -t ProjectA:3.1 'tail -f /var/log/httpd/error_log' C-m

    tmux select-window -t ProjectA:0


tmux -2 attach-session -t ProjectA

tmux basic

SkyHi @ Thursday, September 22, 2011
A comparison of the features (or more-so just a table of notes for accessing some of those features) for GNU screen and BSD-licensed tmux.
This document released for use under the PPL license available at
Want more information about tmux and screen? Check out This page also
The formatting here is simple enough to understand (I would hope). ^ means ctrl+, so ^x is ctrl+x. M- means meta (generally left-alt or escape)+, so M-x is left-alt+x
Action tmux screen
start a new session tmux OR
tmux new OR
tmux new-session
re-attach a detached session tmux attach OR
tmux attach-session
screen -r
re-attach an attached session (detaching it from elsewhere) tmux attach -d OR
tmux attach-session -d
screen -dr
re-attach an attached session (keeping it attached elsewhere) tmux attach OR
tmux attach-session
screen -x
detach from currently attached session ^b d OR
^b :detach
^a ^d OR
^a :detach
rename-window to newname ^b , OR
^b :rename-window
^a A
list windows ^b w ^a w
list windows in chooseable menu
^a "
go to window # ^b # ^a #
go to last-active window ^b l ^a l
go to next window ^b n ^a n
go to previous window ^b p ^a p
see keybindings ^b ? ^a ?
list sessions ^b s OR
tmux ls OR
tmux list-sessions
screen -ls
toggle visual bell
^a ^g
create another shell ^b c ^a c
exit current shell ^d ^d
split pane horizontally ^b "
split pane vertically ^b %
switch to another pane ^b o
kill the current pane ^b x OR (logout/^D)
close other panes except the current one ^b !
swap location of panes ^b ^o
show time ^b t
show numeric values of panes^b q


Ctrl-b c Create new window
Ctrl-b d Detach current client
Ctrl-b l Move to previously selected window
Ctrl-b n Move to the next window
Ctrl-b p Move to the previous window
Ctrl-b & Kill the current window
Ctrl-b , Rename the current window
Ctrl-b % Split the current window into two panes
Ctrl-b q Show pane numbers (used to switch between panes)
Ctrl-b o Switch to the next pane
Ctrl-b ? List all keybindings

Ctrl-b n (Move to the next window)
Ctrl-b p (Move to the previous window)
Ctrl-b l (Move to the previously selected window)
Ctrl-b w (List all windows / window numbers)
Ctrl-b (Move to the specified window number, the default bindings are from 0 – 9)

Ctrl-b % (Split the window vertically)
Ctrl-b : “split-window” (Split window horizontally)
Ctrl-b : “break-pane” (Make pane its own window)
Ctrl-b o (Goto next pane)
Ctrl-b q (Show pane numbers, when the numbers show up type the key to goto that pane)
Ctrl-b { (Move the current pane left)
Ctrl-b } (Move the current pane right)

Ctrl-b : resize-pane (By default it resizes the current pane down)
Ctrl-b : resize-pane -U (Resizes the current pane upward)
Ctrl-b : resize-pane -L (Resizes the current pane left)
Ctrl-b : resize-pane -R (Resizes the current pane right)
Ctrl-b : resize-pane 20 (Resizes the current pane down by 20 cells)
Ctrl-b : resize-pane -U 20 (Resizes the current pane upward by 20 cells)
Ctrl-b : resize-pane -L 20 (Resizes the current pane left by 20 cells)
Ctrl-b : resize-pane -R 20 (Resizes the current pane right by 20 cells)
Ctrl-b : resize-pane -t 2 20 (Resizes the pane with the id of 2 down by 20 cells)
Ctrl-b : resize-pane -t -L 20 (Resizes the pane with the id of 2 left by 20 cells)


Wednesday, September 21, 2011

Hardening guide for Nginx 0.7.65 on RedHat 5.4 (64bit edition)

SkyHi @ Wednesday, September 21, 2011
1..Login to the server using Root account.
2. Create a new account:
groupadd nginx
useradd -g nginx -d /dev/null -s /sbin/nologin nginx

3.Mount RHEL 5.4 DVD, and move to the RPM folder:
mount /dev/hdc /media
cd /media/Server

4.Before compiling the Nginx environment, install the following RPM:
rpm -ivh kernel-headers-2.6.18-164.el5.x86_64.rpm
rpm -ivh glibc-headers-2.5-42.x86_64.rpm
rpm -ivh glibc-devel-2.5-42.x86_64.rpm
rpm -ivh gmp-4.1.4-10.el5.x86_64.rpm
rpm -ivh libgomp-4.4.0-6.el5.x86_64.rpm
rpm -ivh gcc-4.1.2-46.el5.x86_64.rpm
rpm -ivh pcre-devel-6.6-2.el5_1.7.x86_64.rpm
rpm -ivh e2fsprogs-devel-1.39-23.el5.x86_64.rpm
rpm -ivh keyutils-libs-devel-1.2-1.el5.x86_64.rpm
rpm -ivh libsepol-devel-1.15.2-2.el5.x86_64.rpm
rpm -ivh libselinux-devel-1.33.4-5.5.el5.x86_64.rpm
rpm -ivh krb5-devel-1.6.1-36.el5.x86_64.rpm
rpm -ivh zlib-devel-1.2.3-3.x86_64.rpm
rpm -ivh openssl-devel-0.9.8e-12.el5.x86_64.rpm

 5.Download Nginx 0.7.65 from:
6.Copy the Nginx 0.7.65 source files using PSCP (or SCP) into /tmp
7.Move to /tmp
cd /tmp

8.Extract the nginx-0.7.65.tar.gz file:
tar -zxvf nginx-0.7.65.tar.gz

9.Move to the Nginx source folder:
cd /tmp/nginx-0.7.65

10.Edit using VI, the file /tmp/nginx-0.7.65/src/http/ngx_http_header_filter_module.c and replace the following section, from:
static char ngx_http_server_string[] = "Server: nginx" CRLF;
static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;
static char ngx_http_server_string[] = "Server: Secure Web Server" CRLF;
static char ngx_http_server_full_string[] = "Server: Secure Web Server" CRLF;

11.Run the commands bellow to compile the Nginx environment:
./configure --with-http_ssl_module --without-http_autoindex_module --without-http_ssi_module

make install

12.Remove the Nginx source files:
rm -rf /tmp/nginx-0.7.65
rm -f /tmp/nginx-0.7.65.tar.gz

13.Remove Default Content
rm -rf /usr/local/nginx/html

14.Updating Ownership and Permissions on Nginx folders:
chown -R root:root /usr/local/nginx
chmod 750 /usr/local/nginx/sbin/nginx
chmod -R 640 /usr/local/nginx/conf
chmod -R 770 /usr/local/nginx/logs

15.Create folder for the web content:
mkdir -p /www
16.Updating Ownership and Permissions on the web content folder:
chown -R root /www
chmod -R 775 /www

17.Edit using VI the file /usr/local/nginx/conf/nginx.conf and change the following settings:
#user nobody;To:
user nginx nginx;
#error_log logs/error.log notice;To:
error_log logs/error.log notice;

server_name localhost;To:
server_name Server_FQDN;

root html;To:
root /www;
18.Add the following sections to the end of the /usr/local/nginx/conf/nginx.conf file:
server_tokens off;
client_body_buffer_size 1K;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;
client_body_timeout 10;
client_header_timeout 10;
send_timeout 10;

19.Create using VI, the file /etc/init.d/nginx with the following content:
# nginx - this script starts and stops the nginx daemon
# chkconfig: - 85 15
# description: Nginx is an HTTP(S) server, HTTP(S) reverse \
# proxy and IMAP/POP3 proxy server
# processname: nginx
# config: /etc/nginx/nginx.conf
# config: /etc/sysconfig/nginx
# pidfile: /var/run/

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

prog=$(basename $nginx)


[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx


start() {
[ -x $nginx ] exit 5
[ -f $NGINX_CONF_FILE ] exit 6
echo -n $"Starting $prog: "
daemon $nginx -c $NGINX_CONF_FILE
[ $retval -eq 0 ] && touch $lockfile
return $retval

stop() {
echo -n $"Stopping $prog: "
killproc $prog -QUIT
[ $retval -eq 0 ] && rm -f $lockfile
return $retval

restart() {
configtest return $?
sleep 1

reload() {
configtest return $?
echo -n $"Reloading $prog: "
killproc $nginx -HUP

force_reload() {

configtest() {
$nginx -t -c $NGINX_CONF_FILE

rh_status() {
status $prog

rh_status_q() {
rh_status >/dev/null 2>&1

case "$1" in
rh_status_q && exit 0
rh_status_q exit 0
rh_status_q exit 7
rh_status_q exit 0
echo $"Usage: $0 {startstopstatusrestartcondrestarttry-restartreloadforce-reloadconfigtest}"
exit 2

20.Change the permissions of the file /etc/init.d/nginx
chmod +x /etc/init.d/nginx
21.To start Nginx service at server start-up, run the command:
chkconfig nginx on

22.To manually start the Nginx service, use the command:
/etc/init.d/nginx start

23.Uninstall the following RPM:
rpm -e gcc-4.1.2-46.el5
rpm -e libgomp-4.4.0-6.el5
rpm -e gmp-4.1.4-10.el5
rpm -e glibc-devel-2.5-42
rpm -e glibc-headers-2.5-42
rpm -e kernel-headers-2.6.18-164.el5


Iptables Limits Connections Per IP

SkyHi @ Wednesday, September 21, 2011
How do I restrict the number of connections used by a single IP address to my server for port 80 and 25 using iptables?

You need to use the connlimit modules which allows you to restrict the number of parallel TCP connections to a server per client IP address (or address block).
This is useful to protect your server or vps box against flooding, spamming or content scraping.


The syntax is as follows:
/sbin/iptables -A INPUT -p tcp --syn --dport $port -m connlimit --connlimit-above N -j REJECT --reject-with tcp-reset
# save the changes see iptables-save man page, the following is redhat and friends specific command
service iptables save

Example: Limit SSH Connections Per IP / Host

Only allow 3 ssg connections per client host:
/sbin/iptables  -A INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 3 -j REJECT
# save the changes see iptables-save man page, the following is redhat and friends specific command
service iptables save

Example: Limit HTTP Connections Per IP / Host

Only allow 20 http connections per IP (MaxClients is set to 60 in httpd.conf):
WARNING! Please note that large proxy servers may legitimately create a large number of connections to your server. You can skip those ips using ! syntax
/sbin/iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 20 -j REJECT --reject-with tcp-reset
# save the changes see iptables-save man page, the following is redhat and friends specific command
service iptables save
Skip proxy server IP from this kind of limitations:
/sbin/iptables -A INPUT -p tcp --syn --dport 80 -d ! -m connlimit --connlimit-above 20 -j REJECT --reject-with tcp-reset

Example: Class C Limitations

In this example, limit the parallel http requests to 20 per class C sized network (24 bit netmask)
/sbin/iptables  -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 20 --connlimit-mask 24 -j REJECT --reject-with tcp-reset
# save the changes see iptables-save man page
service iptables save

Example: Limit Connections Per Second

The following example will drop incoming connections if IP make more than 10 connection attempts to port 80 within 100 seconds (add rules to your iptables shell script)
# Max connection in seconds
# Max connections per IP
# ....
# ..
# default action can be DROP or REJECT
$IPT -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --set
$IPT -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --update --seconds ${SECONDS} --hitcount ${BLOCKCOUNT} -j ${DACTION}
# ....
# ..

How Do I Test My Firewall Working?

Use the following shell script to connect to your web server hosted at
for i in {1..100}
  # do nothing just connect and exit
  echo "exit" | nc ${ip} ${port};


Tuesday, September 20, 2011

Multi-Site in WordPress

SkyHi @ Tuesday, September 20, 2011
Wordpress is my favorite website platform .One of the really cool features that WordPress offers is Multi-sites. Mult-sites can be turned on in any recent WordPress installation (3.0 and up).Turning on multi-sites allows you to create and manage as many sites as you want from a single WordPress installation. It is not difficult to activate multi-sites and there are tons of blogs out there that will walk you through the process (like this one), but if you want to use different domains on each of your new sites, you will need to either install a plugin ( I have never used this method) or you can use the little trick I am going to write about.

This trick will let you use a different domain for each new website you create in your WordPress installation. So for example, you have your WordPress installed on, and have set up multi-sites. You create a new site called, but you really want to use your other domain “” No problem! You are at the right place. This trick will make that happen, and will work for as many new sites as you care to create (as long as you have a domain for each new site).

This method involves going into  your MySQL database and creating a new record by hand, and modifying another record. If you are not comfortable with doing this, then better to use a plugin. Also, make sure you have backed up your database and website files in case something goes crazy-ape bonkers.

Using Different Domains on WordPress Multi-sites

So you have multi-sites turned on, and you have another domain you would like to use on a new site you will create. There are a few steps you need to do (the following has worked for me using BlueHost and DreamHost, but should work with other domains as well) :
  • Set your new domain to be Parked (BlueHost) or Mirrored to your original domain (DreamHost)
  • Create a new site in your WordPress install. Just using a sub-domain for now.
  • Go into the MySQL database your WordPress is using, and add a new record in the sites table.

Ready? Here we go. For this setup, I have installed WordPress on my brother-in-laws domain space ““, and set up a website for him. I wanted to create an additional site on the same WordPress install for my father-in-law’s website using the domain ““. That way I could manage both websites from a single location.

Firstly, I activated “Multi-Sites” using the basic instructions you can find on your blog of choice. Then I logged in as Network Admin and created a new site called

Next, I needed to point the domain to In DreamHost, this is done by setting to mirror (which is set as “Fully Hosted”.)  In BlueHost, you have one domain that is your primary domain, and then you just “Park” your new domains. whatever your hosting company, the goal is to make your new domain point to wherever you have WordPress installed..WordPress will take care of the rest.

It should be noted that once you change settings for a domain with your hosting company, it can take a few hours or more for those changes to take effect, so make sure to wait a while before freaking out.

So I have my second site set up and I have my second domain pointing to my WordPress install. Now I need to makes some changes to the MySQL database that WordPress is using. I will use phpMyadmin for this, but you could use MySQL Workbench or even PuTTy if you want.
  • Log in to phpMysql and choose the database WordPress is using.
  • From the list of tables on the left, choose wp_sites
  • Click the Insert tab to insert a new record
  • Type in 2 in the ID field (or higher number, depending on how many times you have done this..second site gets 2, 3rd site gets 3…)
  • Type in the domain you want to use for your new site in the Domain field
  • Type in / for path
  • Click the Go button to add this record, now you should see the new site in the list of sites

  • Now click on the wp-blogs table on the left
  • Click the pencil icon next to the blog(site) that will get the new domain
  • Change the domain field to your new domain ( and change the path to /
  • Click the GO button to save changes, you should see your changes saved in the list

  • You can leave phpMyadmin, and log into your WordPress site as Network Admin, and go to Network admin (upper-right hand corner drop-down)
  • Go to Sites
  • Choose “edit” on the site that has the new domain can be hard to tell which is which now because they all have the same path /
  • On the “Settings” tab, check the SiteURL, Home, and FileUploadURL. They should all have your new domain in them. FileUploadURL should have your domain and /files after it. Change them if they need it, click “Save Settings”

After having completed all of that, I found that there was one additional small change I needed to make:
After setting up the Multi-Sites, WordPress gave me some code to add to the wp-config.php file. I had to remove a few of those lines from my wp-config file because it was causing links in the new sites to go back to the original site. You will only need to do this once:
define( ‘MULTISITE’, true );
define( ‘SUBDOMAIN_INSTALL’, false );
$base = ‘/’;
define( ‘DOMAIN_CURRENT_SITE’, ’’ );  ####remove line define( ‘PATH_CURRENT_SITE’, ‘/’ );
define( ‘SITE_ID_CURRENT_SITE’, 1 );   ####remove line define( ‘BLOG_ID_CURRENT_SITE’, 1 );   ####remove line

Thats it. Your new site should be  using the new domain name. You can add as many sites and new domains as you want. In my next article I will write about setting up multiple FTP accounts for each of your new websites you add.


Spamassassin setup and config for User

SkyHi @ Tuesday, September 20, 2011
1User Config

User Setup #1
Spamassassin is called by procmail. A .procmailrc in a users home directory forwards/filters emails via spamassassin. The default lines for spamassassin to be included into .procmailrc are:
| spamc
#forward all emails and pipe them via spam catcher
#make sure spamc is executable on the mail server.
#put in the entire path to spamc if required, e.g. /usr/local/bin/spamc

* ^X-Spam-Status: Yes
#If spamassassin detects a spam email - it includes a Spam header entry. If this Spam header=yes - then the email can be put into a special spam folder to be checked infrequently. The above .Spam/ folder is a Maildir folder.

User Setup #2
The above Step #1 is all that should be needed. Send an email to yourself next. Check the headers, you should see something similar to:
X-Spam-Checker-Version: SpamAssassin 3.0.3 (2005-04-27) on
X-Spam-Status: No, score=-2.5 required=5.0 tests=ALL_TRUSTED,HTML_30_40,
HTML_MESSAGE,MIME_HTML_MOSTLY autolearn=ham version=3.0.3
Note: autolearn is working.
What should also happen:
A .spamassassin folder should be created in your home directory, with ~3-4 default files in it. A spamassassin default file may or may not be created. To copy one from the examples:
cp /usr/share/spamassassin/user_prefs.template /home/$USER/.spamassassin/user_prefs

A user can edit this user_prefs file adding a white and black list etc. etc.
Sample user_prefs Spamassassin User Config
The global spamassassin file is located in /etc/spamassassin/ However a normal user cannot change this. Instead, the users spamassassin config in /home/$USER/.spamassassin/user_prefs can be edited, and different scores can be used, alongside further tests etc. to be carried out. The following are increased scores for tests I consider to be spam catching:
score RCVD_IN_SBL 2.0
score URIBL_SBL 1.5
score URIBL_OB_SURBL 2.5

My thinking is that - if the email is in a Spam BlackList - then its spam, and thus I wanted to give them higher scores than the default. I would consider Bouncing these emails, however I will leave it collect in the Spam folder for the time being. Links:

User Setup #3
Getting and teaching learn and sa_learn to get better at detecting spam emails. See:
More Info on User Config at: = basic procmail integration

Updating Spamassassin Rules

Note: this was tested and run on ubuntu/ hardy (prob work the same on debian lenny). I needed to update spamassassin rules recently after the following was been matched: FH_DATE_PAST_20XX now that its 2010. These updates are not installed via apt-get but via spamassassin's own sa-update. Here is how:
sa-update -D
#-D is for showing debug/log info
/etc/init.d/spamassassin restart

#I sent another email to me, checked the header, and FH_DATE_PAST_20XX no longer showed up

1. cp /home/users/pd/.procmailrc /home/users/gm/
2. chown gm:console .procmailrc
3. cp -r /home/user/pd/.spamassassin /home/users/gm/
4. chown -R gm:console .spamassassin
5. cat /dev/null > auto-whitelist
    cat /dev/null > bayes_seen
    cat /dev/null > bayes_toks
6. vi /home/user/gm/.spamassasin/user_prefs
    required_score         3



Monday, September 19, 2011

Get Size of Files in a Linux Directory Modified in the Past 24 Hours

SkyHi @ Monday, September 19, 2011
find . -mtime -27 -type f -printf "%p %sBytes\n"

With a system thats regularly creating files on-the-fly it’s important to keep track of the filesizes to monitor disk usage. One of the daily tasks I perform is to track the filesize of files created within the last day by running the following on the command line:
view plaincopy to clipboardprint?

find /directory_name -iname "*.zip" -mtime -1 -printf "%p %k\n"

By running the above you will be presented with a list of all ZIP files modified in the last 24 hours along with the filesize of each. Let me break it down a bit further:


‘find’ is a linux command used to locate files on the Linux system. Used in conjunction with additional parameters it can be a powerful command to find a set of specific files.


This is the directory that we wish to search within. All subdirectories of this specified folder will also be included in the search.
view plaincopy to clipboardprint?

-iname "*.zip"

Used to locate all files with a ‘.zip’ extension.

-mtime -1

Here we specify the modified date of the files that we wish to return. In this scenario we are saying show all files modified within the last 1 day.
view plaincopy to clipboardprint?

-printf "%p %k\n"

This is the format of the files output to screen. %p correponds to the filename and %k relates to the size of the file in kilobytes. Each file will be separated by a new line (\n).