Search Posts on Binpipe Blog

Generate CSR in Linux Server

To create a signed ssl certificate from a trusted certificate authority
you will need to generate a csr, certificate signing request, which will
then be sent to your CA where they can generate the ssl cert for you to
install on the server. This is only necessary for production servers
with a domain or sub domain pointing to it. For non-production use it is
fine to just use a self signed cert that will not cost anything.

yum -y install mod_ssl openssl
cd /etc/pki/tls/certs
openssl genrsa -out new_ssl_cert.key 2048
openssl req -new -key new_ssl_cert.key -out new_ssl_cert.csr

Install CurlFTPFS on CentOS or Redhat Linux

CurlFTPFS is a very good tool to mount remote FTP directory to the local filesystem. The following commands are used to install the package:

yum install glib2-devel  yum install fuse-devel  yum install libcurl-devel  wget  tar xvzf curlftpfs-0.9.2.tar.gz  cd curlftpfs-0.9.2  ./configure  make  make install      
If you have any dependency issues, then please use the following rpm package to install  CurlFTPFS:

Once done, the directory can be mounted with the command syntax from here:

Install OpenSSH 5 in CentOS 5.x

In one of my previous posts , we had discussed the steps to get an user chrooted to her home directory. For that we need to install open SSH 5.x and above. But as per feedback from some readers I found that most people are having issues upgrading to the latest OpenSSH 5.2 in CentOS 5.x versions. So, here are the steps for installing OpenSSH 5.2 in CentOS 5.x.

Centos 5.x yum doesn’t seem to support latest OpenSSH 5.2 which supports many new features. (The default Openssh version present in Centos 5.x is around 4.2)

Firstly, install the following prerequisites:

# yum install gcc
# yum install openssl-devel
# yum install pam-devel
# yum install rpm-build

And then download openssh 5.2p1

# wget

Now, we’re going to build RPM based on tar.gz file:

# tar xvfz openssh-5.2p1.tar.gz
# cp ./openssh-5.2p1/contrib/redhat/openssh.spec /usr/src/redhat/SPECS/
# cp  ./openssh-5.2p1.tar.gz /usr/src/redhat/SOURCES/
# cd /usr/src/redhat/SPECS/
# perl -i.bak -pe 's/^(%define no_(gnome|x11)_askpass)\s+0$/$1 1/' openssh.spec
# rpmbuild -bb openssh.spec
# cd /usr/src/redhat/RPMS/`uname -i`
# ls -l

drwxr-xr-x 2 root root   4096 Jun 30 12:39 .
drwxr-xr-x 9 root root   4096 Jun 30 12:35 ..
-rw-r--r-- 1 root root 271758 Jun 30 12:39 openssh-5.2p1-1.i386.rpm
-rw-r--r-- 1 root root 429852 Jun 30 12:39 openssh-clients-5.2p1-1.i386.rpm
-rw-r--r-- 1 root root 268302 Jun 30 12:39 openssh-server-5.2p1-1.i386.rpm

-rw-r--r-- 1 root root 271758 Jun 30 12:39 openssh-5.2p1-1.i386.rpm
-rw-r--r-- 1 root root 429852 Jun 30 12:39 openssh-clients-5.2p1-1.i386.rpm
-rw-r--r-- 1 root root 268302 Jun 30 12:39 openssh-server-5.2p1-1.i386.rpm

# rpm -Uvh openssh*rpm
Preparing... ################################
1: openssh ####
2: openssh-clients ####
3: openssh-server ####
# service sshd restart

Simple Postfix Mail Server with Mysql based backend and RoundCube Webmail

We will setup a mail server with the following features on CentOS 6 :

  • Postfix (SMTP)
  • SASL smtp
  • secure with TLS
  • Dovecot for imap and pop3
  • imaps and pops
  • filtering of spam to a spam folder
  • mysql based domain and users
  • PostfixAdmin for the mail server administration
  • roundcube as webmail frontend
  • amavisd-new, spamassassin and clamav
Operating System Used : CentOS 6.3
Yum repository installation:
The following remi and epel repos have been enabled:
sudo rpm -Uvh remi-release-6*.rpm epel-release-6*.rpm.
Installation of all the required packages:
yum install roundcubemail dovecot dovecot-mysql dovecot-pigeonhole cyrus-sasl-devel cyrus-sasl-sql subversion perl-MailTools perl-MIME-EncWords perl-MIME-Charset perl-Email-Valid perl-Test-Pod perl-TimeDate perl-Mail-Sender perl-Log-Log4perl imapsync offlineimap amavisd-new clamav clamd razor-agents perl-Convert-BinHex
Setting up User, directories and permissions
mkdir /home/vmail
chmod 770 /home/vmail
useradd -r -u 101 -g mail -d /home/vmail -s /sbin/nologin -c “Virtual mailbox” vmail
chown vmail:mail /home/vmail

Postfix admin setup

Download and move
tar zxf postfixadmin-2.3.5.tar.gz
mv postfixadmin-2.3.5 postfixadmin
mv postfixadmin/ /usr/share/
Apache setup for postfixadmin
alias /mailadmin /usr/share/postfixadmin
<Directory “/usr/share/postfixadmin”>
AllowOverride AuthConfig
Create Database
mysql -u admin -p -e “CREATE DATABASE postfix;”
Changes required in the config file
$CONF['database_type'] = ‘mysql’;
$CONF['database_host'] = ‘localhost’;
$CONF['database_user'] = ‘DB_User’;
$CONF['database_password'] = ‘DB_Passowrd’;
$CONF['database_name'] = ‘postfix’;
Enter the setup password as soon as the setup is complete in the following parameter:
$CONF['setup_password'] =”


Following are the file for the setup:
touch /etc/postfix/virtual_regexp
The main configration file: (change the bold text according to your requirement)
# postfix config file
# uncomment for debugging if needed
# postfix main
mail_owner = postfix
setgid_group = postdrop
delay_warning_time = 4
# postfix paths
html_directory = no
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
queue_directory = /var/spool/postfix
sendmail_path = /usr/sbin/sendmail.postfix
newaliases_path = /usr/bin/newaliases.postfix
mailq_path = /usr/bin/mailq.postfix
manpage_directory = /usr/share/man
sample_directory = /usr/share/doc/postfix-2.2.2/samples
readme_directory = /usr/share/doc/postfix-2.2.2/README_FILES
# network settings
inet_interfaces = all
mydomain =
myhostname =
mynetworks = $config_directory/mynetworks
mydestination = $myhostname, localhost.$mydomain, localhost
relay_domains = proxy:mysql:/etc/postfix/
# mail delivery
recipient_delimiter = +
# mappings
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
transport_maps = hash:/etc/postfix/transport
#local_recipient_maps =
# virtual setup
virtual_alias_maps = proxy:mysql:/etc/postfix/,
virtual_mailbox_base = /home/vmail
virtual_mailbox_domains = proxy:mysql:/etc/postfix/
virtual_mailbox_maps = proxy:mysql:/etc/postfix/
virtual_mailbox_limit_maps = proxy:mysql:/etc/postfix/
virtual_minimum_uid = 101
virtual_uid_maps = static:101
virtual_gid_maps = static:12
virtual_transport = dovecot
dovecot_destination_recipient_limit = 1
# debugging
debug_peer_level = 2
debugger_command =
xxgdb $daemon_directory/$process_name $process_id & sleep 5
# authentication
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname
broken_sasl_auth_clients = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
# tls config
smtp_use_tls = yes
smtpd_use_tls = yes
smtp_tls_note_starttls_offer = yes
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom
smtp_tls_session_cache_database = btree:$data_directory/smtp_tls_session_cache
# Change* to your host name
smtpd_tls_key_file = /etc/pki/tls/private/server.key
smtpd_tls_cert_file = /etc/pki/tls/private/server.crt
# smtpd_tls_CAfile = /etc/pki/tls/root.crt
# rules restrictions
smtpd_client_restrictions =
smtpd_helo_restrictions =
smtpd_sender_restrictions =
smtpd_recipient_restrictions = permit_sasl_authenticated,
# uncomment for realtime black list checks
#    ,reject_rbl_client
#    ,reject_rbl_client
#    ,reject_rbl_client
smtpd_helo_required = yes
unknown_local_recipient_reject_code = 550
disable_vrfy_command = yes
smtpd_data_restrictions = reject_unauth_pipelining
Setup The Certificate for the secure mail communication
cd /etc/pki/tls/private/
openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
openssl rsa -in -out server.key
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
# Postfix master process configuration file.  For details on the format
# of the file, see the Postfix master(5) manual page.
# ***** Unused items removed *****
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd
  -o content_filter=smtp-amavis: (comment bold text if you are not using amavis/spam filertin)
  -o receive_override_options=no_address_mappings
pickup    fifo  n       -       n       60      1       pickup
-o content_filter=
-o receive_override_options=no_header_body_checks
cleanup   unix  n       -       n       -       0       cleanup
qmgr      fifo  n       -       n       300     1       qmgr
#qmgr     fifo  n       -       n       300     1       oqmgr
tlsmgr    unix  -       -       n       1000?   1       tlsmgr
rewrite   unix  -       -       n       -       -       trivial-rewrite
bounce    unix  -       -       n       -       0       bounce
defer     unix  -       -       n       -       0       bounce
trace     unix  -       -       n       -       0       bounce
verify    unix  -       -       n       -       1       verify
flush     unix  n       -       n       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
smtp      unix  -       -       n       -       -       smtp
# When relaying mail as backup MX, disable fallback_relay to avoid MX loops
relay     unix  -       -       n       -       -       smtp
-o fallback_relay=
#       -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq     unix  n       -       n       -       -       showq
error     unix  -       -       n       -       -       error
discard   unix  -       -       n       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       n       -       -       lmtp
anvil     unix  -       -       n       -       1       anvil
scache    unix  -       -       n       -       1       scache
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# pages of the non-Postfix software to find out what options it wants.
# ====================================================================
maildrop  unix  -       n       n       -       -       pipe
flags=DRhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient}
uucp      unix  -       n       n       -       -       pipe
flags=Fqhu user=uucp argv=uux -r -n -z -a$sender – $nexthop!rmail ($recipient)
ifmail    unix  -       n       n       -       -       pipe
flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp     unix  -       n       n       -       -       pipe
flags=Fq. user=foo argv=/usr/local/sbin/bsmtp -f $sender $nexthop $recipient
# spam/virus section
smtp-amavis  unix  -    -       y       -       2       smtp
-o smtp_data_done_timeout=1200
-o disable_dns_lookups=yes
-o smtp_send_xforward_command=yes inet n  -       y       -       -       smtpd
-o content_filter=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
-o receive_override_options=no_header_body_checks
-o smtpd_bind_address=
-o smtpd_helo_required=no
-o smtpd_client_restrictions=
-o smtpd_restriction_classes=
-o disable_vrfy_command=no
-o strict_rfc821_envelopes=yes
# Dovecot LDA
dovecot   unix  -       n       n       -       -       pipe
flags=DRhu user=vmail:mail argv=/usr/libexec/dovecot/deliver -d ${recipient}
# Vacation mail
vacation    unix  -       n       n       -       -       pipe
flags=Rq user=vacation argv=/var/spool/vacation/ -f ${sender} — ${recipient}
Define the Allowed networks(Change the networks required)
# This specifies the list of subnets that Postfix considers as
# “trusted” SMTP clients that have more privileges than “strangers”.
# In particular, “trusted” SMTP clients are allowed to relay mail
# through Postfix.
# Be sure to add your public ip address block if needed.
Add the following file for the postfix mysql proxy maps(Change user,password,dbname)
hosts = localhost
user = root
password = hahaha
dbname = postfix
query = SELECT goto FROM alias WHERE address=’%s’ AND active = ’1′
hosts = localhost
user = root
password = hahaha
dbname = postfix
query = SELECT domain FROM domain WHERE domain=’%s’ AND backupmx = ’0′ AND active = ’1′
hosts = localhost
user = root
password = hahaha
dbname = postfix
query = SELECT domain FROM domain WHERE domain=’%s’ and backupmx = ’1′
hosts = localhost
user = root
password = hahaha
dbname = postfix
query = SELECT maildir FROM mailbox WHERE username=’%s’ AND active = ’1′
hosts = localhost
user = root
password = hahaha
dbname = postfix
query = SELECT quota FROM mailbox WHERE username=’%s’ AND active = ’1′
create the regular exp file and postmap the transport
touch /etc/postfix/virtual_regexp
postmap /etc/postfix/transport

Dovecot Configuration(POP/IMAP)

Importnat files
The configuration for imap to work with the mysql, imap, pop, pops, imaps, TLS
## Dovecot config file
protocols = imap pop3 lmtp sieve
auth_mechanisms = plain login
passdb {
driver = sql
args = /etc/dovecot/dovecot-mysql.conf
userdb {
driver = prefetch
userdb {
driver = sql
args = /etc/dovecot/dovecot-mysql.conf
mail_location = maildir:/home/vmail/%d/%n
first_valid_uid = 101
#last_valid_uid = 0
first_valid_gid = 12
#last_valid_gid = 0
#mail_plugins =
mailbox_idle_check_interval = 30 secs
maildir_copy_with_hardlinks = yes
service imap-login {
inet_listener imap {
port = 143
inet_listener imaps {
port = 993
ssl = yes
service pop3-login {
inet_listener pop3 {
port = 110
inet_listener pop3s {
port = 995
ssl = yes
service lmtp {
unix_listener lmtp {
#mode = 0666
service imap {
vsz_limit = 256M
service pop3 {
service auth {
unix_listener auth-userdb {
mode = 0666
user = vmail
group = mail
# Postfix smtp-auth
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
service auth-worker {
service dict {
unix_listener dict {
mode = 0666
user = vmail
group = mail
service managesieve-login {
inet_listener sieve {
port = 4190
service_count = 1
process_min_avail = 0
vsz_limit = 64M
service managesieve {
ssl = yes
ssl_cert = /etc/pki/tls/private/server.crt
ssl_key = /etc/pki/tls/private/server.key
ssl_verify_client_cert = no
#ssl_ca =
lda_mailbox_autocreate = yes
lda_mailbox_autosubscribe = yes
protocol lda {
mail_plugins = quota sieve
postmaster_address = postmaster@your-domain.tld
protocol imap {
mail_plugins = quota imap_quota trash
imap_client_workarounds = delay-newmail
lmtp_save_to_detail_mailbox = yes
protocol lmtp {
mail_plugins = sieve
protocol pop3 {
mail_plugins = quota
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
protocol sieve {
managesieve_max_line_length = 65536
managesieve_implementation_string = Dovecot Pigeonhole
managesieve_max_compile_errors = 5
dict {
quotadict = mysql:/etc/dovecot/dovecot-dict-quota.conf
plugin {
quota = dict:user::proxy::quotadict
acl = vfile:/etc/dovecot/acls
trash = /etc/dovecot/trash.conf
sieve_global_path = /home/sieve/globalfilter.sieve
sieve = ~/dovecot.sieve
sieve_dir = ~/sieve
sieve_global_dir = /home/sieve/
#sieve_extensions = +notify +imapflags
sieve_max_script_size = 1M
#sieve_max_actions = 32
#sieve_max_redirects = 4
Trash folder config dovecot
1 Spam
# Uncomment if you want trash as well
# 2 Trash
Create a file for mysql and dovecot connection
driver = mysql
connect = host=localhost dbname=postfix user=admin password=hahaha
default_pass_scheme = MD5-CRYPT
# following should all be on one line.
password_query = SELECT username as user, password, concat(‘/home/vmail/’, maildir) as userdb_home,concat(‘maildir:/home/vmail/’, maildir) as userdb_mail, 101 as userdb_uid, 12 as userdb_gid FROM mailbox WHERE username = ‘%u’ AND active = ’1′
# following should all be on one line
user_query = SELECT concat(‘/home/vmail/’, maildir) as home, concat(‘maildir:/home/vmail/’, maildir) as mail, 101 AS uid, 12 AS gid, CONCAT(‘*:messages=10000:bytes=’, quota) as quota_rule FROM mailbox WHERE username = ‘%u’ AND active = ’1′
Quota setup for dovecot
connect = host=localhost dbname=postfix user=admin password=hahaha
map {
pattern = priv/quota/storage
table = quota2
username_field = username
value_field = bytes
map {
pattern = priv/quota/messages
table = quota2
username_field = username
value_field = messages
Now Create the sieve filter for SPAM filtering.
mkdir /home/sieve
vi /home/sieve/globalfilter.sieve
chown -R vmail:mail /home/sieve
require “fileinto”;
if exists “X-Spam-Flag” {
if header :contains “X-Spam-Flag” “NO” {
} else {
fileinto “Spam”;
if header :contains “subject” ["***SPAM***"] {
fileinto “Spam”;


vi /etc/httpd/conf.d/roundcubemail.conf
Alias /roundcubemail /usr/share/roundcubemail
Alias /webmail /usr/share/roundcubemail
<Directory /usr/share/roundcubemail/>
Order Deny,Allow
Allow from all
Setup Database
mysql -u root -p -e “CREATE DATABASE roundcubemail;”
mysql -u admin -p roundcubemail < /usr/share/doc/roundcubemail-0.7.3/SQL/mysql.initial.sql
$rcmail_config['db_dsnw'] = ‘mysql://username:password@localhost/roundcubemail’;
$rcmail_config['default_host'] = ‘localhost’;
$rcmail_config['smtp_server'] = ‘localhost’;
$rcmail_config['plugins'] = array(‘managesieve’);
$rcmail_config['quota_zero_as_unlimited'] = true;+
vi /usr/share/roundcubemail/plugins/managesieve/
$rcmail_config['managesieve_port'] = 4190;


vi /etc/clamd.conf
LogFile /var/log/clamav/clamd.log
#LogFileUnlock yes
LogFileMaxSize 20M
LogTime yes
#LogClean yes
LogSyslog yes
#LogFacility LOG_MAIL
#LogVerbose yes
#ExtendedDetectionInfo yes
PidFile /var/spool/amavisd/clamd.sock
TemporaryDirectory /var/tmp
DatabaseDirectory /var/lib/clamav
#OfficialDatabaseOnly no
LocalSocket /var/run/clamav/clamd.sock
#LocalSocketGroup virusgroup
#LocalSocketMode 660
FixStaleSocket yes
TCPSocket 3310
MaxConnectionQueueLength 30
#StreamMaxLength 10M
# Limit port range.
# Default: 1024
#StreamMinPort 30000
# Default: 2048
#StreamMaxPort 32000
MaxThreads 50
ReadTimeout 300
#CommandReadTimeout 5
#SendBufTimeout 200
#MaxQueue 200
#IdleTimeout 60
#ExcludePath ^/proc/
#ExcludePath ^/sys/
#MaxDirectoryRecursion 20
#FollowDirectorySymlinks yes
#FollowFileSymlinks yes
#CrossFilesystems yes
#SelfCheck 600
#VirusEvent /usr/local/bin/send_sms 123456789 “VIRUS ALERT: %v”
User clam
AllowSupplementaryGroups yes
#ExitOnOOM yes
#Foreground yes
#Debug yes
#LeaveTemporaryFiles yes
#DetectPUA yes
#ExcludePUA NetTool
#ExcludePUA PWTool
#IncludePUA Spy
#IncludePUA Scanner
#IncludePUA RAT
#AlgorithmicDetection yes
ScanPE yes
ScanELF yes
DetectBrokenExecutables yes
ScanOLE2 yes
#OLE2BlockMacros no
#ScanPDF yes
ScanMail yes
#ScanPartialMessages yes
PhishingSignatures yes
PhishingScanURLs yes
#PhishingAlwaysBlockSSLMismatch no
#PhishingAlwaysBlockCloak no
#HeuristicScanPrecedence yes
#StructuredDataDetection yes
#StructuredMinCreditCardCount 5
#StructuredMinSSNCount 5
#StructuredSSNFormatNormal yes
#StructuredSSNFormatStripped yes
#ScanHTML yes
ScanArchive yes
ArchiveBlockEncrypted no
#MaxScanSize 150M
#MaxFileSize 30M
#MaxRecursion 10
#MaxFiles 15000
#ClamukoScanOnAccess yes
#ClamukoScannerCount 3
#ClamukoMaxFileSize 10M
#ClamukoScanOnOpen yes
#ClamukoScanOnClose yes
#ClamukoScanOnExec yes
#ClamukoIncludePath /home
#ClamukoIncludePath /students
#ClamukoExcludePath /home/bofh
#ClamukoExcludeUID 0
#Bytecode yes
#BytecodeSecurity TrustSigned
# BytecodeTimeout 1000
Configure Razor. Type the following:
razor-admin -register -user=some_user -pass=somepas
Update and restart clamav:
service clamd restart
Configuring Amavisd-new
vi /etc/amavisd.conf
Here is a list of items you should change. just scroll through the file to find each item.
$mydomain = ‘’; # set to your domain name
$log_level = 1; # set the log leve to one
$sa_tag_level_deflt = -99; # i want to see the headers so change to -99
$sa_tag2_level_deflt = 5.0; # start with 5
$sa_kill_level_deflt = 9; # change to 9
$sa_dsn_cutoff_level = 9; # change to 9
$sa_quarantine_cutoff_level = 50; # remove the starting # and change to 50
$myhostname = ‘’; # remove the starting # and enter your host name
$notify_method = ‘smtp:[]:10025′; # uncomment the line
$forward_method = ‘smtp:[]:10025′; # uncomment the line
$final_banned_destiny = D_DISCARD; # change to D_DISCARD
Now enable clamav:
Change the following:
# ###
# ['ClamAV-clamd',
#   \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd"],
#   qr/\bOK$/m, qr/\bFOUND$/m,
#   qr/^.*?: (?!Infected Archive)(.*) FOUND$/m ],
\&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd"],
qr/\bOK$/m, qr/\bFOUND$/m,
qr/^.*?: (?!Infected Archive)(.*) FOUND$/m ],
Now update spamassassin and start amavisd-new.
service amavisd-new start
Be sure to set amavisd-new to start at boot.
Telling Postfix to Start Filtering SPAM
To get postfix going we need to un-comment a couple lines in /etc/postfix/
smtp      inet  n       -       n       -       -       smtpd
#  -o content_filter=smtp-amavis:
#  -o receive_override_options=no_address_mappings
Change to:
smtp      inet  n       -       n       -       -       smtpd
-o content_filter=smtp-amavis:
-o receive_override_options=no_address_mappings
Restart services and start at bootup. you’re done.
service dovecot restart
service postfix restart
service mysql restart
service clamd.amavisd restart
service clamd restart
service amavisd restart
chkconfig <services> on
Hostfile Setup
vi /etc/hosts (mail server)  (replace with your mail server IP)
vi /etc/hosts (MyLocalComputer) (replace with your mail server IP)
Check the logs
tail -f /var/log/maillog

Restrict Users to Home Directory : Chroot Jail for SFTP Users

We often need to restrict users to their home directories. Here we discuss an easy way to setup jailed SFTP users on CentOS 5.x. Haven't yet tried this on CentOS 6.0, but this should work there too. The only thing is to ensure that the OpenSSH Version is 5.x and not 4.x.

So, the most important step is the first step – upgrading OpenSSH to version 5.x. Version 4.x of OpenSSH which is included in CentOS is missing the necessary functions to “chroot” the users (i.e. set their root directory when they login) so that they can only view files that are under their virtual root directory. Once upgraded, it’s just a few lines of config changes and some basic user setup and you’re good to go. Feel free to ask in comments for help if you get stuck.

1. Upgrade to OpenSSH 5.x

## fetch the packages - 64-bit system  wget  wget  wget

- or -

## fetch the packages - 32-bit system  wget  wget  wget


## upgrade OpenSSH  rpm -Uvh openssh-*

2. Comment out the following line in ‘/etc/ssh/sshd_config’

Subsystem     sftp     /usr/libexec/openssh/sftp-server

3. Append these lines to the end of ‘/etc/ssh/sshd_config’

Subsystem     sftp     internal-sftp  Match Group sftponly      ChrootDirectory /home/%u      ForceCommand internal-sftp      AllowTcpForwarding no

4. Add the ‘sftponly’ user group

groupadd sftponly

5. Modify the user’s group and shell

usermod -g sftponly jsmith  usermod -s /bin/false jsmith

6. Set the proper filesystem permissions

(John Smiths’s home directory is /home/jsmith and his website is in /home/jsmith/public_html)

chmod 755 /home/jsmith/  chmod 755 /home/jsmith  chown root:root /home/jsmith  chown jsmith:sftponly /home/jsmith/public_html

7. Restart the SSHD daemon

/etc/init.d/sshd restart


All about SVN Server in Linux and Tortoise SVN Client

Subversion is an open-source version control system. Subversion manages files and directories, and the changes made to them, over time. This allows you to recover older versions of your data, or examine the history of how your data changed.

The installation steps for SVN server with security modules in place are as follows:

# yum install mod_dav_svn subversion


If you don't have Apache installed already, it'll go ahead and drag that down as well so we don’t need to worry about getting apache installed here prior to SVN.

When you install from yum, there's a longer list than the two packages above that will automatically resolve themselves. Some other things will be installed automatically.

First thing is make sure you open up /etc/httpd/conf/httpd.conf and at least change the ServerName directive.

# vim /etc/httpd/conf/httpd.conf -- Edit what you need and save the file
# service httpd start
# chkconfig httpd on

Browse to your machine on the network and see if you get your test page, which you should: http://serverIP. It should show up the Apache page.

Subversion's Apache configs

The next step is to setup some settings within Apache so Subversion and Apache play nice together. Get yourself to the example configuration file Subversion installed for you.

# cd /etc/httpd/conf.d/
# vim subversion.conf
# Make sure you uncomment the following if they are commented out
LoadModule dav_svn_module     modules/
LoadModule authz_svn_module   modules/
# Add the following to allow a basic authentication and point Apache to where the actual
# repository resides.
&lt;Location /repos&gt;
        DAV svn
        SVNPath /var/www/svn/repos
        AuthType Basic
        AuthName "Subversion repos"
        AuthUserFile /etc/svn-auth-conf
        Require valid-user

The location is what Apache will pass in the URL bar. For instance: http://yourmachine/repos points to the SVNPath that you have specified. My examples are just that, so feel free to put things where you want. Make sure you save the file when you are finished editing.

Next we have to actually create the password file that you specified in the previous step. Initially you'll use the -cm arguments. This creates the file and also encrypts the password with MD5. If you need to add users make sure you simply use the -m flag, and not the -c after the initial creation.

# htpasswd -cm /etc/svn-auth-conf yourusername
New password:
Re-type new password:
Adding password for user yourusername
# htpasswd -m /etc/svn-auth-conf anotherusername
New password:
Re-type new password:
Adding password for user anotherusername

Configure your repository

The next thing you need to do is to create the actual repository from which you will check in and out your files. This is simple to do with some of the included svn tools.

# cd /var/www/ -- Or wherever you placed your path above
# mkdir svn
# cd svn
# svnadmin create repos
# chown -R apache.apache repos
# service httpd restart

Go test out whether or not you can access your repository from a web browser: http://yourmachine/repos. You should get a popup box asking for a username and password. If so, type in your credentials and you should be displayed with a Revision 0:/ page. If so, that's it for setting up a repo. If you want multiple repos, check out the docs from the links provides above. This sets up one repository and shows you how to start using them. Speaking of, let's move on to just that.



Using Subversion

Layout the Repo

If all went well above, you're now ready to start using the repository that you created. Subversions svn tool is the command line client that you will use to talk to the database. To see the use of the tool:

# svn --help

The most common arguments you will most likely be using are: svn import, svn commit (ci), and svn checkout (co). With these you will initially import files into your repository with import, you'll check them out to work on them with checkout, and you'll commit the changes back into the database with commit. It's pretty simple once you see them in use a few times.

Almost all of the documentation talks about creating a certain layout for your directories. They specifically mention about making sure you have a branches, tags, and trunk underneath the root directory structure, where trunk holds all your files. For instance:

|-- project1
|   |-- branches
|   |-- tags
|   `-- trunk
`-- project2
    |-- branches
    |-- tags
    `-- trunk

As an example, I'm going to just create some dummy directories and throw some files in them. This is from the actual SVN server.

# cd /tmp
# mkdir mytestproj
# cd mytestproj
# mkdir configurations options main
# vim configurations/testconf1.cfg -- Add whatever you want to these files.
# vim options/testopts1.cfg
# vim main/mainfile1.cfg

Keep in mind that you can layout anything anyway you'd like. Once you have the initial layout of what you want, let's go ahead and import this up to Subversion.


# svn import /tmp/mytestproj/ file:///var/www/svn/repos/mytestproj -m "Initial repository layout for mytestproj"
Adding         /tmp/mytestproj/main
Adding         /tmp/mytestproj/main/mainfile1.cfg
Adding         /tmp/mytestproj/configurations
Adding         /tmp/mytestproj/configurations/testconf1.cfg
Adding         /tmp/mytestproj/options
Adding         /tmp/mytestproj/options/testopts1.cfg

Checking Out

Now, just to check it out across the web browser: http://serverIP/repos. You'll get whatever you have imported showing up to peruse. Once you upload your original layout from the local SVN server, you're now free to use it remotely on another machine. As long as you are connecting to the Subversion server with the user account(s) that you created earlier. Let's give it a shot.

# cd /tmp
# svn co http://yoursvnserver/repos/mytestproj
Authentication realm: &lt;http://yoursvnserver:80&gt; Subversion repos
Password for 'youruser':
A    mytestproj/main
A    mytestproj/main/mainfile1.cfg
A    mytestproj/configurations
A    mytestproj/configurations/testconf1.cfg
A    mytestproj/options
A    mytestproj/options/testopts1.cfg
Checked out revision 1.

Edit &amp; Commit

As you can see, you've checked out revision 1 from the Subversion server. Now you can edit some things and commit the changes back to the Subversion server.

# cd mytestproj
# vim configurations/testconf1.cfg -- Add or delete something and save.
# svn commit -m "Added a line to testconf1.cfg."
Sending        configurations/testconf1.cfg
Transmitting file data .
Committed revision 2.

The nice thing about this then, is that you can delete all of the directories that you just checked out on your machine. The only reason you checked them out, was to edit them, and then send them back up the line. Web browse to your server to check out the different files.

Adding/Deleting Items

Now this is all fine and dandy, but how do you add more files to an already existing repo directory? Easy, with the add argument. Go ahead and checkout your latest and greatest, copy a file over to a directory, add, then commit the changes.

# svn co http://yoursvnserver/repos/mytestproj
A    mytestproj/main
A    mytestproj/main/mainfile1.cfg
A    mytestproj/configurations
A    mytestproj/configurations/testconf1.cfg
A    mytestproj/options
A    mytestproj/options/testopts1.cfg
Checked out revision 2.
# cd mytestproj
# cp /etc/yum.repos.d/CentOS-Base.repo configurations/
# svn add configurations/CentOS-Base.repo
A         configurations/CentOS-Base.repo
# svn commit -m "Added the CentOS Yum repo file."
Adding         configurations/CentOS-Base.repo
Transmitting file data .
Committed revision 3.

To delete items simply use delete instead of add. Commit your changes back up, and you're good to go. It's as simple as that. Go back over to your web browser again and you'll notice the revision number should say 3. You'll be able to click through the files to pick our your differences as well.

Reverting Back

Ok, this is all great but how do I revert back to an older revision...isn't this the point of Subversion? Yep, it's easy. If you're not sure as to what revision you're at...check out the log command. This is why you put a message in every commit. Short and to the point, but enough information to ring a bell that you perhaps forgot about.

# svn log http://yoursvnserver/repos -- For the entire repository
# svn log http://yoursvnserver/repos/mytestproj -- For the specific project

You'll get a nice complete list of revision numbers along with the comments, like I mentioned above. This allows you to pick which revision you want to check back out now.

# svn co -r 1 http://yoursvnserver/repos/mytestproj

This command will drag down revision number 1.

Access control lists

Usually, you don't want to give every user access to every repository. You can restrict repository access per user by using ACLs. ACLs can be enabled with the AuthzSVNAccessFile file option, which takes a file name as its parameter. For instance:

AuthzSVNAccessFile /etc/svn-acl-conf

You can add this to the relevant Location section:

<Location /repos>
        DAV svn
        SVNParentPath /var/www/svn/repos
        AuthzSVNAccessFile /etc/svn-acl-conf
        AuthType Basic
        AuthName "Subversion repos"
        AuthUserFile /etc/svn-auth-conf
        Require valid-user

You can then create /etc/svn-acl-conf. This file consist of sections of the following form:

user = access

Where access can be r (read), rw (read-write), or empty (no access at all). The default ACL is to give users no access to a repository. Suppose that there is a repository named framework to which you would like to give john read access, and joe read and write access. You could then add the following section:

john =  r
joe = rw

It is also possible to create groups in a section named groups, groups are then prefixed with the 'at' sign (@) in the access control lists. For instance:

staff = joe, george
john =  r
@staff = rw

If you would like to make all repositories readable to all users, you can add a section for the root directory of every repository:

* = r

Finally, to make things work properly throughout the network we will have to setup the iptables as below:


# Generated by iptables-save v1.3.5 on Sun Mar 11 10:11:08 2012




:OUTPUT ACCEPT [241701:28893896]

:RH-Firewall-1-INPUT - [0:0]

-A INPUT -s -d -j ACCEPT

-A INPUT -j RH-Firewall-1-INPUT

-A FORWARD -j RH-Firewall-1-INPUT

-A RH-Firewall-1-INPUT -i lo -j ACCEPT

-A RH-Firewall-1-INPUT -p icmp -m icmp --icmp-type any -j ACCEPT

-A RH-Firewall-1-INPUT -p esp -j ACCEPT

-A RH-Firewall-1-INPUT -p ah -j ACCEPT

-A RH-Firewall-1-INPUT -d -p udp -m udp --dport 5353 -j ACCEPT

-A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT

-A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT

-A RH-Firewall-1-INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

-A RH-Firewall-1-INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT

-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited


# Completed on Sun Mar 11 10:11:08 2012

Run the following command:

# service iptables save

# service iptables start

#chkconfig iptables on


The following part of the document will show you how to interact with the server from the client side.

What you will need to download the Tortoise SVN client application.

Download and install and after a restart (bummer) we are ready to start working!

The Tortoise SVN adds its functionality in the Windows Explorer Context Menu.

Verifying the connection to the SVN Server

Before we start working we will have to Verify the connection to the SVN Server. Right click on any folder in the Windows Explorer and select TortoiseSVN -> Repo-browser

you will be asked for a path to the repository enter : file:///C:/<The location of the repositories>/<The repository name you selected> in my case I will enter :


what you should get is this:

If you got this it means that you can connect to the SVN Server.

If you are trying to connect to a remote server you will have to enter the following when asked for the URL of the repository:

https://<The ip of the Server>/svn/<The Repository Name>

You should get the same results.

 Getting the files from the repository

To get the files from the repository we created earlier (in the previous article) we will have to create a new folder, which I presume everyone knows how to do :).

After you have created the folder, right click on it and select the "SVN Checkout…" option from the context menu. You will see the following screen:

If you followed all the steps the address of the repository should be already written here. All you have to do is click "OK"

This means we have checked out the files successfully and we can start working!

The directory should look like this:

The Green V marks mean that nothing has changed inside the directory. Lets add a new file to the trunk (main branch) directory. We will then Right Click on the trunk and select "Commit"

The SVN Server has detected that you have added a new file and you will have to check the Checkbox next to it in order for it to be inserted to the repository.

Lets try and edit the file and add some text in it. Both the file and the Directory will get a red exclamation mark saying they have been changed:

To send the Changes to the Server you can right click any of them and select "SVN Commit…" from the context menu. Doing it on the Folder will make the Commit recursive to all the files inside it.



The following part of the document is an excerpt from the SVN commandline-guide which will help commandline users to take care of the SVN related activities:


1.) Checkout the code and do an update in case of any changes made since your last update (We assume that you are using apache dav server to access your code and not svnserve):

$svn checkout http://serverIP/svn/repos/server_code server_code

If your repository requires authentication:

$svn checkout –username my_username http://serverIP/svn/repos/server_code server_code

Update your working copy:

$svn update
(update from current)
$svn update -r BASE server_code
(update foo from base revision)
$svn update -r 1200 server_code (update foo from revision number 1200)

2.) Make changes:

$svn add eg svn add new_directory
(add a new directory foo)
$svn delete
$svn copy directory1 directory2
(copy directory directory1 to directory2)
$svn move directory2 renamed_directory

3.) Examine your changes (Can be done even with no network access to the subversion repository):

$svn status
(To get an overview of all your changes)
A stuff/loot/bloo.h # file is scheduled for addition
C stuff/loot/lump.c # file has textual conflicts from an update
D stuff/fish.c # file is scheduled for deletion
M bar.c # the content in bar.c has local modifications

$svn diff
(to show changes between current working directory and the same directory in the repository)

4.) Possibly undo some changes (Can also be done even with no network access to the subversion repository):

$svn revert
After running svn revert as a way to resolve local conflict with the repository copy, Run:

$svn resolve
To inform svn that the conflict has been resolved. You will now be able to successfully run svn update in case of previous conflicts.

5.) Resolve Conflicts (Merge Others’ Changes):

$svn update
$svn resolved

6.) Commit your changes:

$svn commit
$svn commit -m “Removed out of mem errors.”
$svn commit -F comment.txt
$svn commit –file comment.txt

6. Logs:

$svn log (use current working directory as the default target)
$svn log server_code
(current working directory/file is server_code)
$svn log -r 5:19
(shows logs 5 through 19 in chronological order of working directory)
$svn log -r 19:5
(shows logs 5 through 19 in reverse order of working directory)
$svn log -r 8
(shows log for revision 8 of working directory)
$svn log -r 8 -v
(shows verbose? log for revision 8 of working directory)

7. Diffs (Changes):

$svn diff
$svn diff -r 3 rules.txt
(or svn diff –revision 3 rules.txt)
$svn diff -r 2:3 rules.txt
(revisions 2 and 3 are directly compared)
$svn diff -c 3 rules.txt
(compare changes between current revision and revision 2)

8. Browse a file directly:

svn cat -r 2 rules.txt
svn cat -r 2 rules.txt > rules.txt.v2 (send cat output directly to a file)

9. Browse a folder directly:

svn list
svn list -v

10. Fetching older repository snapshots:

$svn checkout -r 1729
(Checks out a new working copy at r1729)
$svn update -r 1729
(Updates an existing working copy to r1729)

11. If you’re building a release and wish to bundle up your files from Subversion but don’t want those pesky .svn directories in the way, then you can use svn export to create a local copy of all or part of your repository sans .svn directories. As with svn update and svn checkout, you can also pass the – -revision switch to svn export:

$svn export
(Exports latest revision)
$svn export -r 1729
(Exports revision r1729)

12. Cleanup if a Subversion operation is interrupted (if the process is killed, or if the machine crashes, for example), the log files remain on disk. By re-executing the log files, Subversion can complete the previously started operation, and your working copy can get itself back into a consistent state.

$svn cleanup

13. Revision specifiers:
HEAD: The latest (or “youngest”) revision in the repository.
BASE: The revision number of an item in a working copy. If the item has been locally modified, the “BASE version” refers to the way the item appears without those local modifications.
COMMITTED: The most recent revision prior to, or equal to, BASE, in which an item changed.
PREV: The revision immediately before the last revision in which an item changed. Technically, this boils down to COMMITTED-1.

$svn diff -r PREV:COMMITTED main.c
(shows the last change committed to main.c)

$svn log -r HEAD
(shows log message for the latest repository commit)

$svn diff -r HEAD
(compares your working copy with all of its local changes to the latest version of that tree in the repository)

svn diff -r BASE:HEAD main.c
(compares the unmodified version of foo.c with the latest version of foo.c in the repository)

$svn log -r BASE:HEAD
(shows all commit logs for the current versioned directory since you last updated

$svn update -r PREV main.c
(rewinds the last change on foo.c, decreasing foo.c’s working revision)

$svn diff -r BASE:14 main.c
(compares the unmodified version of foo.c with the way foo.c looked in revision 14)

14. Checkout based on revisions:

$svn checkout -r {2006-02-17}
$svn checkout -r {15:30}
$svn checkout -r {15:30:00.200000}
$svn checkout -r {“2006-02-17 15:30″}
$svn checkout -r {“2006-02-17 15:30 +0230″}
$svn checkout -r {2006-02-17T15:30}
$svn checkout -r {2006-02-17T15:30Z}
$svn checkout -r {2006-02-17T15:30-04:00}
$svn checkout -r {20060217T1530}
$svn checkout -r {20060217T1530Z}
$svn checkout -r {20060217T1530-0500}

15. Logs based on revisions:

$svn log -r {2006-11-28}
$svn log -r {2006-11-20}:{2006-11-29}

16. Properties of files:

$svn propset copyright ‘(c) 2006 Red-Bean Software’ calc/button.c
property ‘copyright’ set on ‘calc/button.c’

$svn propset license -F /path/to/LICENSE calc/button.c
property ‘license’ set on ‘calc/button.c’

$svn propedit copyright calc/button.c
No changes to property ‘copyright’ on ‘calc/button.c’

$svn propset copyright ‘(c) 2006 Red-Bean Software’ calc/*
property ‘copyright’ set on ‘calc/Makefile’
property ‘copyright’ set on ‘calc/button.c’
property ‘copyright’ set on ‘calc/integer.c’

$svn proplist calc/button.c
Properties on ‘calc/button.c’:

$svn propget copyright calc/button.c
(c) 2006 Red-Bean Software

$svn proplist -v calc/button.c

$svn propset license ” calc/button.c
$svn propdel license calc/button.c

And specify the revision whose property you wish to modify

$svn propset copyright ‘(c) 2006 Red-Bean Software’ calc/button.c -r11 –revprop

17. Locking files:

$svn lock banana.jpg -m “Editing file for tomorrow’s release.”
‘banana.jpg’ locked by user ‘harry’.

$svn status
K banana.jpg

$svn info banana.jpg
Path: banana.jpg
Name: banana.jpg
Repository UUID: edb2f264-5ef2-0310-a47a-87b0ce17a8ec
Revision: 2198
Node Kind: file
Schedule: normal
Last Changed Author: frank
Last Changed Rev: 1950
Last Changed Date: 2006-03-15 12:43:04 -0600 (Wed, 15 Mar 2006)
Text Last Updated: 2006-06-08 19:23:07 -0500 (Thu, 08 Jun 2006)
Properties Last Updated: 2006-06-08 19:23:07 -0500 (Thu, 08 Jun 2006)
Checksum: 3b110d3b10638f5d1f4fe0f436a5a2a5
Lock Token: opaquelocktoken:0c0f600b-88f9-0310-9e48-355b44d4a58e
Lock Owner: harry
Lock Created: 2006-06-14 17:20:31 -0500 (Wed, 14 Jun 2006)
Lock Comment (1 line):
Editing file for tomorrow’s release.

$svnadmin lslocks /usr/local/svn/repos
$svnadmin rmlocks /usr/local/svn/repos /project/raisin.jpg
Force out someone else’s lock:

$svn unlock –force
Force a lock over someone else’s
$ svn lock –force raisin.jpg

18. Creating branches:

$svn checkout bigwc
A bigwc/trunk/
A bigwc/trunk/Makefile
A bigwc/trunk/integer.c
A bigwc/trunk/button.c
A bigwc/branches/
Checked out revision 340.

Now create the branch;

$cd bigwc
$svn copy trunk branches/my-calc-branch
$svn status
A + branches/my-calc-branch

$svn commit -m “Creating a private branch of /calc/trunk.”
Adding branches/my-calc-branch
Committed revision 341.

You can do all the above in one step (Recommended way):

$svn copy \ \
-m “Creating a private branch of /calc/trunk.”
Committed revision 341.

Merging branch to main trunk (Assuming you are in the working branch directory)

$svn merge -c 344 (merge change revision number 344 on your working directory branch)
U integer.c

$svn status
M integer.c

Merging while specifying the destination and target:

$svn merge -c 344 my-calc-branch
U my-calc-branch/integer.c

$svn merge \ \

$svn merge -r 100:200 my-working-copy

$svn merge -r 100:200

Previewing merges:

$svn merge – -dry-run -c 344
U integer.c
(- -dry-run is a double dash without spaces. Word press munges the double dash into one when put together.)

$svn status
(nothing printed, working copy is still unchanged)

Merging branch changes into trunk:

$cd calc/trunk
$svn update
At revision 405.

$svn merge -r 341:405
U integer.c
U button.c
U Makefile

$svn status
M integer.c
M button.c
M Makefile

Examine the diffs, compile, test, etc…

$svn commit -m “Merged my-calc-branch changes r341:405 into the trunk.”
Sending integer.c
Sending button.c
Sending Makefile
Transmitting file data …
Committed revision 406

Undo a merge:

$svn merge -c -303
$svn merge –revision 303:302
U integer.c

$svn status
M integer.c

$svn diff
(Verify that the change is removed)

$svn commit -m “Undoing change committed in r303.”
Sending integer.c
Transmitting file data .
Committed revision 350.

Merging from branch to trunk:

$cd trunk-working-copy

$svn update
At revision 1910.

$svn merge \

U real.c
U integer.c
A newdirectory
A newdirectory/newfile

Resurrecting deleted items:

$svn copy -r 807 \ ./real.c

$ svn status
A + real.c

$svn commit -m “Resurrected real.c from revision 807, /calc/trunk/real.c.”
Adding real.c
Transmitting file data .
Committed revision 1390.

Traversing branches:
$cd calc

$svn info | grep URL

$svn switch
U integer.c
U button.c
U Makefile
Updated to revision 341.

$svn info | grep URL

Making releases using tags (snapshot of a directory at a given instant in time)
$svn copy \ \
-m “Tagging the 1.0 release of the ‘calc’ project.”

Committed revision 351.

Remove your branch after merge:
$svn delete \
-m “Removing obsolete branch of calc project.”

Committed revision 375.

Commit a log message correction:
$echo “Here is the new, correct log message” > newlog.txt
$svnadmin setlog myrepos newlog.txt -r 388

Migrate repository:
Create the dump files first:
$svnadmin dump myrepos -r 23 > rev-23.dumpfile
$svnadmin dump myrepos -r 100:200 > revs-100-200.dumpfile

Load the dump files into the new repository:
$svnadmin dump myrepos -r 0:1000 > dumpfile1
$svnadmin dump myrepos -r 1001:2000 –incremental > dumpfile2
$svnadmin dump myrepos -r 2001:3000 –incremental > dumpfile3